Releasing
Python-package publication is separate from ordinary CI and from evidence-artifact promotion. A successful build is not release approval.
One-time PyPI setup
On PyPI, configure a Trusted Publisher for the GitHub repository
matuteiglesias/kb-artifacts, workflow .github/workflows/release.yml, and GitHub
environment pypi. Do not create or store a long-lived PYPI_TOKEN.
In GitHub, create the protected pypi environment and restrict deployment to the
release authority. The workflow requests id-token: write only in its publish job so
PyPI can exchange GitHub's short-lived OIDC identity for upload authorization.
Release procedure
- Complete the TestPyPI rehearsal.
- Obtain production release acceptance from MatÃas.
- Set the approved stable version in
pyproject.tomland ensure release notes are ready. - Require green CI and documentation checks for the exact source commit.
- Create and push an annotated tag matching the version exactly, such as
v0.2.0. - Approve the protected
pypienvironment deployment when prompted. - Confirm that the workflow verifies the exact version from PyPI and creates the matching GitHub release.
- Confirm that the documentation workflow for the released commit is live at the canonical site.
The release workflow rejects a tag that does not equal v plus the package version.
It tests the tagged source, builds one wheel and one sdist, runs strict metadata and
installed-package checks, records SHA-256 checksums, and stores those exact files as a
workflow artifact. Only the downstream publish job downloads and uploads the validated
distributions.
After publishing, a job with no repository checkout creates a clean environment,
installs the exact tagged version from PyPI, imports the public API, runs
kb-artifact --help, and completes the tutorial. Only after that succeeds does a
least-privilege job create the matching GitHub release with the validated wheel,
sdist, checksum file, and generated release notes. A publication that fails external
verification therefore does not receive a GitHub release claiming success.
The official PyPA publish action uses Trusted Publishing and emits PyPI attestations. No publishing step exists in the ordinary CI workflow.
TestPyPI rehearsal
Before production, set a release-candidate version such as 0.2.0rc1 in
pyproject.toml, obtain approval for the rehearsal, and push the matching annotated
tag v0.2.0rc1. Configure a TestPyPI Trusted Publisher for
.github/workflows/testpypi.yml with the protected GitHub environment testpypi; no
TestPyPI token is stored.
The rehearsal workflow builds and validates the exact candidate distributions,
publishes them to TestPyPI, and then creates a new environment with no repository
checkout. It installs the exact candidate with TestPyPI as the package index and PyPI
as the dependency fallback, imports the public API, runs kb-artifact --help, and
executes the 60-second tutorial. TestPyPI index propagation is retried for a bounded
period.
A failed external-consumer verification blocks production release acceptance. After a successful rehearsal, change the version to the approved stable version and repeat the normal CI checks before creating the production tag. TestPyPI artifacts are rehearsals; they are never promoted or copied into PyPI.