ci: switch from SLSA provenance to actions/attest with subject-path#106
Merged
Conversation
Contributor
🤖 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.
The attest step was already guarded, but the checksums file generation was not. Now both steps are skipped during dry runs.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
kinyoklion
approved these changes
Apr 2, 2026
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.

Requirements
N/A — CI-only changes, no application code or tests modified.
Related issues
Supports the org-wide migration to immutable GitHub releases. Once a release is published, it can no longer be modified, which breaks workflows that upload artifacts after release-please publishes the release.
Describe the solution you've provided
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 rather than as release assets, so the release can be published directly by release-please without a draft→publish flow.This PR makes the following changes:
SLSA →
actions/attest@v4withsubject-path(both workflows): Replaced the separaterelease-provenancejob (usingslsa-framework/slsa-github-generatorwithupload-assets: true) with inlineactions/attest@v4steps. Attestation now usessubject-path: '${{ steps.ci.outputs.dist-dir }}/*tar.gz'to reference the built distribution tarballs directly on disk, eliminating the old base64-encoded hash round-trip entirely. Addedattestations: writepermission.CI action output changed (
.github/actions/ci/action.yml): Replaced thepackage-hashesoutput (base64-encoded sha256 checksums) with adist-diroutput that exposes the stack dist directory path. Removed the "Hash build files for provenance" step. The "Setup dist directory" step now sets both theSTACK_DIRenv var (used by downstream steps in the composite action) and thedist-diroutput (used by workflows for attestation).Removed orphaned declarations: Cleaned up dead code left behind after the
release-provenancejob was removed:release-created,upload-tag-name, andpackage-hashesoutputs from therelease-packagejob inrelease-please.yml(their sole consumer was the deletedrelease-provenancejob).Dry run safety: The
actions/atteststep inmanual-publish.ymlis gated onformat('{0}', inputs.dry_run) == 'false'. Theformat()call coerces both real booleans (fromworkflow_call) and strings (fromworkflow_dispatch) to a string before comparison, ensuring the guard works correctly for both trigger sources.PROVENANCE.md: Updated fromslsa-verifierinstructions togh attestation verifyinstructions and sample output, reflecting the switch to GitHub artifact attestations.No changes to
release-please-config.json—draftandforce-tag-creationare intentionally not set since this attestation-only repo does not need them.Updates since last revision
skip-github-pull-request/skip-github-releasewith inline tag creation) that was briefly added. This pattern is only needed for repos that upload artifacts to releases (which require draft releases). Since this repo is attestation-only, the standard single-pass release-please is correct.dry_runcondition from!inputs.dry_runtoformat('{0}', inputs.dry_run) == 'false'— ensures correct evaluation whether the input is a boolean (fromworkflow_call) or a string (fromworkflow_dispatch).Key points for review:
manual-publish.ymlhascontents: readwhilerelease-please.ymlhascontents: write. Verifyactions/attest@v4does not requirecontents: write— if it does, the manual workflow's attestation step will silently fail.subject-pathglob*tar.gz(no dot prefix) matches the original hash step's glob pattern. Verify this correctly matches only.tar.gzfiles produced bystack sdistand doesn't inadvertently match unexpected files.dist-diroutput is dynamic (resolved at runtime bystack path --dist-dir). If the CI step were skipped or failed, the attest step would receive an empty path. Inrelease-please.yml, the attest step is gated onreleases_created == 'true', and the CI step has the same guard, so this should be safe. Inmanual-publish.yml, both steps run unconditionally (except the attest dry_run guard), so verify the CI step always succeeds before attest runs..intoto.jsonlprovenance file that was previously uploaded as a release asset.release-created/upload-tag-nameoutputs.Describe alternatives you've considered
subject-checksumswith base64 round-trip: An earlier revision decoded the CI action's base64-encoded hashes into a checksums file foractions/attest. This worked but was unnecessarily complex — the tarballs are already on disk in the same job, sosubject-pathis more direct.publish-releasejob to un-draft after all uploads completed. This was simplified since this repo only uses attestation (not artifact uploads), making draft releases unnecessary.actions/attest@v4is the org-standard replacement and simplifies the workflow by running attestation inline.Additional context
Follows the canonical pattern from
launchdarkly/ld-relay(branch v8). Repos that upload actual binaries (e.g. ld-relay, cpp-sdks, roku-client-sdk) use the draft release pattern; attestation-only repos like this one do not need it.Link to Devin session: https://app.devin.ai/sessions/7d5bda4d9dbe4ae0b950b30a50485e60
Requested by: @keelerm84