Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use trusted publishing with both PyPI and TestPyPI #129

Merged
merged 28 commits into from
Mar 20, 2025
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
50f13bf
Use GitHub Actions as the PyPI Trusted Publisher
sajith Mar 17, 2025
dbe7c8a
Merge remote-tracking branch 'origin/master' into 127.pypi-trusted-pu…
sajith Mar 18, 2025
64cd8ad
Use TestPyPI URL for real
sajith Mar 18, 2025
c38b501
Give write permissions to OIDC token
sajith Mar 18, 2025
efc96cf
Put the old comment back
sajith Mar 18, 2025
086a219
Use the environment name hopefully correctly
sajith Mar 18, 2025
2b8d1f2
Be verbose while I debug
sajith Mar 18, 2025
7f3f82a
Build fewer packages while I debug
sajith Mar 18, 2025
7212ba8
Perhaps the URL is important?
sajith Mar 18, 2025
29af5e3
Try overriding URL in the step
sajith Mar 18, 2025
ef08839
Use url one level above
sajith Mar 18, 2025
a04ce7a
Use separate environments for PyPI and TestPyPI
sajith Mar 18, 2025
91a64e4
Use repository_url, not repository-url
sajith Mar 18, 2025
8757b9b
Trim whitespace
sajith Mar 18, 2025
2eff545
Use correct version of pypa/gh-action-pypi-publish, hopefully
sajith Mar 18, 2025
17d8bb2
Use the same pypa/gh-action-pypi-publish version with PyPI also
sajith Mar 18, 2025
8768d22
Break an over-long line
sajith Mar 18, 2025
cf4e220
Avoid duplicating comments
sajith Mar 18, 2025
b24b178
Avoid duplicating condition triggering upload_pypi
sajith Mar 18, 2025
f841ea7
Make comments consistent with current state
sajith Mar 18, 2025
0f7f218
Add a link to the relevant part of Python Packaging User Guide
sajith Mar 18, 2025
5ce17b3
Publish both release builds and PR builds on TestPyPI
sajith Mar 18, 2025
e672269
Use current release tag of pypa/gh-action-pypi-publish, not branch
sajith Mar 18, 2025
d087e33
Add some notes about PyPI trusted publishing
sajith Mar 18, 2025
85371dd
Use repository-url, not repository_url
sajith Mar 18, 2025
3cd18c8
Build all the packages again
sajith Mar 18, 2025
6299f3a
Update comment on the top
sajith Mar 19, 2025
308bcc7
Use quotes more consistently
sajith Mar 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 79 additions & 44 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Build sdist+wheel packages using GitHub Actions. Mostly adopted
# from https://cibuildwheel.readthedocs.io/en/stable/setup/
# Build sdist+wheel packages using GitHub Actions, and publish them on
# TestPyPI (on pull requests and tags) and PyPI (on tags).
#
# The build_wheels job is mostly adopted from
# https://cibuildwheel.readthedocs.io/en/stable/setup/
#
# The upload_pypi and upload_testpypi jobs are adopted from Python
# Packaging User Guide.

name: "Packages"

Expand Down Expand Up @@ -108,19 +114,47 @@ jobs:
name: sdist
path: dist/*.tar.gz

# Both `upload_pypi` and `upload_testpypi` jobs are based on
# "Publishing package distribution releases using GitHub Actions CI/CD
# workflows" page of Python Package User Guide. Specifically see the
# section under "The whole CI/CD workflow".
#
# https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/#the-whole-ci-cd-workflow
#
# The important bit here is that we use GitHub Actions as the "trusted
# publisher" to publish packages on both PyPI and TestPyPI. We do not
# use long-lived tokens anymore. Instead, both PyPI and TestPyPI are
# configured to trust this GH Actions workflow, and the workflow will
# use a short-lived tokens minted by them.
#
# https://docs.pypi.org/trusted-publishers/
#
# There is a bit of duplication below but that seems to be necessary
# because the environment configuration is different for PyPI and
# TestPyPI. Perhaps the duplication is not necessary, but let us just
# stick with the Python Package User Guide's recommendation.

upload_pypi:
name: Publish zfec on PyPI

# Publish to PyPI on release tag pushes.
if: >-
github.event_name == 'push' &&
startsWith(github.event.ref, 'refs/tags/zfec-')

needs:
- "build_wheels"
- "build_sdist"

# It only needs to run once. It will fetch all of the other build
# artifacts created by the other jobs and then upload them.
runs-on: "ubuntu-latest"

# Select the GitHub Actions environment that contains the PyPI tokens
# necessary to perform uploads. This was configured manually using the
# GitHub web interface.
environment: "release"
environment:
name: "release"
url: "https://pypi.org/project/zfec/"

# This permission is mandatory for trusted publishing
permissions:
id-token: write

steps:
# Download all artifacts previously built by this workflow to the dist
Expand All @@ -132,43 +166,44 @@ jobs:
path: "dist"
merge-multiple: true

# Define a conditional step to upload packages to the testing instance
# of PyPI.
#
# The overall workflow is already restricted so that it runs for:
# 1) pushes to master
# 2) pushes to release tags
# 3) pushes to branches with associated PRs
#
# The conditional in this step should cause it to run only for case (3).
- name: "Publish to TEST PyPI"
uses: "pypa/gh-action-pypi-publish@v1.6.4"
if: >-
github.event_name == 'pull_request'
- name: "Publish to PyPI"
uses: "pypa/gh-action-pypi-publish@v1.12.4"
with:
# Run `twine upload --verbose`.
verbose: true

upload_testpypi:
# Publish both builds triggered by pull requests and builds
# triggered by release tags to TestPyPI.
name: Publish zfec on TestPyPI

needs:
- "build_wheels"
- "build_sdist"

runs-on: "ubuntu-latest"

environment:
name: "testpypi"
url: "https://test.pypi.org/project/zfec/"

# This permission is mandatory for trusted publishing
permissions:
id-token: write

steps:
# Do the same thing as the download-artfact step in
# upload_testpypi job.
- uses: "actions/download-artifact@v4"
with:
# Authenticate using a token from a PyPI account with upload
# permission to the project. See https://pypi.org/help/#apitoken
user: "__token__"
# Read it from a GitHub Actions "environment" secret. See
# https://docs.github.com/en/actions/security-guides/encrypted-secrets
password: "${{ secrets.testpypi_token }}"
# Override the default in order to upload it to the testing
# deployment.
repository_url: "https://test.pypi.org/legacy/"

# Now define a conditional step to upload packages to the production
# instance of PyPI.
#
# The cases to consider are the same as for the upload to the testing
# instance. This time, we have a conditional that runs only for case
# (2).
- name: "Publish to LIVE PyPI"
uses: "pypa/gh-action-pypi-publish@v1.6.4"
if: >-
github.event_name == 'push' &&
startsWith(github.event.ref, 'refs/tags/zfec-')
pattern: "*"
path: "dist"
merge-multiple: true

- name: "Publish to TestPyPI"
uses: "pypa/gh-action-pypi-publish@v1.12.4"
with:
user: "__token__"
password: "${{ secrets.pypi_token }}"
# Override the default in order to upload to TestPyPi.
repository-url: https://test.pypi.org/legacy/
# Run `twine upload --verbose`.
verbose: true
Loading