Publish to PyPI on a tag, via Trusted Publishing#9
Merged
Conversation
No API token — not in a secret, not in a file, not in ~/.pypirc. PyPI verifies over OIDC that the upload came from this repo and this workflow, and mints a short-lived credential for that one request. Nothing to store, leak or rotate. It also means the package gets PEP 740 attestations by default, so it carries evidence of where it was built, which this library has no business shipping without. Two guards, because a tag can point at anything: - the tag must match `version` in pyproject. A tag saying v0.2.0 over a tree saying 0.3.0 would publish a version nobody can trace to a commit. - tests, mypy and ruff re-run here. ci.yml runs on main and on PRs, but a tag can point at a commit neither ever saw, so the gate is repeated rather than assumed. Split into build and publish jobs so the job holding `id-token: write` does nothing but download an artifact and upload it. It has no other permission. One-time setup on PyPI, before the first release: Publishing -> add a pending publisher for owner Nik7A, repo chiplog, workflow release.yml, environment pypi. Releasing is then: bump version, land it, `git tag -s vX.Y.Z && git push --tags`.
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.
Publishing needs no API token at all. PyPI verifies over OIDC that the upload came from this repo and this workflow, and mints a short-lived credential for that one request — nothing to store in a secret, nothing to sit in
~/.pypircin plaintext, nothing to rotate or leak. It also means PyPI attaches PEP 740 attestations by default, so the package carries evidence of where it was built. For this library in particular, shipping without that would be odd.Two guards, because a tag can point at any commit:
versioninpyproject.toml. A tag sayingv0.2.0over a tree saying0.3.0would publish a version nobody can trace back to a commit — it fails instead of guessing.ci.ymlcovers main and PRs, but a tag can point at a commit neither ever saw, so the gate is repeated rather than assumed.Build and publish are split so the job holding
id-token: writedoes nothing but download an artifact and upload it. It has no other permission.One-time setup on PyPI, needed before the first release: Publishing → add a pending publisher for owner
Nik7A, repochiplog, workflowrelease.yml, environmentpypi. After the first upload it stops being pending and becomes the project's publisher.Then releasing is: bump
version, land it,git tag -s vX.Y.Z -m "..." && git push origin vX.Y.Z.Note that
v0.2.0is already tagged and pushed, from before this workflow existed. Once this lands, that tag can be deleted and re-pushed to trigger a release, or 0.2.1 can be the first tag that publishes itself.