Hive
feat(cli): release channels (canary / rc / stable)
GitHub issue · Closed
What changed
Implements the release channels RFC, restructuring CLI distribution into three channels with different stability guarantees.
The model shift: today every CLI-touching commit to main cuts a stable X.Y.Z and moves the “Latest” pointer. After this change, main only ever publishes canary prereleases. Stable is reached deliberately:
| Channel | Version | Cadence | Resolved by default? |
|---|---|---|---|
| Canary | X.Y.0-canary.N |
every CLI-touching commit to main |
no — opt-in |
| Release candidate | X.Y.0-rc.N |
cut from main onto releases/X.Y.x, soaks |
no — opt-in |
| Stable | X.Y.Z |
promoted after a clean soak | yes |
Patches on a stable line keep flowing through the unchanged cli-backport.yml.
CLI release pipeline (feat(cli))
mise/tasks/cli/release/channel-version.sh(new) — single script deriving the next version per channel (canary/rc-new/rc/promote) from the git tag set.cli-release.yml— repurposed from stable-cutter into the canary publisher (prerelease, never Latest, no Homebrew; skips when HEAD already has a canary tag).cli-rc.yml(new) — dispatch: emptybranchcuts a newreleases/X.Y.xline +rc.1; an existing branch iteratesrc.N+1.cli-promote.yml(new) — dispatch: promotes a soaked RC to stableX.Y.0(make_latest=true+ Homebrew).cli/cliff.toml—ignore_tags = "rc|canary"so prerelease tags never anchor a changelog section.- All four reuse
cli-build-publish.ymlunchanged and share thecli-publishconcurrency group.
Server + docs (fix(server))
releases.ex— root-cause correctness fix.get_latest_cli_releaseonly filtered tag names that fail to parse as aVersion, but a canary like4.201.0-canary.5parses fine and sorts above the latest stable4.200.x(a prerelease only loses the compare whenmajor.minor.patchare equal). Without this, a canary would be advertised as the recommended install. Now gated on%Version{pre: []}; regression test added.- New Release channels docs page (channels table, pinning strategy, two-line backport policy) registered in the sidebar, with cross-links from the install and compatibility pages.
Why
Teams upgrading Tuist hit regressions because stable releases bundle unrelated changes. Decoupling fixes from features gives a slow-moving recommended install (tuist@latest / tuist@4.200) that only receives backported fixes, while early adopters keep per-commit builds on canary.
How the canary minor advances
The script’s “highest cut line” is the max minor over stable + RC tags only — canary is deliberately excluded, since it tracks the next minor and counting it would chase its own tail. Because rc-new creates the release branch and publishes rc.1 atomically, the moment a line is cut, main’s canary advances to the following minor. So main keeps moving while a line soaks.
Validation
channel-version.shexercised end-to-end in a throwaway git repo: all four channels plus every error guard (already-stable line, missing RC, malformed branch name, unknown channel).mix test test/tuist/github/releases_test.exs→ 14 tests, 0 failures (includes the new prerelease-exclusion test).shellcheckclean;actionlintclean apart from the pre-existingtuist-linuxself-hosted-runner label note (same ascli-backport.yml).
Reviewer notes
cli-rc.ymlauto-creates thereleases/X.Y.xbranch by pushing from CI withTUIST_RELEASE_GITHUB_TOKEN. If a branch-protection ruleset blocks branch creation by that token, the rc-new path will fail and the token needs creation bypass on thereleases/*pattern. Pushes to existing protected branches still go through PRs.- RC cuts, RC iterations, and promotions are all manual
workflow_dispatchper the RFC — no cron. The RFC’s open questions (2-week cadence, soak-gating on tester evidence) are operational and intentionally left unencoded. - No changes to CLI public API/behavior, and no changes to the server/cache release processes beyond the latest-detection filter.
🤖 Generated with Claude Code
This feature is now available in 4.201.0-canary.5. Update to this version to use release channels (canary, rc, stable).
The release channels feature (canary / rc / stable) is now available in 4.201.0-canary.7. This restructures CLI distribution so that main publishes canary prereleases, release candidates soak on dedicated branches, and stable releases are promoted deliberately after a clean soak period.
See the new Release channels documentation for details on pinning strategies and channel stability guarantees.
Update to 4.201.0-canary.7 to use this feature.
Release channels (canary / rc / stable) are now available in 4.201.0-canary.9. This restructures CLI distribution into three channels with different stability guarantees: canary for per-commit builds from main, release candidate for soak testing, and stable as the default recommended install. Update to 4.201.0-canary.9 to use this feature.
Release channels (canary / rc / stable) are now available in 4.201.0-canary.12. This restructures CLI distribution into three channels with different stability guarantees: canary prereleases on every CLI-touching commit to main, release candidates that soak on release branches, and stable releases promoted after a clean soak. Update to this version to start using the new channel model.
Release channels (canary / rc / stable) are now available in 4.201.0-canary.11. This restructures CLI distribution into three channels: canary prereleases for every CLI-touching commit, release candidates that soak on release branches, and stable releases promoted after a clean soak.
Update to 4.201.0-canary.11 to use this feature.
This is now available in 4.201.0-canary.10. Update to pick up the release channels feature (canary / rc / stable).
Release channels (canary / rc / stable) are now available in 4.201.0-canary.19. This introduces a three-channel distribution model: canary builds from main, release candidates that soak on release branches, and stable releases promoted after validation. Update to 4.201.0-canary.19 to start using release channels.