Release Pipeline: migrate from version-specific branches to main/development
Repo: QuickCorp/QCObjects
Current state
The repo has version-specific branches (v2.2, v2.3, v2.4-beta, v2.4-ts, v2.5-beta) and three separate npm publish workflows (npmpublish-beta.yml, npmpublish-lts.yml, npmpublish-main.yml).
Why this change
Version-specific branches tracked different architecture waves (ECMA5, ES6+JS, full TS+JS). As the number of active tracks grew, branch-based management added complexity: CI workflows needed per-branch configuration, PR paths were unclear, and promoting a beta to LTS required manual cross-branch coordination.
What changed
- Removed all version-specific branches (v2.2, v2.3, v2.4-beta, v2.4-ts, v2.5-beta)
- Single active development branch:
development
- Release channel is encoded in the tag suffix, not in a branch name
- Old version tracks preserved as archive tags
Branch model
main ← release digest (merged from development via PR)
development ← single active development branch
feature/* ← topic branches, PR into development
fix/*
bugfix/*
No more version-specific branches. Every release is a tag on main.
Release channels (tags)
| Tag pattern |
npm dist-tag |
Triggered by |
vX.Y.Z |
latest |
consolidated npmpublish.yml |
vX.Y.Z-lts |
lts |
consolidated npmpublish.yml |
vX.Y.Z-beta |
beta |
consolidated npmpublish.yml |
(future) -dev |
dev |
(add pattern) |
(future) -alpha |
alpha |
(add pattern) |
Promotion workflow
- Daily work on
development branch
v-patch --git --npm → tag vX.Y.Z-beta (beta publish)
- Change VERSION suffix →
v-patch --git --npm → tag vX.Y.Z-lts (LTS publish)
- PR
development → main → merge → tag vX.Y.Z on main (latest publish)
Branch snapshot and removal steps
Prerequisites
Archive old version branches
git tag archive/v2.4-beta origin/v2.4-beta
git push origin archive/v2.4-beta
git tag archive/v2.4-ts origin/v2.4-ts
git push origin archive/v2.4-ts
git tag archive/v2.2 origin/v2.2
git push origin archive/v2.2
Bootstrap development from v2.5-beta
git checkout -b development origin/v2.5-beta
git push -u origin development
Delete old remote branches
git push origin --delete v2.5-beta v2.4-beta v2.4-ts v2.3 v2.2
Delete old local branches
Verify
git branch -a # should show only main, development
git tag -ln archive/* # should show archive tags
CI pipeline updates
| File |
Change |
.github/workflows/npmpublish-beta.yml |
Remove — consolidated into single npmpublish.yml |
.github/workflows/npmpublish-lts.yml |
Remove — consolidated into single npmpublish.yml |
.github/workflows/npmpublish-main.yml |
Replace with consolidated npmpublish.yml from qcobjects-cli |
.github/workflows/codeql-analysis.yml |
Branch targets from [v2.3, v2.4] to [main, development] |
The consolidated npmpublish.yml should detect the channel from the tag suffix:
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Set npm dist-tag
run: |
TAG="${GITHUB_REF_NAME#v}" # strip leading v
case "$TAG" in
*-lts) NPM_TAG=lts ;;
*-beta) NPM_TAG=beta ;;
*) NPM_TAG=latest ;;
esac
npm dist-tag add "$(node -p "require('./package.json').name")@${TAG}" "$NPM_TAG"
Archived tracks
| Archive tag |
Source branch |
archive/v2.4-beta |
origin/v2.4-beta |
archive/v2.4-ts |
origin/v2.4-ts |
archive/v2.2 |
origin/v2.2 |
v2.3.50 (existing tag) |
v2.3 branch |
Future considerations
- When starting a new architecture wave (e.g. v2.6), branch from
main into a feature branch, develop on development, and release via the same tag flow
- Archived branches are never deleted from git history — the tags ensure the code is always accessible
Release Pipeline: migrate from version-specific branches to main/development
Repo: QuickCorp/QCObjects
Current state
The repo has version-specific branches (
v2.2,v2.3,v2.4-beta,v2.4-ts,v2.5-beta) and three separate npm publish workflows (npmpublish-beta.yml,npmpublish-lts.yml,npmpublish-main.yml).Why this change
Version-specific branches tracked different architecture waves (ECMA5, ES6+JS, full TS+JS). As the number of active tracks grew, branch-based management added complexity: CI workflows needed per-branch configuration, PR paths were unclear, and promoting a beta to LTS required manual cross-branch coordination.
What changed
developmentBranch model
No more version-specific branches. Every release is a tag on
main.Release channels (tags)
vX.Y.Zlatestnpmpublish.ymlvX.Y.Z-ltsltsnpmpublish.ymlvX.Y.Z-betabetanpmpublish.yml-devdev-alphaalphaPromotion workflow
developmentbranchv-patch --git --npm→ tagvX.Y.Z-beta(beta publish)v-patch --git --npm→ tagvX.Y.Z-lts(LTS publish)development→main→ merge → tagvX.Y.Zonmain(latest publish)Branch snapshot and removal steps
Prerequisites
Archive old version branches
Bootstrap development from v2.5-beta
Delete old remote branches
Delete old local branches
Verify
CI pipeline updates
.github/workflows/npmpublish-beta.ymlnpmpublish.yml.github/workflows/npmpublish-lts.ymlnpmpublish.yml.github/workflows/npmpublish-main.ymlnpmpublish.ymlfrom qcobjects-cli.github/workflows/codeql-analysis.yml[v2.3, v2.4]to[main, development]The consolidated
npmpublish.ymlshould detect the channel from the tag suffix:Archived tracks
archive/v2.4-betaorigin/v2.4-betaarchive/v2.4-tsorigin/v2.4-tsarchive/v2.2origin/v2.2v2.3.50(existing tag)v2.3branchFuture considerations
maininto a feature branch, develop ondevelopment, and release via the same tag flow