Skip to content

Attest published images and create a GitHub release#4

Draft
fnando wants to merge 5 commits into
publishfrom
attest
Draft

Attest published images and create a GitHub release#4
fnando wants to merge 5 commits into
publishfrom
attest

Conversation

@fnando
Copy link
Copy Markdown
Member

@fnando fnando commented May 21, 2026

What

Every published per-arch image is now signed under two independent attestation chains, and each v* release gets a GitHub Release with the supply-chain artifacts attached.

  • buildx-nativeprovenance: mode=max + sbom: true on docker/build-push-action. SLSA build provenance and SPDX SBOM travel with the image in the registry, verifiable via cosign verify-attestation / docker buildx imagetools inspect.
  • GitHub-native — after the push, actions/attest-build-provenance and actions/attest-sbom publish to the repo's attestation store (verifiable via gh attestation verify --repo stellar/stellar-cli-docker). Backing OIDC identity is the same; the verification UX is different.
  • GitHub Release — on v* tag push (skipped on workflow_dispatch), a new release job downloads every per-arch artifact, composes a body listing the per-arch digests + verification commands, and attaches the SBOM and provenance files via softprops/action-gh-release.
  • scripts/verify-image.sh — consumer-facing wrapper that runs gh attestation verify for both predicate types against a digest-pinned image. Refuses tag-only refs.
  • scripts/release-body.sh — composes the release body markdown from the per-arch metadata files the build job uploads. Smoke-tested locally against synthetic metadata.

Why

SEP-58 explicitly recommends CI provenance and an SBOM for trustworthy build images. The previous publish flow shipped the image with no supply-chain claim attached. After this PR, a verifier can:

./scripts/verify-image.sh --image docker.io/stellar/stellar-cli@sha256:...

and get back a passing-or-failing report on both attestations — or follow either chain manually via cosign / docker buildx imagetools inspect / gh attestation verify.

Notable choices

  • Both chains, not one. Same trust root (GitHub OIDC), but doubles the verification surface area — gh, cosign, and docker buildx consumers all have a native path. Workflow cost is small (anchore/sbom-action + two attest-* steps per per-arch build).
  • anchore/sbom-action to generate the SBOM file rather than extracting from the buildx-attached SBOM. The file is needed both for actions/attest-sbom (which takes a sbom-path input) and for the release attachment. Single source.
  • Release job is tag-push-gated (if: startsWith(github.ref, 'refs/tags/v')). workflow_dispatch runs build + manifest + aliases but skips the release page — a manual dispatch has no GH tag context.
  • release is in complete's needs: but a skipped job result ('skipped') doesn't trigger the failure check, so dispatch-mode runs still complete cleanly.
  • Permissions bumped to contents: write (release creation) + attestations: write (attest-* actions) + id-token: write (OIDC for both buildx provenance and the attest actions).
  • All new uses: SHA-pinned to current latest releases: actions/attest-build-provenance@v4.1.0, actions/attest-sbom@v4.1.0, anchore/sbom-action@v0.24.0, actions/upload-artifact@v7.0.1, actions/download-artifact@v8.0.1, softprops/action-gh-release@v3.0.0.

Depends on

#3 (publish) — this branch is based on it. Base will auto-update to main once #3 merges.

Verification

  • ./scripts/release-body.sh renders a clean markdown body against synthetic metadata (4 rows: 2 rust versions × 2 archs).
  • ./scripts/verify-image.sh --help works; refuses tag-only refs (--image .../stellar-cli:latest → exit 1 with clear message).
  • shellcheck clean on both new scripts.
  • End-to-end behavior verifiable by pushing a v* tag once this PR merges — the release page should appear with .spdx.json and .intoto.jsonl attachments, and gh attestation verify against any per-arch digest should pass for both predicate types.

@fnando fnando requested a review from Copilot May 21, 2026 17:05
@fnando fnando self-assigned this May 21, 2026
@fnando fnando added this to DevX May 21, 2026
@github-project-automation github-project-automation Bot moved this to Backlog (Not Ready) in DevX May 21, 2026
@fnando fnando moved this from Backlog (Not Ready) to In Progress in DevX May 21, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR strengthens the container image supply-chain story by adding provenance + SBOM attestations via both buildx (registry-attached) and GitHub’s attestation store, and by publishing a GitHub Release on v* tags that attaches the generated artifacts and includes verification instructions.

Changes:

  • Add scripts/verify-image.sh to verify both GitHub-native attestations (provenance + SBOM) against a digest-pinned image.
  • Add scripts/release-body.sh to generate a GitHub Release body from per-arch build metadata.
  • Extend .github/workflows/publish.yml to generate SBOM files, publish GitHub attestations, upload per-arch artifacts, and create/update a GitHub Release on tag pushes.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
scripts/verify-image.sh New consumer-facing verifier wrapper around gh attestation verify for provenance + SBOM.
scripts/release-body.sh New release body generator that aggregates per-arch metadata into Markdown instructions.
README.md Documents the new scripts/verify-image.sh helper.
.github/workflows/publish.yml Adds provenance/SBOM generation + GitHub attestations, uploads artifacts, and creates a GitHub Release on v* tags.
Comments suppressed due to low confidence (1)

scripts/release-body.sh:60

  • The usage text says --stellar-cli-version "must match the cli in every metadata file", but the aggregation jq currently filters out mismatching files (select(.stellar_cli_version == $cli)) and then succeeds as long as at least one matches. Consider failing if any meta-*.json under the directory has a different stellar_cli_version (or if any are missing that field), so the release body can’t silently omit artifacts.
  # Aggregate all meta-*.json files under the metadata dir into one JSON array.
  local rows
  rows="$(find "$metadata_dir" -type f -name 'meta-*.json' -print0 \
    | xargs -0 jq -s --arg cli "$cli" \
        'map(select(.stellar_cli_version == $cli))
         | sort_by(.rust_version, .arch)')"
  test "$(jq 'length' <<<"$rows")" -gt 0 \
    || die "no metadata files for stellar-cli $cli under $metadata_dir"


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/verify-image.sh Outdated
Comment thread scripts/release-body.sh Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants