| name | release-zakura |
| description | Prepare, review, and publish Zakura releases and release candidates. Use when bumping Zakura versions, preparing a release PR, validating the crates.io package graph, reviewing release readiness, or running the protected Create release workflow. |
Release Zakura
Use the repository's
.github/PULL_REQUEST_TEMPLATE/release-checklist.md as the canonical checklist.
Release policy (tag protection, promotion, retention) is canonical in
docs/release-tag-protection.md; this skill points at policy rather than
defining it, and adds the Zakura-specific checks that are easy to miss.
Safety
- Preparing or reviewing a release does not authorize publishing it.
- Get explicit confirmation immediately before dispatching
create-release.yml
or publishing crates to crates.io.
- Dispatch releases only from merged
main.
- Never create a
v* tag manually. create-release.yml is the only supported
tag creation path.
- Do not promote a release candidate from pre-release to Latest. Published
release candidates stay up as pre-releases; removing one is an owner-level
decision, never part of a release flow.
- If a release-capable maintainer has announced a release hold, stop: do not
prepare or publish until it is lifted. A security hotfix may be in flight
for the same version, invisible under embargo.
Gather release context
Determine:
- target tag, including the
v prefix, such as v1.0.0-rc5
- previous GitHub tag
- latest published version of each affected crate on crates.io
- whether this release publishes crates, GitHub assets, Docker images, or all
three
- changed crates since each crate's last published version
- the release tracking issue and checkpoint plan
Do not infer the crate publish set only from the previous GitHub tag. A binary
release may have skipped crates.io publishing.
Useful commands:
gh release list --repo zakura-core/zakura --limit 10
cargo search zakura --limit 5
git diff --stat <previous-tag>
Prepare the release branch
Name the branch release/v<version>. Never use hotfix/v* — that namespace
is reserved for the hotfix release process
(docs/security-hotfix-release.md), and keeping the namespaces disjoint is
what prevents collisions with an embargoed hotfix.
Package versions
Always update the zakura package version in zakurad/Cargo.toml; release
binaries self-report CARGO_PKG_VERSION.
Stable releases always publish to crates.io. Release candidates decide
per-release: a crates.io-publishing release candidate bumps all changed
crates like a stable release; a GitHub-only release candidate bumps only
zakura.
For crates.io publishing:
- Identify changed publishable crates.
- Bump those crates before their dependents.
- Update every direct dependency requirement that must select the new crate.
- Refresh
Cargo.lock.
- Confirm unchanged published versions still satisfy the resulting graph.
Partial version graphs are allowed, but all tooling must handle them. Do not
assume every publishable crate has the zakura package version.
Release metadata
Update:
- the README
cargo install --git ... --tag example for stable releases only;
while preparing a release candidate, keep the general install example on the
latest stable tag
zakurad/tests/common/configs/<version>.toml, then remove stale generated
release fixtures so the directory retains only the current release fixture
and custom test configurations
ESTIMATED_RELEASE_HEIGHT from the current chain tip and expected tag date
- pending
changelog-unreleased/<PR-number>.md fragments according to project
policy
- the root changelog by running the fragment assembler after the
zakura
package version bump is final
- examples in release documentation only when they are intended to track the
current release
Generate the stored config from the release branch; do not copy it blindly when
config defaults or fields changed. Run the exact acceptance config test to
verify both the generated fixture and the retained fixture set:
cargo test -p zakura --test acceptance config_tests -- --exact
After the zakura package version bump is final, run:
make prepare-release-changelog RELEASE_TAG=<tag>
This target is defined in make/release.mk. It must consume every numbered
changelog-unreleased/<PR-number>.md fragment into the root changelog,
including explicit no-changelog fragments. Keep
changelog-unreleased/README.md; it documents the fragment format and is not a
pending fragment.
Review and commit the generated root changelog and numbered fragment deletions.
For a stable release, confirm the generated section combines and replaces all
matching release-candidate sections; no X.Y.Z-rc* section for that stable
version should remain in the root changelog.
Verify before opening or approving the PR
Run:
cargo metadata --no-deps --format-version 1 --locked
make pre-release RELEASE_TAG=<tag> BASE_TAG=<previous-tag>
./scripts/check-crate-packaging.sh --verify
Also:
- run Markdown lint on every changed Markdown file
- check IDE diagnostics on changed files
- run
cargo semver-checks and cargo public-api diff for changed library
crates when publishing them
- verify the packaging script resolves each archive using that crate's actual
version when the workspace contains mixed versions
- confirm the package preflight rebuilds packaged archives, not just workspace
sources
- confirm checkpoints are current or record an explicit rapid-RC waiver
Follow the repository's risk policy for additional Rust checks. Report skipped
checks and why.
Release PR requirements
- Use a conventional title such as
chore(release): prepare v1.0.0-rc5.
- Add the
A-release label before treating CI as complete.
- Confirm
Check no git dependencies and Docker configuration/build checks ran;
a skipped result usually means the label is missing.
- Include motivation, solution, test evidence, issue/reference links, risk
classification, follow-up work, and AI disclosure.
- Confirm all
changelog-unreleased/<PR-number>.md files were consumed and the
generated root changelog was committed.
- Verify the release graph independently; a green ordinary PR build does not
prove crates.io packaging.
- Post-1.0.0 releases only: confirm the assembled root changelog contains
concrete release notes for every user-visible change since the previous
release. Through 1.0.0 the changelog is frozen — 1.0.0 ships "Initial
release" only in the root changelog.
- Audit the checklist against
docs/release-tag-protection.md.
- Wait for required human approval and all enabled CI checks.
Publish
After the release PR is merged and explicit confirmation is given, run the
T-0 orchestrator — it preflights competing release trains, dispatches,
watches to the approval gate, and verifies the published release; it is
resumable and re-runs skip completed steps:
./scripts/release-t0.sh publish --tag <tag> --mode main --head-sha <merged-commit>
Raw dispatch fallback:
gh workflow run create-release.yml \
--repo zakura-core/zakura \
--ref main \
-f release_tag=<tag>
The workflow must:
- validate the tag against the
zakura package version
- build and verify assets before tag creation
- wait for approval of the
release environment
- create the immutable tag and GitHub pre-release
- publish the release assets; the tag push then triggers
release-binaries.yml, which publishes the Docker images
Do not retry from an unmerged branch. A version mismatch failure means main
still has the previous package version.
Post-release verification
- Verify both
zakurad-<tag> archives, the manifest, and SHA256SUMS.txt are
present.
- Verify release checksums.
- Verify the standard Docker image has amd64 and arm64; verify the
zcashd-compat image has amd64.
- Publish only changed crates, preserving dependency order.
- Install the exact version from crates.io and run
zakurad --version.
- Replace the boilerplate GitHub release body with concrete notes from the final
changelog or approved release-note draft.
- Promote stable releases with
./scripts/release-t0.sh promote --tag <tag>
after signing; it refuses unsigned releases and release candidates.
- Keep release candidates marked as pre-releases.
Review output
When reviewing readiness, report:
- blockers
- missing gates or skipped checks
- verified items
- exact remaining publish steps
Distinguish repository changes required before merge from post-release
automation and operator follow-up.