gh-action-pypi-publish: [error] * `invalid-publisher`: valid token, but no corresponding publisher

From validators/actions/runs/4550595346/jobs/8023753623

Run pypa/gh-action-pypi-publish@release/v1
/usr/bin/docker run --name c0442075403f75bc9417ab8fbffed20a2928e_3f477f --label 6c0442 --workdir /github/workspace --rm -e "pythonLocation" -e "PKG_CONFIG_PATH" -e "Python_ROOT_DIR" -e "Python2_ROOT_DIR" -e "Python3_ROOT_DIR" -e "LD_LIBRARY_PATH" -e "VENV" -e "INPUT_PASSWORD" -e "INPUT_USER" -e "INPUT_REPOSITORY-URL" -e "INPUT_REPOSITORY_URL" -e "INPUT_PACKAGES-DIR" -e "INPUT_PACKAGES_DIR" -e "INPUT_VERIFY-METADATA" -e "INPUT_VERIFY_METADATA" -e "INPUT_SKIP-EXISTING" -e "INPUT_SKIP_EXISTING" -e "INPUT_VERBOSE" -e "INPUT_PRINT-HASH" -e "INPUT_PRINT_HASH" -e "HOME" -e "GITHUB_JOB" -e "GITHUB_REF" -e "GITHUB_SHA" -e "GITHUB_REPOSITORY" -e "GITHUB_REPOSITORY_OWNER" -e "GITHUB_REPOSITORY_OWNER_ID" -e "GITHUB_RUN_ID" -e "GITHUB_RUN_NUMBER" -e "GITHUB_RETENTION_DAYS" -e "GITHUB_RUN_ATTEMPT" -e "GITHUB_REPOSITORY_ID" -e "GITHUB_ACTOR_ID" -e "GITHUB_ACTOR" -e "GITHUB_TRIGGERING_ACTOR" -e "GITHUB_WORKFLOW" -e "GITHUB_HEAD_REF" -e "GITHUB_BASE_REF" -e "GITHUB_EVENT_NAME" -e "GITHUB_SERVER_URL" -e "GITHUB_API_URL" -e "GITHUB_GRAPHQL_URL" -e "GITHUB_REF_NAME" -e "GITHUB_REF_PROTECTED" -e "GITHUB_REF_TYPE" -e "GITHUB_WORKFLOW_REF" -e "GITHUB_WORKFLOW_SHA" -e "GITHUB_WORKSPACE" -e "GITHUB_ACTION" -e "GITHUB_EVENT_PATH" -e "GITHUB_ACTION_REPOSITORY" -e "GITHUB_ACTION_REF" -e "GITHUB_PATH" -e "GITHUB_ENV" -e "GITHUB_STEP_SUMMARY" -e "GITHUB_STATE" -e "GITHUB_OUTPUT" -e "RUNNER_OS" -e "RUNNER_ARCH" -e "RUNNER_NAME" -e "RUNNER_TOOL_CACHE" -e "RUNNER_TEMP" -e "RUNNER_WORKSPACE" -e "ACTIONS_RUNTIME_URL" -e "ACTIONS_RUNTIME_TOKEN" -e "ACTIONS_CACHE_URL" -e "ACTIONS_ID_TOKEN_REQUEST_URL" -e "ACTIONS_ID_TOKEN_REQUEST_TOKEN" -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/validators/validators":"/github/workspace" 6c0442:075403f75bc9417ab8fbffed20a2928e  "__token__" "" "" "" "" "" "false" ""
Notice: Attempting to perform OIDC credential exchange  to retrieve a temporary short-lived API token for authentication  against https://upload.pypi.org/legacy/
Error: OIDC exchange failure: 
Token request failed: the server refused the request for the following reasons:

* `invalid-publisher`: valid token, but no corresponding publisher

What’s wrong with validators/.github/workflows/build.yml?

# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

name: Build for PyPI

on:
  workflow_dispatch:
  release:
    types: [published]

permissions:
  contents: read

jobs:
  build_and_publish:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    steps:
      # checkout repository
      - uses: actions/checkout@v3
      # setup lowest supported python version
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: "3.8"
      # install & configure poetry
      - name: Install Poetry
        uses: snok/install-poetry@v1
        with:
          version: 1.4.1
          virtualenvs-create: true
          virtualenvs-in-project: true
      # install dependencies
      - name: Install dependencies
        run: poetry install --no-interaction --no-ansi --only docs
      # build package
      - name: Build package
        run: |
          source .venv/bin/activate
          python build.py
      # publish package
      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.PYPI_API_TOKEN }}

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 15 (10 by maintainers)

Commits related to this issue

Most upvoted comments

Ah yep, that would do it – if you specify an environment on the PyPI side, then the trusted publisher will only be authorized if the workflow actually runs in that environment.

The behavior is as follows:

  • No environment configured on PyPI: any explicit environment on GHA is okay (or none at all)
  • Environment configured on PyPI: the GHA workflow’s environment must match exactly

That makes sense, thanks for confirming @woodruffw 😃

Thanks for the rapid response @woodruffw! I’ve actually solved it since my post 30 mins ago. I think the solution was to remove the optional ‘environment’ entry on the trusted publisher form on PyPI. I had previously named an environment in my GH repo containing PyPI secrets, which was a legacy from trying to set up publishing with API tokens. I had a theory that these secrets or the environment were somehow disrupting the authentication process, so I re-entered the trusted publisher form with the environment entry omitted and that solved it. Might be worth seeing if you can reproduce?

@woodruffw thanks for the PR! I was thinking that we could also have a clearer indication of why the OIDC flow got triggered in the first place. Like “Not using token- or password-based authentication because the user-provided password is empty”. Other branches show things like “Using a user-provided API token for authentication” but this specific one doesn’t, which is the primary cause for confusion, I suppose.

Makes sense to me, I can do that in a bit!

@woodruffw thanks for the PR! I was thinking that we could also have a clearer indication of why the OIDC flow got triggered in the first place. Like “Not using token- or password-based authentication because the user-provided password is empty”. Other branches show things like “Using a user-provided API token for authentication” but this specific one doesn’t, which is the primary cause for confusion, I suppose.

@joe733 suggested the following earlier:

Before the above notice another message could be given like:

Warning: secrets.PYPI_API_TOKEN is empty or rejected.

Or course, we cannot say secrets.PYPI_API_TOKEN in the error message because we have no way of knowing how the user named their secret or if they even provided token via a secret and not a plain text input 🤷‍♂️ but the idea in general is nice.

Or provide another option like:

with:
    oidc: false
    password: ${{ secrets.PYPI_API_TOKEN }} # gets ignored if oidc is true

Nope, the extra input idea was rejected to simplify the process for the end-users. Besides, we already have a clear indication for the OIDC opt-in which is an empty password + the __token__ user. Making the users manage a combination of inputs would increase cognitive load which would be unhelpful.

I think the author @kvesteri currently uses conventional authentication.

rel: python-validators/validators#256 (comment)

Likely, not many folks enrolled and have the feature flag for the private beta enabled.

do you think we should add some title/pointer to the job summary to mention it’s OIDC? Also explaining that to turn off the flow, one should pass in a token/password?

Yeah, that makes sense to me. I can do that in a bit.

do we need to start pointing to the new public docs?

Also makes sense to me!