Skip to content

feat(release): add SBOM-to-archive attestation linkage#141

Open
jmeridth wants to merge 1 commit into
mainfrom
feat/release-attest-sbom-linkage
Open

feat(release): add SBOM-to-archive attestation linkage#141
jmeridth wants to merge 1 commit into
mainfrom
feat/release-attest-sbom-linkage

Conversation

@jmeridth
Copy link
Copy Markdown
Collaborator

Proposed Changes

Add a new attest_sboms matrix job that runs actions/attest-sbom per (archive, SBOM) pair after release_goreleaser produces artifacts. Expose sbom_matrix and is_public as outputs from release_goreleaser, upload dist/ as a workflow artifact when SBOMs are detected, and gate publish_release on attest_sboms so the draft publishes only after all SBOM attestations complete.

Why

The workflow already generates build provenance attestations against every artifact in dist/, including *.spdx.json files as standalone subjects, but it does not link an archive to its corresponding SBOM. Consumers running gh attestation verify --predicate-type https://spdx.dev/Document against a downloaded archive cannot discover its SBOM via the attestation graph. Adding actions/attest-sbom linkage closes that gap and removes the need for per-consumer follow-on jobs that replicate the matrix dance locally (downstream consumers have been writing this exact pattern in their callers).

Notes for reviewers

  • New job runs only when create-attestation: true, the repo is public, and dist/*.spdx.json files exist. Behavior is unchanged when SBOMs are not produced or attestation is off.
  • Matrix is generated from dist/*.spdx.json filenames, stripping .spdx.json to derive the archive path. Relies on GoReleaser's default ${artifact}.spdx.json naming pattern (or any pattern that maps 1:1 by the same suffix strip).
  • publish_release now waits for attest_sboms to succeed-or-skip — mirrors the existing gates on release_goreleaser and release_image. Matrix uses fail-fast: false so one failed pair does not cancel the others.
  • dist/ upload uses 1-day retention; consumed by the matrix job immediately, no long-term need.
  • release_goreleaser continues to do attest-build-provenance over dist/*.spdx.json; the new SBOM linkage is additive, not a replacement.
  • No new inputs or secrets — feature rides on the existing create-attestation flag. Considered adding a separate attest-sboms: boolean knob but it felt redundant given the existing flag's name.

Testing

  • actionlint .github/workflows/release.yaml clean.
  • YAML parses cleanly.
  • test-release.yaml does not pass goreleaser-config-path, so release_goreleaser is skipped in tests; attest_sboms cascades to skipped via its if: guard — no test regression. End-to-end verification requires triggering a release in a downstream caller that exercises goreleaser + SBOMs (planned: ossf/pvtr-github-repo-scanner will consume this once released).

Readiness Checklist

Author/Contributor

  • If documentation is needed for this change, has that been included in this pull request — docs/release.md updated with the new job and SBOM linkage behavior.

## What

Add a new `attest_sboms` matrix job that runs `actions/attest-sbom` per
(archive, SBOM) pair after `release_goreleaser` produces artifacts.
Expose `sbom_matrix` and `is_public` as outputs from `release_goreleaser`,
upload `dist/` as a workflow artifact when SBOMs are detected, and gate
`publish_release` on `attest_sboms` so the draft is published only after
all SBOM attestations complete.

## Why

Today the workflow generates build provenance attestations against every
artifact in `dist/`, including `*.spdx.json` files as standalone
subjects, but it does not link an archive to its corresponding SBOM.
Consumers running `gh attestation verify --predicate-type https://spdx.dev/Document`
against a downloaded archive cannot discover its SBOM via the
attestation graph. Adding `actions/attest-sbom` linkage closes that gap
and removes the need for per-consumer follow-on jobs that replicate the
matrix dance locally.

## Notes

- New job runs only when `create-attestation: true`, the repo is public,
  and `dist/*.spdx.json` files exist. Behavior is unchanged when SBOMs
  are not produced or attestation is off.
- Matrix is generated from `dist/*.spdx.json` filenames, stripping
  `.spdx.json` to derive the archive path. Requires GoReleaser's default
  `${artifact}.spdx.json` naming pattern (or any pattern that maps 1:1
  by the same suffix strip).
- `publish_release` now waits for `attest_sboms` to succeed-or-skip, so
  SBOM attestation failures will block publish (mirrors the existing
  gate on `release_goreleaser` and `release_image`). Matrix uses
  `fail-fast: false` so one failed pair does not cancel the others.
- `dist/` upload uses 1-day retention; consumed by the matrix job
  immediately, no long-term need.
- `release_goreleaser` continues to do `attest-build-provenance` over
  `dist/*.spdx.json`; the new linkage is additive, not a replacement.

Signed-off-by: jmeridth <jmeridth@gmail.com>
@jmeridth jmeridth self-assigned this May 18, 2026
@github-actions github-actions Bot marked this pull request as ready for review May 18, 2026 23:17
@github-actions github-actions Bot requested a review from zkoppert as a code owner May 18, 2026 23:17
@jmeridth
Copy link
Copy Markdown
Collaborator Author

@zkoppert this has me thinking on how to split out specific release parts for specific languages. This release yaml is smelling of a bit too much Go IMO. 😄

For now, need this to be reviewed and merged for now. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant