Skip to content

Switch PyPI publish workflow to OIDC trusted publishing#7879

Draft
Copilot wants to merge 3 commits into
mainfrom
copilot/update-pypi-publishing-flow
Draft

Switch PyPI publish workflow to OIDC trusted publishing#7879
Copilot wants to merge 3 commits into
mainfrom
copilot/update-pypi-publishing-flow

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 12, 2026

Replaces the long-lived PYPI_TOKEN upload in .github/workflows/pypi.yml with PyPA's official action using OIDC trusted publishing, per the linked GitHub/PyPI guidance.

Changes

  • Action: drop the pip install twine + twine upload -u __token__ -p ${{ secrets.PYPI_TOKEN }} step in favour of pypa/gh-action-pypi-publish@release/v1.
  • Permissions: add id-token: write on the job so GitHub can mint the OIDC token PyPI exchanges for a short-lived API token.
  • Artifact layout: download the released wheel into dist/ (the action's default packages-dir) instead of python/.
  • Environment: bind the publish job to a GitHub Actions environment named pypi for additional hardening (deployment branch/tag restrictions, optional required reviewers, deployment record).
  • Secret: secrets.PYPI_TOKEN is no longer referenced and can be removed from repo secrets once trusted publishing is live.
permissions:
  id-token: write
...
jobs:
  build_and_publish:
    runs-on: ubuntu-latest
    environment: pypi
    permissions:
      id-token: write
    ...
    - name: Publish PyPi Package to https://pypi.org/project/ccf/
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        skip-existing: true

Out-of-band setup required

  1. Repo settings → Environments: create an environment named pypi (must match the workflow exactly). Optionally restrict "Deployment branches and tags" to the release tag pattern (e.g. ccf-*) and add required reviewers for a manual gate.
  2. PyPI: register/update the trusted publisher for the ccf project pointing at microsoft/CCF, workflow pypi.yml, and set the Environment name to pypi. Both sides must match or token minting will fail.

Copilot AI linked an issue May 12, 2026 that may be closed by this pull request
…C trusted publishing

Agent-Logs-Url: https://github.com/microsoft/CCF/sessions/ae6b3f94-23af-4d89-adae-716929b33a1e

Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com>
Copilot AI changed the title [WIP] Update PyPI publishing flow to use OIDC Switch PyPI publish workflow to OIDC trusted publishing May 12, 2026
Copilot AI requested a review from achamayou May 12, 2026 15:16
@achamayou
Copy link
Copy Markdown
Member

@copilot what does setting an environment on the job do? Also is there a way to set the write permission at the step level rather than the job?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 12, 2026

@copilot what does setting an environment on the job do? Also is there a way to set the write permission at the step level rather than the job?

Two separate things:

environment: on the job ties the job to a GitHub Actions environment, which gives you:

  • Protection rules: required reviewers, wait timers, and a branch/tag allow-list before the job is allowed to run.
  • Environment-scoped secrets/variables.
  • A deployment record visible in the repo's "Environments" UI.

For trusted publishing specifically, it also acts as an additional constraint on the PyPI side: when you register the trusted publisher on PyPI you can pin it to a workflow and an environment name (e.g. pypi), so even a workflow change on main can't mint a PyPI token unless it runs in that environment — which in turn can be gated by required reviewers. It's the recommended hardening for publish jobs. Happy to add environment: pypi here if you'd like (it'd need to be created in repo settings and matched on PyPI).

Step-level permissions: — no, GitHub Actions doesn't support that. permissions: is only valid at the workflow or job level (docs). The narrowest scope available is the job, which is what this PR does. The usual way to limit blast radius further is to isolate the publish step in its own single-step job (which is already the shape here).

@achamayou
Copy link
Copy Markdown
Member

@copilot add an environment to this workflow, call it pypi - what do I need to do in repo settings?

Agent-Logs-Url: https://github.com/microsoft/CCF/sessions/5bef9d3b-cd2a-45ab-9b30-b8275f2f5b9e

Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 12, 2026

@copilot add an environment to this workflow, call it pypi - what do I need to do in repo settings?

Done in 84b59be — added environment: pypi to the build_and_publish job.

Repo settings to do:

  1. Settings → Environments → New environment → name it pypi (must match the workflow exactly).
  2. (Recommended) On that environment, configure:
    • Deployment branches and tags → "Selected branches and tags" → allow only the tag pattern ccf-* (or main), so only release tags can deploy.
    • Required reviewers → add yourself / the release approvers if you want a manual gate before publishing.
    • Wait timer is optional.
  3. No secrets need to live in the environment — OIDC handles auth, and PYPI_TOKEN can be deleted from repo secrets once trusted publishing is confirmed working.

PyPI side: in the ccf project's Publishing settings, edit the existing trusted publisher and set Environment name to pypi. Both sides must match or token minting will fail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PyPI releases with OIDC/Trusted Publishing

2 participants