Release operations (RC model)
This is the operator runbook for cutting and promoting releases. The model is
the classic one: main takes all merges, and every release — stable or
candidate — is cut deliberately by a maintainer. Nothing is ever published
automatically when code lands on main.
main— the integration branch. All pull requests (human and automated) target it. It is never frozen.release/vX.Y.Z— one frozen branch per stable version, created atrc.1and kept forever after promotion. Only cherry-picked bug fixes land on it during the RC window.
Cut a release candidate
Run the Release workflow (.github/workflows/release.yml, action: rc) from
the Actions tab, on main:
| Input | Meaning |
|---|---|
bump | patch, minor or major — anchors the n8nac (CLI) target version |
rc_number | 1 for the first cut, 2+ to re-cut an existing release branch |
target_version | optional explicit X.Y.Z for n8nac (e.g. to force 3.0.0) |
What happens:
- Per-package target versions are computed from conventional commits since each package's last stable tag (internal dependencies propagate as patch bumps, as before).
- The frozen branch
release/vX.Y.Zis created frommain(rc.1) or reused as-is (rc.2+ — it carries your cherry-picks, never delete it). - Every changed package is bumped to
X.Y.Z-rc.Non the release branch only and committed with[skip ci]. - Packages are published to npm with the
nextdist-tag (and mirrored torc), the VS Code extension is published as a--pre-release(Marketplace only — Open VSX never gets RCs), the tagvX.Y.Z-rc.Nis pushed, and a GitHub prerelease is created.
Install an RC locally with:
npm install n8nac@next
# (or npm install n8nac@rc)
Cherry-pick a fix during the RC window
git fetch origin
git checkout release/vX.Y.Z
git cherry-pick <fix-sha>
git push origin release/vX.Y.Z
Then re-run Release (.github/workflows/release.yml with action: rc) with the same bump/target_version and
rc_number + 1. The re-cut re-publishes -rc.N+1 including the fix.
Note: the branch name is always the stable version (release/v2.6.0),
never suffixed with -rc.N. Suffixing the branch name breaks promote.
Promote to stable
Run the Release workflow (.github/workflows/release.yml with action: promote)
with rc_tag = the last validated RC (e.g. v2.6.0-rc.2). In order:
- The release branch is checked out and must contain the RC tag.
-rc.Nsuffixes are stripped, final versions and CHANGELOGs are committed to the release branch.- npm packages are published under
latest(with provenance), the VS Code extension goes stable on the Marketplace and Open VSX. - Per-package tags (
[email protected], …) and the repo tagv2.6.0are pushed; a GitHub release marked latest is published. The MCP docker images build off the@n8n-as-code/mcp@v*tags — if thedocker-mcpworkflow did not trigger (tag pushes withGITHUB_TOKENdo not fire downstream events), dispatch it manually on the tag. - A sync pull request (
release/vX.Y.Z-sync→main) is opened and merged automatically (rebase), somaincarries the released versions and changelogs. If the auto-merge fails, merge that PR by hand — the release itself is already published and unaffected.
Order matters: everything that publishes runs before the main sync, so a sync failure can never mask a release.
Manual fallback
If a workflow is broken, the equivalent shell sequence is:
# Cut an RC
git checkout -b release/v2.6.0 origin/main
node scripts/release/workspace-release.mjs rc --bump minor --rc 1 --apply
git commit -am "chore(release): bump to 2.6.0-rc.1 [skip ci]"
git push origin release/v2.6.0
# Promote (on the release branch)
node scripts/release/workspace-release.mjs promote --apply
git commit -am "chore(release): bump to 2.6.0 [skip ci]"
git push origin release/v2.6.0
Dry-run any plan without applying by omitting --apply; the computed plan is
printed as JSON.
Credentials and environments
Both workflows run in the prod GitHub environment (npm trusted publishing
needs id-token: write and npm ≥ 11.5.1; VS Code tokens live there). RC runs
stamp telemetry as rc. CI uses the legacy next environment purely for its
cloud regression credentials — renaming it would require recreating the
environment and re-adding its secrets.
Invariants
- A tag containing
-(i.e.-rc.N) is a prerelease everywhere: npm dist-tagrc, VS Code--pre-release, GitHub prerelease. - VS Code Marketplace versions must be plain
major.minor.patchand strictly increasing. RCs are mappedX.Y.Z-rc.N→X.(Y-1).Non the odd minor below the stable line (even minor = stable, odd minor = pre-release). RC numbers only move forward, so pre-release versions always increase; re-publishing an existing version is skipped safely by the workflow, never forced. - Every published version must equal the workflow's computed target — promote re-asserts each package version before publishing.
- Versions and changelogs live on release branches;
mainreceives them only through the sync PR. - Release branches are never deleted; they are the record of what shipped and the base for backports.