Repository navigation
Publish to PyPI with trusted publishing - #95
Merged
Merged
Conversation
added 2 commits
August 14, 2026 16:15
Replaces the twine upload driven by the PYPI_USERNAME/PYPI_PASSWORD secrets with pypa/gh-action-pypi-publish over OIDC, so no long-lived PyPI credential is stored in the repository. Build and publish are split into separate jobs as PyPA recommends, keeping the id-token permission off the job that runs build-time dependencies. Requires a trusted publisher for taraskiba/forestspot with workflow pypi.yml to be registered on PyPI before the next release.
- skip-existing made a failed release report green: re-releasing an already published version would skip the upload and exit 0 while PyPI kept serving the old files. PyPA advises against it for PyPI for that reason, so let a duplicate upload fail loudly instead. - Add contents: read at the workflow level and persist-credentials: false on the checkout, so the job that resolves and executes build dependencies does not carry a writable GITHUB_TOKEN. The publish job overrides this with the id-token permission it needs. - overwrite: true lets "Re-run all jobs" on a failed release work; v4 artifacts are immutable per run, so the second attempt would otherwise 409 in the build job before publish is reached. - if-no-files-found: error reports an empty build where it happens instead of as a missing artifact one job later. - The header comment claimed no PyPI secret is stored; the secrets stay until Tara deletes them, so say the workflow no longer uses them.
mihiarc
force-pushed
the
ci/pypi-trusted-publishing
branch
from
August 14, 2026 20:15
c4b0874 to
a6427e8
Compare
mihiarc
marked this pull request as ready for review
August 14, 2026 20:21
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.
pypi.ymlstill uploads with twine using thePYPI_USERNAME/PYPI_PASSWORDsecrets. This switches it to PyPI trusted publishing (OIDC viapypa/gh-action-pypi-publish), so no long-lived PyPI credential is needed to publish.Build and publish are split into separate jobs, as PyPA recommends:
id-token: writeis scoped to the publish job, and the build job — the one that resolves and executes build dependencies — runs withcontents: readand a checkout that doesn't persist credentials.Draft until the PyPI side is configured. On https://pypi.org/manage/project/forestspot/settings/publishing/, add a GitHub publisher:
taraskibaforestspotpypi.ymlOnce that's registered I'll mark this ready. Merging it before then would break the next release.
Notes for review
skip-existing. The old workflow passedtwine --skip-existing. Keeping it would let a re-release of an already-published version skip the upload and exit 0, so the Actions tab and the release page both go green while PyPI keeps serving the old files. PyPA advises against it for PyPI for exactly this reason; a duplicate upload now fails loudly.gh-action-pypi-publishgenerates and uploads PEP 740 attestations by default for trusted-publishing projects, whichtwine uploadnever did. Left at the default (on) — worth knowing it's in the release path if a future upload fails verification.environment:. PyPA's example gates publishing behind a GitHub environment with required reviewers. Creating one needs admin, which I don't have, so this is left off and the PyPI publisher must be registered with the environment field blank to match. Worth adding later, @taraskiba — it's a two-sided change (workflow and the PyPI publisher config) or the OIDC claim won't match.PYPI_USERNAME/PYPI_PASSWORDsecrets stay live and valid until they're deleted in repo settings. That needs your access, @taraskiba.Verified:
python -m buildsucceeds from a clean checkout and produces the sdist and wheel the publish job expects; actionlint and pre-commit clean.