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
0.2.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 the first public 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 new features or pre-1.0 breaking changes;
- major for post-1.0 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 rebuilds
distributions from the tagged source, generates the SBOM, smoke-tests the wheel,
creates artifact attestations, uploads package distributions and the SBOM as
separate workflow artifacts, attaches those files to the GitHub Release, and
then publishes only the distributions to PyPI from the pypi environment.
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
publish=true only for an intentional publication from a tag ref named
refs/tags/vX.Y.Z; the publish job is guarded and will not run from branch refs
or non-v tags.
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.