Publish on a published release, not on every merged PR - #96
Open
Marius1311 wants to merge 1 commit into
Open
Conversation
publish.yaml triggered on `pull_request: closed` with `merged == true`, then bumped the patch version, committed it to main, tagged, built and published. Every merge was therefore a release, with several consequences (dpeerlab#95): * a docs typo, a CI tweak or an internal refactor each shipped a version, and changes could not be batched; * the bump was always `patch`, so the number said "how many merges", not what kind of change it was; * the publish job had no `needs:` and ran no tests, so nothing re-checked the merge result before uploading; * it cannot work for pull requests from forks, which get no secrets and a read-only token -- both `secrets.PYPI_TOKEN` and `git push origin HEAD:main` would fail; * CI pushed straight to main, bypassing any branch protection; * two merges landing close together raced on the same version number; * uploads used a long-lived API token rather than PyPI trusted publishing. Releasing is now two explicit steps: bump `version` in pyproject.toml in a normal pull request, then draft a GitHub release tagged `v<version>`. Merging alone releases nothing. The workflow follows scverse's cookiecutter template: trigger on `release: types: [published]`, no top-level permissions, `id-token: write` on the job, build with `uv build`, upload with pypa/gh-action-pypi-publish via trusted publishing. No token is stored. The template derives its version from the tag via hatch-vcs; scenvi's is written by hand in pyproject.toml, so the two can drift. A step therefore compares the release tag against the version of the wheel that was just built -- the artifact about to be uploaded, rather than a second parse of pyproject.toml -- and fails the release on a mismatch. test.yaml additionally runs on pushes to main, so that main is known-good before a release is cut from it. Nothing covered that once publishing stopped happening on merge. Co-Authored-By: Claude Opus 5 (1M context) <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.
Closes #95.
What changes
Releasing becomes two explicit steps:
versioninpyproject.tomlin a normal pull request, and merge it;v<version>and publish it.Merging alone no longer releases anything. That means changes can be batched into
one release, the version number can say what kind of change it is rather than just
counting merges, and there is a natural place to write release notes.
The workflow itself follows the
scverse cookiecutter template:
trigger on
release: types: [published], empty top-levelpermissions,id-token: writeon the job only, build withuv build, upload withpypa/gh-action-pypi-publish.One deliberate difference from the template. It derives the version from the
tag via
hatch-vcs, so tag and version cannot disagree. scenvi's version iswritten by hand in
pyproject.toml, so they can. A step therefore compares therelease tag against the version of the wheel that was just built — the artifact
actually about to be uploaded, rather than a second parse of
pyproject.toml—and fails the release on a mismatch:
(If you do move to
hatchling+hatch-vcslater, as #94 touches on, that stepcan just be deleted.)
Also here
test.yamlnow runs on pushes tomainas well as on pull requests. Oncepublishing stops happening on merge, nothing else re-checks the merge result, and
a release should only be cut from a green
main. Happy to drop this if you'drather keep it to one concern per PR.
What is removed
The version bump, the commit, the tag push and the
git push origin HEAD:mainallgo, along with
contents: write. CI no longer writes to the repository at all, sothis also stops bypassing branch protection on
main.Testing
Workflow changes can't really be exercised until they run on
main, so what Icould check locally:
release;workflow_dispatch/pull_request/push);uv buildsucceeds against the currentpoetry-corebackend, producingscenvi-0.4.6.tar.gzandscenvi-0.4.6-py3-none-any.whl—uv buildonly runsthe PEP 517 backend, so it does not require moving off poetry;
v0.4.6against that wheel, rejectsv0.4.7with theerror above, and errors if
dist/does not contain exactly one wheel.