Fix pypi deployment - #173
Open
philrhc wants to merge 2 commits into
Open
Conversation
Releases have been blocked since Jan 2025 (zeromq#171): the PYPI_TOKEN secret belongs to a single PyPI account that is no longer reachable, so uploads fail with "does not have a verified primary email address". Rotating the token only moves the problem to whoever holds the next one. Trusted publishing removes the stored credential entirely. The workflow mints a short-lived OIDC token which PyPI exchanges for a single-use upload token, so upload rights belong to this repository and workflow rather than to an individual's account. Any maintainer able to trigger the workflow can cut a release, and there is nothing to rotate or lose when a maintainer moves on. Also pins pypa/gh-action-pypi-publish from @master to @release/v1, and drops the checkout step from the publish job, which never used the source tree. Requires a matching publisher on the PyPI project (Manage -> Publishing): owner zeromq, repository pyre, workflow deploy.yml. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019gLbEtgftbkCLmbZwSCsSp
extra_requires is not a setuptools keyword, so it was silently ignored and the 'deploy' and 'test' extras documented in MAINTENANCE.md did not actually exist. Renaming to extras_require registers them. Without long_description the PyPI project page renders empty. README.md is already shipped via MANIFEST.in, so read it in and declare it as markdown. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019gLbEtgftbkCLmbZwSCsSp
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.
Fix PyPI deployment: trusted publishing + packaging metadata
Problem
Deployment has been broken since January 2025 (#171). PyPI is stuck at 0.3.4, while
masteris at 0.3.5 and taggedv0.3.5. The upload fails with:The
PYPI_TOKENrepository secret (last updated June 2021) belongs to a single PyPI account that is no longer reachable. Issuing a fresh token would unblock today's release but leaves the same structural problem: the project's ability to publish depends on one individual's account remaining active and reachable.Changes
1. Trusted publishing instead of a stored token (
e34297a)Trusted publishing is PyPI's recommended mechanism and removes the stored credential entirely. The workflow mints a short-lived OIDC token, which PyPI exchanges for a single-use upload token.
The practical difference: upload rights belong to this repository and workflow, not to any individual's PyPI account. Any maintainer who can trigger the workflow can cut a release, and there is no long-lived credential to rotate, leak, or lose when a maintainer moves on. That directly addresses the failure mode in #171 rather than deferring it.
The diff follows the canonical PyPA example:
permissions: id-token: writeto thepublishjobuser/passwordinputs — no secret is referenced anywhere in the workflow after thisactions/checkoutfrompublish, which never used the source treepypa/gh-action-pypi-publishfrom@masterto@release/v1—@masteris a mutable branch, so the previous form ran whatever was on that branch at the timeMAINTENANCE.mdis updated to match, since it currently documents the token mechanism this removes.2. Packaging metadata fixes (
2809e3d)extra_requires→extras_require.extra_requiresis not a setuptools keyword, so it was silently ignored — thedeployandtestextras documented inMAINTENANCE.mddid not actually exist. Confirmed fixed: the built sdist now declares them.long_description. Without it the PyPI project page renders empty.README.mdis already shipped viaMANIFEST.in, so it is read in and declared as markdown.Required on the PyPI side
The workflow cannot upload until a matching publisher exists on the project (Manage → Publishing → GitHub):
zeromqpyredeploy.ymlI have owner access on the PyPI project and will configure this. Adding a GitHub Environment (e.g.
pypi) as an extra approval gate would be a good hardening follow-up, but it needs repository admin.Note: merging this will not publish anything
bump_version.ymlpushes its tag usingsecrets.GITHUB_TOKEN(lines 97, 105), and GitHub deliberately does not trigger workflows fromGITHUB_TOKENpushes. So merging bumps the version and pushes a tag, butdeploy.ymlwill not fire on its own — the release has to be dispatched manually from the Actions tab. Flagging this so nobody expects a merge to ship a release.Open question for reviewers
Whether to publish 0.3.5 (matching the existing
v0.3.5tag, which never made it to PyPI) or let the merge bump to 0.3.6. I have no strong preference; 0.3.6 has the mild advantage of including the metadata fixes above, so the first successful release renders a proper project page. Happy to go either way.For context on why it is worth unblocking: the 15 commits since 0.3.4 are mostly CI and Python version upgrades, but they include
set_interfacebeing implemented (e782257), which is what #132 asks for. Users currently have no released version containing it.Verification
Built and checked locally from this branch:
twine check— PASSED__version__ == 0.3.5requires.txtin the sdist now lists the[deploy]and[test]extras (confirming the typo fix)PKG-INFOnow embeds the README (247 lines, previously ~12)deploy.ymlparses;publishjob haspermissions: {id-token: write}and zerosecrets.referencesNothing here changes library code — no behavioural change for users.
Follow-ups, not in this PR
MAINTENANCE.md"Note 1" still describesPERSONAL_ACCESS_TOKENas required for the version bump, butbump_version.ymlhas since moved toGITHUB_TOKEN. The docs and the workflow disagree; worth reconciling separately.MAINTENANCE.mdjustifies sdist-only by Python 2 support, which no longer applies.Refs #171 — deliberately not using a closing keyword, since merging this does not itself publish anything. Better to close #171 once a release actually lands on PyPI.