Skip to content

Commit 5f2a68d

Browse files
committed
ci: use draft releases to support immutable GitHub releases
1 parent 53fd95e commit 5f2a68d

2 files changed

Lines changed: 161 additions & 58 deletions

File tree

.github/workflows/release-please.yml

Lines changed: 157 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,29 @@ jobs:
5858
needs: ['release-please']
5959
permissions:
6060
id-token: write # Needed for OIDC to get release secrets from AWS.
61+
attestations: write # Needed for actions/attest.
62+
contents: write # Needed for creating tags.
6163
if: ${{ needs.release-please.outputs.package-server-ai-released == 'true' }}
62-
outputs:
63-
package-hashes: ${{ steps.build.outputs.package-hashes }}
6464
steps:
6565
- uses: actions/checkout@v4
6666
with:
6767
fetch-depth: 0
6868

69+
- name: Create release tag
70+
env:
71+
TAG_NAME: ${{ needs.release-please.outputs.package-server-ai-tag-name }}
72+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
73+
run: |
74+
if gh api "repos/${{ github.repository }}/git/ref/tags/${TAG_NAME}" >/dev/null 2>&1; then
75+
echo "Tag ${TAG_NAME} already exists, skipping creation."
76+
else
77+
echo "Creating tag ${TAG_NAME}."
78+
git config user.name "github-actions[bot]"
79+
git config user.email "github-actions[bot]@users.noreply.github.com"
80+
git tag "${TAG_NAME}"
81+
git push origin "${TAG_NAME}"
82+
fi
83+
6984
- uses: ./.github/actions/ci
7085
with:
7186
workspace_path: packages/sdk/server-ai
@@ -75,6 +90,17 @@ jobs:
7590
with:
7691
workspace_path: packages/sdk/server-ai
7792

93+
- name: Generate checksums file
94+
env:
95+
HASHES: ${{ steps.build.outputs.package-hashes }}
96+
run: |
97+
echo "$HASHES" | base64 -d > checksums.txt
98+
99+
- name: Attest build provenance
100+
uses: actions/attest@v4
101+
with:
102+
subject-checksums: checksums.txt
103+
78104
- uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0
79105
name: 'Get PyPI token'
80106
with:
@@ -92,14 +118,29 @@ jobs:
92118
needs: ['release-please']
93119
permissions:
94120
id-token: write # Needed for OIDC to get release secrets from AWS.
121+
attestations: write # Needed for actions/attest.
122+
contents: write # Needed for creating tags.
95123
if: ${{ needs.release-please.outputs.package-server-ai-langchain-released == 'true' }}
96-
outputs:
97-
package-hashes: ${{ steps.build.outputs.package-hashes }}
98124
steps:
99125
- uses: actions/checkout@v4
100126
with:
101127
fetch-depth: 0
102128

129+
- name: Create release tag
130+
env:
131+
TAG_NAME: ${{ needs.release-please.outputs.package-server-ai-langchain-tag-name }}
132+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
133+
run: |
134+
if gh api "repos/${{ github.repository }}/git/ref/tags/${TAG_NAME}" >/dev/null 2>&1; then
135+
echo "Tag ${TAG_NAME} already exists, skipping creation."
136+
else
137+
echo "Creating tag ${TAG_NAME}."
138+
git config user.name "github-actions[bot]"
139+
git config user.email "github-actions[bot]@users.noreply.github.com"
140+
git tag "${TAG_NAME}"
141+
git push origin "${TAG_NAME}"
142+
fi
143+
103144
- uses: ./.github/actions/ci
104145
with:
105146
workspace_path: packages/ai-providers/server-ai-langchain
@@ -109,6 +150,17 @@ jobs:
109150
with:
110151
workspace_path: packages/ai-providers/server-ai-langchain
111152

153+
- name: Generate checksums file
154+
env:
155+
HASHES: ${{ steps.build.outputs.package-hashes }}
156+
run: |
157+
echo "$HASHES" | base64 -d > checksums.txt
158+
159+
- name: Attest build provenance
160+
uses: actions/attest@v4
161+
with:
162+
subject-checksums: checksums.txt
163+
112164
- uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0
113165
name: 'Get PyPI token'
114166
with:
@@ -153,45 +205,34 @@ jobs:
153205
password: ${{ env.PYPI_AUTH_TOKEN }}
154206
packages-dir: ${{ inputs.workspace_path }}/dist/
155207

