ci: switch from SLSA provenance to actions/attest with subject-path#116
Merged
ci: switch from SLSA provenance to actions/attest with subject-path#116
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Since actions/attest@v4 stores attestations via GitHub's attestation API (not as release assets), repos that only use attestation don't need draft releases. Release-please can publish the release directly. Changes: - Remove draft:true from release-please-config.json - Remove create-tag job/steps (force-tag-creation handles this) - Remove publish-release job (release is published directly) - Remove publish_release input from manual workflows
force-tag-creation only operates in conjunction with draft releases. Since this repo does not use draft releases (attestation-only, no artifact uploads to the release), force-tag-creation is not needed.
kinyoklion
approved these changes
Apr 1, 2026
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
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
Adapts the release workflow for GitHub's immutable releases feature. Since this repo only uses attestation (no binary/artifact uploads to the release), draft releases are not needed —
actions/attest@v4stores attestations via GitHub's attestation API, not as release assets.Changes across 5 files:
.github/actions/publish/action.yml— Removed thehashesoutput and "Hash nuget packages" step that base64-encoded SHA256 checksums. These existed to feed the old SLSA generator'sbase64-subjectsinput and are no longer needed since attestation now usessubject-pathto reference artifacts directly on disk..github/workflows/publish.yml— Replaced the separateprovenancejob (SLSAgenerator_generic_slsa3reusable workflow withupload-assets: true) with an inlineactions/attest@v4step in thepublishjob usingsubject-path: 'nupkgs/*'. Addedattestations: writepermission. Removed the unusedtaginput from bothworkflow_dispatchandworkflow_calltriggers. This eliminates the base64 encode/decode round-trip, the checksums file generation, and the.intoto.jsonlrelease asset upload entirely..github/workflows/release-please.yml— Removedtag: ${{ needs.release-please.outputs.tag_name }}from the publish workflow call and thetag_nameoutput from therelease-pleasejob (both are dead code after thetaginput removal).PROVENANCE.md(new) — Added provenance verification guide withgh attestation verifyinstructions and sample output, using thex-release-please-start-versionmarker to keep the version in sync with releases.README.md— Added a "Verifying build provenance with the SLSA framework" section linking to the newPROVENANCE.md.Why
subject-pathinstead ofsubject-checksums?The previous intermediate revision used
subject-checksumswith a base64 decode step to convert the composite action's hash output into a checksums file. This was redundant — the.nupkgand.snupkgfiles are already on disk in./nupkgs/within the same job, sosubject-path: 'nupkgs/*'letsactions/attest@v4compute checksums directly. This removes all hash-related plumbing from both the composite action and the workflow.Why no draft releases?
The old SLSA generator uploaded
.intoto.jsonlprovenance files as release assets (viaupload-assets: true), which would fail under immutable releases if the release was already published. The newactions/attest@v4stores attestations in GitHub's attestation API instead, so the release can be published directly by release-please without needing a draft→publish flow.Why
format('{0}', inputs.dry_run)for the condition?GitHub Actions
workflow_dispatchdelivers boolean inputs as strings ('false'), whileworkflow_calldelivers them as actual booleans (false). A plain== 'false'comparison silently fails when receiving a real boolean. Usingformat('{0}', inputs.dry_run)coerces either type to a string before comparison, ensuring the guard works for both trigger sources.Review & Testing Checklist for Human
subject-path: 'nupkgs/*'glob matches the output ofdotnet pack --output nupkgsin the composite action (should capture both.nupkgand.snupkgfiles). If the directory is empty or missing at attest time (e.g. during a dry run), confirm theformat('{0}', inputs.dry_run) == 'false'guard prevents the attest step from running.attestations: writepermission on thepublishjob is sufficient foractions/attest@v4(the old SLSA generator ran as a separate job withactions: read,id-token: write, andcontents: write).publish.yml(should skip attestation) and then a real release to confirm the attest step succeeds and no.intoto.jsonlasset is expected by downstream consumers.PROVENANCE.mdsample output references the correct workflow path — the attest step runs insidepublish.yml(called viarelease-please.yml); confirm GitHub records the expected workflow in the attestation so the sample output matches reality.PROVENANCE.mdversion placeholder (5.3.0) is updated by release-please via thex-release-please-start-version/x-release-please-endmarkers on the next release.Notes
format('{0}', inputs.dry_run) == 'false'condition coerces the boolean/string input to a consistent string before comparison, per GitHub Actions expressions docs.release-please.ymlstill referencesreleases_created(plural) — existing output names are preserved.release-please-config.jsonremain in the final diff (the previously-addedforce-tag-creationwas reverted as unnecessary for non-draft repos).provenancejob previously generated a named.intoto.jsonlfile uploaded as a release asset. Confirm no tooling or verification process depends on that specific asset being present on the GitHub release.PROVENANCE.mdsample output is templated from the realgh attestation verifyoutput format — repo name and workflow references are specific to this repository.Link to Devin session: https://app.devin.ai/sessions/7d5bda4d9dbe4ae0b950b30a50485e60
Requested by: @keelerm84
Note
Medium Risk
Medium risk because it changes the release/publish GitHub Actions flow for provenance generation and permissions; mistakes could block releases or fail to emit attestations, but it doesn’t affect runtime code.
Overview
Replaces the prior SLSA provenance generation/upload flow with GitHub artifact attestations: the
publishworkflow now runsactions/attest@v4(guarded bydry_run) overnupkgs/*and addsattestations: writepermissions.Simplifies the publish composite action and release automation by removing the nuget package hashing output/plumbing and dropping the now-unused
taginputs/outputs frompublish.ymlandrelease-please.yml.Adds
PROVENANCE.mdwithgh attestation verifyinstructions, links it fromREADME.md, and updatesrelease-please-config.jsonso the provenance doc is version-bumped with releases.Written by Cursor Bugbot for commit 70122a9. This will update automatically on new commits. Configure here.