The release path creates a signed tag and draft GitHub Release from an approved release-please PR. The tag starts a build-once workflow that verifies the candidate before it promotes images by digest and publishes the release.
Choose the source branch
| Release | Source branch | Rule |
|---|---|---|
Prerelease or first stable X.Y.0 | Frozen main | Do not create the release branch before the first stable release succeeds. |
Patch X.Y.Z | release-X.Y | Backport only the fixes and documentation intended for that release line. |
| Edge | main after successful CI | Validation channel, not a stable release. |
| Nightly | Successful Nightly run | Scheduled drift and compatibility channel, not a stable release. |
Create release-X.Y from the published X.Y.0 commit. Normal development can then resume on main while patch
releases remain narrow.
Prepare the release content
Keep CHANGELOG.md generated by release-please. Put the human summary, upgrade notes, and migration callouts in
release-notes/X.Y.Z.md. The tag workflow prepends that file to the generated changelog section when it creates the
draft release. Prereleases use their exact version, for example release-notes/X.Y.Z-rc.1.md; do not reuse stable
notes whose installation commands reference a version that has not been published yet.
When a stable X.Y.0 follows one or more release candidates, release-please generates its new changelog section from
the latest release-candidate tag. After release-please creates the stable release PR, replace only that new section
with a concise rollup from the previous stable release to X.Y.0. Use the previous stable tag in the comparison link,
and keep the incremental release-candidate sections below it. Do not add the stable section before release-please
creates the PR because that can produce duplicate version headings.
If the final release candidate contains all user-facing commits, the pinned exact-version wrapper permits release-please to create a stable PR with only the new version heading. Replace that heading-only section with the same reviewed previous-stable rollup before you authorize the release.
For a patch, make the conventional commit or squash title describe the user-visible fix. Release-please uses that text to generate the changelog.
Check release automation locally
devenv test
devenv tasks run operator:bootstrap
devenv tasks run operator:doctor
devenv tasks run operator:ci-core
devenv shell -- make verify-workflowsAlso confirm that compatibility guidance, generated API surfaces, and release notes match the candidate. Review current main, Nightly, release-gate E2E, previous-stable operator-upgrade, security, provenance, and performance evidence before authorizing publication.
Request an exact version
Release-please opens normal release PRs from conventional commits. Use the Prepare Release-As PR workflow when a
prerelease, patch, or other exact version must be requested explicitly.
Create an auditable Release-As marker PR
gh workflow run prepare-release-as-pr.yml \
--repo dc-tec/openbao-operator \
-f target_branch=main \
-f version=X.Y.Z-rc.1For a patch, use target_branch=release-X.Y and a version in that release line. The workflow rejects invalid SemVer,
missing or mismatched branches, existing tags or releases, open release-please PRs, and conflicting marker state. It
creates an empty signed-off commit containing Release-As: <version> on an automation/release-as-* branch.
Merge the marker PR first. Because protected branches require squash merges, the branch-aware Release Please PR
workflow validates that the resulting marker commit is empty and recovers the exact version from its generated squash
subject. It then opens or updates the actual release PR. The direct release_as dispatch input remains available, but
the marker PR is the preferred auditable path.
Review and merge the release PR
Before merge, verify that the release PR updates these surfaces consistently:
.release-please-manifest.jsonand generatedCHANGELOG.md;charts/openbao-operator/Chart.yamlversion andappVersion;- Artifact Hub changes, image metadata, prerelease flag, and security-update flag;
release-notes/X.Y.Z.mdwhen the release needs a human summary or upgrade guidance.
The release PR gate requires the release:ready label and approval from the configured release manager (dc-tec in
the current workflow). Do not bypass that gate to repair automation.
After merge, the Release Tag workflow resolves the exact merged release PR, verifies its release files, creates a
GPG-signed annotated SemVer tag, and creates or refreshes the matching draft GitHub Release. The tag GitHub App is the only
automation identity that should have SemVer tag-ruleset bypass.
Use the manual branch-head tag target only to retry a failed draft-release creation after an approved release-branch
fix. The branch head must descend from the release PR merge and carry the same release version.
Let the tag workflow publish
The tag triggers the Release workflow. It:
- checks that the chart version, app version, tag, and draft release agree;
- builds the four images and performs an independent rebuild;
- runs vulnerability, Semgrep, image, release E2E, operator-upgrade, provenance, and byte-reproducibility gates;
- waits at the
release-publishenvironment before public promotion; - promotes the verified image manifests by digest, without rebuilding;
- signs images and the OCI Helm chart with the tag-scoped workflow identity;
- signs and attests checksums, generates SBOMs and
provenance-index.json, uploads assets, and publishes the draft GitHub Release.
The stable public distribution surface is:
| Surface | Published result |
|---|---|
| GHCR images | Version-tagged, digest-addressable, signed manager, init, backup, and upgrade images |
| GHCR Helm OCI | Canonical signed chart at ghcr.io/dc-tec/charts/openbao-operator |
| GitHub Release | Installer manifest, CRDs, checksums and signature bundles, SBOMs, and provenance index |
| Artifact Hub | Discovery and metadata for the GHCR chart |
OLM bundles remain repository and CI validation assets; public OperatorHub publication is not part of the supported release procedure.
dist/install.yaml and dist/crds.yaml are generated release outputs. Do not treat local copies as source-controlled
publication artifacts.
Verify the published release
Post-Release Verification runs after a successful Release workflow and can also be dispatched for a tag. It verifies
the remote tag, required assets, checksum signature, OCI chart signature, release-please label cleanup, and absence of
open or stale release-please branches. It stores JSON evidence for 30 days and adds the evidence link and digest to the
release PR.
Run post-release verification
VERSION=X.Y.Z \
REPO=dc-tec/openbao-operator \
EVIDENCE_OUT=dist/post-release-verification.json \
hack/ci/verify-post-release.shLocal verification requires gh, jq, git, Docker Buildx, and cosign.
Use the provenance index to select digest-pinned subjects for additional checks:
Verify release identity and subjects
gh release download X.Y.Z \
--repo dc-tec/openbao-operator \
--pattern provenance-index.json \
--pattern checksums.txt \
--pattern checksums.txt.bundle
jq '.release, .identity_constraints, .images, .chart' provenance-index.json
cosign verify \
--new-bundle-format=true \
--certificate-identity \
"https://github.com/dc-tec/openbao-operator/.github/workflows/release.yml@refs/tags/X.Y.Z" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
"ghcr.io/dc-tec/openbao-operator@sha256:<digest>"
gh attestation verify \
"oci://ghcr.io/dc-tec/charts/openbao-operator@sha256:<digest>" \
--repo dc-tec/openbao-operator \
--signer-workflow dc-tec/openbao-operator/.github/workflows/release.yml \
--source-ref refs/tags/X.Y.Z \
--cert-oidc-issuer https://token.actions.githubusercontent.com \
--deny-self-hosted-runnersIf artifacthub-repo.yml changes, refresh the repository metadata separately:
Publish Artifact Hub repository metadata
oras push \
ghcr.io/dc-tec/charts/openbao-operator:artifacthub.io \
--config /dev/null:application/vnd.cncf.artifacthub.config.v1+yaml \
artifacthub-repo.yml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yamlIf verification fails or publication state is unexpected, stop and use the publishing incident runbook.