Skip to content

Commit dc6d5fd

Browse files
CI: Update build/test/release workflows
Signed-off-by: ModeSevenIndustrialSolutions <mwatkins@linuxfoundation.org>
1 parent 99bda82 commit dc6d5fd

File tree

2 files changed

+165
-25
lines changed

2 files changed

+165
-25
lines changed

.github/workflows/build-test-release.yaml

Lines changed: 124 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,18 @@ jobs:
2323
timeout-minutes: 1
2424
outputs:
2525
tag: "${{ steps.tag-validate.outputs.tag }}"
26+
should_promote: "${{ steps.check-release.outputs.should_promote }}"
2627
steps:
2728
# Harden the runner used by this workflow
2829
# yamllint disable-line rule:line-length
29-
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
30+
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
3031
with:
3132
egress-policy: 'audit'
3233

3334
- name: 'Verify Pushed Tag'
3435
id: 'tag-validate'
3536
# yamllint disable-line rule:line-length
36-
uses: lfreleng-actions/tag-push-verify-action@80e2bdbbb9ee7b67557a31705892b75e75d2859e # v0.1.1
37+
uses: lfreleng-actions/tag-push-verify-action@80e2bdbbb9ee7b67557a31705892b75e75d2859e # v0.1.1
3738
with:
3839
versioning: 'semver'
3940

@@ -47,6 +48,32 @@ jobs:
4748
>> "$GITHUB_STEP_SUMMARY"
4849
exit 1
4950
51+
- name: 'Check if release exists'
52+
id: 'check-release'
53+
shell: bash
54+
env:
55+
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
56+
run: |
57+
TAG="${{ steps.tag-validate.outputs.tag }}"
58+
59+
# Check if release exists and get its draft status
60+
if RELEASE_INFO=$(gh release view "$TAG" --json isDraft \
61+
2>/dev/null); then
62+
IS_DRAFT=$(echo "$RELEASE_INFO" | jq -r '.isDraft')
63+
if [ "$IS_DRAFT" = "false" ]; then
64+
echo "should_promote=false" >> "$GITHUB_OUTPUT"
65+
echo "Published release already exists for tag $TAG, " \
66+
"skipping promotion"
67+
else
68+
echo "should_promote=true" >> "$GITHUB_OUTPUT"
69+
echo "Draft release exists for tag $TAG, " \
70+
"will proceed with promotion"
71+
fi
72+
else
73+
echo "should_promote=true" >> "$GITHUB_OUTPUT"
74+
echo "No release found for tag $TAG, will proceed with promotion"
75+
fi
76+
5077
python-build:
5178
name: 'Python Build'
5279
needs: 'tag-validate'
@@ -65,17 +92,17 @@ jobs:
6592
steps:
6693
# Harden the runner used by this workflow
6794
# yamllint disable-line rule:line-length
68-
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
95+
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
6996
with:
7097
egress-policy: 'audit'
7198

7299
# yamllint disable-line rule:line-length
73-
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
100+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
74101

75102
- name: 'Build Python project'
76103
id: 'python-build'
77104
# yamllint disable-line rule:line-length
78-
uses: lfreleng-actions/python-build-action@48381cece78a990a6ba93bd5924bcd40bf0d1a7d # v0.1.20
105+
uses: lfreleng-actions/python-build-action@48381cece78a990a6ba93bd5924bcd40bf0d1a7d # v0.1.20
79106
with:
80107
sigstore_sign: true
81108
attestations: true
@@ -94,16 +121,16 @@ jobs:
94121
steps:
95122
# Harden the runner used by this workflow
96123
# yamllint disable-line rule:line-length
97-
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
124+
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
98125
with:
99126
egress-policy: 'audit'
100127

101128
# yamllint disable-line rule:line-length
102-
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
129+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
103130

104131
- name: 'Test Python project [PYTEST]'
105132
# yamllint disable-line rule:line-length
106-
uses: lfreleng-actions/python-test-action@bdde9e4e6221e858359f9036bd4f41ab3b1af90e # v0.1.11
133+
uses: lfreleng-actions/python-test-action@bdde9e4e6221e858359f9036bd4f41ab3b1af90e # v0.1.11
107134
with:
108135
python_version: "${{ matrix.python-version }}"
109136

@@ -121,19 +148,60 @@ jobs:
121148
steps:
122149
# Harden the runner used by this workflow
123150
# yamllint disable-line rule:line-length
124-
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
151+
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
125152
with:
126153
egress-policy: 'audit'
127154

128155
# yamllint disable-line rule:line-length
129-
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
156+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
130157

131158
- name: 'Audit Python project'
132159
# yamllint disable-line rule:line-length
133-
uses: lfreleng-actions/python-audit-action@bab5316468c108870eb759ef0de622bae9239aad # v0.2.2
160+
uses: lfreleng-actions/python-audit-action@bab5316468c108870eb759ef0de622bae9239aad # v0.2.2
134161
with:
135162
python_version: "${{ matrix.python-version }}"
136163

