-
fix(ci): make CLI releases reliably ship binary assets (#3515)
发布于
2026-06-16 11:07:23 +00:00 Summary
Permanently stops the recurring "release published with zero assets →
install/upgrade 404s" outage
(https://github.com/ComposioHQ/composio/issues/3408,
https://github.com/ComposioHQ/composio/issues/3269; regressions of
https://github.com/ComposioHQ/composio/issues/2625 and
https://github.com/ComposioHQ/composio/issues/1820 — 3 of the last 5
stable releases shipped empty).Root cause: a concurrent-writer race. On a CLI version bump,
changesets/actioncreates an empty@composio/cli@x.y.zGitHub
Release in seconds, then the slowerbuild-cli-binaries.ymlfails its
gh release createbecause the release already exists — so binaries
never attach.🥞 Stacked on #3415 (
pi/exclude-cli-ts-release-42161920), which
removes the second writer (changesets no longer creates CLI releases).
Review/merge #3415 first; this PR targets that branch. This PR hardens
the now-sole writer so a partial build can't publish either, and fixes
the monitoring that hid the failure.What changed (
build-cli-binaries.yml+ canary)- Draft → verify → publish. The release is built as a draft,
then a gate asserts all 6 canonical assets are present andstate == "uploaded"(loud::error::+ fail otherwise), and only the final step
flips it to published. Drafts fire norelease: publishedevent and are
excluded from/releases/latest, so no install.sh / Homebrew / redirect
consumer can observe an incomplete release. fail-fast: falseon the build matrix → a single platform failure
can never publish a partial set (needs.build.resultissuccessonly
if all legs pass).- Per-tag job-level
concurrencyso re-runs / quick pushes can't
interleave uploads on the same tag, without serializing unrelated betas. - Beta-safe:
--prereleaseis set on the draft so betas stay
prereleases through the publish flip. promote-stableguard usesgh release view --json isDraft(the
REST tags endpoint 404s on drafts) to resume an existing draft but
refuse an already-published tag.- Least privilege: workflow defaults to
contents: read; only the
release job opts up tocontents: write. - Canary fix (
cli.install-health-check.yml): install the newest
stable pinned tag (npm view @composio/cli version) instead of the
asset-aware no-arg flow, which self-heals to the last good release and
kept the canary green through every outage.
Idempotency note
Re-running a run that failed before publish is safe (reuse draft +
--clobber). An already-published tag is refused, not mutated — by
design.Testing
- Extended
test/release-workflow.test.ts(run viapnpm test:release-workflow) to lock in: draft→verify→publish ordering,
fail-fast: false, per-tag concurrency, preserved--prerelease, and
the pinned-tag canary. ✅ passes. shellcheckclean on the newrun:scripts; YAML validated.
actionlintruns in CI.- Runtime verification of the full green path happens on the next
release CI run.
Out of scope (deferred to their own PRs)
Per reviewer consensus, these are real but not this bug: a per-release
npm↔GitHub asset auditor (needs a grace window), the Homebrew trigger
constraint (folds into #3355),composio upgrademissing-asset back-off
(https://github.com/ComposioHQ/composio/issues/3269), and a rollback
runbook.
Co-authored-by: Rahul Tarak cryogenicplanet@gmail.com
下载附件
- Draft → verify → publish. The release is built as a draft,