156-
release-server-ai-provenance:
157-
needs: ['release-please', 'release-server-ai']
158-
if: ${{ needs.release-please.outputs.package-server-ai-released == 'true' }}
159-
permissions:
160-
actions: read # Needed for detecting the GitHub Actions environment.
161-
id-token: write # Needed for provenance signing.
162-
contents: write # Needed for uploading assets to the release.
163-
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
164-
with:
165-
base64-subjects: "${{ needs.release-server-ai.outputs.package-hashes }}"
166-
upload-assets: true
167-
upload-tag-name: ${{ needs.release-please.outputs.package-server-ai-tag-name }}
168-
169-
release-server-ai-langchain-provenance:
170-
needs: ['release-please', 'release-server-ai-langchain']
171-
if: ${{ needs.release-please.outputs.package-server-ai-langchain-released == 'true' }}
172-
permissions:
173-
actions: read # Needed for detecting the GitHub Actions environment.
174-
id-token: write # Needed for provenance signing.
175-
contents: write # Needed for uploading assets to the release.
176-
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@5a775b367a56d5bd118a224a811bba288150a563 # v2.0.0
177-
with:
178-
base64-subjects: "${{ needs.release-server-ai-langchain.outputs.package-hashes }}"
179-
upload-assets: true
180-
upload-tag-name: ${{ needs.release-please.outputs.package-server-ai-langchain-tag-name }}
181-
182208
release-server-ai-openai:
183209
runs-on: ubuntu-latest
184210
needs: ['release-please']
185211
permissions:
186212
id-token: write # Needed for OIDC to get release secrets from AWS.
213+
attestations: write # Needed for actions/attest.
214+
contents: write # Needed for creating tags.
187215
if: ${{ needs.release-please.outputs.package-server-ai-openai-released == 'true' }}
188-
outputs:
189-
package-hashes: ${{ steps.build.outputs.package-hashes }}
190216
steps:
191217
- uses: actions/checkout@v4
192218
with:
193219
fetch-depth: 0
194220

221+
- name: Create release tag
222+
env:
223+
TAG_NAME: ${{ needs.release-please.outputs.package-server-ai-openai-tag-name }}
224+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
225+
run: |
226+
if gh api "repos/${{ github.repository }}/git/ref/tags/${TAG_NAME}" >/dev/null 2>&1; then
227+
echo "Tag ${TAG_NAME} already exists, skipping creation."
228+
else
229+
echo "Creating tag ${TAG_NAME}."
230+
git config user.name "github-actions[bot]"
231+
git config user.email "github-actions[bot]@users.noreply.github.com"
232+
git tag "${TAG_NAME}"
233+
git push origin "${TAG_NAME}"
234+
fi
235+
195236
- uses: ./.github/actions/ci
196237
with:
197238
workspace_path: packages/ai-providers/server-ai-openai
@@ -201,6 +242,17 @@ jobs:
201242
with:
202243
workspace_path: packages/ai-providers/server-ai-openai
203244

245+
- name: Generate checksums file
246+
env:
247+
HASHES: ${{ steps.build.outputs.package-hashes }}
248+
run: |
249+
echo "$HASHES" | base64 -d > checksums.txt
250+
251+
- name: Attest build provenance
252+
uses: actions/attest@v4
253+
with:
254+
subject-checksums: checksums.txt
255+
204256
- uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0
205257
name: 'Get PyPI token'
206258
with:
@@ -213,32 +265,34 @@ jobs:
213265
password: ${{ env.PYPI_AUTH_TOKEN }}
214266
packages-dir: packages/ai-providers/server-ai-openai/dist/
215267

216-
release-server-ai-openai-provenance:
217-
needs: ['release-please', 'release-server-ai-openai']
218-
if: ${{ needs.release-please.outputs.package-server-ai-openai-released == 'true' }}
219-
permissions:
220-
actions: read # Needed for detecting the GitHub Actions environment.
221-
id-token: write # Needed for provenance signing.
222-
contents: write # Needed for uploading assets to the release.
223-
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
224-
with:
225-
base64-subjects: "${{ needs.release-server-ai-openai.outputs.package-hashes }}"
226-
upload-assets: true
227-
upload-tag-name: ${{ needs.release-please.outputs.package-server-ai-openai-tag-name }}
228-
229268
release-server-ai-optimization:
230269
runs-on: ubuntu-latest
231270
needs: ['release-please']
232271
permissions:
233272
id-token: write # Needed for OIDC to get release secrets from AWS.
273+
attestations: write # Needed for actions/attest.
274+
contents: write # Needed for creating tags.
234275
if: ${{ needs.release-please.outputs.package-server-ai-optimization-released == 'true' }}
235-
outputs:
236-
package-hashes: ${{ steps.build.outputs.package-hashes }}
237276
steps:
238277
- uses: actions/checkout@v4
239278
with:
240279
fetch-depth: 0
241280

281+
- name: Create release tag
282+
env:
283+
TAG_NAME: ${{ needs.release-please.outputs.package-server-ai-optimization-tag-name }}
284+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
285+
run: |
286+
if gh api "repos/${{ github.repository }}/git/ref/tags/${TAG_NAME}" >/dev/null 2>&1; then
287+
echo "Tag ${TAG_NAME} already exists, skipping creation."
288+
else
289+
echo "Creating tag ${TAG_NAME}."
290+
git config user.name "github-actions[bot]"
291+
git config user.email "github-actions[bot]@users.noreply.github.com"
292+
git tag "${TAG_NAME}"
293+
git push origin "${TAG_NAME}"
294+
fi
295+
242296
- uses: ./.github/actions/ci
243297
with:
244298
workspace_path: packages/optimization
@@ -248,6 +302,17 @@ jobs:
248302
with:
249303
workspace_path: packages/optimization
250304

