ci: use draft releases to support immutable GitHub releases#516
ci: use draft releases to support immutable GitHub releases#516
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:
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
| run: > | ||
| gh release edit "$TAG_NAME" | ||
| --repo ${{ github.repository }} | ||
| --draft=false |
There was a problem hiding this comment.
Server-otel draft release never gets published
High Severity
The global "draft": true setting causes release-please to create draft releases for all packages, and the create-tags job explicitly creates a tag for server-otel when released. However, there is no publish-release-server-otel job to un-draft the release. The server-otel release will remain permanently invisible as a draft on GitHub, which is a regression from pre-PR behavior where release-please published it directly.
Additional Locations (2)
| fi | ||
| shell: bash | ||
| - name: Attest build provenance | ||
| uses: actions/attest@v4 |
There was a problem hiding this comment.
Attest action unpinned unlike all other actions
Medium Severity
All 8 instances of actions/attest@v4 are referenced by a mutable major-version tag, while every other action in both workflows (actions/checkout, googleapis/release-please-action) is pinned to a specific commit SHA. A compromised or force-pushed v4 tag could inject malicious code into the release pipeline, which runs with contents: write, attestations: write, and id-token: write permissions.
Additional Locations (1)
| elif [ -n "${HASHES_MACOS}" ]; then | ||
| echo "${HASHES_MACOS}" | base64 -d > checksums.txt | ||
| fi | ||
| shell: bash |
There was a problem hiding this comment.
macOS base64 -d triggers debug, not decode
High Severity
On macOS, BSD base64 -d means --debug (verbose logging), not --decode (which requires uppercase -D). The sdk-release action already handles this asymmetry when encoding (base64 -w0 on Linux vs base64 -b 0 on macOS), but all new decoding steps use GNU-style base64 -d universally. On macOS runners, this produces incorrect checksums.txt content, causing the attestation step to fail. Since the matrix job then fails, publish-release-* jobs are blocked and releases remain permanently in draft.


Summary
Migrates the release workflow to support GitHub's immutable releases feature. Once a release is published it can no longer be modified, so we now create releases in draft state, upload all artifacts, and only then publish.
Changes across three files:
release-please-config.json— Added top-level"draft": trueso release-please creates draft releases for all packages. Added"force-tag-creation": trueto every package (not yet supported by release-please, but included for forward compatibility).release-please.yml— Split release-please pattern — release-please is now invoked twice within the same job:skip-github-pull-request: true— only creates releases (no PRs).skip-github-release: true— only creates/updates PRs, and only runs if no releases were created. This ordering ensures tags exist before release-please checks whether a release PR is still needed.release-client,release-server, etc.) now depend only onrelease-please(the former separatecreate-tagsjob has been removed).googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38(v4.4.0).actions/attest@v4— Removed all 7 SLSA provenance jobs (release-{client,server,server-redis}-provenance,release-{client,server,server-redis}-mac-arm64-provenance, plus 2 in the manual workflow). Replaced with inlineactions/attest@v4steps in each build job that decode the base64 hashes into a checksums file and attest in-place.publish-release-*jobs — Three new jobs (publish-release-client,publish-release-server,publish-release-server-redis) that un-draft their respective release only after all artifact jobs complete.manual-sdk-release-artifacts.yml—publish_releaseinput — Added apublish_releaseboolean input (default:true) and apublish-releasejob gated on it, so operators can optionally keep the release in draft after manual artifact uploads.Review & Testing Checklist for Human
ifcondition on the second call correctly uses!= 'true'with&&across all 4 packages.needsarrays inpublish-release-*jobs: Verify each publish job waits on ALL artifact-uploading jobs for that package before un-drafting. A missing dependency means the release gets published before all artifacts are uploaded — the exact problem we're solving. For example,publish-release-clientneeds bothrelease-client(3-OS matrix) andrelease-client-mac-arm64.release-pleasecreates a tag for server-otel if released, and"draft": truemeans release-please creates a draft release, but there is nopublish-release-server-oteljob to un-draft it. If server-otel has no artifact uploads this is fine — but confirm the draft release won't stay stuck.actions/attest@v4(unpinned): The attest action is referenced by major version tag, not a pinned SHA. Verify this aligns with the repo's policy on action pinning (other actions like checkout are SHA-pinned).publish_release: falseto verify the release stays in draft.Notes
ld-relay(commit 1581de9). The key insight is that release-please depends on the tag existing when determining if a release PR is still needed — so tags must be created between the release step and the PR step.${{ github.repository }}expression appears inrun:blocks (tag creation and publish-release jobs). This value is GitHub-controlled (not user input) so script injection risk is negligible, but worth noting since tag names are deliberately routed through env vars.force-tag-creationhas no effect with the current release-please version — it is a forward-compatibility placeholder that will take effect once release-please supports it, at which point the inline tag creation steps can be removed.manual-sdk-release-artifacts.yml'spublish_releasedefaults totrueforworkflow_dispatch, matching the expectation that manual runs typically want to finalize the release.Link to Devin session: https://app.devin.ai/sessions/7d5bda4d9dbe4ae0b950b30a50485e60
Requested by: @keelerm84