ci: sign releases with cosign and generate SLSA provenance#222
Conversation
The Scorecard report still flagged the inline `pip install --upgrade pip pipenv poetry` in smoke.yml and update-smoke-goldens.yml as unpinned. Replace it with a hash-locked, fully-resolved requirements file (pip-compile --generate-hashes) installed via `pip install --require-hashes`, covering pip/pipenv/poetry and their full transitive dependency graph (45 packages). Verified the lockfile installs cleanly under Python 3.12 with --require-hashes and that the resolved wheels include manylinux builds for the Linux CI runner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses the Scorecard Signed-Releases check, which scans GitHub release assets for signature/provenance file patterns and currently scores 0/10. - .goreleaser.yaml: add a `signs:` block that signs SHA256SUMS keylessly with cosign (GitHub OIDC identity, no managed keys), producing SHA256SUMS.sigstore.json. Satisfies the check's 8/10 tier. - release.yml: install cosign before the GoReleaser step, grant `id-token: write` for keyless signing, and add a `provenance` job that calls slsa-framework/slsa-github-generator's generic builder over the release artifact hashes to produce a SLSA Build Level 3 `multiple.intoto.jsonl`, uploaded to the same release. Satisfies the check's 10/10 tier. - .github/pinact.yaml: exclude the SLSA generator's `uses:` line from automated re-pinning. It must stay pinned to a vX.Y.Z tag (not a commit SHA) for slsa-verifier's builder-identity check to resolve — SHA-pinning it would break verification. This is a known, intentional exception to repo's usual SHA-pinning convention. - docs/INSTALLATION.md: add cosign and slsa-verifier commands so users can verify a release's signature and provenance, not just checksums. - dev-docs/CI.md: document the new release-pipeline steps and the pinning exception. Validated locally: `goreleaser check` accepts the signs config, and a `goreleaser release --snapshot --clean --skip=sign,publish,announce` run confirms the build/archive/checksum pipeline is unaffected. The cosign OIDC signing and SLSA provenance steps themselves only run in GitHub Actions and need verification on the next real tagged release. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 14 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| # shorter tag — slsa-verifier resolves the builder identity from this exact ref, | ||
| # and SHA-pinning breaks that resolution. See .github/pinact.yaml, which excludes | ||
| # this line from automated re-pinning. | ||
| uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 |
Bomly Diff SummaryCompared Overview
Dependency ChangesSummary: 2 added, 0 changed, 0 removed. Added Dependencies
Vulnerabilities✅ No vulnerability changes. License Changes✅ No license changes. Project Posture✅ No project posture changes ( Policy FindingsSummary: 2 introduced, 0 persisted, 0 resolved. Introduced Findings
|
…se upload failure (#223) * ci: keep release draft until provenance lands, fixing immutable-release upload failure The v0.15.3 release run (#222's first real release) failed: the SLSA provenance job tried to upload multiple.intoto.jsonl to the release after GoReleaser had already published it, and GitHub's immutable releases feature (GA Oct 2025) rejects asset uploads to any release once published — "Cannot upload assets to an immutable release." Per GitHub's own guidance, the fix is to keep the release as a draft until every asset is attached, and publish last: - .goreleaser.yaml: release.draft is now true. GoReleaser creates the release and uploads its assets (archives, packages, checksums, signature) without publishing. - release.yml: the provenance job now uploads to the still-draft release (drafts are exempt from the immutability restriction). A new `publish` job, gated on `needs: [release, provenance]`, mints a fresh release-bot app token and runs `gh release edit --draft=false` once both are done — preserving the existing requirement that publishing use an app-attributed token so `release: published` cascades to notify-landing-yank.yml. - dev-docs/CI.md: documents the new draft -> provenance -> publish sequencing and the immutable-releases constraint driving it. Known minor tradeoff: the Homebrew/Scoop/WinGet manifest PRs are opened by GoReleaser before publish, so their release-asset URLs are briefly (well under a minute) not yet publicly downloadable until the `publish` job finishes. Documented in dev-docs/CI.md; not fixed here since it's a narrow timing window with low practical impact. Validated locally: `goreleaser check` accepts the config (only the pre-existing, unrelated `brews` deprecation warning remains), and `make test` passes. The draft/publish/token-cascade behavior itself can only be verified by a real tagged release in GitHub Actions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci: avoid template-injection in release publish step Address CodeRabbit/zizmor finding on #223: github.ref_name was interpolated directly into the run: shell command, which expands before Bash parses the line. Pass it through env instead and reference it as a quoted shell variable, so a crafted tag name can't inject shell commands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Summary
Addresses the Scorecard Signed-Releases check (currently 0/10). Scorecard scans the last five releases' assets for specific signature/provenance filename patterns — it doesn't verify trust chains itself, just presence — so this adds both tiers:
.goreleaser.yamlgets asigns:block that signsSHA256SUMSkeylessly with cosign via GitHub OIDC (no managed keys, no secrets to rotate), producingSHA256SUMS.sigstore.json.release.ymladds aprovenancejob calling slsa-framework/slsa-github-generator's generic builder over the release artifact hashes, producing a SLSA Build Level 3multiple.intoto.jsonlattestation, auto-uploaded to the same GitHub release.A note on Pinned-Dependencies
The SLSA generator's
uses:line must stay pinned to av2.1.0tag, not a commit SHA —slsa-verifierresolves the trusted builder's identity from that exact tag ref, and SHA-pinning it breaks that resolution (this is the generator's own documented requirement, not a choice we're making). This is a known, narrow exception to the repo's usual SHA-pinning convention from #217/#220. Added.github/pinact.yamlwith anignore_actionsrule so a futurepinact rundoesn't "fix" this into a SHA and silently break provenance verification. Scorecard's Pinned-Dependencies check may ding this one line slightly, but the net Scorecard score moves up substantially once Signed-Releases jumps from 0 to ~10.Verification
goreleaser checkaccepts the newsigns:config (only pre-existing, unrelatedbrewsdeprecation warning remains — already tracked in a comment in.goreleaser.yaml).goreleaser release --snapshot --clean --skip=sign,publish,announcerun locally — full build/archive/checksum pipeline still produces all platform archives, Linux packages, andSHA256SUMScorrectly; confirms my changes don't break the build.slsa-framework/slsa-github-generator@v2.1.0is the current stable release andsigstore/cosign-installer@v4.1.2's SHA was resolved directly from GitHub's API.make testpasses.What I could not test locally: cosign's keyless OIDC signing and the SLSA generator's provenance generation both require a real GitHub Actions OIDC token — neither can run outside Actions. The actual signing + provenance flow needs to be verified on the next real tagged release (or via a
workflow_dispatchrun against a tagged commit).Test plan
goreleaser check/ snapshot build pass locallymake testpassesSHA256SUMS.sigstore.jsonandmultiple.intoto.jsonlappear as release assetscosign verify-blobandslsa-verifier verify-artifact(commands now documented indocs/INSTALLATION.md) succeed against the published assets🤖 Generated with Claude Code