305+
- name: Generate checksums file
306+
env:
307+
HASHES: ${{ steps.build.outputs.package-hashes }}
308+
run: |
309+
echo "$HASHES" | base64 -d > checksums.txt
310+
311+
- name: Attest build provenance
312+
uses: actions/attest@v4
313+
with:
314+
subject-checksums: checksums.txt
315+
251316
- uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0
252317
name: 'Get PyPI token'
253318
with:
@@ -260,15 +325,49 @@ jobs:
260325
password: ${{ env.PYPI_AUTH_TOKEN }}
261326
packages-dir: packages/optimization/dist/
262327

263-
release-server-ai-optimization-provenance:
264-
needs: ['release-please', 'release-server-ai-optimization']
265-
if: ${{ needs.release-please.outputs.package-server-ai-optimization-released == 'true' }}
328+
publish-release:
329+
needs: ['release-please', 'release-server-ai', 'release-server-ai-langchain', 'release-server-ai-openai', 'release-server-ai-optimization']
330+
if: ${{ always() && needs.release-please.result == 'success' && (needs.release-please.outputs.package-server-ai-released == 'true' || needs.release-please.outputs.package-server-ai-langchain-released == 'true' || needs.release-please.outputs.package-server-ai-openai-released == 'true' || needs.release-please.outputs.package-server-ai-optimization-released == 'true') }}
331+
runs-on: ubuntu-latest
266332
permissions:
267-
actions: read # Needed for detecting the GitHub Actions environment.
268-
id-token: write # Needed for provenance signing.
269-
contents: write # Needed for uploading assets to the release.
270-
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
271-
with:
272-
base64-subjects: "${{ needs.release-server-ai-optimization.outputs.package-hashes }}"
273-
upload-assets: true
274-
upload-tag-name: ${{ needs.release-please.outputs.package-server-ai-optimization-tag-name }}
333+
contents: write
334+
steps:
335+
- name: Publish server-ai release
336+
if: ${{ needs.release-please.outputs.package-server-ai-released == 'true' && needs.release-server-ai.result == 'success' }}
337+
env:
338+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
339+
TAG_NAME: ${{ needs.release-please.outputs.package-server-ai-tag-name }}
340+
run: >
341+
gh release edit "$TAG_NAME"
342+
--repo ${{ github.repository }}
343+
--draft=false
344+
345+
- name: Publish server-ai-langchain release
346+
if: ${{ needs.release-please.outputs.package-server-ai-langchain-released == 'true' && needs.release-server-ai-langchain.result == 'success' }}
347+
env:
348+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
349+
TAG_NAME: ${{ needs.release-please.outputs.package-server-ai-langchain-tag-name }}
350+
run: >
351+
gh release edit "$TAG_NAME"
352+
--repo ${{ github.repository }}
353+
--draft=false
354+
355+
- name: Publish server-ai-openai release
356+
if: ${{ needs.release-please.outputs.package-server-ai-openai-released == 'true' && needs.release-server-ai-openai.result == 'success' }}
357+
env:
358+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
359+
TAG_NAME: ${{ needs.release-please.outputs.package-server-ai-openai-tag-name }}
360+
run: >
361+
gh release edit "$TAG_NAME"
362+
--repo ${{ github.repository }}
363+
--draft=false
364+
365+
- name: Publish server-ai-optimization release
366+
if: ${{ needs.release-please.outputs.package-server-ai-optimization-released == 'true' && needs.release-server-ai-optimization.result == 'success' }}
367+
env:
368+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
369+
TAG_NAME: ${{ needs.release-please.outputs.package-server-ai-optimization-tag-name }}
370+
run: >
371+
gh release edit "$TAG_NAME"
372+
--repo ${{ github.repository }}
373+
--draft=false

release-please-config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"versioning": "default",
88
"bump-minor-pre-major": true,
99
"include-v-in-tag": false,
10+
"draft": true,
1011
"extra-files": ["src/ldai/__init__.py", "PROVENANCE.md"],
1112
"component": "launchdarkly-server-sdk-ai"
1213
},
@@ -15,6 +16,7 @@
1516
"versioning": "default",
1617
"bump-minor-pre-major": true,
1718
"include-v-in-tag": false,
19+
"draft": true,
1820
"extra-files": ["src/ldai_langchain/__init__.py"],
1921
"component": "launchdarkly-server-sdk-ai-langchain"
2022
},
@@ -23,6 +25,7 @@
2325
"versioning": "default",
2426
"bump-minor-pre-major": true,
2527
"include-v-in-tag": false,
28+
"draft": true,
2629
"extra-files": ["src/ldai_openai/__init__.py"],
2730
"component": "launchdarkly-server-sdk-ai-openai"
2831
},
@@ -31,6 +34,7 @@
3134
"versioning": "default",
3235
"bump-minor-pre-major": true,
3336
"include-v-in-tag": false,
37+
"draft": true,
3438
"extra-files": ["src/ldai_optimization/__init__.py"],
3539
"component": "launchdarkly-server-sdk-ai-optimization"
3640
}

0 commit comments

Comments
 (0)