Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions .github/workflows/squad-version-promote.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
name: Squad Version Promote

# Automatically bumps the dev branch base version after an official release from main.
# Triggered when a GitHub Release is published (which squad-release.yml creates after a push to main).
# Reads the released version, computes the next minor version, and commits updated
# package.json files to dev so the branch is always prepared for the next release cycle.
#
# Example: release v0.11.0 is published → dev is bumped to 0.12.0
#
# Safety: the bump is skipped when dev is already ahead of the released version,
# so manually pre-bumped branches are never overwritten.

on:
release:
types: [published]

# Manual trigger for testing / recovery — supports dry_run and version override
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run — show what would happen without pushing'
required: false
default: 'false'
type: choice
options: ['false', 'true']
released_version:
description: 'Override released version (for testing, e.g. 0.11.0)'
required: false
default: ''

# Prevent two concurrent runs so version bumps never interleave
concurrency:
group: squad-version-promote
cancel-in-progress: false

permissions:
contents: write

jobs:
bump-dev-version:
name: Bump dev branch base version
runs-on: ubuntu-latest

steps:
# ── Checkout & git setup ────────────────────────────────────────────────
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Configure git identity
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

Comment on lines +46 to +56
- name: Fetch all branches
run: git fetch --all

# ── Determine released version ──────────────────────────────────────────
- name: Read released version
id: released
run: |
if [ -n "${{ inputs.released_version }}" ]; then
RELEASED_VERSION="${{ inputs.released_version }}"
echo "Using manual override: $RELEASED_VERSION"
else
# Strip leading 'v' from the release tag name (e.g. v0.11.0 → 0.11.0)
RELEASED_VERSION="${{ github.event.release.tag_name }}"
RELEASED_VERSION="${RELEASED_VERSION#v}"
echo "Using release tag: $RELEASED_VERSION"
fi
echo "version=$RELEASED_VERSION" >> "$GITHUB_OUTPUT"
Comment on lines +63 to +73

# ── Compute next minor version ──────────────────────────────────────────
- name: Compute next minor version
id: next
run: |
RELEASED="${{ steps.released.outputs.version }}"
MAJOR=$(echo "$RELEASED" | cut -d. -f1)
MINOR=$(echo "$RELEASED" | cut -d. -f2)
NEXT_MINOR=$((MINOR + 1))
NEXT_VERSION="${MAJOR}.${NEXT_MINOR}.0"
echo "Released: $RELEASED → Next: $NEXT_VERSION"
echo "version=$NEXT_VERSION" >> "$GITHUB_OUTPUT"

# ── Switch to dev and read its current version ──────────────────────────
- name: Checkout dev branch
run: git checkout dev

- name: Read current dev version
id: dev
run: |
DEV_VERSION=$(node -e "console.log(require('./package.json').version)")
echo "version=$DEV_VERSION" >> "$GITHUB_OUTPUT"
echo "Dev branch version: $DEV_VERSION"

# ── Decide whether a bump is necessary ──────────────────────────────────
- name: Check if bump is needed
id: check
run: |
DEV="${{ steps.dev.outputs.version }}"
RELEASED="${{ steps.released.outputs.version }}"

# Bump is needed only when dev version <= released version
NEEDS_BUMP=$(node -e "
const semver = (v) => v.split('.').map(Number);
const cmp = (a, b) => {
const [aMaj, aMin, aPat] = semver(a);
const [bMaj, bMin, bPat] = semver(b);
if (aMaj !== bMaj) return aMaj - bMaj;
if (aMin !== bMin) return aMin - bMin;
return aPat - bPat;
};
console.log(cmp('$DEV', '$RELEASED') <= 0 ? 'true' : 'false');
")
Comment on lines +106 to +116

echo "needs_bump=$NEEDS_BUMP" >> "$GITHUB_OUTPUT"

if [ "$NEEDS_BUMP" = "true" ]; then
echo "✅ Bump needed: dev($DEV) <= released($RELEASED)"
else
echo "⏭️ Skipping: dev($DEV) is already ahead of released($RELEASED)"
fi

# ── Update all package.json files ───────────────────────────────────────
- name: Bump version in all package.json files
if: steps.check.outputs.needs_bump == 'true'
run: |
NEW_VERSION="${{ steps.next.outputs.version }}"
echo "Bumping all package.json files to $NEW_VERSION"

update_version() {
local FILE="$1"
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('$FILE', 'utf8'));
pkg.version = '$NEW_VERSION';
fs.writeFileSync('$FILE', JSON.stringify(pkg, null, 2) + '\n');
console.log('Updated $FILE → ' + pkg.version);
"
}

update_version "package.json"
update_version "packages/squad-cli/package.json"
update_version "packages/squad-sdk/package.json"
Comment on lines +144 to +146

- name: Show diff
if: steps.check.outputs.needs_bump == 'true'
run: git diff

# ── Commit and push (skipped on dry run) ─────────────────────────────────
- name: Commit and push to dev
if: >-
steps.check.outputs.needs_bump == 'true' &&
(github.event_name != 'workflow_dispatch' || inputs.dry_run == 'false')
Comment on lines +154 to +156
run: |
RELEASED="${{ steps.released.outputs.version }}"
NEW_VERSION="${{ steps.next.outputs.version }}"

git add package.json packages/squad-cli/package.json packages/squad-sdk/package.json

if git diff --cached --quiet; then
echo "ℹ️ No changes to commit — files already at $NEW_VERSION"
else
git commit -m "chore: bump dev base version to ${NEW_VERSION} after v${RELEASED} release"
git push origin dev
echo "✅ Pushed version bump to dev: ${NEW_VERSION}"
fi

# ── Summary steps ────────────────────────────────────────────────────────
- name: Dry run summary
if: inputs.dry_run == 'true'
run: |
Comment on lines +172 to +174
echo "🔍 Dry run complete — no changes pushed."
echo " Released version : ${{ steps.released.outputs.version }}"
echo " Dev version : ${{ steps.dev.outputs.version }}"
echo " Next version : ${{ steps.next.outputs.version }}"
echo " Bump needed : ${{ steps.check.outputs.needs_bump }}"

- name: Skip summary
if: steps.check.outputs.needs_bump != 'true'
run: |
echo "⏭️ Version bump skipped."
echo " Dev (${{ steps.dev.outputs.version }}) is already ahead of released (${{ steps.released.outputs.version }})."