88permissions :
99 contents : read
1010
11+ concurrency :
12+ group : release
13+
1114jobs :
1215 release :
1316 runs-on : ubuntu-latest
14- concurrency : release
1517 environment : release
1618 permissions :
1719 id-token : write
@@ -37,12 +39,73 @@ jobs:
3739 ssh_private_signing_key : ${{ secrets.SEMANTIC_RELEASE_PRIVATE_KEY }}
3840 ssh_public_signing_key : ${{ secrets.SEMANTIC_RELEASE_PUBLIC_KEY }}
3941
40- - name : Publish to PyPI
41- uses : pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # release/v1
42+ - name : Hash Build Artifacts
43+ if : steps.release.outputs.released == 'true'
44+ id : hash
45+ run : |
46+ cd dist
47+ echo "hashes=$(find . -type f -exec sha256sum {} + | sort | base64 | tr -d '\n')" >> "$GITHUB_OUTPUT"
48+
49+ - name : Upload Build Artifacts
4250 if : steps.release.outputs.released == 'true'
51+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
52+ with :
53+ name : dist
54+ path : dist/
55+
56+ outputs :
57+ hashes : ${{ steps.hash.outputs.hashes }}
58+ released : ${{ steps.release.outputs.released }}
59+
60+ provenance :
61+ needs : release
62+ if : ${{ needs.release.outputs.released == 'true' }}
63+ permissions :
64+ actions : read
65+ id-token : write
66+ contents : write
67+ uses :
slsa-framework/slsa-github-generator/.github/workflows/[email protected] 68+ with :
69+ base64-subjects : " ${{ needs.release.outputs.hashes }}"
70+
71+ publish :
72+ runs-on : ubuntu-latest
73+ needs : [release, provenance]
74+ if : ${{ needs.release.outputs.released == 'true' && needs.provenance.outputs.outcome == 'success' }}
75+ environment : release
76+ permissions :
77+ id-token : write
78+
79+ steps :
80+ - name : Harden Runner
81+ uses : step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
82+ with :
83+ egress-policy : audit
84+
85+ - uses : actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
86+ with :
87+ fetch-depth : 0
88+ token : ${{ secrets.GH_TOKEN }}
89+
90+ - name : Download Build Artifacts
91+ uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
92+ with :
93+ name : dist
94+ path : dist
95+
96+ - name : Download Provenance
97+ uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
98+ with :
99+ name : ${{ needs.provenance.outputs.provenance-name }}
100+ path : dist
43101
44102 - name : Publish to GitHub Releases
45103 uses : python-semantic-release/publish-action@b717f67f7e7e9f709357bce5a542846503ce46ec # v10.2.0
46- if : steps.release.outputs.released == 'true'
47104 with :
48105 github_token : ${{ secrets.GH_TOKEN }}
106+
107+ - name : Remove Provenance for PyPI Upload
108+ run : rm -f dist/${{ needs.provenance.outputs.provenance-name }}
109+
110+ - name : Publish to PyPI
111+ uses : pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # release/v1
0 commit comments