88 - main
99 paths :
1010 - " .github/workflows/update-ca-cert.yaml"
11- - " ssg-chainguard-gpos-ds.xml"
11+ - " gpos/xml/scap/ssg/content/ssg-chainguard-gpos-ds.xml"
12+ - " tests/e2e/fixtures/*/Dockerfile"
13+ - " tests/oscap-offline/internal/scan/fixtures_test.go"
1214concurrency :
1315 group : update-ca-cert-${{ github.ref }}
1416 cancel-in-progress : false
2931 DATASTREAM_PATH : gpos/xml/scap/ssg/content/ssg-chainguard-gpos-ds.xml
3032 TESTS_PATH : tests
3133 FIXTURES_GLOB : tests/e2e/fixtures/*/Dockerfile
34+ TEST_PIN_FILE : tests/oscap-offline/internal/scan/fixtures_test.go
3235 steps :
3336 - name : Checkout
3437 uses : actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -153,8 +156,9 @@ jobs:
153156 # The offline harness (tests/oscap-offline) reads its pinned base image
154157 # from tests/e2e/fixtures/baseline-clean/Dockerfile, so re-pinning that
155158 # fixture here also keeps the offline CertificateAudit pass fixture in
156- # lockstep with the datastream hash. There is no separate offline pin to
157- # update.
159+ # lockstep with the datastream hash. The one remaining copy of the
160+ # digest — the `pinned` constant in TestParseWolfiBaseRef — is
161+ # re-pinned by the next step.
158162
159163 fixtures_changed=false
160164 updated_files=()
@@ -203,14 +207,71 @@ jobs:
203207 else
204208 echo "- **Status**: Already up-to-date" >> "$GITHUB_STEP_SUMMARY"
205209 fi
210+ - name : Re-pin offline harness test digest
211+ id : testpin
212+ env :
213+ STEPS_IMAGE_OUTPUTS_DIGEST : ${{ steps.image.outputs.digest }}
214+ run : |
215+ set -euo pipefail
216+
217+ # TestParseWolfiBaseRef asserts the exact digest-pinned wolfi-base ref
218+ # parsed from tests/e2e/fixtures/baseline-clean/Dockerfile against a
219+ # hardcoded `pinned` constant, so that constant must move together
220+ # with the fixture re-pin above or the test breaks on every update
221+ # (see #123 for the manual fix this step replaces).
222+ #
223+ # The grep guard fails the run loudly if the constant's shape changes
224+ # (e.g. the test is refactored) so the workflow gets updated instead
225+ # of silently reintroducing drift.
226+
227+ if ! grep -qE 'wolfiBaseRepo \+ ":latest@sha256:[0-9a-f]{64}"' "${TEST_PIN_FILE}"; then
228+ echo "::error::Pinned digest constant not found in ${TEST_PIN_FILE}; update this workflow to match the test"
229+ exit 1
230+ fi
231+
232+ cp "${TEST_PIN_FILE}" "${TEST_PIN_FILE}.bak"
233+ sed -i -E "s|(wolfiBaseRepo \+ \":latest@sha256:)[0-9a-f]{64}|\1${STEPS_IMAGE_OUTPUTS_DIGEST#sha256:}|" "${TEST_PIN_FILE}"
234+
235+ if diff -q "${TEST_PIN_FILE}.bak" "${TEST_PIN_FILE}" > /dev/null; then
236+ echo "Test pin already up to date"
237+ echo "test_pin_changed=false" >> "$GITHUB_OUTPUT"
238+ testpin_status="Already up-to-date"
239+ else
240+ echo "Updated ${TEST_PIN_FILE} -> ${STEPS_IMAGE_OUTPUTS_DIGEST}"
241+ echo "test_pin_changed=true" >> "$GITHUB_OUTPUT"
242+ testpin_status="Updated"
243+ fi
244+ rm "${TEST_PIN_FILE}.bak"
245+
246+ cat >> "$GITHUB_STEP_SUMMARY" <<EOF
247+ ### Test Pin Update Summary
248+ - **File**: \`${TEST_PIN_FILE}\`
249+ - **Status**: ${testpin_status}
250+ EOF
251+ - name : Setup Go
252+ uses : actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
253+ with :
254+ go-version-file : ' tests/oscap-offline/go.mod'
255+ cache-dependency-path : ' tests/oscap-offline/go.sum'
256+ - name : Verify test pin matches fixture
257+ working-directory : tests/oscap-offline
258+ run : |
259+ set -euo pipefail
260+
261+ # Proves the re-pinned `pinned` constant agrees with the re-pinned
262+ # baseline-clean Dockerfile before any PR is opened, so a bad sed (or
263+ # drift introduced outside this workflow) fails here instead of
264+ # landing as a broken PR. Pure parse test; needs no container runtime.
265+ go test -count=1 -run 'TestParseWolfiBaseRef' ./internal/scan/
206266 - name : Aggregate change status
207267 id : changed
208268 env :
209269 DS_CHANGED : ${{ steps.update.outputs.datastream_changed }}
210270 FX_CHANGED : ${{ steps.fixtures.outputs.fixtures_changed }}
271+ TP_CHANGED : ${{ steps.testpin.outputs.test_pin_changed }}
211272 run : |
212273 set -euo pipefail
213- if [ "${DS_CHANGED}" = "true" ] || [ "${FX_CHANGED}" = "true" ]; then
274+ if [ "${DS_CHANGED}" = "true" ] || [ "${FX_CHANGED}" = "true" ] || [ "${TP_CHANGED}" = "true" ] ; then
214275 echo "changed=true" >> "$GITHUB_OUTPUT"
215276 else
216277 echo "changed=false" >> "$GITHUB_OUTPUT"
@@ -227,10 +288,12 @@ jobs:
227288 commit-message : |
228289 chore(oscap): re-pin CA bundle hash and fixture base-image digests
229290
230- Atomically updates the CA bundle SHA in the OSCAP datastream and the
231- digest-pinned FROM lines in tests/e2e/fixtures/*/Dockerfile so the
232- two values can never drift out of sync (which would flake the
233- CertificateAudit E2E assertions).
291+ Atomically updates the CA bundle SHA in the OSCAP datastream, the
292+ digest-pinned FROM lines in tests/e2e/fixtures/*/Dockerfile, and the
293+ pinned wolfi-base digest in the offline harness test
294+ (TestParseWolfiBaseRef) so the three values can never drift out of
295+ sync (which would flake the CertificateAudit E2E assertions or
296+ break the offline unit tests).
234297
235298 Image: ${{ env.IMAGE_REF }}
236299 Digest: ${{ steps.image.outputs.digest }}
@@ -243,25 +306,30 @@ jobs:
243306 body : |
244307 ## CA Certificate + Fixture Base-Image Update
245308
246- Atomically re-pins two values that must stay in lockstep:
309+ Atomically re-pins three values that must stay in lockstep:
247310
248311 1. The `<ind:hash>` under `oval:org.CABundleHash:ste:1` in the OSCAP
249312 datastream (`${{ env.DATASTREAM_PATH }}`).
250313 2. The `FROM cgr.dev/chainguard/wolfi-base:latest@sha256:...` line in
251314 every `tests/e2e/fixtures/*/Dockerfile`.
315+ 3. The `pinned` wolfi-base digest constant asserted by
316+ `TestParseWolfiBaseRef` in `${{ env.TEST_PIN_FILE }}`.
252317
253318 If these drift (e.g. Dependabot bumps the fixture digest before this
254319 workflow refreshes the datastream hash, or vice versa), the
255320 `baseline-clean` / `cabundle-tampered` E2E CertificateAudit check
256321 fails because the fixture's CA bundle no longer matches the hash the
257- datastream asserts. This workflow is now the authoritative update
258- point for both values together.
322+ datastream asserts, and the offline harness unit tests break against
323+ the stale test pin. This workflow is the authoritative update point
324+ for all three values together; `TestParseWolfiBaseRef` was run
325+ against the updated tree before this PR was opened.
259326
260327 - **Image**: `${{ env.IMAGE_REF }}`
261328 - **Digest**: `${{ steps.image.outputs.digest }}`
262329 - **New CA SHA256**: `${{ steps.ca.outputs.sha }}`
263330 - **Datastream changed**: `${{ steps.update.outputs.datastream_changed }}`
264331 - **Fixtures changed**: `${{ steps.fixtures.outputs.fixtures_changed }}`
332+ - **Test pin changed**: `${{ steps.testpin.outputs.test_pin_changed }}`
265333 labels : |
266334 automated pr
267335 # - name: Enable auto-merge
0 commit comments