Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
022505d130
|
||
|
|
03ed383587 | ||
|
|
85e9ab1316 | ||
|
|
03215cab62 | ||
|
|
6866e6653f | ||
|
|
eceb2a6d59
|
||
|
|
3f8ca0ef1f | ||
|
|
e341a90df3
|
||
|
|
a7e6a40924 | ||
|
|
0222074cf9 | ||
|
|
4033590078
|
No files matched your search
+11
-57
@@ -1,60 +1,14 @@
|
||||
version: 2.1
|
||||
|
||||
setup: true
|
||||
orbs:
|
||||
qqq-orb: kingsrook/qqq-orb@0.6.9
|
||||
|
||||
commands:
|
||||
configure-package-install:
|
||||
steps:
|
||||
- run:
|
||||
name: Keep package installation unattended
|
||||
command: |
|
||||
# These build machines are discarded after the job.
|
||||
sudo install -d /etc/needrestart/conf.d
|
||||
printf '%s\n' '$nrconf{restart} = "l";' | sudo tee /etc/needrestart/conf.d/99-qqq-ci.conf >/dev/null
|
||||
|
||||
qqq-orb: kingsrook/qqq-orb@0.7.12
|
||||
workflows:
|
||||
test_only:
|
||||
jobs:
|
||||
- qqq-orb/mvn_test_only:
|
||||
pre-steps:
|
||||
- configure-package-install
|
||||
context: [qqq-maven-registry-credentials]
|
||||
filters:
|
||||
branches:
|
||||
ignore: /(develop|release\/.*)/
|
||||
|
||||
publish_snapshot:
|
||||
jobs:
|
||||
- qqq-orb/mvn_publish:
|
||||
pre-steps:
|
||||
- configure-package-install
|
||||
context: [qqq-maven-registry-credentials]
|
||||
branch_type: snapshot
|
||||
filters:
|
||||
branches:
|
||||
only: [develop]
|
||||
|
||||
publish_release_candidate:
|
||||
jobs:
|
||||
- qqq-orb/mvn_publish:
|
||||
pre-steps:
|
||||
- configure-package-install
|
||||
context: [qqq-maven-registry-credentials]
|
||||
branch_type: release_candidate
|
||||
filters:
|
||||
branches:
|
||||
only: [/release\/.*/]
|
||||
|
||||
publish_release:
|
||||
jobs:
|
||||
- qqq-orb/mvn_publish:
|
||||
pre-steps:
|
||||
- configure-package-install
|
||||
context: [qqq-maven-registry-credentials]
|
||||
branch_type: release
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: [/^v\d+\.\d+\.\d+$/]
|
||||
setup:
|
||||
jobs:
|
||||
- qqq-orb/generate_pipeline:
|
||||
orb_version: 0.7.12
|
||||
filters:
|
||||
branches:
|
||||
ignore: automation/qbit-rc-pending
|
||||
tags:
|
||||
only: /^v\d+\.\d+\.\d+$/
|
||||
@@ -0,0 +1,23 @@
|
||||
name: CodeQL
|
||||
'on':
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
- release/**
|
||||
- hotfix/**
|
||||
pull_request: {}
|
||||
schedule:
|
||||
- cron: 41 16 * * 0
|
||||
workflow_dispatch: {}
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
security-events: write
|
||||
packages: read
|
||||
concurrency:
|
||||
group: codeql-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
jobs:
|
||||
analyze:
|
||||
uses: QRun-IO/qqq-orb/.github/workflows/qbit-codeql.yml@c288a8864fe9054f68410e1d78f5863aea4c4d22
|
||||
@@ -1,25 +1,74 @@
|
||||
# Cut the next release candidate (QRun-IO/qqq docs/QRUN-QBIT-REPO-STANDARD.md, C6):
|
||||
# run this workflow by hand, or merge a develop PR labelled `release:rc`. It merges develop into
|
||||
# the release line and the release/* push runs CircleCI publish_release_candidate.
|
||||
name: Release candidate
|
||||
|
||||
on:
|
||||
'on':
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: Print the plan without merging or creating branches
|
||||
description: Plan a cut without changing release state
|
||||
type: boolean
|
||||
default: false
|
||||
finalize:
|
||||
description: Retry finalization of an existing cut; do not cut another RC
|
||||
type: boolean
|
||||
default: false
|
||||
recover:
|
||||
description: Recover the same published RC after a deployment timeout; never
|
||||
reupload
|
||||
type: boolean
|
||||
default: false
|
||||
circle_build:
|
||||
description: Original Circle publisher build number (recovery only)
|
||||
type: string
|
||||
default: ''
|
||||
merge_sha:
|
||||
description: Existing cut merge_sha (finalize retry only)
|
||||
type: string
|
||||
default: ''
|
||||
bump_sha:
|
||||
description: Existing cut bump_sha (finalize retry only)
|
||||
type: string
|
||||
default: ''
|
||||
branch:
|
||||
description: Existing cut branch (finalize retry only)
|
||||
type: string
|
||||
default: ''
|
||||
version:
|
||||
description: Existing cut version (finalize retry only)
|
||||
type: string
|
||||
default: ''
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches: [develop]
|
||||
|
||||
types:
|
||||
- closed
|
||||
branches:
|
||||
- develop
|
||||
repository_dispatch:
|
||||
types:
|
||||
- qbit-rc-published
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
actions: read
|
||||
checks: read
|
||||
jobs:
|
||||
release-rc:
|
||||
if: github.event_name == 'workflow_dispatch' || (github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'release:rc'))
|
||||
uses: QRun-IO/.github/.github/workflows/qbit-release-rc.yml@main
|
||||
if: github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch'
|
||||
|| (github.event_name == 'pull_request' && github.event.pull_request.merged
|
||||
== true && github.event.pull_request.base.ref == 'develop' && contains(github.event.pull_request.labels.*.name,
|
||||
'release:rc'))
|
||||
uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@cc30f599e63c8e41629c99d23395bac1adb8bc44
|
||||
with:
|
||||
dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }}
|
||||
dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false
|
||||
}}
|
||||
finalize: ${{ github.event_name == 'repository_dispatch' || (github.event_name
|
||||
== 'workflow_dispatch' && inputs.finalize) }}
|
||||
recover: ${{ github.event_name == 'workflow_dispatch' && inputs.recover || false
|
||||
}}
|
||||
circle_build: ${{ github.event_name == 'workflow_dispatch' && inputs.circle_build
|
||||
|| '' }}
|
||||
merge_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.merge_sha
|
||||
|| inputs.merge_sha || '' }}
|
||||
bump_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.bump_sha
|
||||
|| inputs.bump_sha || '' }}
|
||||
branch: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.branch
|
||||
|| inputs.branch || '' }}
|
||||
version: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.version
|
||||
|| inputs.version || '' }}
|
||||
secrets: inherit
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
profile: qbit
|
||||
orb_version: 0.7.12
|
||||
default_branch: develop
|
||||
java_version: '21'
|
||||
browsers: true
|
||||
api_checks: false
|
||||
docs_only: false
|
||||
release_on_main: false
|
||||
release_tag_policy: stable
|
||||
test_branch_policy: non-release
|
||||
publish:
|
||||
snapshot: true
|
||||
release_candidate: true
|
||||
release: true
|
||||
asciidoc: false
|
||||
release_completion: true
|
||||
@@ -62,6 +62,7 @@ public class ObjectStorageQBitConfig implements QBitConfig
|
||||
private String appName = "objectStorageAdmin";
|
||||
private String appLabel = "Storage";
|
||||
private String parentAppName;
|
||||
private String tablePathPrefix;
|
||||
private List<String> allowedSecretRefPatterns = new ArrayList<>(SecretRefs.DEFAULT_ALLOWED_PATTERNS);
|
||||
private Integer bulkCap = 10_000;
|
||||
private Boolean bucketScoping = true;
|
||||
@@ -425,6 +426,39 @@ public class ObjectStorageQBitConfig implements QBitConfig
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
** Getter for tablePathPrefix: the front of the links the Storage home makes to
|
||||
** tables and records. Defaults to /app, the route every QQQ frontend serves
|
||||
** tables at (/app/<tableName>).
|
||||
*******************************************************************************/
|
||||
public String getTablePathPrefix()
|
||||
{
|
||||
return (this.tablePathPrefix == null ? "/app" : this.tablePathPrefix);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
** Setter for tablePathPrefix.
|
||||
*******************************************************************************/
|
||||
public void setTablePathPrefix(String tablePathPrefix)
|
||||
{
|
||||
this.tablePathPrefix = tablePathPrefix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
** Fluent setter for tablePathPrefix.
|
||||
*******************************************************************************/
|
||||
public ObjectStorageQBitConfig withTablePathPrefix(String tablePathPrefix)
|
||||
{
|
||||
this.tablePathPrefix = tablePathPrefix;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
** Getter for allowedSecretRefPatterns.
|
||||
*******************************************************************************/
|
||||
|
||||
@@ -106,16 +106,12 @@ public final class StorageWidgets
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** The prefix of table and record links.
|
||||
** The prefix of table and record links: /app, so a link is /app/<tableName>
|
||||
** (the frontend serves every table, in any app, at that one flat route).
|
||||
*******************************************************************************/
|
||||
public static String tablePathPrefix()
|
||||
{
|
||||
if(!ObjectStorageRuntime.isInstalled())
|
||||
{
|
||||
return ("/objectStorageAdmin");
|
||||
}
|
||||
ObjectStorageQBitConfig config = ObjectStorageRuntime.getConfig();
|
||||
return (config.getParentAppName() == null ? "/" + config.getAppName() : "/" + config.getParentAppName() + "/" + config.getAppName());
|
||||
return (ObjectStorageRuntime.isInstalled() ? ObjectStorageRuntime.getConfig().getTablePathPrefix() : "/app");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -574,4 +574,40 @@ class MinioIndexTest
|
||||
.contains("Usage trend").contains("collecting since")
|
||||
.contains("Connections").contains("Never tested");
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Every link the home emits is a /app/<table>[...] route that the Next frontend
|
||||
** resolves, never an /<appName>/<table> path, with data and without.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void everyHomeLinkUsesTheAppRoute() throws Exception
|
||||
{
|
||||
String prefix = com.kingsrook.qbits.objectstorage.app.StorageWidgets.tablePathPrefix();
|
||||
assertThat(prefix).isEqualTo("/app");
|
||||
java.util.List<String> hrefs = new java.util.ArrayList<>(hrefs(com.kingsrook.qbits.objectstorage.app.StorageHome.render(prefix, Instant.now())));
|
||||
|
||||
rawPut(target.indexBucket, "media/1/a.jpg", 2048);
|
||||
rawPut(target.indexBucket, "media/9/orphan.jpg", 1024);
|
||||
ObjectIndex.scan("indexed");
|
||||
ObjectIndex.headBacklog("indexed", 10);
|
||||
ReferenceScan.run("indexed");
|
||||
ObjectStorage.bucket("indexed").put(PutRequest.of("media/1/c.jpg", new byte[3]));
|
||||
hrefs.addAll(hrefs(com.kingsrook.qbits.objectstorage.app.StorageHome.render(prefix, Instant.now())));
|
||||
|
||||
assertThat(hrefs).isNotEmpty().allSatisfy(href -> assertThat(href).startsWith("/app/"));
|
||||
assertThat(hrefs).noneMatch(href -> href.contains("objectStorageAdmin"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static java.util.List<String> hrefs(String html)
|
||||
{
|
||||
java.util.List<String> hrefs = new java.util.ArrayList<>();
|
||||
java.util.regex.Matcher m = java.util.regex.Pattern.compile("href=\"([^\"]*)\"").matcher(html);
|
||||
while(m.find())
|
||||
{
|
||||
hrefs.add(m.group(1).replace("&", "&"));
|
||||
}
|
||||
return (hrefs);
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@ class TablesAndConfigTest
|
||||
new com.kingsrook.qbits.objectstorage.ObjectStorageQBitProducer().withQBitConfig(config).produce(instance);
|
||||
assertThat(instance.getApp("objectStorageAdmin").getParentAppName()).isEqualTo("admin");
|
||||
assertThat(instance.getApp("admin").getChildren()).extracting(c -> c.getName()).contains("objectStorageAdmin");
|
||||
assertThat(com.kingsrook.qbits.objectstorage.app.StorageWidgets.tablePathPrefix()).isEqualTo("/admin/objectStorageAdmin");
|
||||
assertThat(com.kingsrook.qbits.objectstorage.app.StorageWidgets.tablePathPrefix()).isEqualTo("/app");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user