Target: 1.3.1 (Tier 0 — hygiene)
.github/workflows/release.yml triggers on push: tags: ["v*"] and runs
uv build then uv publish --trusted-publishing always in a single
publish job. It has no needs: on the lint, typecheck, test or
build jobs in ci.yml, and does not re-run them itself.
A tag pushed against broken code therefore publishes to PyPI
unchallenged. Nothing catches it, and a published version cannot be
replaced — only yanked.
What to do
Either make the publish job depend on the CI gates, or have the release
workflow re-run ruff check, ruff format --check, mypy and pytest
before the uv publish step. The second is simpler given the workflows
are currently independent.
Acceptance criteria
Target: 1.3.1 (Tier 0 — hygiene)
.github/workflows/release.ymltriggers onpush: tags: ["v*"]and runsuv buildthenuv publish --trusted-publishing alwaysin a singlepublishjob. It has noneeds:on thelint,typecheck,testorbuildjobs inci.yml, and does not re-run them itself.A tag pushed against broken code therefore publishes to PyPI
unchallenged. Nothing catches it, and a published version cannot be
replaced — only yanked.
What to do
Either make the publish job depend on the CI gates, or have the release
workflow re-run
ruff check,ruff format --check,mypyandpytestbefore the
uv publishstep. The second is simpler given the workflowsare currently independent.
Acceptance criteria
does not publish to PyPI.