Skip to content

Commit efe1392

Browse files
authored
Automate PyPI Releases (python-telegram-bot#4364)
1 parent 0a673e8 commit efe1392

3 files changed

Lines changed: 215 additions & 5 deletions

File tree

.github/workflows/release_pypi.yml

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
# Run on any tag
5+
push:
6+
tags:
7+
- '**'
8+
# manually trigger the workflow - for testing only
9+
workflow_dispatch:
10+
11+
jobs:
12+
build:
13+
name: Build Distribution
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Set up Python
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: "3.x"
22+
- name: Install pypa/build
23+
run: >-
24+
python3 -m pip install build --user
25+
- name: Build a binary wheel and a source tarball
26+
run: python3 -m build
27+
- name: Store the distribution packages
28+
uses: actions/upload-artifact@v4
29+
with:
30+
name: python-package-distributions
31+
path: dist/
32+
33+
publish-to-pypi:
34+
name: Publish to PyPI
35+
# only publish to PyPI on tag pushes
36+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
37+
needs:
38+
- build
39+
runs-on: ubuntu-latest
40+
environment:
41+
name: release_pypi
42+
url: https://pypi.org/p/python-telegram-bot
43+
permissions:
44+
id-token: write # IMPORTANT: mandatory for trusted publishing
45+
46+
steps:
47+
- name: Download all the dists
48+
uses: actions/download-artifact@v4
49+
with:
50+
name: python-package-distributions
51+
path: dist/
52+
- name: Publish to PyPI
53+
uses: pypa/gh-action-pypi-publish@release/v1
54+
55+
publish-to-test-pypi:
56+
name: Publish to Test PyPI
57+
needs:
58+
- build
59+
runs-on: ubuntu-latest
60+
environment:
61+
name: release_test_pypi
62+
url: https://test.pypi.org/p/python-telegram-bot
63+
permissions:
64+
id-token: write # IMPORTANT: mandatory for trusted publishing
65+
66+
steps:
67+
- name: Download all the dists
68+
uses: actions/download-artifact@v4
69+
with:
70+
name: python-package-distributions
71+
path: dist/
72+
- name: Publish to Test PyPI
73+
uses: pypa/gh-action-pypi-publish@release/v1
74+
with:
75+
repository-url: https://test.pypi.org/legacy/
76+
77+
compute-signatures:
78+
name: Compute SHA1 Sums and Sign with Sigstore
79+
runs-on: ubuntu-latest
80+
needs:
81+
- publish-to-pypi
82+
- publish-to-test-pypi
83+
# run if either of the publishing jobs ran successfully
84+
# see also:
85+
# https://github.com/actions/runner/issues/491#issuecomment-850884422
86+
if: |
87+
always() && (
88+
(needs.publish-to-pypi.result == 'success') ||
89+
(needs.publish-to-test-pypi.result == 'success')
90+
)
91+
92+
permissions:
93+
id-token: write # IMPORTANT: mandatory for sigstore
94+
95+
steps:
96+
- name: Download all the dists
97+
uses: actions/download-artifact@v4
98+
with:
99+
name: python-package-distributions
100+
path: dist/
101+
- name: Compute SHA1 Sums
102+
run: |
103+
# Compute SHA1 sum of the distribution packages and save it to a file with the same name,
104+
# but with .sha1 extension
105+
for file in dist/*; do
106+
sha1sum $file > $file.sha1
107+
done
108+
- name: Sign the dists with Sigstore
109+
uses: sigstore/[email protected]
110+
with:
111+
inputs: >-
112+
./dist/*.tar.gz
113+
./dist/*.whl
114+
- name: Store the distribution packages and signatures
115+
uses: actions/upload-artifact@v4
116+
with:
117+
name: python-package-distributions-and-signatures
118+
path: dist/
119+
120+
github-release:
121+
name: Upload to GitHub Release
122+
needs:
123+
- publish-to-pypi
124+
- compute-signatures
125+
if: |
126+
always() && (
127+
(needs.publish-to-pypi.result == 'success') &&
128+
(needs.compute-signatures.result == 'success')
129+
)
130+
131+
runs-on: ubuntu-latest
132+
133+
permissions:
134+
contents: write # IMPORTANT: mandatory for making GitHub Releases
135+
136+
steps:
137+
- name: Download all the dists
138+
uses: actions/download-artifact@v4
139+
with:
140+
name: python-package-distributions-and-signatures
141+
path: dist/
142+
- name: Create GitHub Release
143+
env:
144+
GITHUB_TOKEN: ${{ github.token }}
145+
# Create a GitHub Release for this tag. The description can be changed later, as for now
146+
# we don't define it through this workflow.
147+
run: >-
148+
gh release create
149+
'${{ github.ref_name }}'
150+
--repo '${{ github.repository }}'
151+
--generate-notes
152+
- name: Upload artifact signatures to GitHub Release
153+
env:
154+
GITHUB_TOKEN: ${{ github.token }}
155+
# Upload to GitHub Release using the `gh` CLI.
156+
# `dist/` contains the built packages, and the
157+
# sigstore-produced signatures and certificates.
158+
run: >-
159+
gh release upload
160+
'${{ github.ref_name }}' dist/**
161+
--repo '${{ github.repository }}'
162+
163+
github-test-release:
164+
name: Upload to GitHub Release Draft
165+
needs:
166+
- publish-to-test-pypi
167+
- compute-signatures
168+
if: |
169+
always() && (
170+
(needs.publish-to-test-pypi.result == 'success') &&
171+
(needs.compute-signatures.result == 'success')
172+
)
173+
runs-on: ubuntu-latest
174+
175+
permissions:
176+
contents: write # IMPORTANT: mandatory for making GitHub Releases
177+
178+
steps:
179+
- name: Download all the dists
180+
uses: actions/download-artifact@v4
181+
with:
182+
name: python-package-distributions-and-signatures
183+
path: dist/
184+
- name: Create GitHub Release
185+
env:
186+
GITHUB_TOKEN: ${{ github.token }}
187+
# Create a GitHub Release *draft*. The description can be changed later, as for now
188+
# we don't define it through this workflow.
189+
run: >-
190+
gh release create
191+
'${{ github.ref_name }}'
192+
--repo '${{ github.repository }}'
193+
--generate-notes
194+
--draft
195+
- name: Upload artifact signatures to GitHub Release
196+
env:
197+
GITHUB_TOKEN: ${{ github.token }}
198+
# Upload to GitHub Release using the `gh` CLI.
199+
# `dist/` contains the built packages, and the
200+
# sigstore-produced signatures and certificates.
201+
run: >-
202+
gh release upload
203+
'${{ github.ref_name }}' dist/**
204+
--repo '${{ github.repository }}'

README.rst

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,19 @@ You can also install ``python-telegram-bot`` from source, though this is usually
117117
Verifying Releases
118118
~~~~~~~~~~~~~~~~~~
119119

120-
We sign all the releases with a GPG key.
121-
The signatures are uploaded to both the `GitHub releases page <https://github.com/python-telegram-bot/python-telegram-bot/releases>`_ and the `PyPI project <https://pypi.org/project/python-telegram-bot/>`_ and end with a suffix ``.asc``.
120+
To enable you to verify that a release file that you downloaded was indeed provided by the ``python-telegram-bot`` team, we have taken the following measures.
121+
122+
Starting with NEXT.VERSION, all releases are signed via `sigstore <https://sigstore.dev>`_.
123+
The corresponding signature files are uploaded to the `GitHub releases page`_.
124+
To verify the signature, please install the `sigstore Python client <https://pypi.org/project/sigstore/>`_ and follow the instructions for `verifying signatures from GitHub Actions <https://github.com/sigstore/sigstore-python#signatures-from-github-actions>`_. As input for the ``--repository`` parameter, please use the value ``python-telegram-bot/python-telegram-bot``.
125+
126+
Earlier releases are signed with a GPG key.
127+
The signatures are uploaded to both the `GitHub releases page`_ and the `PyPI project <https://pypi.org/project/python-telegram-bot/>`_ and end with a suffix ``.asc``.
122128
Please find the public keys `here <https://github.com/python-telegram-bot/python-telegram-bot/tree/master/public_keys>`_.
123-
The keys are named in the format ``<first_version>-<last_version>.gpg`` or ``<first_version>-current.gpg`` if the key is currently being used for new releases.
129+
The keys are named in the format ``<first_version>-<last_version>.gpg``.
124130

125131
In addition, the GitHub release page also contains the sha1 hashes of the release files in the files with the suffix ``.sha1``.
126132

127-
This allows you to verify that a release file that you downloaded was indeed provided by the ``python-telegram-bot`` team.
128-
129133
Dependencies & Their Versions
130134
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131135

@@ -227,3 +231,5 @@ License
227231

228232
You may copy, distribute and modify the software provided that modifications are described and licensed for free under `LGPL-3 <https://www.gnu.org/licenses/lgpl-3.0.html>`_.
229233
Derivatives works (including modifications or anything statically linked to the library) can only be redistributed under LGPL-3, but applications that use the library don't have to be.
234+
235+
.. _`GitHub releases page`: https://github.com/python-telegram-bot/python-telegram-bot/releases>

0 commit comments

Comments
 (0)