164+
sbom:
165+
name: 'Generate SBOM'
166+
runs-on: ubuntu-latest
167+
needs: 'python-build'
168+
timeout-minutes: 10
169+
permissions:
170+
contents: read
171+
steps:
172+
# yamllint disable-line rule:line-length
173+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
174+
175+
- name: "Generate SBOM"
176+
id: sbom
177+
# yamllint disable-line rule:line-length
178+
uses: lfreleng-actions/python-sbom-action@ae4aca2ef28d7da4ec95049cc78be43e632d322a # v0.1.0
179+
with:
180+
include_dev: "false"
181+
sbom_format: "both"
182+
183+
- name: "Upload SBOM artifacts"
184+
# yamllint disable-line rule:line-length
185+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
186+
with:
187+
name: sbom-files
188+
path: |
189+
sbom-cyclonedx.json
190+
sbom-cyclonedx.xml
191+
retention-days: 45
192+
193+
- name: "Security scan with Grype"
194+
# yamllint disable-line rule:line-length
195+
uses: anchore/scan-action@f6601287cdb1efc985d6b765bbf99cb4c0ac29d8 # v7.0.0
196+
with:
197+
sbom: "${{ steps.sbom.outputs.sbom_json_path }}"
198+
199+
- name: "Summary step"
200+
run: |
201+
# Summary step
202+
echo "SBOM count: ${{ steps.sbom.outputs.component_count }}"
203+
echo "Tool used: ${{ steps.sbom.outputs.dependency_manager }}"
204+
137205
test-pypi:
138206
name: 'Test PyPI Publishing'
139207
runs-on: 'ubuntu-latest'
@@ -150,20 +218,20 @@ jobs:
150218
steps:
151219
# Harden the runner used by this workflow
152220
# yamllint disable-line rule:line-length
153-
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
221+
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
154222
with:
155223
egress-policy: 'audit'
156224

157225
# yamllint disable-line rule:line-length
158-
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
226+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
159227

160228
- name: 'Test PyPI publishing'
161229
# yamllint disable-line rule:line-length
162-
uses: lfreleng-actions/pypi-publish-action@81a056957ed050f8305760055b1fd8103a916989 # v0.1.1
230+
uses: lfreleng-actions/pypi-publish-action@81a056957ed050f8305760055b1fd8103a916989 # v0.1.1
163231
with:
164232
environment: 'development'
165233
tag: "${{ needs.tag-validate.outputs.tag }}"
166-
pypi_credential: "${{ secrets.PYPI_CREDENTIAL }}"
234+
pypi_credential: "${{ secrets.TEST_PYPI_CREDENTIAL }}"
167235

168236
pypi:
169237
name: 'Release PyPI Package'
@@ -180,26 +248,27 @@ jobs:
180248
steps:
181249
# Harden the runner used by this workflow
182250
# yamllint disable-line rule:line-length
183-
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
251+
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
184252
with:
185253
egress-policy: 'audit'
186254

187255
# yamllint disable-line rule:line-length
188-
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
256+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
189257

190258
- name: 'PyPI release'
191259
# yamllint disable-line rule:line-length
192-
uses: lfreleng-actions/pypi-publish-action@81a056957ed050f8305760055b1fd8103a916989 # v0.1.1
260+
uses: lfreleng-actions/pypi-publish-action@81a056957ed050f8305760055b1fd8103a916989 # v0.1.1
193261
with:
194262
environment: 'production'
195263
attestations: true
196264
tag: "${{ needs.tag-validate.outputs.tag }}"
197265
pypi_credential: "${{ secrets.PYPI_CREDENTIAL }}"
198266

267+
199268
promote-release:
200269
name: 'Promote Draft Release'
201270
# yamllint disable-line rule:line-length
202-
if: startsWith(github.ref, 'refs/tags/')
271+
if: needs.tag-validate.outputs.should_promote == 'true'
203272
needs:
204273
- 'tag-validate'
205274
- 'pypi'
@@ -212,22 +281,50 @@ jobs:
212281
steps:
213282
# Harden the runner used by this workflow
214283
# yamllint disable-line rule:line-length
215-
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
284+
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
216285
with:
217286
egress-policy: 'audit'
218287

