Skip to content

Commit fb224e9

Browse files
committed
chore: Use trusted publishing for PyPi package
Speakeasy doesn't support it out of the box, but we can manully mint a short-lived API token using OIDC which we then pass to speakeasy. This allows us to remove the long-lived API token from our CI variables.
1 parent e48c9a7 commit fb224e9

3 files changed

Lines changed: 45 additions & 4 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Mint PyPI Token
2+
on:
3+
workflow_call:
4+
outputs:
5+
pypi_token:
6+
description: Minted PyPI API token via OIDC
7+
value: ${{ jobs.mint.outputs.pypi_token }}
8+
jobs:
9+
mint:
10+
name: Mint PyPI token
11+
runs-on: ubuntu-latest
12+
permissions:
13+
id-token: write
14+
steps:
15+
- name: Mint API token
16+
id: mint-token
17+
run: |
18+
# retrieve the ambient OIDC token
19+
resp=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
20+
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=pypi")
21+
oidc_token=$(jq -r '.value' <<< "${resp}")
22+
23+
# exchange the OIDC token for an API token
24+
resp=$(curl -X POST https://pypi.org/_/oidc/mint-token -d "{\"token\": \"${oidc_token}\"}")
25+
api_token=$(jq -r '.token' <<< "${resp}")
26+
27+
# mask the newly minted API token, so that we don't accidentally leak it
28+
echo "::add-mask::${api_token}"
29+
30+
# see the next step in the workflow for an example of using this step output
31+
echo "api-token=${api_token}" >> "${GITHUB_OUTPUT}"
32+
outputs:
33+
pypi_token: ${{ steps.mint-token.outputs.pypi_token }}

.github/workflows/sdk_generation.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ permissions:
44
contents: write
55
pull-requests: write
66
statuses: write
7-
"on":
7+
id-token: write
8+
on:
89
workflow_dispatch:
910
inputs:
1011
force:
@@ -17,7 +18,10 @@ permissions:
1718
schedule:
1819
- cron: 0 0 * * *
1920
jobs:
21+
mint_pypi_token:
22+
uses: ./.github/workflows/pypi_mint_token.yaml
2023
generate:
24+
needs: mint_pypi_token
2125
uses: speakeasy-api/sdk-generation-action/.github/workflows/workflow-executor.yaml@v15
2226
with:
2327
force: ${{ github.event.inputs.force }}
@@ -26,5 +30,5 @@ jobs:
2630
speakeasy_version: latest
2731
secrets:
2832
github_access_token: ${{ secrets.GITHUB_TOKEN }}
29-
pypi_token: ${{ secrets.PYPI_TOKEN }}
33+
pypi_token: ${{ needs.mint_pypi_token.outputs.pypi_token }}
3034
speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }}

.github/workflows/sdk_publish.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@ permissions:
44
contents: write
55
pull-requests: write
66
statuses: write
7-
"on":
7+
id-token: write
8+
on:
89
push:
910
branches:
1011
- main
1112
paths:
1213
- RELEASES.md
1314
- '*/RELEASES.md'
1415
jobs:
16+
mint_pypi_token:
17+
uses: ./.github/workflows/pypi_mint_token.yaml
1518
publish:
19+
needs: mint_pypi_token
1620
uses: speakeasy-api/sdk-generation-action/.github/workflows/sdk-publish.yaml@v15
1721
secrets:
1822
github_access_token: ${{ secrets.GITHUB_TOKEN }}
19-
pypi_token: ${{ secrets.PYPI_TOKEN }}
23+
pypi_token: ${{ needs.mint_pypi_token.outputs.pypi_token }}
2024
speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }}

0 commit comments

Comments
 (0)