Repository navigation
ci: build and publish a release when a tag is pushed - #3
Merged
Merged
Conversation
Pushing a tag matching v* now builds the wheel and the sdist and attaches both to a GitHub Release. A bare tag gives you only the "Source code" archives GitHub generates, which are snapshots of the repository rather than built packages, so installing from one means building from source. The workflow refuses to build when the tag does not match __version__. A tag can point at any commit, so nothing else keeps the version in the artefact and the version people install by from drifting apart. It runs the tests for the same reason, and imports the built wheel in an empty environment before publishing. `gh release create` rather than a third-party action: the CLI is already on the runner, and this is one less thing with write access to the repository. Also adds .gitattributes. Without it git checks out CRLF on Windows while the mixed-line-ending hook rewrites to LF, so the two undo each other on every run and every commit warns about it. Drop this file if the churn is preferable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Needed before
v2.0.0can be tagged: a workflow file only runs if it exists in the commit the tag points at, so this has to land onmainfirst.What pushing a tag does
git tag -a v2.0.0 -m "v2.0.0" git push origin v2.0.0.github/workflows/release.ymlthen:__version__and stops before building if they differuv buildSteps 1 and 2 are there because a tag can point at any commit — nothing else keeps the version in the artefact matching the version people install by, or guarantees the tagged commit ever passed CI.
Why the release, and not just the tag
A bare tag gives you only what GitHub generates:
loggerhelper-2.0.0-py3-none-any.whlloggerhelper-2.0.0.tar.gzThe last row is the one worth knowing about: those archives are the repo at that commit, so installing from one builds from source rather than installing a wheel.
After a release, the wheel is directly installable:
Implementation notes
gh release createrather than a third-party action — the CLI is already on the runner, and it is one less thing holding write access to the repository.permissions: contents: writeis scoped to this job only.uv publishstays manual and documented, since it needs a token.Also:
.gitattributesUnrelated to releases, but it has been generating noise all along. Git checks out CRLF on Windows while the
mixed-line-endinghook rewrites to LF, so the two undo each other on everypre-commit run --all-filesand every commit prints a wall ofLF will be replaced by CRLFwarnings.* text=auto eol=lfsettles it. Drop this file if you would rather keep the current behaviour — it is the one change here that is not about releasing.Content was already stored as LF, so
git add --renormalize .was a no-op; the diff is three files.Verification
__version__extraction was run against the real__init__.pyand matches2.0.0pre-commit run --all-filesclean,uv buildproduces a wheel that imports from a clean environment🤖 Generated with Claude Code