-
Notifications
You must be signed in to change notification settings - Fork 1
142 lines (122 loc) · 4.96 KB
/
Copy pathpython-publish.yml
File metadata and controls
142 lines (122 loc) · 4.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# Publish the sdist and wheel to PyPI when a GitHub release is published.
#
# The upload uses trusted publishing (OIDC), so there is no API token in the
# repository secrets: PyPI is configured to trust this workflow file, running in
# the `pypi` environment, on this repository. Changing the workflow's filename
# or environment name breaks the upload until the publisher on PyPI is updated
# to match.
#
# Release checklist:
# 1. Bump `version` in pyproject.toml on main and merge it.
# 2. Draft a release whose tag is `v<that version>`; the tag check below
# rejects a mismatch.
# 3. Publish the release. This workflow runs the tests and the packaging
# checks, and only then uploads.
name: Upload Python Package
on:
release:
types: [published]
workflow_dispatch:
inputs:
target:
description: "Index to upload to"
type: choice
options: [testpypi, pypi]
default: testpypi
permissions:
contents: read
jobs:
verify-tag:
# Cheap and first, so a mistyped tag fails in seconds instead of after the
# full test matrix. Skipped on a manual run, which has no release tag.
name: Verify the release tag
if: github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-python@v7
with:
python-version: "3.12"
- name: Verify the release tag matches the package version
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
pkg="v$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')"
[ "$pkg" = "$RELEASE_TAG" ] || { echo "::error::release tag $RELEASE_TAG does not match package version $pkg"; exit 1; }
tests:
# A release is the one build nobody gets to retry, so run the suite again
# against the tagged commit rather than trusting the branch run.
name: Tests
needs: verify-tag
if: ${{ !cancelled() && !failure() }}
uses: ./.github/workflows/tests.yml
packaging:
# Builds the distributions, checks their metadata and contents, and uploads
# them as the `release-dists` artifact that the publish job consumes. The
# files that go to PyPI are therefore exactly the ones that passed here.
name: Packaging
needs: verify-tag
if: ${{ !cancelled() && !failure() }}
uses: ./.github/workflows/packaging.yml
publish:
name: Publish to ${{ github.event_name == 'release' && 'PyPI' || inputs.target }}
needs: [tests, packaging]
runs-on: ubuntu-latest
permissions:
# Mandatory for trusted publishing: mints the OIDC token that stands in
# for an API token, and signs the PEP 740 attestations.
id-token: write
environment:
name: ${{ github.event_name == 'release' && 'pypi' || inputs.target }}
url: ${{ (github.event_name == 'release' || inputs.target == 'pypi') && 'https://pypi.org/p/assemblytheorytools' || 'https://test.pypi.org/p/assemblytheorytools' }}
steps:
- name: Retrieve the built distributions
uses: actions/download-artifact@v8
with:
name: release-dists
path: dist/
- name: List what is about to be uploaded
run: ls -l dist/
- name: Publish to TestPyPI
# Manual dry run of the real upload path. It needs a pending publisher
# for this workflow on test.pypi.org, configured once under the
# `testpypi` environment; without it the run fails at this step and the
# release path is unaffected.
if: github.event_name == 'workflow_dispatch' && inputs.target == 'testpypi'
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
packages-dir: dist/
# A version already uploaded to TestPyPI must not fail the rehearsal.
skip-existing: true
- name: Publish to PyPI
if: github.event_name == 'release' || inputs.target == 'pypi'
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
# PEP 740 provenance, so installers can verify the files were built
# by this workflow.
attestations: true
attach-to-release:
# Put the published files on the GitHub release too, so the tag and PyPI
# can be compared byte for byte later.
name: Attach the distributions to the release
needs: publish
if: github.event_name == 'release'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Retrieve the built distributions
uses: actions/download-artifact@v8
with:
name: release-dists
path: dist/
- name: Upload the distributions to the release
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$RELEASE_TAG" dist/* --clobber