Skip to content

fix(release-train): rebuild versioning as tag-driven, cross-channel aware and atomic#9

Merged
JSisques merged 1 commit into
mainfrom
claude/cicd-versioning-workflow-ew7711
Jun 12, 2026
Merged

fix(release-train): rebuild versioning as tag-driven, cross-channel aware and atomic#9
JSisques merged 1 commit into
mainfrom
claude/cicd-versioning-workflow-ew7711

Conversation

@JSisques

Copy link
Copy Markdown
Contributor

Problem

The release train could publish a beta of a version that had already graduated to stable — exactly what happened on gardenia-api: staging kept iterating 0.15.1-beta.N after v0.15.1 had shipped stable on main, while develop was already on 0.15.2-alpha.N.

Root causes:

  1. Each channel derived its version from its own latest tag in isolation. Once any beta tag existed, staging always continued the highest beta cycle — the promote-beta path could literally never run after the first cycle, and there was no check against the stable line (only the alpha channel had a partial patch for this).
  2. Bumps were computed relative to package.json (npm version prerelease), which drifts between branches. This is how v0.15.1-beta.1 appeared with no beta.0 ever existing.
  3. The Docker image was published before the git tag was pushed. A failed push meant the next run recomputed and reused the same version with different content.

Changes

  • detect.sh rewritten: git tags are the single source of truth and the exact next version is computed in one place, with full cross-channel awareness. Core invariant: every emitted version is strictly greater than the latest stable release — a stale pre-release cycle whose base already shipped is abandoned, never continued. Staging promotes the live alpha cycle; main graduates the leading beta; hotfixes merged straight to staging or main get their own paths (previously these errored). New-cycle bumps follow conventional commits (feat: → minor, breaking → major, otherwise patch).
  • docker-release.yml: applies the computed version verbatim (npm version <exact>), removing the relative npm-version math and the now-obsolete release-train-bump action. Safe publish ordering: build image (no push) → atomic git push of release commit + tag (with retries) → registry push → GitHub Release. A git tag can no longer lag behind a published image. Release commits now use chore(release): so git-cliff skips them in changelogs.
  • Tests: 17-scenario suite for the version computation (36 assertions), including a regression test reproducing the exact production failure, plus a CI workflow running it and shellcheck on every PR.
  • Docs: full release-train section in the README.

Verification

  • All 36 test assertions pass.
  • Simulated the full train over the real (broken) gardenia-api tag state: the next merge to staging produces 0.15.2-beta.0 (abandoning the stale 0.15.1-beta.3), main graduates 0.15.2, develop then opens 0.16.0-alpha.0. The system self-heals with no manual tag surgery.

https://claude.ai/code/session_01MFD8imoXtKUEUoZTvL5Ztv


Generated by Claude Code

…ware and atomic

The release train could publish a beta of a version that had already
graduated to stable (e.g. 0.15.1-beta.N after v0.15.1 shipped) because
each channel derived its version from its own latest tag in isolation,
and bumps were computed relative to package.json, which drifts between
branches.

- detect.sh now computes the EXACT next version in one place, from git
  tags only, with full cross-channel awareness: every version is
  strictly greater than the latest stable; stale pre-release cycles are
  abandoned; staging promotes the newest alpha cycle; main graduates
  the leading beta (with hotfix fallbacks for staging/main).
- Conventional commits drive new-cycle bumps (feat -> minor, breaking
  -> major, otherwise patch).
- docker-release applies the computed version verbatim (npm version
  <exact>), removing the relative npm-version math and the
  release-train-bump action.
- Safe publish ordering: build image (no push) -> atomic git push of
  release commit + tag (with retries) -> registry push -> GitHub
  Release. A git tag can no longer lag behind a published image.
- Release commits now use chore(release): so git-cliff skips them in
  changelogs.
- Add a 17-scenario test suite (incl. a regression test for the
  stale-beta bug) and a CI workflow running it + shellcheck.

https://claude.ai/code/session_01MFD8imoXtKUEUoZTvL5Ztv
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants