Skip to content

Commit 9c56a55

Browse files
authored
ci: publish to PyPI from a single workflow (#1201)
Beta and stable releases are published to PyPI from different workflows (`manual_release_beta.yaml` and `manual_release_stable.yaml`), so PyPI shows a "Change of provenance" warning on every stable release that follows a beta. All publishing now happens in a new `publish_to_pypi.yaml`, which both release workflows dispatch with `apify/actions/execute-workflow`. Crawlee JS runs `publish-to-npm.yml` the same way. Before merging, add a PyPI trusted publisher for `apify-client` with workflow `publish_to_pypi.yaml` and environment `pypi`. Remove the old ones once the first release goes through. Relates to: apify/crawlee-python#2382 *✍️ Drafted by Claude Code*
1 parent 17fb82d commit 9c56a55

4 files changed

Lines changed: 86 additions & 58 deletions

File tree

‎.github/workflows/manual_release_beta.yaml‎

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ name: Beta release
33
on:
44
# Runs when manually triggered from the GitHub UI, or dispatched from `on_master.yaml`
55
# via the `apify/actions/execute-workflow` action for the automatic beta release on push to master.
6-
# Note: This workflow is intentionally NOT a reusable workflow (no `workflow_call`) because PyPI's
7-
# Trusted Publishing does not currently support reusable workflows.
8-
# See: https://docs.pypi.org/trusted-publishers/troubleshooting/#reusable-workflows-on-github
96
workflow_dispatch:
107

118
concurrency:
@@ -55,39 +52,24 @@ jobs:
5552
changelog: ${{ needs.release_prepare.outputs.changelog }}
5653
secrets: inherit
5754

55+
# Publishing runs as a separate workflow run of `publish_to_pypi.yaml` (see the comment there).
5856
pypi_publish:
5957
name: PyPI publish
6058
needs: [release_prepare, changelog_update]
6159
runs-on: ubuntu-latest
6260
permissions:
63-
contents: write
64-
id-token: write # Required for OIDC authentication.
65-
environment:
66-
name: pypi
67-
url: https://pypi.org/project/apify-client
61+
actions: write # Required by execute-workflow.
6862
steps:
69-
- name: Prepare distribution
70-
uses: apify/actions/prepare-pypi-distribution@v1.6.2
71-
with:
72-
package_name: apify-client
73-
is_prerelease: "yes"
74-
version_number: ${{ needs.release_prepare.outputs.version_number }}
75-
ref: ${{ needs.changelog_update.outputs.changelog_commitish }}
76-
77-
- name: Verify built package
78-
uses: apify/actions/python-package-check@v1.6.2
63+
- name: Dispatch PyPI publish workflow
64+
uses: apify/actions/execute-workflow@v1.6.2
7965
with:
80-
package_name: apify_client
81-
dist_dir: dist
82-
python_version: "3.14"
83-
smoke_code: |
84-
from apify_client import ApifyClient, ApifyClientAsync
85-
ApifyClient(token='x')
86-
ApifyClientAsync(token='x')
87-
88-
# Publish the package to PyPI using PyPA official GitHub action with OIDC authentication.
89-
- name: Publish package to PyPI
90-
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # release/v1
66+
workflow: publish_to_pypi.yaml
67+
inputs: >
68+
{
69+
"version_number": "${{ needs.release_prepare.outputs.version_number }}",
70+
"ref": "${{ needs.changelog_update.outputs.changelog_commitish }}",
71+
"is_prerelease": "true"
72+
}
9173
9274
doc_release_post_publish:
9375
name: Doc release post publish

‎.github/workflows/manual_release_stable.yaml‎

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,39 +88,24 @@ jobs:
8888
target_commitish: ${{ needs.changelog_update.outputs.changelog_commitish }}
8989
body: ${{ needs.release_prepare.outputs.release_notes }}
9090

91+
# Publishing runs as a separate workflow run of `publish_to_pypi.yaml` (see the comment there).
9192
pypi_publish:
9293
name: PyPI publish
9394
needs: [release_prepare, changelog_update]
9495
runs-on: ubuntu-latest
9596
permissions:
96-
contents: write
97-
id-token: write # Required for OIDC authentication.
98-
environment:
99-
name: pypi
100-
url: https://pypi.org/project/apify-client
97+
actions: write # Required by execute-workflow.
10198
steps:
102-
- name: Prepare distribution
103-
uses: apify/actions/prepare-pypi-distribution@v1.6.2
104-
with:
105-
package_name: apify-client
106-
is_prerelease: ""
107-
version_number: ${{ needs.release_prepare.outputs.version_number }}
108-
ref: ${{ needs.changelog_update.outputs.changelog_commitish }}
109-
110-
- name: Verify built package
111-
uses: apify/actions/python-package-check@v1.6.2
99+
- name: Dispatch PyPI publish workflow
100+
uses: apify/actions/execute-workflow@v1.6.2
112101
with:
113-
package_name: apify_client
114-
dist_dir: dist
115-
python_version: "3.14"
116-
smoke_code: |
117-
from apify_client import ApifyClient, ApifyClientAsync
118-
ApifyClient(token='x')
119-
ApifyClientAsync(token='x')
120-
121-
# Publish the package to PyPI using PyPA official GitHub action with OIDC authentication.
122-
- name: Publish package to PyPI
123-
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # release/v1
102+
workflow: publish_to_pypi.yaml
103+
inputs: >
104+
{
105+
"version_number": "${{ needs.release_prepare.outputs.version_number }}",
106+
"ref": "${{ needs.changelog_update.outputs.changelog_commitish }}",
107+
"is_prerelease": "false"
108+
}
124109
125110
version_docs:
126111
name: Version docs

‎.github/workflows/on_master.yaml‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ jobs:
4343
uses: ./.github/workflows/manual_release_docs.yaml
4444
secrets: inherit
4545

46-
# The beta release is dispatched as a separate workflow run (instead of calling `manual_release_beta.yaml` via `uses:`)
47-
# because PyPI's Trusted Publishing does not currently support reusable workflows.
48-
# See: https://docs.pypi.org/trusted-publishers/troubleshooting/#reusable-workflows-on-github
4946
beta_release:
5047
# Only on push, and only for "feat", "fix", "perf", "refactor" and "style" commits.
5148
if: >-
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
# Dispatched from `manual_release_beta.yaml` and `manual_release_stable.yaml` via the `apify/actions/execute-workflow`
5+
# action. All releases are published from this single workflow, which is the one registered as the PyPI Trusted
6+
# Publisher, so PyPI attests the same provenance for beta and stable releases. It is a standalone workflow, not
7+
# a reusable one, because PyPI's Trusted Publishing does not currently support reusable workflows.
8+
# See: https://docs.pypi.org/trusted-publishers/troubleshooting/#reusable-workflows-on-github
9+
workflow_dispatch:
10+
inputs:
11+
version_number:
12+
description: Version to publish (for a prerelease, the base version the beta number is appended to)
13+
required: true
14+
type: string
15+
ref:
16+
description: Git ref to build the package from (branch, tag, or commit SHA)
17+
required: true
18+
type: string
19+
is_prerelease:
20+
description: Whether to publish a beta prerelease
21+
required: false
22+
type: boolean
23+
default: false
24+
25+
concurrency:
26+
group: publish-to-pypi
27+
cancel-in-progress: false
28+
29+
permissions:
30+
contents: read
31+
32+
jobs:
33+
pypi_publish:
34+
name: PyPI publish
35+
runs-on: ubuntu-latest
36+
permissions:
37+
contents: read
38+
id-token: write # Required for OIDC authentication.
39+
environment:
40+
name: pypi
41+
url: https://pypi.org/project/apify-client
42+
steps:
43+
- name: Prepare distribution
44+
uses: apify/actions/prepare-pypi-distribution@v1.6.2
45+
with:
46+
package_name: apify-client
47+
is_prerelease: ${{ inputs.is_prerelease && 'yes' || '' }}
48+
version_number: ${{ inputs.version_number }}
49+
ref: ${{ inputs.ref }}
50+
51+
- name: Verify built package
52+
uses: apify/actions/python-package-check@v1.6.2
53+
with:
54+
package_name: apify_client
55+
dist_dir: dist
56+
python_version: "3.14"
57+
smoke_code: |
58+
from apify_client import ApifyClient, ApifyClientAsync
59+
ApifyClient(token='x')
60+
ApifyClientAsync(token='x')
61+
62+
# Publish the package to PyPI using PyPA official GitHub action with OIDC authentication.
63+
- name: Publish package to PyPI
64+
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # release/v1

0 commit comments

Comments
 (0)