Skip to content

ci: switch from SLSA provenance to actions/attest with subject-path#118

Merged
keelerm84 merged 10 commits intomainfrom
devin/1774991582-immutable-releases
Apr 2, 2026
Merged

ci: switch from SLSA provenance to actions/attest with subject-path#118
keelerm84 merged 10 commits intomainfrom
devin/1774991582-immutable-releases

Conversation

@keelerm84
Copy link
Copy Markdown
Member

@keelerm84 keelerm84 commented Mar 31, 2026

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

N/A — CI-only changes (plus updated documentation), no application code or tests affected.

Related issues

Supports the org-wide migration to immutable GitHub releases. Reference implementation: launchdarkly/ld-relay (branch v8).

Describe the solution you've provided

GitHub's immutable releases feature prevents modifying a release after publishing. The old SLSA provenance generator (slsa-framework/slsa-github-generator) used upload-assets: true to upload .intoto.jsonl files as release assets, which would fail under immutable releases. Since this repo only uses attestation (no binary/artifact uploads to the release), draft releases are not needed — actions/attest@v4 stores attestations via GitHub's attestation API, not as release assets, so release-please can publish directly.

This PR makes changes across all 4 packages (server-ai, server-ai-langchain, server-ai-openai, optimization):

  1. Replaced SLSA provenance with actions/attest@v4 using subject-path — Removed all 4 separate *-provenance jobs that used slsa-framework/slsa-github-generator. Attestation is now an inline step in each release job using actions/attest@v4 with subject-path pointing directly to the built distribution files (e.g. packages/sdk/server-ai/dist/*). Added attestations: write permission. Removed package-hashes outputs from each release job since they are no longer needed.

  2. Removed base64 hash round-trip from build action — The composite build action (.github/actions/build/action.yml) no longer computes base64-encoded SHA256 hashes or exposes a package-hashes output. The old pattern (hash → base64 encode → output → base64 decode → checksums file → subject-checksums) is replaced by subject-path, which lets actions/attest@v4 read artifacts directly from disk.

  3. Removed unnecessary contents: write permission — The old *-provenance jobs needed contents: write for uploading assets to the release. Since actions/attest@v4 only requires attestations: write (and id-token: write for OIDC), contents: write has been removed from all 4 release jobs.

  4. Removed unnecessary fetch-depth: 0 — All 4 release jobs had fetch-depth: 0 on checkout, which fetches full git history. This is not needed since the jobs only build and publish packages — they don't perform any git operations that require history.

  5. Fixed dry_run condition for boolean/string compatibility — The callable workflow's dry_run conditions now use format('{0}', inputs.dry_run) != 'true' instead of inputs.dry_run != true. When workflow_call passes a boolean true, GitHub Actions' == operator uses loose string coercion that can silently mismatch. format() stringifies the value first, ensuring consistent string-to-string comparison regardless of whether the caller is workflow_call (boolean) or workflow_dispatch (string).

  6. Updated PROVENANCE.md — Replaced slsa-verifier instructions with gh attestation verify commands and updated sample output to reflect the new GitHub artifact attestation format.

  7. release-please-config.json — Cosmetic reformatting only (inline extra-files arrays expanded to multi-line). No functional config changes (draft and force-tag-creation are intentionally not set — they are only needed for repos that upload artifacts to releases).

Updates since last revision

  • Removed unnecessary contents: write permission from all 4 release jobs (flagged by Cursor Bugbot — only needed by the now-deleted SLSA provenance jobs, not by actions/attest@v4).
  • Removed unnecessary fetch-depth: 0 from all 4 release job checkout steps (flagged by Cursor Bugbot — full git history is not needed for build/publish).
  • Fixed dry_run conditions in the callable workflow to use format('{0}', inputs.dry_run) != 'true' for reliable boolean/string handling across both workflow_call and workflow_dispatch triggers.
  • Updated PROVENANCE.md to use gh attestation verify with sample output matching the new GitHub artifact attestation format.
  • Reverted the split release-please pattern (two-pass skip-github-pull-request / skip-github-release with 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.

⚠️ Human review checklist

  • Verify the subject-path glob patterns match the actual build output for each package (e.g. packages/sdk/server-ai/dist/*, packages/ai-providers/server-ai-langchain/dist/*, etc.). If the build step produces files outside dist/, they won't be attested.
  • Verify nothing else consumed the package-hashes output from the build action. The only consumers were the now-deleted *-provenance jobs and the removed "Generate checksums file" steps, but confirm no external workflows or callers depend on it.
  • Confirm actions/attest@v4 does not require contents: write. Per its docs it needs id-token: write and attestations: write, both of which are present. If any attestation step actually needs contents: write, the release jobs will fail.
  • Note that attestation only runs in the automated release-please path (the 4 release-* jobs). The callable manual publish workflow does not include an attest step — manual publishes will not generate attestations. Confirm this is acceptable.
  • Verify the format('{0}', inputs.dry_run) != 'true' pattern works correctly for both workflow_call (boolean input) and workflow_dispatch (string input) triggers. A real dry-run test of the manual publish workflow would confirm this.
  • Review PROVENANCE.md sample output and verify the build/signer workflow paths are accurate for this repo (currently shows release-please.yml).
  • Only packages/sdk/server-ai/PROVENANCE.md is modified in this PR. Confirm whether the other 3 packages (server-ai-langchain, server-ai-openai, optimization) also need their own PROVENANCE.md files or if the single file is intentional.
  • The extra-files arrays in release-please-config.json were reformatted from inline to multi-line — this is cosmetic only but could cause merge conflicts with concurrent PRs.

Describe alternatives you've considered

An earlier revision used subject-checksums with a base64 decode step to produce a checksums file. This was simplified to use subject-path directly since the built artifacts are always on disk in the same job where attestation runs, making the hash round-trip redundant.

For dry_run conditions, fromJSON(inputs.dry_run) was considered but there is no documentation confirming fromJSON() handles an already-boolean value safely. format() is documented to stringify any type, making it the safer choice.

A split release-please pattern (two-pass: releases first, then PRs) was briefly applied but reverted — it is only necessary for repos that upload artifacts to releases and need draft releases. This repo is attestation-only.

Additional context

These workflow changes can only be fully validated by an actual release run — they cannot be exercised by CI on a feature branch.

Link to Devin session: https://app.devin.ai/sessions/7d5bda4d9dbe4ae0b950b30a50485e60
Requested by: @keelerm84

@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@devin-ai-integration devin-ai-integration bot added the devin-pr Pull request created by Devin AI label Mar 31, 2026
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
@devin-ai-integration devin-ai-integration bot changed the title ci: use draft releases to support immutable GitHub releases ci: switch to actions/attest for provenance and add force-tag-creation Mar 31, 2026
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.
@devin-ai-integration devin-ai-integration bot changed the title ci: switch to actions/attest for provenance and add force-tag-creation ci: switch from SLSA provenance to actions/attest Mar 31, 2026
@devin-ai-integration devin-ai-integration bot changed the title ci: switch from SLSA provenance to actions/attest ci: switch from SLSA provenance to actions/attest with subject-path Mar 31, 2026
@kinyoklion kinyoklion marked this pull request as ready for review April 1, 2026 17:46
@kinyoklion kinyoklion requested a review from a team as a code owner April 1, 2026 17:46
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

needs: ['release-please']
permissions:
id-token: write # Needed for OIDC to get release secrets from AWS.
attestations: write # Needed for actions/attest.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused tag-name outputs left after provenance job removal

Low Severity

The four *-tag-name outputs in the release-please job (package-server-ai-tag-name, package-server-ai-langchain-tag-name, package-server-ai-openai-tag-name, package-server-ai-optimization-tag-name) are now dead code. Their only consumers were the *-provenance jobs (e.g., release-server-ai-provenance) which used them for upload-tag-name, and those jobs were all removed in this PR. No other workflow or job references these outputs.

Fix in Cursor Fix in Web

@keelerm84 keelerm84 merged commit 3f8d13c into main Apr 2, 2026
39 checks passed
@keelerm84 keelerm84 deleted the devin/1774991582-immutable-releases branch April 2, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devin-pr Pull request created by Devin AI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants