This repository contains automated scripts for managing release candidates (RC) in a hybrid development workflow. The scripts support two distinct lifecycles: Normal Development (hybrid automation) and Hotfix (manual process).
- π Normal Development Lifecycle
- π§ Hotfix Lifecycle
- π― Key Insights
- Scripts Overview
- Setup
- Script Documentation
- Workflow Examples
- Troubleshooting
- CI/CD Integration
Starting from production tag creation
π View Interactive Flow Diagram β
β
Production tag created (e.g., v2.11.0) from latest RC
β
Production workflow triggers: Deploy + bump main to next minor (2.12.0)
β
Main becomes: The starting point for next development cycle
π§ Engineer runs: ../cliq-rc-scripts/cut_rc.sh --version 2.12.0 --replace
π§ Or grab version from package.json: ../cliq-rc-scripts/cut_rc.sh --version $(node -p "require('./package.json').version") --replace
β
New RC created: release/2.12.0-rc.0 (first staging snapshot)
β
Staging workflow triggered: RC branch push triggers build and deploy
β
Development begins: Feature branches cut from main
π₯ Engineers create: Feature branches from main (feature/EN-1234-cool-thing)
π Work flows through: PRs back to main
π Each main merge: Triggers staging workflow β cut_rc.sh --replace (automatic)
π¦ RC train advances: rc.0 β rc.1 β rc.2... (each deletes previous)
π§ͺ Each RC deployment: Tests the cumulative changes on staging
β
Latest RC: Contains all merged features (e.g., release/2.12.0-rc.8)
π Engineer promotes:
../cliq-rc-scripts/promote_rc.shβ createsv2.12.0tag and GitHub Release../cliq-rc-scripts/promote_rc.sh --auto-next-rcβ promotes + automatically starts next RC train π¦ Production deployment: Release triggers production workflow
π Cycle repeats: Production workflow bumps main to2.13.0, ready for next development cycle
π Automatic continuation: With--auto-next-rc, the next RC train (release/2.13.0-rc.0) is created automatically
Starting with cutting hotfix branch
π View Interactive Flow Diagram β
π¨ Critical bug found in production v2.11.0
π Current state: Main is ahead at 2.12.0-rc.5, production is behind
π§ Engineer cuts: git checkout -b hotfix/critical-bug v2.11.0 (from production tag)
π οΈ Fix applied: Minimal change to address the issue
π¦ Version bumped: package.json β 2.11.1 (patch increment)
π·οΈ Tag created: v2.11.1 directly from hotfix branch (no RC process)
π¦ GitHub Release created: Published via gh release create or GitHub UI
π Production deploys: Hotfix goes live immediately
β
Production workflow: Detects hotfix β deploys only (no main version bump)
π Engineer creates PR: Merge hotfix/critical-bug β main
π Team reviews: Visible integration of production fix
β
PR merged: Hotfix code now in main alongside ongoing development
π Staging workflow: Triggered by main merge
π¦ Continues RC: release/2.12.0-rc.5 β release/2.12.0-rc.6 (now includes hotfix)
π§ͺ Staging testing: Validates hotfix works with new features
- Linear progression: Each cycle builds on the last
- Predictable: Version bumps and RC creation follow pattern
- Hybrid automation: First RC after production release is manual, subsequent RCs are automatic via staging workflow
- Collaborative: Multiple features flow through main
- Branch from production: Not from main (which may be ahead)
- Direct tagging: Hotfix is tagged directly (v2.11.1) without RC process
- Manual integration: Visible via PR process for team awareness
- Non-disruptive: Doesn't interfere with ongoing development train
- Eventually consistent: Hotfix gets into next release automatically when merged to main
The release management workflow consists of three main scripts that support both normal development and hotfix processes:
cut_rc.sh- Creates or advances release candidate branchespromote_rc.sh- Promotes an RC branch to a production release tagstatus_rc.sh- Shows current release state and recommends next actions
These scripts enforce a structured release workflow:
- Development happens on
main - Release candidates are cut to
release/X.Y.Z-rc.Nbranches - After testing, RCs are promoted to production tags
vX.Y.Z - Hotfixes branch from production tags and integrate back to main
Before you can run these scripts from anywhere in your filesystem, you need to pull down the repo and make them executable:
git clone git@github.com:adsupnow/cliq-rc-scripts.gitchmod +x ../cliq-rc-scripts/scripts/cut_rc.sh
chmod +x ../cliq-rc-scripts/promote_rc.sh
chmod +x ../cliq-rc-scripts/status_rc.shOr to make all scripts in the directory executable at once:
chmod +x ../cliq-rc-scripts/scripts/*.shUsed in the staging and prod github actions or by the engineer managing the production release or hotfix.
Purpose: Creates or advances release candidate branches from the main branch.
Usage:
./cut_rc.sh [options]Key Options:
--version X.Y.Z- Force specific target version--bump <patch|minor|major>- Start a new train with semantic version bump--base <ref>- Base ref for cutting RC (default:origin/main)--replace- Delete previous RC branch for the same version--dry-run- Preview actions without making changes
Examples:
# Start new development cycle after production release
./cut_rc.sh --version 2.12.0 --replace
# Continue existing RC train (rc.0 β rc.1 β rc.2...)
./cut_rc.sh --replacePurpose: Promotes a tested release candidate branch to a production release tag, with optional automatic creation of the next RC train.
Usage:
./promote_rc.sh [options]Key Options:
--rc <branch>- RC branch to promote (defaults to current branch)--message "<text>"- Custom annotated tag message--auto-next-rc- After promotion, automatically create next RC train from updated main branch--dry-run- Preview actions without making changes
Examples:
# Promote latest RC to production
./promote_rc.sh
# Promote specific RC branch
./promote_rc.sh --rc release/2.12.0-rc.8
# Promote with custom message
./promote_rc.sh --message "Release v2.12.0 - New features and bug fixes"
# Promote and automatically create next RC train (streamlined workflow)
./promote_rc.sh --auto-next-rc
# Dry run with auto-next-rc to preview full workflow
./promote_rc.sh --auto-next-rc --dry-runAuto Next RC Feature:
When --auto-next-rc is used, the script will automatically:
- Checkout main branch and pull latest changes
- Read version from
package.json - Run
cut_rc.sh --version $(node -p "require('./package.json').version") --replace - Create the new RC train (e.g.,
release/X.Y.Z-rc.0)
This eliminates the manual step of switching branches and creating the next RC after promotion.
Purpose: Displays the current state of release management and provides intelligent recommendations.
Usage:
./status_rc.sh [options]Key Options:
--commits- Show commits since last release--verbose- Show additional details like authors and commit counts--max <n>- Maximum commits to display (default: 10)
Examples:
# Check current release state
./status_rc.sh
# See what commits are ready for next release
./status_rc.sh --commits
# Detailed status for team reviews
./status_rc.sh --verbose --commits --max 20# Production v2.11.0 was just released
# Production workflow automatically bumps main to 2.12.0
# Engineer manually creates first RC:
./cut_rc.sh --version 2.12.0 --replace
# Creates: release/2.12.0-rc.0
# Pushes to remote β staging workflow builds and deploys automatically# Engineer merges feature PR to main
# Staging workflow automatically runs: cut_rc.sh --replace
# Creates: release/2.12.0-rc.1 (deletes rc.0)
# Staging workflow builds and deploys automatically
# Another feature merged to main
# Staging workflow automatically runs: cut_rc.sh --replace
# Creates: release/2.12.0-rc.2 (deletes rc.1)
# Staging workflow builds and deploys automatically
# Continue until ready for production...
# Latest RC: release/2.12.0-rc.8# All tests pass on release/2.12.0-rc.8
# Option 1: Standard promotion
./promote_rc.sh
# Creates: v2.12.0 production tag
# Publishes GitHub Release
# Production workflow deploys and bumps main to 2.13.0
# Engineer manually creates next RC train later
# Option 2: Streamlined promotion (recommended)
./promote_rc.sh --auto-next-rc
# Creates: v2.12.0 production tag
# Publishes GitHub Release
# Production workflow deploys and bumps main to 2.13.0
# Automatically creates: release/2.13.0-rc.0 (next development train ready)# 1. Promote RC to production
./promote_rc.sh
# β
Creates v2.12.0 tag and GitHub Release
# β
Production deploys and bumps main to 2.13.0
# 2. Engineer manually starts next development cycle (later)
git checkout main
git pull origin main # Get updated package.json with 2.13.0
./cut_rc.sh --version $(node -p "require('./package.json').version") --replace
# β
Creates release/2.13.0-rc.0
# Problem: Manual step, easy to forget, workflow gap# Single command handles promotion + next RC train
./promote_rc.sh --auto-next-rc
# β
Creates v2.12.0 tag and GitHub Release
# β
Production deploys and bumps main to 2.13.0
# β
Automatically creates release/2.13.0-rc.0
# β
Next development cycle immediately ready
# Benefit: No manual steps, no workflow gaps, seamless transitions# Production is on v2.11.0, main is ahead with 2.12.0-rc.5
git checkout -b hotfix/critical-security-fix v2.11.0
# Apply minimal fix
# Update patch in package.json to 2.11.1
git commit -am "fix: critical security vulnerability"
git push origin hotfix/critical-security-fix# Tag the hotfix directly (no RC process for hotfixes)
git tag -a v2.11.1 -m "Hotfix: critical security vulnerability"
git push origin v2.11.1
# Create GitHub Release (triggers production deployment)
gh release create v2.11.1 --title "Hotfix v2.11.1" --notes "Critical security vulnerability fix"
# OR create release via GitHub UI
# Production workflow detects hotfix (v2.11.1 < v2.12.0 on main) and deploys without bumping main# Create PR: hotfix/critical-security-fix β main
# Team reviews and merges
# Staging automatically picks up hotfix in next RC
# (CI/CD runs cut_rc.sh --replace after main merge)
# Creates: release/2.12.0-rc.6 (includes hotfix + ongoing features)# Check current state before any action
./status_rc.sh --commits
# Example output guides next steps:
# Latest Production: v2.11.0
# Active RC: release/2.12.0-rc.5
# Commits since v2.11.0: 25 commits
# Recommendation: Test RC or continue developmentWorking Tree Not Clean
# Error: working tree not clean
git status
git stash # or commit your changesTag Already Exists
# Error: tag vX.Y.Z already exists
# Could be a failed promotion or the version was already released
# If promotion failed, delete the tag and retry:
git tag -d v2.10.0 # delete local tag
git push origin :refs/tags/v2.10.0 # delete remote tag
# Fix any issues in RC, then re-run:
./promote_rc.sh
# If version was already released, continue RC train or start new version:
./cut_rc.sh --replace # continue current train
# or
./cut_rc.sh --version X.Y.Z+1 --replace # start new versionWrong Branch for Promotion
# Error: branch 'xxx' must match pattern: release/X.Y.Z-rc.N
git checkout release/2.12.0-rc.8 # switch to correct RC branch
./promote_rc.shUndo RC Branch (if not yet promoted)
git push origin :release/X.Y.Z-rc.N # delete remote branch
git branch -D release/X.Y.Z-rc.N # delete local branchUndo Production Tag (
git push origin :refs/tags/vX.Y.Z # delete remote tag
git tag -d vX.Y.Z # delete local tagCheck Current State
./status_rc.sh --commits # see what's ready for release
git tag -l 'v*' --sort=-version:refname | head -5 # recent production tags- Always use
--dry-runfirst when learning the scripts - Use
./status_rc.shbefore taking any action - Coordinate with team - only one person should manage releases at a time
- Use
--replaceto keep branch history clean - Test RCs thoroughly before promoting to production