Skip to content

Commit 3842a5e

Browse files
ci: use PyPI trusted publishing (#3365)
1 parent 2a91011 commit 3842a5e

4 files changed

Lines changed: 91 additions & 22 deletions

File tree

.github/workflows/create-releases.yml

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ jobs:
1010
if: github.ref == 'refs/heads/main' && github.repository == 'openai/openai-python'
1111
runs-on: ubuntu-latest
1212
environment: publish
13+
outputs:
14+
releases_created: ${{ steps.release.outputs.releases_created }}
15+
permissions:
16+
contents: read
1317

1418
steps:
1519
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -20,16 +24,55 @@ jobs:
2024
repo: ${{ github.event.repository.full_name }}
2125
stainless-api-key: ${{ secrets.STAINLESS_API_KEY }}
2226

27+
build:
28+
name: build
29+
needs: release
30+
if: ${{ needs.release.outputs.releases_created == 'true' }}
31+
runs-on: ubuntu-latest
32+
# Build distributions without OIDC access so package build code cannot mint
33+
# a PyPI publishing token. The publish job handles only the upload.
34+
permissions:
35+
contents: read
36+
37+
steps:
38+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
39+
2340
- name: Set up Rye
24-
if: ${{ steps.release.outputs.releases_created }}
2541
uses: eifinger/setup-rye@c694239a43768373e87d0103d7f547027a23f3c8
2642
with:
2743
version: '0.44.0'
2844
enable-cache: true
2945

30-
- name: Publish to PyPI
31-
if: ${{ steps.release.outputs.releases_created }}
46+
- name: Build package
3247
run: |
33-
bash ./bin/publish-pypi
34-
env:
35-
PYPI_TOKEN: ${{ secrets.OPENAI_PYPI_TOKEN || secrets.PYPI_TOKEN }}
48+
mkdir -p dist
49+
rye build --clean
50+
51+
- name: Upload package distributions
52+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
53+
with:
54+
name: python-package-distributions
55+
path: dist/
56+
if-no-files-found: error
57+
retention-days: 1
58+
59+
publish:
60+
name: publish
61+
needs: build
62+
runs-on: ubuntu-latest
63+
environment: publish
64+
# PyPI Trusted Publishing requires id-token: write. Keep it scoped to this
65+
# minimal upload-only job rather than the build job.
66+
permissions:
67+
contents: read
68+
id-token: write
69+
70+
steps:
71+
- name: Download package distributions
72+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
73+
with:
74+
name: python-package-distributions
75+
path: dist/
76+
77+
- name: Publish to PyPI
78+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0

.github/workflows/publish-pypi.yml

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ on:
55
workflow_dispatch:
66

77
jobs:
8-
publish:
9-
name: publish
8+
build:
9+
name: build
10+
if: github.ref == 'refs/heads/main' && github.repository == 'openai/openai-python'
1011
runs-on: ubuntu-latest
11-
environment: publish
12+
# Build distributions without OIDC access so package build code cannot mint
13+
# a PyPI publishing token. The publish job handles only the upload.
14+
permissions:
15+
contents: read
1216

1317
steps:
1418
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -19,8 +23,37 @@ jobs:
1923
version: '0.44.0'
2024
enable-cache: true
2125

22-
- name: Publish to PyPI
26+
- name: Build package
2327
run: |
24-
bash ./bin/publish-pypi
25-
env:
26-
PYPI_TOKEN: ${{ secrets.OPENAI_PYPI_TOKEN || secrets.PYPI_TOKEN }}
28+
mkdir -p dist
29+
rye build --clean
30+
31+
- name: Upload package distributions
32+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
33+
with:
34+
name: python-package-distributions
35+
path: dist/
36+
if-no-files-found: error
37+
retention-days: 1
38+
39+
publish:
40+
name: publish
41+
needs: build
42+
if: github.ref == 'refs/heads/main' && github.repository == 'openai/openai-python'
43+
runs-on: ubuntu-latest
44+
environment: publish
45+
# PyPI Trusted Publishing requires id-token: write. Keep it scoped to this
46+
# minimal upload-only job rather than the build job.
47+
permissions:
48+
contents: read
49+
id-token: write
50+
51+
steps:
52+
- name: Download package distributions
53+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
54+
with:
55+
name: python-package-distributions
56+
path: dist/
57+
58+
- name: Publish to PyPI
59+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0

CONTRIBUTING.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,8 @@ the changes aren't made through the automated pipeline, you may want to make rel
119119

120120
### Publish with a GitHub workflow
121121

122-
You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/openai/openai-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up.
122+
You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/openai/openai-python/actions/workflows/publish-pypi.yml). PyPI publishing uses Trusted Publishing, so the PyPI project must trust this repository's GitHub Actions workflow and the `publish` environment.
123123

124124
### Publish manually
125125

126-
If you need to manually release a package, you can run the `bin/publish-pypi` script with a `PYPI_TOKEN` set on
127-
the environment.
126+
If you need to retry a PyPI release, use the `Publish PyPI` GitHub action. Local manual publishing is not the standard release path because the GitHub workflow uses OIDC instead of a long-lived PyPI token.

bin/publish-pypi

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)