Releasing¶
CI & Supply Chain¶
All CI workflows live in .github/workflows/. When adding or modifying
workflows, follow these conventions:
GitHub Actions pinning¶
Pin all uses: references by full commit SHA, not version tag. Add a
version comment for readability:
Why: Version tags are mutable — a compromised upstream can retag a malicious commit to an existing version. SHA pinning makes the reference immutable. Dependabot automatically proposes SHA updates when new versions are released, so maintenance overhead is minimal.
Tool binary pinning¶
When downloading binaries in CI (e.g., kind, helm), always:
- Pin to a specific version (never
latest) - Verify with a SHA256 checksum
Use scripts/install-helm.sh for CI Helm installs so the pinned Helm version
and checksum stay in one place.
Workflow permissions¶
Every workflow must declare permissions: at the top level. Default to the
minimum required:
Only add broader permissions when needed (e.g., packages: write for image
publishing, security-events: write for CodeQL).
Renovate¶
renovate.json is configured to propose weekly dependency updates for Go
modules and GitHub Actions. A 7-day minimum release age is enforced — Renovate
will not propose a version until it has been published for at least 7 days. This
reduces the risk of adopting a compromised release before the community detects
it. Review and merge these PRs promptly to stay current on security patches.
Versioning¶
The project follows Semantic Versioning. The operator and Helm chart versions are coupled for release artifacts:
| Version | Location | Purpose |
|---|---|---|
| Operator version | VERSION in Makefile |
Operator image tag. Single source of truth. |
| Chart version | version in charts/superset-operator/Chart.yaml |
Helm chart package version. |
| Chart app version | appVersion in charts/superset-operator/Chart.yaml |
Default operator image tag used by the chart. |
Release preparation sets all three to the same base release version, for example
0.1.0. The tag-triggered release workflow packages RC convenience artifacts
with the RC suffix, for example 0.1.0-rc1.
While the project is pre-1.0, all versions use 0.x.y to signal instability per semver.
Release Checklist¶
The release workflow (.github/workflows/release.yml) builds multi-platform
images and pushes them to GHCR. It runs automatically on pushes to main
(producing dev and sha-<commit> tags) and on version tags (producing semver
tags). It can also be triggered manually via workflow_dispatch.
Image tagging:
| Trigger | Image tag | Example |
|---|---|---|
Push to main |
dev + sha-<commit> |
dev, sha-1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b |
| RC tag | Semver without v prefix |
0.1.0-rc1 |
| Release tag | Semver without v prefix + latest |
0.1.0, latest |
See Downloads for full details on published images and registries.
Before creating the first RC for a minor release, run or verify:
make codegenleaves no diffmake lintmake testmake helm-lintmake docs-buildmake check-licensemake test-e2eon a working Kind or equivalent Kubernetes cluster- The release workflow is using pinned/checksum-verified tool downloads
Reviewing the Changelog¶
Contributors add bullets to ## Unreleased in
docs/reference/releases.md as PRs land (see the
changelog convention). Before
tagging the RC, the release manager does one review pass to make sure the
section accurately reflects the release:
- Skim
git log v<previous>..HEADfor noteworthy changes that nobody added an entry for, and add them. Skim for changes that were added but aren't actually noteworthy (typo fixes, internal refactors that snuck in), and drop them. - Merge bullets that describe the same user-visible change — separate PRs often touch on a single feature.
- Make sure each bullet leads with the user-facing effect and reads in a consistent voice.
- Group bullets under the standard Keep a Changelog subheadings —
Added,Changed,Deprecated,Removed,Fixed,Security— dropping any that end up empty. - Rename the section header from
## Unreleasedto## <version>and add a fresh empty## Unreleasedabove it. Add the final release date after the vote passes and the release has been promoted (## <version> - <date>).
Two flows depending on whether the minor release branch already exists:
- First RC of a minor release. The
<major>.<minor>branch does not exist yet. Create it frommain, commit the reviewed changelog and any release-only polish there, then runrelease-rc.shso the RC tag picks it up. - Subsequent RCs (
rc2,rc3, …). The<major>.<minor>branch already exists. Commit changelog polish on that branch directly, then runrelease-rc.shto bump the RC number.
Creating a Release Candidate¶
The scripts/release-rc.sh script automates the full RC preparation: creates
the minor release branch (first RC only), bumps the operator version and Helm
chart version/appVersion metadata to the target release version, regenerates
manifests, runs the lint/license/test/docs/helm-lint checks, commits, and tags.
The tag-triggered release workflow packages and publishes the RC image and Helm
chart with the RC version suffix. The script also verifies that
docs/reference/releases.md contains a heading for the target release version.
# First RC for 0.2.0 — create the 0.2 branch first, then tag v0.2.0-rc1.
git checkout main
git pull
git checkout -b 0.2
# Commit docs/reference/releases.md and any release-only polish here.
scripts/release-rc.sh 0.2.0 --expect-rc 1
# Build and verify signed source artifacts before pushing anything.
scripts/release-source.sh
# Push branch + tag to trigger the release workflow after source verification.
git push origin 0.2 v0.2.0-rc1
Running the script again from the same release branch increments the RC number automatically (rc1, rc2, ...).
ASF Source Release Artifacts¶
Per the ASF Release Policy, the signed source archive is the official release. The OCI images and Helm chart published to GHCR by the release workflow are convenience binaries and cannot be voted on in isolation.
A release candidate therefore needs three artifacts staged on dist.apache.org:
| Artifact | Filename pattern | Notes |
|---|---|---|
| Source archive | apache-superset-kubernetes-operator-<version>-rc<n>.tar.gz |
A git archive of the RC tag, prefixed with the project directory. |
| Detached PGP signature | apache-superset-kubernetes-operator-<version>-rc<n>.tar.gz.asc |
Generated with a key in KEYS. |
| SHA-512 checksum | apache-superset-kubernetes-operator-<version>-rc<n>.tar.gz.sha512 |
shasum -a 512 output, with a bare filename so verifiers can run shasum -c after a plain download. |
Pre-requisites for the release manager¶
- Be a Superset PMC member (binding vote), or coordinate with one if you are a committer driving the release.
- Have a PGP key registered in
https://dist.apache.org/repos/dist/release/superset/KEYSand uploaded to the public keyservers. To add a new key, append the output ofgpg --list-sigs <fingerprint> && gpg --armor --export <fingerprint>toKEYSin the SVN checkout below and commit. - Have
svncheckouts of both ASF dist locations:
svn co https://dist.apache.org/repos/dist/dev/superset/ ~/asf/dev-superset
svn co https://dist.apache.org/repos/dist/release/superset/ ~/asf/release-superset
Producing the source tarball¶
scripts/release-source.sh wraps git archive, gpg, and shasum and
self-verifies before exiting. It infers the local RC tag from HEAD, writes to
dist/<version>-rc<n>/, and signs with the newest usable local secret key that
has an @apache.org UID:
scripts/release-source.sh
# → dist/0.2.0-rc1/apache-superset-kubernetes-operator-0.2.0-rc1.tar.gz{,.asc,.sha512}
Pass --gpg-key <id> to pick a specific signing key, and --out-dir <path> to
write the artifacts somewhere other than dist/<version>-rc<n>/.
Why a script, not raw
git archive+gpg+shasum. The script avoids a small set of subtle errors that are easy to make manually:
shasum -a 512 path/to/filewrites the path into the checksum file. If the file is later renamed (RC → final),shasum -cfails. The script always runsshasumfrom the file's own directory so the checksum line contains a bare filename.- Detached PGP signatures verify the tarball contents, not the filename. RC → final promotion only needs to copy the
.asc; no re-signing is required. The--finalizemode below relies on this.
Staging the artifacts¶
cd ~/asf/dev-superset
mkdir kubernetes-operator-${VERSION}-rc${RC}
cp /path/to/dist/${VERSION}-rc${RC}/apache-superset-kubernetes-operator-${VERSION}-rc${RC}.tar.gz{,.asc,.sha512} \
kubernetes-operator-${VERSION}-rc${RC}/
svn add kubernetes-operator-${VERSION}-rc${RC}
svn commit -m "Stage Superset Kubernetes Operator ${VERSION}-rc${RC}"
After the commit lands, the artifacts appear at
https://dist.apache.org/repos/dist/dev/superset/kubernetes-operator-<version>-rc<n>/.
Vote email template¶
Generate a vote email draft from the RC tag on HEAD, review it, then send the
thread to dev@superset.apache.org with [VOTE] in the subject:
The vote thread must stay open for at least 72 hours and pass with at least
three +1 votes from PMC members and no -1 votes (per
ASF voting rules).
After the vote thread closes, post a [RESULT][VOTE] summary to the same list
with the tally and the binding/non-binding breakdown:
Finalizing a Release¶
After the ASF vote passes, the scripts/release-finalize.sh script tags the
final release on the same commit as the voted RC. Do not commit changelog date
updates or other polish before finalizing; those changes were not part of the
voted source release.
# From the 0.2 branch
scripts/release-finalize.sh 0.2.0
# Push the tag to trigger the release workflow
git push origin v0.2.0
The release workflow pushes the 0.2.0 and latest images to GHCR.
After the final tag is pushed, add the final release date to
docs/reference/releases.md on main only (the docs site builds from main).
Leave the release-branch changelog undated so it continues to match the voted
source.
After the binary release workflow finishes, promote the source artifacts.
release-source.sh sees the final tag on HEAD, requires a matching RC tag on
the same commit, reuses the staged RC tarball bytes (so the detached signature
stays valid), and regenerates the SHA-512 file under the final filename:
scripts/release-source.sh
# → dist/0.2.0/apache-superset-kubernetes-operator-0.2.0.tar.gz{,.asc,.sha512}
cd ~/asf/release-superset
mkdir kubernetes-operator-0.2.0
cp /path/to/dist/0.2.0/apache-superset-kubernetes-operator-0.2.0.tar.gz{,.asc,.sha512} \
kubernetes-operator-0.2.0/
svn add kubernetes-operator-0.2.0
svn commit -m "Release Apache Superset Kubernetes Operator 0.2.0"
Generate the release announcement after the artifacts have propagated to the ASF
mirror network (typically within 24 hours), review it, then send it to
announce@apache.org and dev@superset.apache.org: