11name : Publish to PyPI
22
33on :
4- pull_request :
5- types : [closed]
4+ push :
65 branches :
76 - master
87
98permissions :
109 contents : write
1110 id-token : write
11+ pull-requests : read
12+
13+ env :
14+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 : " true"
1215
1316jobs :
1417 publish :
15- # Run only after PR is merged with release labels
16- if : |
17- github.event.pull_request.merged == true && (
18- contains(github.event.pull_request.labels.*.name, 'release:major') ||
19- contains(github.event.pull_request.labels.*.name, 'release:minor') ||
20- contains(github.event.pull_request.labels.*.name, 'release:patch')
21- )
2218 runs-on : ubuntu-latest
2319
2420 steps :
2521 - name : Check out repository
26- uses : actions/checkout@v4
22+ uses : actions/checkout@v6.0.2
2723 with :
2824 fetch-depth : 0
2925
26+ - name : Check merged PR release label
27+ id : release_label_check
28+ uses : actions/github-script@v9.0.0
29+ with :
30+ script : |
31+ const releaseLabels = ['release:major', 'release:minor', 'release:patch'];
32+ const { owner, repo } = context.repo;
33+ const commitSha = context.sha;
34+
35+ const prs = await github.rest.repos.listPullRequestsAssociatedWithCommit({
36+ owner,
37+ repo,
38+ commit_sha: commitSha,
39+ });
40+
41+ const mergedPr = prs.data.find((pr) => pr.merged_at && pr.base?.ref === 'master');
42+
43+ if (!mergedPr) {
44+ core.notice(`No merged PR associated with commit ${commitSha}. Skipping publish.`);
45+ core.setOutput('should_publish', 'false');
46+ return;
47+ }
48+
49+ const labelNames = (mergedPr.labels || [])
50+ .map((label) => label?.name)
51+ .filter(Boolean);
52+ const matchedLabel = releaseLabels.find((label) => labelNames.includes(label));
53+
54+ if (!matchedLabel) {
55+ core.notice(
56+ `Merged PR #${mergedPr.number} does not include a release label (${releaseLabels.join(', ')}). Skipping publish.`
57+ );
58+ core.setOutput('should_publish', 'false');
59+ return;
60+ }
61+
62+ core.info(`Merged PR #${mergedPr.number} has label ${matchedLabel}. Publishing enabled.`);
63+ core.setOutput('should_publish', 'true');
64+ core.setOutput('release_label', matchedLabel);
65+ core.setOutput('pr_number', String(mergedPr.number));
66+
3067 - name : Set up Python
31- uses : actions/setup-python@v5
68+ if : steps.release_label_check.outputs.should_publish == 'true'
69+ uses : actions/setup-python@v6.2.0
3270 with :
3371 python-version : " 3.13"
3472
3573 - name : Install tools
74+ if : steps.release_label_check.outputs.should_publish == 'true'
3675 run : pip install bump-my-version build
3776
3877 - name : Extract version
3978 id : version
79+ if : steps.release_label_check.outputs.should_publish == 'true'
4080 run : |
4181 VERSION=$(bump-my-version show current_version)
4282 echo "version=$VERSION" >> $GITHUB_OUTPUT
4383
44- - name : Create GitHub Release
45- uses : softprops/action-gh-release@v2
46- with :
47- tag_name : v${{ steps.version.outputs.version }}
48- name : v${{ steps.version.outputs.version }}
49- body_path : CHANGELOG.md
50- generate_release_notes : false
51-
5284 - name : Build package
85+ if : steps.release_label_check.outputs.should_publish == 'true'
5386 run : python -m build
5487
5588 - name : Publish to TestPyPI
5689 id : test-pypi
90+ if : steps.release_label_check.outputs.should_publish == 'true'
5791 uses : pypa/gh-action-pypi-publish@v1.13.0
5892 with :
5993 repository-url : https://test.pypi.org/legacy/
6094 skip-existing : true
6195 attestations : false
6296
6397 - name : Publish to PyPI
64- if : steps.test-pypi.outcome == 'success'
98+ id : pypi
99+ if : steps.release_label_check.outputs.should_publish == 'true' && steps.test-pypi.outcome == 'success'
65100 uses : pypa/gh-action-pypi-publish@v1.13.0
66101 with :
67- skip-existing : true
102+ skip-existing : true
103+
104+ - name : Create GitHub Release
105+ if : steps.release_label_check.outputs.should_publish == 'true' && steps.pypi.outcome == 'success'
106+ uses : softprops/action-gh-release@v2
107+ with :
108+ tag_name : v${{ steps.version.outputs.version }}
109+ name : v${{ steps.version.outputs.version }}
110+ body_path : CHANGELOG.md
111+ generate_release_notes : false
0 commit comments