Compare commits

..
Author SHA1 Message Date
CircleCI 0abedf482b Bump version to 0.1.0-RC.8 [skip ci] 2026-10-15 22:22:19 +00:00
james.maesandClaude Opus 5.5 2f94e04fec Merge develop into release/0.1 for 0.1.0-RC.8 (#27 cluster caches, #28 QQQ RC.15 S3 core)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:13:02 -05:00
CircleCI dec9d063a6 Bump version to 0.1.0-RC.7 [skip ci] 2026-10-15 02:45:16 +00:00
james.maesandClaude Opus 5.5 89e0e5915b Merge develop into release/0.1 for 0.1.0-RC.7 (#24 help bundle)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:35:47 -05:00
CircleCI cf2e9fca77 Bump version to 0.1.0-RC.6 [skip ci] 2026-10-14 23:07:52 +00:00
james.maesandClaude Opus 5.5 cd26342cfd Merge develop into release/0.1 for 0.1.0-RC.6 (#18 ConfigSync session fix, #19, #20, #23)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:58:53 -05:00
CircleCI 93c116ff01 Bump version to 0.1.0-RC.5 [skip ci] 2026-10-14 22:34:39 +00:00
james.maesandClaude Opus 5.5 9f2d7fc202 Merge develop into release/0.1 for 0.1.0-RC.5 (#21 setup card, seeds, help)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:25:24 -05:00
CircleCI 5c8f2f595b Bump version to 0.1.0-RC.4 [skip ci] 2026-10-14 12:37:00 +00:00
james.maesandClaude Opus 5.5 1ea40241f7 Merge develop into release/0.1 for 0.1.0-RC.4 (#13 maxUploadBytes, #14 QQQ RC.6 and guardrails)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 07:28:10 -05:00
CircleCI 8692857891 Bump version to 0.1.0-RC.3 [skip ci] 2026-10-14 01:02:56 +00:00
james.maesandClaude Opus 5.5 b6db9aff8b Merge develop into release/0.1 for 0.1.0-RC.3 (ConnectionRuntime/S3ClientFactory consolidation, #11)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:55:34 -05:00
CircleCI 07275bce3f Bump version to 0.1.0-RC.2 [skip ci] 2026-10-13 15:51:56 +00:00
james.maesandClaude Opus 5.5 9eefc0b071 Merge develop into release/0.1 for 0.1.0-RC.2
AWS SDK for Java v2 2.41.10 -> 2.41.34 (GHSA-443w-3rq3-5m5h, #8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:44:08 -05:00
CircleCI f1fb2462f9 Bump version to 0.1.0-RC.1 [skip ci] 2026-10-12 23:02:00 +00:00
9 changed files with 79 additions and 187 deletions

No files matched your search

+57 -11
View File
@@ -1,14 +1,60 @@
version: 2.1
setup: true
orbs:
qqq-orb: kingsrook/qqq-orb@0.7.12
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
workflows:
setup:
jobs:
- qqq-orb/generate_pipeline:
orb_version: 0.7.12
filters:
branches:
ignore: automation/qbit-rc-pending
tags:
only: /^v\d+\.\d+\.\d+$/
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+$/]
-23
View File
@@ -1,23 +0,0 @@
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
+13 -62
View File
@@ -1,74 +1,25 @@
# 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: Plan a cut without changing release state
description: Print the plan without merging or creating branches
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
repository_dispatch:
types:
- qbit-rc-published
types: [closed]
branches: [develop]
permissions:
contents: write
actions: read
checks: read
jobs:
release-rc:
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
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
with:
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
dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }}
-16
View File
@@ -1,16 +0,0 @@
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
+1 -1
View File
@@ -20,7 +20,7 @@
<properties>
<qbit.guardrails.enforce>true</qbit.guardrails.enforce>
<qbit.guardrails.strictUiApiRoutes>true</qbit.guardrails.strictUiApiRoutes>
<revision>0.1.0-SNAPSHOT</revision>
<revision>0.1.0-RC.8</revision>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<jacoco.version>0.8.15</jacoco.version>
@@ -62,7 +62,6 @@ 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;
@@ -426,39 +425,6 @@ 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,12 +106,16 @@ public final class StorageWidgets
/*******************************************************************************
** 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).
** The prefix of table and record links.
*******************************************************************************/
public static String tablePathPrefix()
{
return (ObjectStorageRuntime.isInstalled() ? ObjectStorageRuntime.getConfig().getTablePathPrefix() : "/app");
if(!ObjectStorageRuntime.isInstalled())
{
return ("/objectStorageAdmin");
}
ObjectStorageQBitConfig config = ObjectStorageRuntime.getConfig();
return (config.getParentAppName() == null ? "/" + config.getAppName() : "/" + config.getParentAppName() + "/" + config.getAppName());
}
@@ -574,40 +574,4 @@ 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("&amp;", "&"));
}
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("/app");
assertThat(com.kingsrook.qbits.objectstorage.app.StorageWidgets.tablePathPrefix()).isEqualTo("/admin/objectStorageAdmin");
}