Release¶
The release process is automated via GitHub Actions. It handles version bumping, changelog updates, tag creation, package publishing, release signing, and reproducibility verification.
Prerequisites¶
- The
## [Unreleased]section inCHANGELOG.mdmust contain at least one entry.
Steps¶
- Ensure
CHANGELOG.mdhas the desired entries under## [Unreleased]. - Go to Actions → Prepare Release → Run workflow.
- Select the bump type (
patch,minor, ormajor) and run it. - The workflow creates a
release/vX.Y.Zbranch with:- Updated version in
pyproject.toml - New version section in
CHANGELOG.md(with today's date) - Updated comparison links at the bottom of
CHANGELOG.md - Regenerated
uv.lock
- Updated version in
- Review and merge the generated PR into
main. - On merge, the Tag Release workflow automatically creates and pushes the
vX.Y.Ztag. - The tag push triggers the existing release pipelines:
- Python package build using a pinned build toolchain
- Reproducibility verification by rebuilding the wheel and sdist and comparing hashes
- PyPI publishing
- GitHub Release creation with the built artifacts and Sigstore signatures attached during release creation
- Docker Hub image build and push
- Documentation deployment via mike
Notes¶
- GitHub Releases are configured as immutable. The workflow therefore creates the release together with all assets in one operation, instead of publishing first and uploading assets afterwards.
- Python package builds are configured to be reproducible. The release workflow pins the build backend/tool versions, sets
SOURCE_DATE_EPOCHfrom the tagged commit, rebuilds the distributions, and blocks publishing if the hashes differ.
Verifying reproducibility locally¶
To verify that a tagged release is reproducible, build it twice from a clean checkout of the same tag and compare the hashes:
git checkout vX.Y.Z
rm -rf dist build *.egg-info
export SOURCE_DATE_EPOCH="$(git log -1 --format=%ct HEAD)"
python -m pip install --user "build==1.4.3"
python -m build
sha256sum dist/* > /tmp/sereto-build1.sha256
rm -rf dist build *.egg-info
python -m build
sha256sum dist/* > /tmp/sereto-build2.sha256
diff -u /tmp/sereto-build1.sha256 /tmp/sereto-build2.sha256
If the output is empty, the wheel and source distribution are bit-for-bit identical for that environment and toolchain.