From a42792928f49c6d8424c672979a46ac1086b5656 Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 25 Jun 2026 09:12:04 +0100 Subject: [PATCH] feat(ci): attest build provenance Add GitHub native build-provenance attestation to the container publish workflow. The image is built and pushed with Podman; the pushed manifest digest is captured via 'podman push --digestfile' and bound to the attestation via actions/attest-build-provenance. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/container-publish.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/container-publish.yml b/.github/workflows/container-publish.yml index afeff765..f5e3077e 100644 --- a/.github/workflows/container-publish.yml +++ b/.github/workflows/container-publish.yml @@ -23,6 +23,8 @@ jobs: permissions: contents: read packages: write + id-token: write # mint the OIDC token the attestation is signed with + attestations: write # write the build-provenance attestation (the "claim") steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -74,9 +76,26 @@ jobs: . - name: Push to GitHub Container Registry + id: push run: | - podman push "${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.version }}" + # --digestfile makes podman write the digest of the pushed manifest; + # this is the real sha256 the attestation must bind to. + podman push --digestfile=/tmp/ghcr-digest \ + "${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.version }}" podman push "${{ steps.meta.outputs.image }}:latest" + echo "digest=$(cat /tmp/ghcr-digest)" >> "$GITHUB_OUTPUT" + + # GitHub native artifact attestation (build provenance) for the pushed + # image — a signed, verifiable claim binding the image digest to this + # build. Verify with: + # gh attest verify oci://ghcr.io/${{ github.repository }}: \ + # --repo ${{ github.repository }} + - name: Attest container provenance + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2 + with: + subject-name: ghcr.io/${{ github.repository }} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true - name: Tag and push to Docker Hub if: steps.dockerhub.outputs.available == 'true'