Storage Benchmark Kit
SBK uses one guarded GitHub Actions workflow for GitHub Release assets,
GitHub Packages, Docker Hub, and the GitHub Container Registry. Publication
is independent from qualification. releasecheck can prove a candidate, but
.github/workflows/release.yml neither invokes it nor requires its output.
Maven Central publication is an
independent maintainer operation performed with the established local
JReleaser configuration; the GitHub workflow never configures or invokes
JReleaser. The legacy Gradle -Pmaven repository path is not used.
Qualification and publication are deliberately separate operations. Complete this checklist in order for a normal stable release:
sbkVersion in gradle.properties, complete the matching release
notes at .github/release-notes/<version>.md, merge the changes, and use a
clean local checkout of the latest origin/master.Qualify that exact commit independently with the release profile:
./gradlew clean releasecheck \
-Pprofile=release \
-PreleaseInventory=/secure/sbk-release-inventory.properties \
--no-daemon --rerun-tasks
Preserve build/reports/release-qualification/qualification.json and the
functional reports as release evidence. The publication workflow does not
consume them, so the maintainer must verify that qualification covered the
same commit that will be released.
Assemble and inspect every publication artifact without publishing:
./gradlew releasePublicationDryRun --no-daemon --rerun-tasks
# Linux:
(cd build/release-assets && sha256sum -c SHA256SUMS)
# macOS:
(cd build/release-assets && shasum -a 256 -c SHA256SUMS)
Export the local Docker Hub and GitHub dispatch credentials, then invoke the guarded root task with the exact version confirmation:
export DOCKER_USERNAME="<docker-user>"
export DOCKER_PASSWORD="<docker-access-token>"
export GITHUB_TOKEN="<actions-workflow-token>"
VERSION=$(sed -n 's/^sbkVersion=//p' gradle.properties)
./gradlew publish \
"-PreleaseConfirm=RELEASE-${VERSION}" \
--no-daemon
Do not run step 5 from an unmerged commit. The Docker image records the local
HEAD, while the workflow runs from master and rejects an image whose
revision label differs from the dispatched commit. Do not insert clean
between qualification and evidence retention unless the reports have first
been copied outside build/.
The following command exercises every core-module Maven publish task against
project-local repositories, validates
the exact main/source/Javadoc/documentation artifact set that JReleaser will
deploy, assembles the container context, and creates the complete release asset
contract:
./gradlew clean releasePublicationDryRun \
--no-daemon --rerun-tasks
It never creates or pushes a Git tag, GitHub Release, Maven package, Docker
Hub image, or GHCR image. The former publish -Pgithub selector has been
removed; GitHub Packages are part of the complete guarded release. Results are
written to:
build/release-assets/
build/release-container/
The Gradle dry run prepares the Docker context but does not require a Docker
daemon. The GitHub release workflow never runs or consumes releasecheck.
Open Actions > SBK Release > Run workflow, enter the version, and keep
dry_run=true to build the complete asset contract and execute native AMD64
and ARM64 images without performing a registry login or push.
The local dry run and GitHub workflow intentionally do not invoke
jreleaserDeploy. JReleaser requires the maintainer’s private signing and
Sonatype credentials and remains a separate Maven Central publication step.
Every release contains:
sbk-<version>.zip
sbk-<version>.tar
sbm-<version>.zip
sbm-<version>.tar
sbk-web-console-<version>.zip
sbk-web-console-<version>.tar
sbk-agent-docs.tar.gz
<core-module>-<version>-sbom.cdx.json
<core-module>-<version>-sbom.cdx.xml
release-manifest.json
SHA256SUMS
release-manifest.json binds the version and Git commit to every payload
checksum, supported container platform, image repository, and immutable
container digest. SHA256SUMS also covers the manifest itself.
The root SBK distribution already contains the sbk, sbk-yal, sbk-gem,
and sbk-gem-yal launchers. SBM and the Local Web Console have separate
standalone distributions.
No drivers:* project is published as a standalone archive, Maven package, or
CycloneDX project. The guarded workflow calls
releasePublishCoreToGitHubPackages for GitHub Packages. Independent local
JReleaser publication uses releaseStageCorePublications. Both paths use the
same explicit allow-list that excludes drivers/; the
scope verifier also fails if a driver ever applies maven-publish. Drivers
remain runtime plugins inside the SBK distribution and container. Direct
CycloneDX release files are generated only for the publishable core modules:
PerL, SBK API, SBK Web Console transport, SBM, SBK-YAL, SBK-GEM, and
SBK-GEM-YAL. sbk-api and sbk-web-console are included because they are
required compile/runtime dependencies of the public SBK API used by external
applications. BuildKit separately generates an image SBOM from the complete
container filesystem, including the driver libraries actually bundled there.
The local publish task first publishes one multi-architecture manifest to
Docker Hub. The workflow validates independently built native linux/amd64
and linux/arm64 images, then copies the exact public Docker Hub manifest to:
kmgowda/sbk
ghcr.io/kmgowda/sbk
Every version receives the exact version tag. Stable releases also update the
major-version and latest tags; prereleases never update stable aliases. The
workflow verifies both registries against the same Buildx digest. The local
Buildx publication emits SBOM/provenance attestations. The workflow signs the
GHCR immutable repository digest with Cosign and GitHub OIDC; Docker Hub is
verified by immutable digest without transmitting its credentials to GitHub.
The AMD64 validation job also reports HIGH and CRITICAL Trivy findings. This scan is advisory because the aggregate image intentionally bundles every enabled driver’s third-party SDK; findings must be assessed and remediated per driver without blocking publication of unrelated benchmark backends. Native image builds, launcher/version checks, and the real File benchmark remain mandatory for both architectures.
GitHub workflow dispatch and the internal GitHub Packages publication resolve the GitHub identity from these sources:
github.username and github.token, when Gradle is run
directly;GITHUB_USER and GITHUB_TOKEN environment variables;GITHUB_USERNAME variable for compatibility; orRELEASE_GITHUB_USER and RELEASE_GITHUB_TOKEN secrets,
falling back to the workflow actor and repository GITHUB_TOKEN.Docker Hub is a different authentication service; a GitHub token cannot be
used there. Set DOCKER_USERNAME and DOCKER_PASSWORD only in the local
environment that invokes Gradle. The publishDockerHub task supplies the
password through docker login --password-stdin, uses a temporary
DOCKER_CONFIG, pushes the multi-architecture image, records its public
immutable digest, and deletes the temporary configuration before Gradle exits.
The supplied Docker identity must have push permission for kmgowda/sbk.
Neither Docker credential is sent to GitHub or stored in the repository. The
workflow receives only the non-secret public digest and copies that exact
manifest to GHCR.
JReleaser does not use the GitHub credentials above for Maven Central and is
never invoked by the GitHub workflow. Local invocations resolve its private
TOML configuration from Gradle property
jreleaser.configFile, environment variable JRELEASER_CONFIG_FILE, or the
existing default ~/.jreleaser/config.toml, in that order. Keep this private
configuration on the authorized Maven Central publication host; it is not a
GitHub Actions secret.
The private TOML supplies JReleaser credentials and environment values. The
root Gradle release configuration remains authoritative for the staging
repository inventory and always registers PerL, SBK Web Console, SBK API,
SBM, SBK-YAL, SBK-GEM, and SBK-GEM-YAL. Module Maven publication stages
unsigned artifacts; JReleaser is the sole component that signs the Maven
Central payload. Legacy Gradle signing properties must not create
signMavenJavaPublication tasks.
Release qualification may independently use the real-host secrets documented in Release qualification. The publication workflow does not receive or require remote benchmark credentials.
Dispatch the complete guarded release from Gradle:
VERSION=$(sed -n 's/^sbkVersion=//p' gradle.properties)
DOCKER_USERNAME="<docker-user>" \
DOCKER_PASSWORD="<docker-access-token>" \
GITHUB_TOKEN="<actions-workflow-token>" \
./gradlew publish \
"-PreleaseConfirm=RELEASE-${VERSION}" \
--no-daemon
The confirmation value must exactly match RELEASE-<sbkVersion>. The task
always sends dry_run=false and dispatches .github/workflows/release.yml
from master; therefore, it performs an actual release rather than a local
dry run. Use -Pgithub.token=<token> instead of GITHUB_TOKEN when Gradle
property-based authentication is preferred. This token authorizes only the
GitHub Actions workflow dispatch and GitHub-owned publication steps.
Optional release controls are:
-PreleasePrerelease=true
-PreleaseResume=true
Both default to false. The task submits the following workflow inputs:
version=<exact sbkVersion from gradle.properties>
dry_run=false
prerelease=false
resume=false
dockerhub_digest=sha256:<immutable-public-digest>
The same inputs remain available through Actions > SBK Release > Run
workflow when a browser-driven release is required. For an actual
browser-driven publication, first run publishDockerHub locally with the same
confirmation and credentials, then copy the resulting
build/reports/release-publication/dockerhub-digest.txt value into the
dockerhub_digest workflow input. A dry run does not require that digest.
The local Gradle task publishes Docker Hub before dispatch. The workflow builds
the complete contracted asset set without running or depending on
releasecheck, validates both container architectures, copies the exact image
to GHCR, invokes
releasePublishCoreToGitHubPackages for GitHub Packages, creates an annotated
tag, creates a draft GitHub Release, uploads and compares every asset, and
publishes the release last with the versioned details from
.github/release-notes/<version>.md. It does not configure or execute
JReleaser.
If publication stops after the exact tag or draft release is created, inspect
the partial state before rerunning with resume=true. Resume is accepted only
for the same tag and commit, and existing assets must be byte-identical.
GitHub Packages versions are also immutable. A retry accepts HTTP 409 only
after authenticated verification proves that every required artifact exists
for all seven core modules and that each POM, executable JAR, and sources JAR
is byte-identical to the locally staged publication. Javadoc and documentation
JARs must exist and be non-empty; generated Javadoc can vary across JDK patch
releases, and the documentation JAR may contain newer release-operations
guidance added while recovering the same immutable code release.
If Docker Hub publication succeeds but workflow dispatch or a later workflow
job fails, do not delete or overwrite the version tag. Inspect the public
digest written to build/reports/release-publication/dockerhub-digest.txt and
the partial GitHub state. Correct the failure and rerun with
-PreleaseResume=true; the workflow accepts only the same tag, commit,
byte-identical assets, and immutable image digest.
Publish the Maven Central coordinates independently from an authorized host:
./gradlew verifyCorePublicationStaging jreleaserConfig --no-daemon
JRELEASER_MAVENCENTRAL_STAGE=FULL ./gradlew jreleaserDeploy --no-daemon
JReleaser resolves the private configuration described above. Its source
default remains UPLOAD; setting the stage to FULL is the explicit Central
release operation.
The published coordinates remain io.github.kmgowda.sbk:<module>:<version>.
External projects can therefore build custom storage benchmarks without an
SBK source checkout, for example with sbk-api, sbk-gem, or sbm from Maven
Central. The same coordinates may be resolved from GitHub Packages after
adding its repository and credentials. See the
SBK examples repository.
Verify the public state rather than relying only on the workflow conclusion:
VERSION=$(sed -n 's/^sbkVersion=//p' gradle.properties)
git fetch --tags origin
git rev-list -n 1 "v${VERSION}"
gh release view "v${VERSION}" \
--json isDraft,isPrerelease,tagName,targetCommitish,url,assets
docker buildx imagetools inspect "kmgowda/sbk:${VERSION}"
docker buildx imagetools inspect "ghcr.io/kmgowda/sbk:${VERSION}"
Confirm that:
v<version> tag resolves to the qualified master commit;SHA256SUMS verifies every downloaded release asset;linux/amd64 and linux/arm64 manifests;<major> and latest, while prereleases do not;Record the release URL, workflow-run URL, tag commit, container digest, and Maven Central result with the retained qualification evidence.