fix(release): standardize on pulseengine cosign + SLSA flow (synth ref)#244
Open
avrabe wants to merge 1 commit into
Open
fix(release): standardize on pulseengine cosign + SLSA flow (synth ref)#244avrabe wants to merge 1 commit into
avrabe wants to merge 1 commit into
Conversation
The brief: standardize all six pulseengine tools on one release-asset
shape so consumers verify with a single one-liner. spar already had
sums + an SBOM, but signed neither and used `gh attestation create …
|| true` which silently swallowed failures. This PR adopts the synth
reference flow verbatim:
archive build → CycloneDX SBOM → sha256sum ./*
→ actions/attest-build-provenance@v2 (subject: tar.gz + zip)
→ sigstore/cosign-installer@v3 at cosign v2.4.1
→ cosign sign-blob --yes (SHA256SUMS.txt → .sig + .pem + .cosign.bundle)
→ build-env.txt
→ gh release create/upload (idempotent)
Per-tag asset set is now: spar-vX.Y.Z-<triple>.{tar.gz,zip},
spar-X.Y.Z.cdx.json, SHA256SUMS.txt + .sig/.pem/.cosign.bundle,
build-env.txt, plus the spar-specific VSIXes and compliance archive
which fold into SHA256SUMS.txt.
The SBOM step is adapted: `cargo cyclonedx --manifest-path
crates/spar-cli/Cargo.toml --format json --spec-version 1.5`. The
version-stamped name `spar-<bare>.cdx.json` is applied at
release-assets flatten time.
Job-level `permissions:` restate the trio (contents: write, id-token:
write, attestations: write) the OIDC/keyless flow needs. The old
`gh attestation create … || true` step is removed.
Verification one-liner consumers will use after the next release:
cosign verify-blob \\
--certificate-identity-regexp \\
'https://github.com/pulseengine/spar/.github/workflows/release.yml@.*' \\
--certificate-oidc-issuer \\
'https://token.actions.githubusercontent.com' \\
--bundle SHA256SUMS.txt.cosign.bundle SHA256SUMS.txt
gh attestation verify spar-vX.Y.Z-<triple>.tar.gz --repo pulseengine/spar
Artifacts: REQ-RELEASE-ASSETS-STANDARD + TEST-RELEASE-ASSETS-STANDARD.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rivet verification gate✅ 20/20 passed
Filter: Failed artifacts(none) Updated automatically by |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Per the per-tool brief: standardize all six pulseengine release flows
on the synth reference so consumers verify with a single one-liner.
spar already had sums + an SBOM but signed neither and used
gh attestation create … || true— which silently swallowed failures.This PR adopts the synth flow verbatim with the SBOM
--manifest-pathadapted to spar's CLI crate (the only documented adaptation per the
brief). No assets are removed — the brief specifies "spar: ... remove
no existing assets".
Step order in
create-release(now matches the brief exactly)build-binariesjob)--manifest-path crates/spar-cli/Cargo.toml --format json --spec-version 1.5(upstreambuild-sbomjob; version-stamped tospar-<bare>.cdx.jsonat flatten)cd release-assets && sha256sum ./* > SHA256SUMS.txtactions/attest-build-provenance@v2withsubject-path: release-assets/*.tar.gzANDrelease-assets/*.zip(spar ships Windows zip)sigstore/cosign-installer@v3pinned atv2.4.1cosign sign-blob --yes --bundle SHA256SUMS.txt.cosign.bundle --output-signature SHA256SUMS.txt.sig --output-certificate SHA256SUMS.txt.pem SHA256SUMS.txtbuild-env.txt(rustc / cargo / cosign / runner)gh release create … --generate-notes release-assets/*(idempotent: existing release getsgh release upload --clobber)Permissions
Workflow-level already had the trio; job-level
permissions:blockadded on
create-releaseto make the requirement locally explicit.Removed
gh attestation create "$file" --bundle-output … || trueloopthat ran after release creation and silently swallowed failures.
Verification (works after the next tag)
Artifacts:
REQ-RELEASE-ASSETS-STANDARD+TEST-RELEASE-ASSETS-STANDARD.Test plan
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/release.yml'))"— YAML parsesattest-build-provenance@v2,cosign-installer@v3,v2.4.1,sign-blob,build-env.txtall presentrivet validate— 0 broken cross-refs; totals byte-identical to baselinegh attestation verify+cosign verify-blobone-liners above)🤖 Generated with Claude Code