Releases are tagged, built reproducibly, accompanied by an SBOM, and carry a Sigstore-signed build-provenance attestation so a downloader can verify a release artifact was built from this source by this repository's CI. The release tag itself is signed too, going forward (git tag signature, verified by a CI guard before anything builds) — see the one-time setup below. These are two different signatures: one over the build (always present since v0.2.0), one over the tag identity (new; existing v0.1.0/v0.2.0 tags predate it and are not signed).
- Ensure
mainis green:make verify, thea11ygate, and CodeQL all pass. - Update
CHANGELOG.md(move[Unreleased]→ the new version) and bumpversioninpyproject.toml.__version__is derived from the installed distribution (importlib.metadata.version), so there is nothing to hand-edit insrc/habitable/__init__.py— that is the point (REL-02/03: no second place for the version to drift). - Tag with a signed, annotated tag and push (see one-time setup below):
$ git tag -s vX.Y.Z -m "vX.Y.Z" && git push origin vX.Y.Z - The
releaseworkflow (.github/workflows/release.yml) first runs two guards, before building anything: the tag must be a valid signature per.github/allowed_signers, and its version must matchpyproject.toml. It then re-runsmake verifyat the tagged commit — a red commit cannot ship. Only then does it:- build the wheel + sdist (
uv build); - generate a runtime SBOM (CycloneDX) into
dist/sbom.cdx.json; - produce a signed build-provenance attestation for the artifacts
(
actions/attest-build-provenance, Sigstore); - create/update the GitHub release and upload
dist/*.
- build the wheel + sdist (
The release workflow verifies tag signatures against .github/allowed_signers
using git's SSH signing format. Until a maintainer completes this setup, the tag
guard fails closed (intentional — an unsigned tag must never publish):
$ ssh-keygen -t ed25519 -C "release-signing@habitable" -f ~/.ssh/habitable-release
$ git config gpg.format ssh
$ git config user.signingkey ~/.ssh/habitable-release.pubThen add the matching public key as a line in .github/allowed_signers
(format documented in that file) and commit it — public keys are not secret.
Anyone can confirm an artifact came from this repo's CI:
$ gh attestation verify habitable-X.Y.Z-py3-none-any.whl --repo ChelseaKR/habitableThe SBOM (sbom.cdx.json) lists the runtime dependency set for that release.
SemVer for the package. The packet format and verification protocol are
versioned independently and older packets must keep verifying — enforced by the
golden-packet corpus and the version-contract test (see
evidence-method.md and tests/test_golden.py), not by
prose.
- PyPI Trusted Publishing (OIDC): once a PyPI project and trusted publisher
are configured, add a publish step to
release.yml(no stored tokens). - Reproducible-build verification: document and verify a byte-identical rebuild of the wheel.