Skip to content

Release preflight reports PyPI 422 as "no verdict", so main fails with "verified nothing (1 unknown)" instead of naming the missing trusted publisher #108

Closed

Description

@konard

Problem

Every main run of the CI/CD Pipeline fails in Release Preflight with an error that says nothing actionable:

##[warning]release-preflight: PyPI answered 422 to the mint-token probe (no verdict on trusted publishing)
##[error]release-preflight: verified nothing (1 unknown) -- refusing to release on an unproven credential set

Template main at 533e0b7, run 38041366369. The same happens in every repository generated from the template, for example konard/medical-neural-network-ml run 38725259374.

Root cause

scripts/preflight-credentials.sh L129-L144 treats only 400/401/403 as a refusal. Any other status is unknown. PyPI answers every refused exchange with 422 and a JSON body:

{"message": "Token request failed", "errors": [{"code": "invalid-publisher", "description": "valid token, but no corresponding publisher (Publisher with matching claims was not found)"}]}

The body format comes from warehouse/oidc/views.py _invalid(), L75. The invalid-publisher code is at L322.

So the most common setup problem, "no trusted publisher exists yet", is reported as "no verdict", and the maintainer is not told what to fix. pypa/gh-action-pypi-publish decodes the same errors[] list, but only at publish time.

Suggested fix

Read errors[0].code on a 422:

  • invalid-publisher and invalid-pending-publisher are a definite answer, so they should be FAIL. Print the publisher form fields filled from the run (owner, repository, workflow file from GITHUB_WORKFLOW_REF, blank environment).
  • Probe GET /pypi/<project>/json to link the right page:
    • 404: a pending publisher at /manage/account/publishing/.
    • 200: the project's /settings/publishing/ page, plus a hint to rename [project].name when the project is someone else's. The template's my-package already exists on PyPI.
  • rate-limited, not-enabled, invalid-token, invalid-reuse-token, invalid-payload and a 422 without a body stay unknown ("report unknown, never a guess").

This is implemented with 9 tests in konard/medical-neural-network-ml#5 (scripts/preflight-credentials.sh, tests/test_preflight_credentials.py). After the change the same run prints:

FAIL: PyPI refused to mint an upload token (422 invalid-publisher: valid token, but no corresponding publisher (Publisher with matching claims was not found)) -- the publish step would be rejected the same way. A PyPI maintainer must add a GitHub trusted publisher with owner=konard, repository=medical-neural-network-ml, workflow=release.yml, environment=(blank) to the existing project "my-package" at https://pypi.org/manage/project/my-package/settings/publishing/. If that project is not yours, rename [project].name in pyproject.toml first.

Reference: hive-mind CI/CD best practices #16 ("Prove You Can Publish Before You Build") and #17.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions