Release runbook¶
Use this when preparing and publishing a benchmatrix release.
Preconditions¶
- You have maintainer permission for
ryancswallace/benchmatrix. - The default branch is green.
- The GitHub
pypienvironment exists and has the intended reviewers. - PyPI Trusted Publishing is configured for
release.ymland thepypienvironment. - You know the exact version being released, such as
1.0.0. - The GitHub CLI is authenticated with permission to push branches and open
pull requests, and
GH_TOKENorGITHUB_TOKENis exported for GitHub API checks.
Before each major release, complete the external repository setup runbook,
especially the pypi environment and PyPI Trusted Publishing checklist.
Prepare the release pull request¶
- Start from an up-to-date
mainbranch. -
Choose the release version and export it without a leading
v:export BENCHMATRIX_RELEASE_VERSION=X.Y.ZUse:
- patch for compatible fixes and documentation;
- minor for backward-compatible features and deprecations;
- major for breaking public API changes.
-
Update the
CHANGELOG.mdentries under## Unreleased. -
Prepare release metadata, validate the release, and open the pull request:
make release-pr-readyTo use an explicit release date instead of today's date, run:
make release-pr-ready RELEASE_DATE=YYYY-MM-DDThis runs
make release-preflight,make prepare-release,make check, andmake release-prin order. The preparation step updatespyproject.toml,CITATION.cff, andCHANGELOG.md, setsdate-releasedinCITATION.cff, creates the dated changelog section, and runsuv lockafter thepyproject.tomlversion changes. The validation step builds the distribution artifacts, smoke-tests the wheel, generates the SBOM, and fails unless the release artifact files indist/are the expected wheel, source distribution, and SBOM for$BENCHMATRIX_RELEASE_VERSION.The pull request step creates or reuses
release/v$BENCHMATRIX_RELEASE_VERSION, stages onlypyproject.toml,CITATION.cff,CHANGELOG.md, anduv.lock, commits withPrepare benchmatrix $BENCHMATRIX_RELEASE_VERSION release, pushes the branch, and creates or reuses a GitHub pull request titledRelease $BENCHMATRIX_RELEASE_VERSION. It accepts already-staged release metadata files, but refuses unrelated local changes.If you need to debug the flow, run the component targets separately:
make release-preflight,make prepare-release,make check, andmake release-pr.All release targets validate that
BENCHMATRIX_RELEASE_VERSIONis set and hasX.Y.Zsyntax before continuing. Invalid or missing versions fail with a diagnostic before release side effects run. -
Wait for required checks, review the pull request, and merge it normally.
Tag and publish¶
-
Create and push the annotated tag for the release commit:
make release-tagmake release-tagrequires a clean working tree, switches tomain, pullsorigin/mainwith--ff-only, validates that release metadata still agrees with$BENCHMATRIX_RELEASE_VERSION, refuses to overwrite an existing local or remote tag, createsv$BENCHMATRIX_RELEASE_VERSION, and pushes it toorigin. -
Open the draft GitHub Release created by
.github/workflows/draft-release.yml. Confirm the tag, title, notes, source distribution, wheel, and SBOM are correct.If the draft workflow fails before assets are attached, rerun the
Draft releaseworkflow manually with the samevX.Y.Ztag after fixing the failure. -
Publish the draft GitHub Release.
- Watch
.github/workflows/release.ymlthrough the publish and verification jobs. Review and approve thepypienvironment release if required.
The draft-release workflow intentionally stops at a draft with reviewable
package assets attached. The workflow uses GITHUB_TOKEN, and GitHub
suppresses most follow-on workflow runs caused by that token to avoid recursive
automation. Publishing the draft from GitHub remains the deliberate deployment
action that triggers PyPI publication.
The release workflow runs on the GitHub release event with the published
activity type. Drafting a release does not publish to PyPI; publishing the
GitHub Release does. The publish job only runs when the workflow ref starts with
refs/tags/v, so releases must use tags such as v0.2.0. The workflow
downloads the wheel, source distribution, and SBOM that were already attached
to and reviewed on the draft release. It validates and smoke-tests those exact
files, creates artifact attestations, stores them as workflow artifacts, and
publishes the reviewed distributions to PyPI. It does not replace reviewed
assets with a second build after publication.
If the pypi environment requires approval, approve the deployment only after
confirming the tag, changelog, and workflow run are for the intended version.
The verification job depends on the publish job, so it verifies the package
after publication rather than racing the publishing job.
Verify after publication¶
-
Open the PyPI project page for
$BENCHMATRIX_RELEASE_VERSIONand confirm:- the version is visible;
- the source distribution and wheel are present;
- project metadata, license, Python requirements, and links look correct.
-
Install from PyPI in a clean environment:
verify_env=$(mktemp -d) uv venv --quiet "$verify_env" VIRTUAL_ENV="$verify_env" uv pip install --quiet "benchmatrix==$BENCHMATRIX_RELEASE_VERSION" "$verify_env/bin/python" -c "from benchmatrix import BenchmarkCase; print(BenchmarkCase.__name__)" rm -rf "$verify_env" -
Confirm the command prints
BenchmarkCase. - Check the GitHub Release assets, release workflow artifacts, and attestations. Confirm the Release page lists the source distribution, wheel, and SBOM in addition to GitHub's automatic source archives.
- Confirm the release workflow's
Verify PyPI installjob installedbenchmatrix==$BENCHMATRIX_RELEASE_VERSIONfrom PyPI and importedBenchmarkCasesuccessfully. - Confirm the Docker workflow published and smoke-tested the GHCR images for the release tag.
- Confirm the documentation deployment for
maincompleted if release docs changed. - Close the release issue or checklist item, if one exists.
Manual workflow dispatch¶
.github/workflows/release.yml also supports manual dispatch. Use it with
publish set to false for a build-only release smoke check. Use
tag=vX.Y.Z to download and validate an existing GitHub Release's reviewed
assets, including when recovering from a failed release-event run. Set
publish=true only when intentionally publishing those assets, or when running
the workflow directly from a tag ref named refs/tags/vX.Y.Z; the publish job
will not run for a branch ref without a valid v* tag input.
Abort conditions¶
Abort before publishing if any of these are true:
- validation fails;
- the changelog is missing user-visible changes;
pyproject.toml,CITATION.cff,CHANGELOG.md, and the Git tag disagree;- built artifact filenames do not contain the intended version;
- the GitHub Release points at the wrong tag or a tag that does not start with
v; - the PyPI Trusted Publisher or
pypienvironment is missing or misconfigured.
If publication already happened, do not delete or overwrite the PyPI release. Prepare a follow-up patch release, and yank the bad file only when users should stop installing it.