Skip to content

Commit 7fdd61a

Browse files
authored
chore: Bump stackabletech/actions to v0.16.0 and add SLSA provenance (#1559)
* chore: Bump stackabletech/actions to v0.16.0 * feat: generate SLSA provenance for product images * docs: Add changelog entries for actions bump and SLSA provenance
1 parent 46ad345 commit 7fdd61a

5 files changed

Lines changed: 132 additions & 15 deletions

File tree

.github/workflows/mirror.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ jobs:
7373
7474
- name: Publish Container Image on oci.stackable.tech/sdp
7575
if: inputs.destination-project == 'sdp'
76-
uses: stackabletech/actions/publish-image@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
76+
uses: stackabletech/actions/publish-image@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
7777
with:
7878
image-registry-uri: oci.stackable.tech
7979
image-registry-username: robot$sdp+github-action-build
@@ -84,7 +84,7 @@ jobs:
8484

8585
- name: Publish Container Image on oci.stackable.tech/stackable
8686
if: inputs.destination-project == 'stackable'
87-
uses: stackabletech/actions/publish-image@8a8085be0a8cec3d24ad3970e602d65be487da6a # v0.14.1
87+
uses: stackabletech/actions/publish-image@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
8888
with:
8989
image-registry-uri: oci.stackable.tech
9090
image-registry-username: robot$stackable+github-action-build
@@ -113,7 +113,7 @@ jobs:
113113
114114
- name: Publish and Sign Image Index Manifest to oci.stackable.tech/sdp
115115
if: inputs.destination-project == 'sdp'
116-
uses: stackabletech/actions/publish-image-index-manifest@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
116+
uses: stackabletech/actions/publish-image-index-manifest@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
117117
with:
118118
image-registry-uri: oci.stackable.tech
119119
image-registry-username: robot$sdp+github-action-build
@@ -123,7 +123,7 @@ jobs:
123123

124124
- name: Publish and Sign Image Index Manifest to oci.stackable.tech/stackable
125125
if: inputs.destination-project == 'stackable'
126-
uses: stackabletech/actions/publish-image-index-manifest@8a8085be0a8cec3d24ad3970e602d65be487da6a # v0.14.1
126+
uses: stackabletech/actions/publish-image-index-manifest@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
127127
with:
128128
image-registry-uri: oci.stackable.tech
129129
image-registry-username: robot$stackable+github-action-build

.github/workflows/pr_pre-commit.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
persist-credentials: false
2323
fetch-depth: 0
2424

25-
- uses: stackabletech/actions/run-pre-commit@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
25+
- uses: stackabletech/actions/run-pre-commit@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
2626
with:
2727
python-version: ${{ env.PYTHON_VERSION }}
2828
rust: ${{ env.RUST_TOOLCHAIN_VERSION }}

.github/workflows/reusable_build_image.yaml

Lines changed: 122 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ jobs:
8888
persist-credentials: false
8989

9090
- id: shard
91-
uses: stackabletech/actions/shard@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
91+
uses: stackabletech/actions/shard@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
9292
with:
9393
product-name: ${{ inputs.product-name }}
9494
boil-version: 0.2.2
@@ -116,11 +116,11 @@ jobs:
116116
persist-credentials: false
117117

118118
- name: Free Disk Space
119-
uses: stackabletech/actions/free-disk-space@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
119+
uses: stackabletech/actions/free-disk-space@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
120120

121121
- name: Build Product Image
122122
id: build
123-
uses: stackabletech/actions/build-product-image@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
123+
uses: stackabletech/actions/build-product-image@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
124124
with:
125125
registry-namespace: ${{ inputs.registry-namespace }}
126126
product-name: ${{ inputs.product-name }}
@@ -130,7 +130,7 @@ jobs:
130130

131131
- name: Publish Container Image on oci.stackable.tech
132132
if: inputs.publish
133-
uses: stackabletech/actions/publish-image@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
133+
uses: stackabletech/actions/publish-image@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
134134
with:
135135
image-registry-uri: oci.stackable.tech
136136
image-registry-username: robot$${{ inputs.registry-namespace }}+github-action-build
@@ -146,7 +146,7 @@ jobs:
146146

147147
- name: Publish Container Image on quay.io
148148
if: inputs.publish && inputs.publish-to-quay
149-
uses: stackabletech/actions/publish-image@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
149+
uses: stackabletech/actions/publish-image@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
150150
with:
151151
image-registry-uri: quay.io
152152
image-registry-username: stackable+robot_${{ inputs.registry-namespace }}_github_action_build
@@ -178,8 +178,9 @@ jobs:
178178
persist-credentials: false
179179

180180
- name: Publish and Sign Image Index Manifest to oci.stackable.tech
181+
id: publish-oci
181182
if: inputs.publish
182-
uses: stackabletech/actions/publish-image-index-manifest@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
183+
uses: stackabletech/actions/publish-image-index-manifest@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
183184
with:
184185
image-registry-uri: oci.stackable.tech
185186
image-registry-username: robot$${{ inputs.registry-namespace }}+github-action-build
@@ -193,8 +194,9 @@ jobs:
193194
image-index-manifest-tag: ${{ matrix.versions }}-stackable${{ inputs.sdp-version }}
194195

195196
- name: Publish and Sign Image Index Manifest to quay.io
197+
id: publish-quay
196198
if: inputs.publish && inputs.publish-to-quay
197-
uses: stackabletech/actions/publish-image-index-manifest@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
199+
uses: stackabletech/actions/publish-image-index-manifest@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
198200
with:
199201
image-registry-uri: quay.io
200202
image-registry-username: stackable+robot_${{ inputs.registry-namespace }}_github_action_build
@@ -207,16 +209,127 @@ jobs:
207209
image-repository: stackable/${{ inputs.registry-namespace }}/${{ inputs.image-name || inputs.product-name }}
208210
image-index-manifest-tag: ${{ matrix.versions }}-stackable${{ inputs.sdp-version }}
209211

212+
# Record the pushed index manifest digest(s) for this matrix version so the
213+
# provenance jobs can pick them up. Matrix jobs cannot expose per-version
214+
# outputs (they overwrite each other), so we pass the digests through
215+
# artifacts instead.
216+
- name: Record image index digests for provenance
217+
if: inputs.publish
218+
shell: bash
219+
env:
220+
VERSION: ${{ matrix.versions }}
221+
OCI_DIGEST: ${{ steps.publish-oci.outputs.image-index-manifest-digest }}
222+
QUAY_DIGEST: ${{ steps.publish-quay.outputs.image-index-manifest-digest }}
223+
run: |
224+
set -euo pipefail
225+
jq -n \
226+
--arg version "$VERSION" \
227+
--arg oci "$OCI_DIGEST" \
228+
--arg quay "$QUAY_DIGEST" \
229+
'{version: $version, oci_digest: $oci, quay_digest: $quay}' > digests.json
230+
231+
- name: Upload provenance digests
232+
if: inputs.publish
233+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
234+
with:
235+
name: provenance-digests-${{ matrix.versions }}
236+
path: digests.json
237+
retention-days: 1
238+
239+
# Collect the per-version index manifest digests uploaded by publish_manifests
240+
# and turn them into a matrix (one entry per version and registry) for the
241+
# provenance job. This is needed because a matrix job cannot expose per-leg
242+
# outputs directly.
243+
collect-provenance-matrix:
244+
name: Collect Provenance Matrix
245+
if: inputs.publish
246+
needs: [publish_manifests]
247+
permissions:
248+
contents: read
249+
runs-on: ubuntu-latest
250+
outputs:
251+
matrix: ${{ steps.build-matrix.outputs.matrix }}
252+
has-entries: ${{ steps.build-matrix.outputs.has_entries }}
253+
steps:
254+
- name: Download provenance digests
255+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
256+
with:
257+
pattern: provenance-digests-*
258+
path: artifacts
259+
260+
- name: Build provenance matrix
261+
id: build-matrix
262+
shell: bash
263+
env:
264+
REGISTRY_NAMESPACE: ${{ inputs.registry-namespace }}
265+
PRODUCT_NAME: ${{ inputs.product-name }}
266+
IMAGE_NAME: ${{ inputs.image-name }}
267+
run: |
268+
set -euo pipefail
269+
IMAGE="${IMAGE_NAME:-$PRODUCT_NAME}"
270+
271+
# Build a JSON matrix include array. Each version contributes one entry
272+
# for oci.stackable.tech and, if a quay digest was recorded, one for
273+
# quay.io. The slsa generator attaches provenance by digest, so no tag
274+
# is needed in the image reference.
275+
INCLUDE=$(jq -c -s \
276+
--arg ns "$REGISTRY_NAMESPACE" \
277+
--arg img "$IMAGE" '
278+
[ .[]
279+
| ( { registry: "oci.stackable.tech",
280+
image: ("oci.stackable.tech/" + $ns + "/" + $img),
281+
digest: .oci_digest,
282+
username: ("robot$" + $ns + "+github-action-build") } ),
283+
( if (.quay_digest // "") != ""
284+
then { registry: "quay.io",
285+
image: ("quay.io/stackable/" + $ns + "/" + $img),
286+
digest: .quay_digest,
287+
username: ("stackable+robot_" + $ns + "_github_action_build") }
288+
else empty end )
289+
]' artifacts/*/digests.json)
290+
291+
echo "matrix={\"include\":$INCLUDE}" | tee -a "$GITHUB_OUTPUT"
292+
if [ "$INCLUDE" = "[]" ]; then
293+
echo "has_entries=false" | tee -a "$GITHUB_OUTPUT"
294+
else
295+
echo "has_entries=true" | tee -a "$GITHUB_OUTPUT"
296+
fi
297+
298+
# Generate SLSA build provenance for every published multi-arch image index
299+
# (one matrix entry per version and registry) and attach it to the image. The
300+
# reusable workflow signs the provenance with keyless signing (GitHub Actions
301+
# as the OIDC identity) and pushes the attestation next to the image.
302+
provenance:
303+
name: Generate Provenance (${{ matrix.image }}@${{ matrix.digest }})
304+
if: inputs.publish && needs.collect-provenance-matrix.outputs.has-entries == 'true'
305+
needs: [collect-provenance-matrix]
306+
permissions:
307+
actions: read # detect the build workflow that generated the image
308+
id-token: write # mint the OIDC token for keyless signing
309+
packages: write # needed until https://github.com/slsa-framework/slsa-github-generator/issues/1257 is resolved
310+
strategy:
311+
fail-fast: false
312+
matrix: ${{ fromJson(needs.collect-provenance-matrix.outputs.matrix) }}
313+
# MUST be referenced by a @vX.Y.Z tag (not a SHA), otherwise the reusable
314+
# workflow cannot verify its own provenance.
315+
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
316+
with:
317+
image: ${{ matrix.image }}
318+
digest: ${{ matrix.digest }}
319+
registry-username: ${{ matrix.username }}
320+
secrets:
321+
registry-password: ${{ matrix.registry == 'quay.io' && secrets.quay-robot-secret || secrets.harbor-robot-secret }}
322+
210323
notify:
211324
name: Failure Notification
212-
needs: [generate_version_dimension, build, publish_manifests]
325+
needs: [generate_version_dimension, build, publish_manifests, collect-provenance-matrix, provenance]
213326
runs-on: ubuntu-latest
214327
# TODO (@NickLarsenNZ): Allow a condition from input so that we can always
215328
# be notified of new builds for precompiled product images.
216329
if: failure() || (github.run_attempt > 1 && !cancelled())
217330
steps:
218331
- name: Send Notification
219-
uses: stackabletech/actions/send-slack-notification@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
332+
uses: stackabletech/actions/send-slack-notification@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
220333
with:
221334
publish-manifests-result: ${{ needs.publish_manifests.result }}
222335
build-result: ${{ needs.build.result }}

.github/workflows/ubi-rust-builder.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ jobs:
123123
if: failure() || (github.run_attempt > 1 && !cancelled())
124124
steps:
125125
- name: Send Notification
126-
uses: stackabletech/actions/send-slack-notification@1b8db26b7406c66a7ab74e344a9e54edb2bc2690 # v0.14.3
126+
uses: stackabletech/actions/send-slack-notification@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0
127127
with:
128128
publish-manifests-result: ${{ needs.publish_manifests.result }}
129129
build-result: ${{ needs.build.result }}

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file.
66

77
### Added
88

9+
- ci: Generate SLSA build provenance for published image indexes and attest it in each registry ([#1559]).
10+
911
- hadoop: Add precompiled hadoop for later reuse in dependent images ([#1466], [#1474]).
1012
- nifi: Add version `2.9.0` ([#1463]).
1113
- nifi: Backport NIFI-15801 to 2.x versions ([#1481]).
@@ -28,6 +30,7 @@ All notable changes to this project will be documented in this file.
2830

2931
- airflow: Bump statsd_exporter to `0.30.0` ([#1524]).
3032
- ci: Bump `docker/login-action` from `v3.6.0` to `v4.1.0` and `stackabletech/actions` to `v0.14.3` to escape Node.js 20 deprecation ([#1507]).
33+
- ci: Bump `stackabletech/actions` to `v0.16.0` ([#1559]).
3134
- hbase: Update `hbase-opa-authorizer` from `0.1.0` to `0.2.0` and then `0.3.0` ([#1446], [#1454]).
3235
- stackable-base: Bump `containerdebug` to `0.4.0` and `config-utils` to `0.4.0` ([#1521]).
3336
- statsd_exporter: Bump version from `0.28.0` to `0.30.0` ([#1524]).
@@ -91,6 +94,7 @@ All notable changes to this project will be documented in this file.
9194
[#1549]: https://github.com/stackabletech/docker-images/pull/1549
9295
[#1550]: https://github.com/stackabletech/docker-images/pull/1550
9396
[#1551]: https://github.com/stackabletech/docker-images/pull/1551
97+
[#1559]: https://github.com/stackabletech/docker-images/pull/1559
9498

9599
## [26.3.0] - 2026-03-16
96100

0 commit comments

Comments
 (0)