Versioning is automatic via setuptools_scm: the version is derived from the
latest git tag. Do not hand-edit versions — version.py is generated and
git-ignored.
-
Make sure
mainis up to date and green. -
Create an annotated tag and push it together with the branch:
git tag -a v1.2.0 -m "v1.2.0" git push origin main --follow-tagsUse a
vX.Y.Ztag matching the release you want.
Pushing the tag triggers the publish-to-pypi workflow, which runs the tests,
builds the distribution, publishes to PyPI, and creates a sigstore-signed
GitHub release.
Every push to main (without a tag) publishes a dev version
(1.2.0.devN) to TestPyPI. Use this to validate the build/publish
pipeline before cutting the real tag:
git push origin mainskip-existing is enabled, so re-pushing without new commits won't fail.
The single workflow routes by git ref:
| Push | Publishes to |
|---|---|
branch (main) |
TestPyPI |
tag (vX.Y.Z) |
PyPI + GitHub release |
Both targets use PyPI trusted publishing — no API tokens.
- PyPI: trusted publisher +
pypiGitHub environment. - TestPyPI: trusted publisher +
testpypiGitHub environment.
Register the repo/workflow as a trusted publisher on each index and create the matching GitHub environment before the first publish.