219288
# yamllint disable-line rule:line-length
220-
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
289+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
290+
291+
- name: 'Check if release is already promoted'
292+
id: 'check-promoted'
293+
shell: bash
294+
env:
295+
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
296+
run: |
297+
TAG="${{ needs.tag-validate.outputs.tag }}"
298+
if gh release view "$TAG" --json isDraft --jq '.isDraft' \
299+
2>/dev/null | grep -q "false"; then
300+
echo "Release $TAG is already promoted, skipping promotion"
301+
echo "already_promoted=true" >> "$GITHUB_OUTPUT"
302+
else
303+
echo "Release $TAG is draft or doesn't exist, " \
304+
"proceeding with promotion"
305+
echo "already_promoted=false" >> "$GITHUB_OUTPUT"
306+
fi
221307
222308
- name: 'Promote draft release'
223309
id: 'promote-release'
310+
if: steps.check-promoted.outputs.already_promoted == 'false'
224311
# yamllint disable-line rule:line-length
225-
uses: lfreleng-actions/draft-release-promote-action@d7e7df12e32fa26b28dbc2f18a12766482785399 # v0.1.2
312+
uses: lfreleng-actions/draft-release-promote-action@d7e7df12e32fa26b28dbc2f18a12766482785399 # v0.1.2
226313
with:
227314
token: "${{ secrets.GITHUB_TOKEN }}"
228315
tag: "${{ needs.tag-validate.outputs.tag }}"
229316
latest: true
230317

318+
- name: 'Set release URL for already promoted release'
319+
if: steps.check-promoted.outputs.already_promoted == 'true'
320+
shell: bash
321+
env:
322+
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
323+
run: |
324+
TAG="${{ needs.tag-validate.outputs.tag }}"
325+
RELEASE_URL=$(gh release view "$TAG" --json url --jq '.url')
326+
echo "release_url=$RELEASE_URL" >> "$GITHUB_OUTPUT"
327+
231328
# Need to attach build artefacts to the release
232329
# This step could potentially be moved
233330
# (May be better to when/where the release is still in draft state)
@@ -238,28 +335,30 @@ jobs:
238335
- 'tag-validate'
239336
- 'python-build'
240337
- 'promote-release'
338+
# yamllint disable-line rule:line-length
339+
if: always() && (needs.promote-release.result == 'success' || needs.promote-release.result == 'skipped')
241340
permissions:
242341
contents: write # IMPORTANT: needed to edit release, attach artefacts
243342
timeout-minutes: 5
244343
steps:
245344
# Harden the runner used by this workflow
246345
# yamllint disable-line rule:line-length
247-
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
346+
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
248347
with:
249348
egress-policy: 'audit'
250349

251350
# Note: no need for a checkout step in this job
252351

253352
- name: '⬇ Download build artefacts'
254353
# yamllint disable-line rule:line-length
255-
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
354+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
256355
with:
257356
name: "${{ needs.python-build.outputs.artefact_name }}"
258357
path: "${{ needs.python-build.outputs.artefact_path }}"
259358

260359
- name: 'Attach build artefacts to release'
261360
# yamllint disable-line rule:line-length
262-
uses: alexellis/upload-assets@13926a61cdb2cb35f5fdef1c06b8b591523236d3 # 0.4.1
361+
uses: alexellis/upload-assets@13926a61cdb2cb35f5fdef1c06b8b591523236d3 # 0.4.1
263362
env:
264363
GITHUB_TOKEN: "${{ github.token }}"
265364
with:

.github/workflows/build-test.yaml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,44 @@ jobs:
106106
uses: lfreleng-actions/python-audit-action@bab5316468c108870eb759ef0de622bae9239aad # v0.2.2
107107
with:
108108
python_version: "${{ matrix.python-version }}"
109+
110+
sbom:
111+
name: 'Generate SBOM'
112+
runs-on: ubuntu-latest
113+
needs: 'python-build'
114+
timeout-minutes: 10
115+
permissions:
116+
contents: read
117+
steps:
118+
# yamllint disable-line rule:line-length
119+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
120+
121+
- name: "Generate SBOM"
122+
id: sbom
123+
# yamllint disable-line rule:line-length
124+
uses: lfreleng-actions/python-sbom-action@ae4aca2ef28d7da4ec95049cc78be43e632d322a # v0.1.0
125+
with:
126+
include_dev: "false"
127+
sbom_format: "both"
128+
129+
- name: "Upload SBOM artifacts"
130+
# yamllint disable-line rule:line-length
131+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
132+
with:
133+
name: sbom-files
134+
path: |
135+
sbom-cyclonedx.json
136+
sbom-cyclonedx.xml
137+
retention-days: 45
138+
139+
- name: "Security scan with Grype"
140+
# yamllint disable-line rule:line-length
141+
uses: anchore/scan-action@f6601287cdb1efc985d6b765bbf99cb4c0ac29d8 # v7.0.0
142+
with:
143+
sbom: "${{ steps.sbom.outputs.sbom_json_path }}"
144+
145+
- name: "Summary step"
146+
run: |
147+
# Summary step
148+
echo "SBOM count: ${{ steps.sbom.outputs.component_count }}"
149+
echo "Tool used: ${{ steps.sbom.outputs.dependency_manager }}"

0 commit comments

Comments
 (0)