This document provides guidance on how to create Zarf releases, address release issues, and other helpful tips.
This project uses Release Please to automate release management and goreleaser for building and publishing release artifacts.
Release Please automatically:
- Monitors commits to
mainand creates/updates a release PR with changelog entries - When the release PR is merged, it creates and pushes a version tag (e.g.,
v0.71.0) - The tag push triggers the existing release workflow (
.github/workflows/release.yml)
The release PR accumulates changes based on Conventional Commits:
feat:commits trigger a minor version bumpfix:commits trigger a patch version bumpfeat!:orfix!:(breaking changes) trigger a major version bump
Release candidates are still created manually by pushing signed tags with an -rcX suffix. This allows testing the release process before cutting a final release.
The zarf release cadence aims to happen every 2 weeks at a minimum. Final scheduling is determined by the team once any release goals are met, ideally keeping to about a 1–2 week timeline between releases.
When there have been changes that could potentially impact the release process — such as updates to goreleaser, changes to GitHub runners, major testing updates, significant shifts in Zarf artifact size, or new artifacts being released — it is recommended to cut a Release Candidate (RC) first. To evaluate the criticality of a Release Candidate - perform the following:
- Review all changed files since the last tag
- In the command-line:
git diff -stat <prev-tag>..origin/mainand then review specific files withgit diff <prev-tag>..origin/main -- path/to/file - In the browser:
https://github.com/zarf-dev/zarf/compare/<prev-tag>...main
- In the command-line:
- Check for changes to known areas of CI/Release failure
goreleaserupdates- Testing structure refactor
- Known brittle or flaky tests
- Review any changes to the GitHub Runners
Tag the candidate with a suffix of the form -rcX and push it:
# Example RC tag
git tag -sa v0.50.0-rc1 -m "v0.50.0-rc1"
git push origin v0.50.0-rc1The .goreleaser.yaml configuration will automatically mark -rc tags as prereleases in GitHub:
release:
prerelease: autoOnce the prerelease artifacts are published, a Homebrew Tap PR is created. It is at the team's discretion whether to merge or close this PR to prevent publishing to brew users until the final release is ready.
- Refresh the embedded Sigstore TrustedRoot used for keyless verification (see Embedded TrustedRoot)
- Review and merge the open Release Please PR
- The tag is automatically created and pushed, triggering the release workflow
- Review the GitHub release:
- Add a summary of release updates and any required documentation around updates or breaking changes
- Ensure goreleaser workflows execute successfully and review the release assets
- Review, approve, and merge the homebrew-tap PR for the zarf release
Zarf binaries embed a Sigstore TrustedRoot JSON used by zarf package verify for keyless verification when --trusted-root is not supplied. The TUF-fetched copy is committed at src/pkg/signing/embedded_trusted_root.json and must be refreshed before each release so binaries ship with current Sigstore trust material.
make build
hack/refresh-trusted-root.sh
git add src/pkg/signing/embedded_trusted_root.json
git commit -m "chore: refresh embedded trusted root"The script wraps zarf tools trusted-root create --with-default-services, which reaches tuf-repo-cdn.sigstore.dev and writes the verified TrustedRoot to the embed path. Users who run their own Sigstore infrastructure can bypass the embedded copy at runtime via zarf package verify --trusted-root /path/to/custom.json.
After refreshing, verify the output before committing:
# Confirm the file is valid, non-empty JSON containing expected Sigstore CA entries
jq '.certificateAuthorities | length' src/pkg/signing/embedded_trusted_root.json
jq '.tlogs | length' src/pkg/signing/embedded_trusted_root.json
# Optionally round-trip a keyless verify against the new root to confirm it functions
zarf package verify <package.tar.zst> --trusted-root src/pkg/signing/embedded_trusted_root.json \
--certificate-identity <identity> --certificate-oidc-issuer <issuer>If the refresh fails (network unavailable, TUF root mismatch), do not commit the file. The previous committed version remains valid until the next successful refresh.
The init package is signed with keyless Sigstore signing during the release workflow. Consumers can verify offline using the embedded TrustedRoot:
Tagged release:
zarf package verify zarf-init-amd64-vX.Y.Z.tar.zst \
--certificate-identity-regexp "https://github.com/zarf-dev/zarf/.github/workflows/release.yml@refs/tags/" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"Nightly build:
zarf package verify zarf-init-amd64-vX.Y.Z-nightly.tar.zst \
--certificate-identity-regexp "https://github.com/zarf-dev/zarf/.github/workflows/nightly-release.yaml@refs/heads/" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"The --certificate-identity-regexp pins the identity to the specific release workflow and ref type, preventing acceptance of packages signed by an unrelated workflow. The embedded TrustedRoot (refreshed before each release) validates the Fulcio certificate chain without network access.
For cases where you need to manually create a release (e.g., release candidates):
-
Review open Pull Requests
-
Cut the new release by tagging and pushing:
git tag -sa vX.Y.Z -m "vX.Y.Z" git push origin vX.Y.Z -
Update
.release-please-manifest.jsonto reflect the new version -
Review the GitHub release:
- Add a summary of release updates and any required documentation around updates or breaking changes
-
Ensure goreleaser workflows execute successfully and review the release assets
-
Review, approve, and merge the homebrew-tap PR for the zarf release
Rather than removing a broken release, mark it in the release notes and cut a new release that fixes the issue(s).
-
Manual approach:
-
Find the impacted release on GitHub
-
Edit the release notes and add this warning at the top:
>[!WARNING] >PLEASE USE A NEWER VERSION (there are known issues with this release)
-
Create and publish a new release to address the issues
-