Releases¶
Publishing is automated. Pushing a vX.Y.Z tag runs the release workflow, which tests, builds, and validates the sdist and wheel, publishes them to PyPI, and creates the matching GitHub release with the built artifacts attached.
How tagging works¶
A tag is a separate ref from a branch, not part of any commit's metadata. git push origin master never pushes tags, and the release workflow never fires from an ordinary branch push. A tag only exists on GitHub once you push it explicitly:
git tag -a vX.Y.Z -m "Tinax X.Y.Z" # create the tag locally, pointing at the current commit
git push origin vX.Y.Z # push just that tag; this is what triggers the release
-a makes it an annotated tag (a real object with author, date, and message, the kind you want for releases) instead of a bare pointer. -m supplies that message, which only needs to be something recognizable to you later (git show vX.Y.Z, git tag -n) — the workflow's gh release create --generate-notes step builds the actual GitHub release notes from commit history, not from this message.
The workflow trigger matches on the tag's ref name alone (v*.*.*), so a lightweight tag (git tag vX.Y.Z, no -a/-m) publishes exactly the same way. Annotated is the convention this project uses since it's a permanent record, but nothing in the pipeline depends on it.
To release the branch you just pushed to master, tag its current HEAD after CI is green; the tag doesn't need to be created in any particular order relative to the branch push, only pushed separately afterward.
Cutting a release¶
- Update the
versioninpyproject.tomland add an entry toCHANGES.md, then commit andgit push origin masteras usual. This does not publish anything; it only runs CI. - Tag the commit and push the tag:
- Watch the
Releaseworkflow run. It fails closed: if the tag doesn't matchpyproject.toml's version, or if tests, lint, type checking,zensical build,twine check, or the inert-import wheel smoke test fail, nothing is published. - Once it succeeds, verify from a clean environment (any supported Python, 3.12–3.14):
uv venv --python 3.14 /tmp/tinax-pypi-check
uv pip install --python /tmp/tinax-pypi-check/bin/python "tinax==X.Y.Z"
/tmp/tinax-pypi-check/bin/python -I -c "import tinax"
Do not re-push a tag once it has been used for a publish; cut a new patch version instead.