Skip to content

ci: use draft releases to support immutable GitHub releases#516

Merged
kinyoklion merged 15 commits into
mainfrom
devin/1774991616-immutable-releases
Jun 29, 2026
Merged

ci: use draft releases to support immutable GitHub releases#516
kinyoklion merged 15 commits into
mainfrom
devin/1774991616-immutable-releases

Conversation

@keelerm84

@keelerm84 keelerm84 commented Mar 31, 2026

Copy link
Copy Markdown
Member

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:

  1. release-please-config.json — Added top-level "draft": true so release-please creates draft releases for all packages. Added "force-tag-creation": true to every package (not yet supported by release-please, but included for forward compatibility).
  2. release-please.yml — Split release-please pattern — release-please is now invoked twice within the same job:
    • First call with skip-github-pull-request: true — only creates releases (no PRs).
    • Inline tag creation — if any package was released, checks out the repo and creates git tags manually (release-please skips tag creation for drafts). Iterates over all 4 packages (client, server, server-redis, server-otel) using env vars to avoid script injection. Idempotent — skips if the tag already exists.
    • Second call with 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.
    • All downstream artifact jobs (release-client, release-server, etc.) now depend only on release-please (the former separate create-tags job has been removed).
    • Action pinned to googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 (v4.4.0).
  3. SLSA → 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 inline actions/attest@v4 steps in each build job that decode the base64 hashes into a checksums file and attest in-place.
  4. 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.
  5. manual-sdk-release-artifacts.ymlpublish_release input — Added a publish_release boolean input (default: true) and a publish-release job gated on it, so operators can optionally keep the release in draft after manual artifact uploads.

Review & Testing Checklist for Human

  • Split release-please ordering: The two release-please invocations must run in this exact order — releases first, then PRs. If the second call (PR creation) ran when a release was created, it would see no tag and open a duplicate release PR. Verify the if condition on the second call correctly uses != 'true' with && across all 4 packages.
  • needs arrays in publish-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-client needs both release-client (3-OS matrix) and release-client-mac-arm64.
  • server-otel has no publish-release job: release-please creates a tag for server-otel if released, and "draft": true means release-please creates a draft release, but there is no publish-release-server-otel job 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).
  • End-to-end test: Trigger a test release (or review a prior release's output) to confirm: (a) draft release is created, (b) tags are pushed, (c) artifacts upload successfully, (d) attestation succeeds, (e) release is un-drafted. Also test the manual workflow with publish_release: false to verify the release stays in draft.

Notes

  • This follows the split release-please pattern established in 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.
  • The ${{ github.repository }} expression appears in run: 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-creation has 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's publish_release defaults to true for workflow_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


Note

Medium Risk
Changes release publishing order and provenance model; mis-timed publish jobs could finalize releases before all artifacts upload, and otel publish runs without waiting on artifact jobs.

Overview
Supports immutable GitHub releases by having release-please create draft releases (draft + force-tag-creation in release-please-config.json), uploading artifacts while still draft, then gh release edit --draft=false only after all build jobs finish (publish-release-* in release-please.yml, optional publish_release on the manual workflow).

Provenance moves from separate SLSA jobs to per-platform actions/attest steps that decode base64 artifact hashes into checksums.txt (with macOS vs GNU base64 handling). Build jobs gain attestations / id-token permissions; matrix jobs no longer export hash outputs for downstream SLSA.

release-please is bumped to v5.0.0 (single run; tags for drafts via force-tag-creation). server-sdk-dynamodb is wired through automated release (outputs, matrix + arm64 jobs, publish job) and the manual artifact workflow target list.

sdk-release sets CURL_ROOT / CMAKE_PREFIX_PATH on Linux/macOS non-CURL builds so aws-sdk-cpp (dynamodb) can satisfy find_package(CURL) during CMake configure.

Reviewed by Cursor Bugbot for commit 722ee53. Bugbot is set up for automated code reviews on this repo. Configure here.

@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

@kinyoklion kinyoklion marked this pull request as ready for review April 1, 2026 17:59
@kinyoklion kinyoklion requested a review from a team as a code owner April 1, 2026 17:59
Comment thread .github/workflows/release-please.yml
Comment thread .github/workflows/release-please.yml Outdated
Comment thread .github/workflows/release-please.yml
Comment thread release-please-config.json Outdated
…table-releases

# Conflicts:
#	.github/workflows/manual-sdk-release-artifacts.yml
#	.github/workflows/release-please.yml
Comment thread .github/workflows/release-please.yml Outdated
Comment thread release-please-config.json

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 using default effort 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.

Reviewed by Cursor Bugbot for commit 79db44b. Configure here.

Comment thread release-please-config.json
beekld added 2 commits June 29, 2026 10:19
## Summary

Wires `libs/server-sdk-dynamodb-source` into the release-please draft +
publish flow so its releases cut and un-draft automatically, same as
client/server/redis.

- `"draft": true` in `release-please-config.json` for dynamodb.
- `release-server-dynamodb` (matrix) + `-mac-arm64` +
`publish-release-server-dynamodb` jobs in `release-please.yml`. Mirrors
the redis pattern.
- `sdk-release` action passes `CURL_ROOT` and `CMAKE_PREFIX_PATH` to its
Linux and macOS Boost.Beast build steps. aws-sdk-cpp calls
`find_package(CURL)` on Linux/macOS regardless of `LD_CURL_NETWORKING`;
on macOS the hint is needed because homebrew's curl isn't in cmake's
default search path. Windows uses WinHTTP, so aws-sdk-cpp doesn't need
libcurl there and the env isn't passed.

The dynamodb release path has never been cut end-to-end. Per-package CI
builds dynamodb daily, but the `sdk-release` composite action hasn't
been run against it -- the first real release may surface latent issues.
@kinyoklion kinyoklion merged commit 9373dad into main Jun 29, 2026
47 checks passed
@kinyoklion kinyoklion deleted the devin/1774991616-immutable-releases branch June 29, 2026 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants