ci(release): support release/* branches with version-comparison gating#3530
ci(release): support release/* branches with version-comparison gating#3530
Conversation
Lets us ship a patch (e.g. 4.4.6) from a release/4.4.x branch without
including unreleased work merged into main, and without the patch
clobbering floating tags incorrectly.
The release-pipeline pieces this touches and how each behaves now:
npm dist-tag latest if version > current latest, else release-<M.m>
Docker :v4-beta same gate (highest version only)
Docker :release-X.Y new per-line floating tag, always set on a semver build
GitHub release --latest=true|false set explicitly (no auto-detect)
How the gate is computed:
release.yml's 'Compare new version to current latest' step queries
npm view @trigger.dev/sdk dist-tags.latest, compares via sort -V,
sets is_latest=true|false. Drives every floating tag.
Triggers / refs:
- pull_request:branches[main, release/**]
- if-conditions allow head.ref starting with 'changeset-release/'
- workflow_dispatch ref must be reachable from main OR a release/* branch
- changesets-pr.yml fires on push to release/** too; PR-enhance step
discovers source branch dynamically (no more hardcoded changeset-release/main)
Other changes:
- gh release create: drop --target main (tag carries right commit)
- dispatch-changelog payload includes is_latest so the marketing site
can render lagged-line releases differently
- enhance-release-pr.mjs prepends a Release prep header on release/*
branches showing version, current latest, and whether the PR will
take the latest dist-tag
release-helm.yml unchanged — already creates as draft+prerelease so it
can't claim Latest. publish-worker.yml (coordinator/provider) unchanged
since those don't have a :v4-beta-equivalent floating tag.
Validated end-to-end in ericallam/pkgring-sandbox across both scenarios:
Scenario A (lagged hotfix): latest stays put, only release-X.Y moves
Scenario B (main has unreleased work, hotfix is highest): latest moves
|
|
Caution Review failedFailed to post review comments WalkthroughWorkflows and a PR enhancer were updated to support release/** branches and to propagate a computed is_latest flag through the release pipeline. changesets-pr now derives SOURCE_BRANCH from the PR ref, fetches the corresponding changeset-release branch, reads the package version from that branch, and passes SOURCE_BRANCH to the enhancer. release.yml compares the new version to npm dist-tags.latest, emits is_latest and dist_tag outputs, and forwards them to downstream steps. publish workflows accept is_latest and perform semver-aware Docker tagging (adding release-MAJOR.MINOR and optionally v4-beta). scripts/enhance-release-pr.mjs obtains release context and renders a “Release prep” section in PR bodies. Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Detailed summary
No public API or exported symbol declarations were changed. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Adds support for shipping a patch release from a
release/<major>.<minor>.xbranch alongside the existing main-only flow. Use this when main has unreleased changes you can't include in the next release — a customer hotfix on the current line, an emergency patch, etc.When to use this
You're on
4.4.5. Main has merged work queued for4.5.0(a feature, a refactor — anything not ready to ship). A customer hits a bug. Normally you'd be stuck: shipping from main bundles the unreleased work; reverting on main is messy.With this PR you can cut
release/4.4.x, ship4.4.6, and main stays untouched. The patch goes through the normal release pipeline — npm publish, Docker image, Helm chart, GitHub release, marketing-site changelog — and customers runningnpm install @trigger.dev/sdkget it.If you don't need this, don't use it. Normal main releases work exactly as before.
How to ship a patch from a release branch
The flow has five logical steps. Two of them are automated by the existing release pipeline and you don't do anything for them — they're called out here so you understand what's happening.
1. Create the release branch from the last release tag
A release branch is a parallel timeline that starts from a known-released commit and accumulates patches independently of main.
You always cut from a tag (
v4.4.5), not from main HEAD. The tag is immutable and points at exactly the code customers are running. Cutting from main HEAD would pull in any commits or pending changesets that have landed since the tag — defeating the purpose.The branch name follows the pattern
release/<major>.<minor>.x— one branch per minor line.release/4.4.xaccumulates4.4.6,4.4.7, etc. — never a4.5.xrelease.2. Apply the fix
The release branch represents
v4.4.5 + the fix, and nothing else from main. Two ways to get the fix onto the branch:git cherry-pick <sha>for a single commit,git cherry-pick A..Bfor a range.Either way, the result is the same: this branch's tip is
v4.4.5 + the fix.3. Add a changeset (and optionally a
.server-changes/entry)Changesets is the system that tells the release pipeline what to bump. Without a changeset, the pipeline has no work to do — there's no version to publish. Each changeset is a markdown file in
.changeset/declaring which packages bump and by how much.For a patch release, you typically want
patchon the package(s) you fixed. The changesetsfixedconfig will cascade the bump across the linked packages automatically, so you don't need to list every package.If the fix is server-only (webapp behavior, not a published package), use
.server-changes/instead. Both formats are picked up by the pipeline; only.changeset/ones bump versions.4. (Automated) Version PR opens
Pushing to a
release/*branch triggerschangesets-pr.yml, the same workflow that opens release PRs from main. It runschangeset version, applies the bumps, stampsChart.yaml, consumes any.server-changes/, and opens a pull request titledchore: release v4.4.6(the title comes from the post-process script — that's also where the version is computed and shown).The PR's body now starts with a "Release prep" header containing:
lateston npmlatestfloating tags ("yes" if the proposed version is higher than current latest; "no" otherwise — see "What gets published" below for what that means)That header is the at-a-glance check that the release pipeline understood the situation correctly. Review the rest of the PR like any other release PR.
5. Merge the version PR → release ships
Merging triggers
release.yml. From the release pipeline's point of view, a release-branch merge looks identical to a main merge — same publish steps, same Docker tags, same Helm chart push, same marketing-site dispatch. The only thing that changes is which floating tags the publish takes (see below).6. Port the fix back to main
After the release ships, the fix exists on the release branch but not on main. If you don't bring it back, main's next release won't include the fix and the same bug will reappear.
You want to cherry-pick the fix commit only — not the version-bump commit. The version-bump commit is the changeset PR's auto-generated bump (it edits
package.json,Chart.yaml, etc.) and cherry-picking it onto main would conflict with main's existing versions and delete the consumed changeset.Main's next release naturally rolls up the fix at whatever version main is on.
What gets published
A successful release-branch run publishes:
@trigger.dev/{sdk,core,cli-v3,...}@4.4.6ghcr.io/triggerdotdev/trigger.dev:v4.4.6andghcr.io/triggerdotdev/trigger.dev:release-4.44.4.6v4.4.6Whether it also takes the floating tags (
npm latest, Docker:v4-beta, GitHub "Latest" badge, headline placement on the changelog) depends on whether4.4.6is higher than the currentlateston npm:4.4.5(queued work unreleased) →4.4.6 > 4.4.54.4.64.6.0→4.4.6 < 4.6.0(lagged hotfix)4.6.0In the lagged case,
4.4.6still publishes — but customers runningnpm install(no version pin) keep getting4.6.0. Customers who want the patch on the4.4.xline install withnpm install @trigger.dev/sdk@release-4.4(or pin Docker to:release-4.4).The version PR's "Release prep" header shows which case you're in before you merge.
Common pitfalls
package.jsonconflicts and deletes the consumed changeset on main.release/4.4.xandrelease/4.5.xwork concurrently. The repo-wideconcurrency.grouponrelease.ymlserializes them so they don't collide on tags.release/4.0.xcut six months ago has the.github/workflows/from then. If you need a hotfix on a very old line, expect to update the workflows on that branch first (cherry-pick relevant CI changes from main).Files changed
CI / scripts only. No package or app code changes.
release.yml— version-comparison gating,release/**triggers, propagatesis_latestpublish.yml,publish-webapp.yml,publish-worker-v4.yml—is_latestinput, gate:v4-beta, add:release-<M.m>changesets-pr.yml— trigger onrelease/**, dynamic source-branch handlingscripts/enhance-release-pr.mjs— release-branch context header on the version PRValidation
End-to-end tested in a sandbox repo with the same pipeline shape (3 npm packages, Docker image, Helm chart, cross-repo dispatch). Real npm publishes, real GHCR builds. Confirmed:
is_latestvalue