Skip to content

Commit 8b27a20

Browse files
committed
ci: use draft releases to support immutable GitHub releases
1 parent 8116d20 commit 8b27a20

File tree

3 files changed

+81
-19
lines changed

3 files changed

+81
-19
lines changed

.github/workflows/manual-publish.yml

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ on:
66
description: "Is this a dry run? If so no package will be published."
77
type: boolean
88
required: true
9+
tag:
10+
description: 'Tag of an existing draft release to upload artifacts to.'
11+
type: string
12+
required: false
13+
publish_release:
14+
description: 'Publish (un-draft) the release after all artifacts are uploaded?'
15+
type: boolean
16+
required: false
17+
default: true
918

1019
jobs:
1120
build-publish:
@@ -14,6 +23,7 @@ jobs:
1423
permissions:
1524
id-token: write
1625
contents: read
26+
attestations: write # Needed for artifact attestations
1727
outputs:
1828
package-hashes: ${{ steps.build.outputs.package-hashes}}
1929
steps:
@@ -41,13 +51,31 @@ jobs:
4151
with:
4252
password: ${{env.PYPI_AUTH_TOKEN}}
4353

44-
release-provenance:
45-
needs: ["build-publish"]
54+
- name: Generate checksums file
55+
if: ${{ !inputs.dry_run }}
56+
env:
57+
HASHES: ${{ steps.build.outputs.package-hashes }}
58+
run: |
59+
echo "$HASHES" | base64 -d > checksums.txt
60+
61+
- name: Attest build provenance
62+
if: ${{ !inputs.dry_run }}
63+
uses: actions/attest@v4
64+
with:
65+
subject-checksums: checksums.txt
66+
67+
publish-release:
68+
needs: ['build-publish']
69+
if: ${{ !inputs.dry_run && inputs.publish_release }}
70+
runs-on: ubuntu-latest
4671
permissions:
47-
actions: read
48-
id-token: write
4972
contents: write
50-
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@5a775b367a56d5bd118a224a811bba288150a563 # v2.0.0
51-
with:
52-
base64-subjects: "${{ needs.build-publish.outputs.package-hashes }}"
53-
upload-assets: ${{ !inputs.dry_run }}
73+
steps:
74+
- name: Publish release
75+
env:
76+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77+
TAG_NAME: ${{ inputs.tag }}
78+
run: >
79+
gh release edit "$TAG_NAME"
80+
--repo ${{ github.repository }}
81+
--draft=false

.github/workflows/release-please.yml

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ jobs:
1111
id-token: write # Needed if using OIDC to get release secrets.
1212
contents: write # Contents and pull-requests are for release-please to make releases.
1313
pull-requests: write
14+
attestations: write # Needed for artifact attestations
1415
outputs:
1516
release-created: ${{ steps.release.outputs.release_created }}
1617
upload-tag-name: ${{ steps.release.outputs.tag_name }}
@@ -22,7 +23,23 @@ jobs:
2223
- uses: actions/checkout@v4
2324
if: ${{ steps.release.outputs.releases_created == 'true' }}
2425
with:
25-
fetch-depth: 0 # Full history is required for proper changelog generation
26+
fetch-depth: 0
27+
28+
- name: Create release tag
29+
if: ${{ steps.release.outputs.releases_created == 'true' }}
30+
env:
31+
TAG_NAME: ${{ steps.release.outputs.tag_name }}
32+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
run: |
34+
if gh api "repos/${{ github.repository }}/git/ref/tags/${TAG_NAME}" >/dev/null 2>&1; then
35+
echo "Tag ${TAG_NAME} already exists, skipping creation."
36+
else
37+
echo "Creating tag ${TAG_NAME}."
38+
git config user.name "github-actions[bot]"
39+
git config user.email "github-actions[bot]@users.noreply.github.com"
40+
git tag "${TAG_NAME}"
41+
git push origin "${TAG_NAME}"
42+
fi
2643
2744
- uses: actions/setup-python@v5
2845
if: ${{ steps.release.outputs.releases_created == 'true' }}
@@ -53,15 +70,31 @@ jobs:
5370
with:
5471
password: ${{env.PYPI_AUTH_TOKEN}}
5572

56-
release-provenance:
57-
needs: ["release-package"]
73+
- name: Generate checksums file
74+
if: ${{ steps.release.outputs.releases_created == 'true' }}
75+
env:
76+
HASHES: ${{ steps.build.outputs.package-hashes }}
77+
run: |
78+
echo "$HASHES" | base64 -d > checksums.txt
79+
80+
- name: Attest build provenance
81+
if: ${{ steps.release.outputs.releases_created == 'true' }}
82+
uses: actions/attest@v4
83+
with:
84+
subject-checksums: checksums.txt
85+
86+
publish-release:
87+
needs: ['release-package']
5888
if: ${{ needs.release-package.outputs.release-created == 'true' }}
89+
runs-on: ubuntu-latest
5990
permissions:
60-
actions: read
61-
id-token: write
6291
contents: write
63-
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@5a775b367a56d5bd118a224a811bba288150a563 # v2.0.0
64-
with:
65-
base64-subjects: "${{ needs.release-package.outputs.package-hashes }}"
66-
upload-assets: true
67-
upload-tag-name: ${{ needs.release-package.outputs.upload-tag-name }}
92+
steps:
93+
- name: Publish release
94+
env:
95+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
96+
TAG_NAME: ${{ needs.release-package.outputs.upload-tag-name }}
97+
run: >
98+
gh release edit "$TAG_NAME"
99+
--repo ${{ github.repository }}
100+
--draft=false

release-please-config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"ldclient/version.py",
99
"PROVENANCE.md"
1010
],
11-
"include-component-in-tag": false
11+
"include-component-in-tag": false,
12+
"draft": true
1213
}
1314
}
1415
}

0 commit comments

Comments
 (0)