Releases¶
A release is a version tag vX.Y.Z on main. CI builds and tags the image (X.Y.Z, X.Y, latest) and makes the GitHub release from the pull requests merged since the last tag.
Why¶
A tag is a single, reviewable act: what is released is exactly what is on main at that commit, and the release notes come from the pull requests that already describe each change. Nothing is published from a laptop.
How¶
- Tag
main:git tag -a vX.Y.Z -m "vX.Y.Z" && git push origin vX.Y.Z. - The release workflow checks that the tag matches the version in the project (
package.json,pyproject.toml) before it builds. - The image gets three tags: the exact version, the minor line and
latest. - A Python library goes to PyPI from the same tag, through Trusted Publishing: the workflow publishes with a short-lived token bound to the repository, the workflow file and an environment named
pypi, so no API token is stored anywhere. The workflow checks that the tag matchespyproject.toml, runs the tests, runsuv build, publishes withpypa/gh-action-pypi-publishand attaches the same files to the GitHub release. - The release notes list the merged pull requests; a project may also post them elsewhere (notefeed posts its releases to a feed).
CLAUDE.mdnames the release command.
Rules out¶
- Publishing an image or a package from a local machine.
- A PyPI API token in the repository's secrets.
- A release whose tag doesn't match the version in the project.
- Hand-written release notes that repeat the pull requests.
Reference¶
freundebuch and notefeed (image releases); mcp-login-oauth (PyPI through Trusted Publishing).