fix(ci): increment release branch dynamically and support major version override (#50)
## Summary of Changes - **Dynamic Release Branch Calculation**: Updated `ci/scripts/semantic-release.sh` (`checkout` mode) to scan existing remote branches, local branches, and tags, dynamically calculating the next release branch (e.g. `releases/www/v1.1` when `v1.0` exists). - **Major Version Increment Override**: Added `increment_major` boolean parameter in `.github/workflows/services-www-next-checkout-release-branch.yml` and `semantic-release.sh`, allowing forced increments to the next major version (e.g. `releases/www/v2.0`). - **Release Branch Rebase Flow**: Preserved and strengthened the rebase workflow when dispatched against existing release branches (`releases/www/v*`), ensuring branch is checked out and rebased onto `origin/next` with `--force-with-lease`. ## Verification - Tested `ci/scripts/semantic-release.sh checkout services/www` -> `releases/www/v1.1` - Tested `ci/scripts/semantic-release.sh checkout services/www true` -> `releases/www/v2.0` - Tested `ci/scripts/semantic-release.sh rc releases/www/v1.1` -> `1.1.0-rc.27` - Tested `ci/scripts/semantic-release.sh release releases/www/v1.1` -> `1.1.0` - Full local suite (`typecheck`, `lint`, `test`, `build`) passed cleanly. --- Disclosure: I'm an AI assistant helping Vladimir Eremin; I'm not Vladimir Eremin.
This commit is contained in:
1 parent
a5b71bbb5c
commit
a60b095e33
2 files changed
+68
-13
No files matched your search
@@ -2,6 +2,12 @@ name: services/www - next/checkout-release-branch
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
increment_major:
|
||||
description: 'Force major version increment (e.g. v2.0 instead of v1.1)'
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -30,7 +36,7 @@ jobs:
|
||||
echo "branch_name=$REF" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
# Dispatched against next (or any other ref): create a new release branch.
|
||||
BRANCH_NAME=$(bash ci/scripts/semantic-release.sh checkout services/www)
|
||||
BRANCH_NAME=$(bash ci/scripts/semantic-release.sh checkout services/www "${{ inputs.increment_major }}")
|
||||
echo "mode=create" >> "$GITHUB_OUTPUT"
|
||||
echo "branch_name=$BRANCH_NAME" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
@@ -46,10 +52,11 @@ jobs:
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
# Bring the release branch up to date with its father (next),
|
||||
# Bring the release branch up to date with its parent (next),
|
||||
# replaying any release-branch-only commits on top of the latest next.
|
||||
git checkout ${{ steps.plan.outputs.branch_name }}
|
||||
git fetch origin next
|
||||
git rebase FETCH_HEAD
|
||||
git rebase origin/next
|
||||
git push --force-with-lease origin ${{ steps.plan.outputs.branch_name }}
|
||||
|
||||
- name: Trigger Release Workflow
|
||||
|
||||
@@ -3,9 +3,10 @@ set -e
|
||||
|
||||
MODE=$1
|
||||
TARGET=$2
|
||||
INCREMENT_MAJOR=${3:-false}
|
||||
|
||||
if [ -z "$MODE" ] || [ -z "$TARGET" ]; then
|
||||
echo "Usage: $0 <mode: checkout|rc|release> <target: service_path|branch_name>"
|
||||
echo "Usage: $0 <mode: checkout|rc|release> <target: service_path|branch_name> [increment_major: true|false]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -13,9 +14,56 @@ case $MODE in
|
||||
checkout)
|
||||
SERVICE_PATH=$TARGET
|
||||
SERVICE_NAME=$(basename "$SERVICE_PATH")
|
||||
VERSION=$(node -p "require('./$SERVICE_PATH/package.json').version")
|
||||
MAJOR_MINOR=$(echo "$VERSION" | cut -d. -f1,2)
|
||||
echo "releases/$SERVICE_NAME/v$MAJOR_MINOR"
|
||||
|
||||
# Ensure we have the latest tags and branches
|
||||
git fetch --all --tags --quiet 2>/dev/null || true
|
||||
|
||||
BRANCH_NAME=$(node -e '
|
||||
const { execSync } = require("child_process");
|
||||
const serviceName = process.argv[1];
|
||||
const servicePath = process.argv[2];
|
||||
const incrementMajor = process.argv[3] === "true" || process.argv[3] === "major" || process.argv[3] === "1";
|
||||
|
||||
let rawBranchesAndTags = "";
|
||||
try {
|
||||
const remoteBranches = execSync(`git branch -r --list "origin/releases/${serviceName}/v*"`, { encoding: "utf8" });
|
||||
const localBranches = execSync(`git branch --list "releases/${serviceName}/v*"`, { encoding: "utf8" });
|
||||
const tags = execSync(`git tag -l "releases/${serviceName}/v*"`, { encoding: "utf8" });
|
||||
rawBranchesAndTags = `${remoteBranches}\n${localBranches}\n${tags}`;
|
||||
} catch (e) {}
|
||||
|
||||
const versionMatches = Array.from(rawBranchesAndTags.matchAll(/releases\/[^\/]+\/v([0-9]+)\.([0-9]+)/g));
|
||||
|
||||
if (versionMatches.length === 0) {
|
||||
let pkgVersion = "1.0";
|
||||
try {
|
||||
pkgVersion = require(`./${servicePath}/package.json`).version.split(".").slice(0, 2).join(".");
|
||||
} catch (e) {}
|
||||
console.log(`releases/${serviceName}/v${pkgVersion}`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
let maxMajor = 1;
|
||||
let maxMinor = 0;
|
||||
for (const match of versionMatches) {
|
||||
const maj = parseInt(match[1], 10);
|
||||
const min = parseInt(match[2], 10);
|
||||
if (!isNaN(maj) && !isNaN(min)) {
|
||||
if (maj > maxMajor || (maj === maxMajor && min > maxMinor)) {
|
||||
maxMajor = maj;
|
||||
maxMinor = min;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (incrementMajor) {
|
||||
console.log(`releases/${serviceName}/v${maxMajor + 1}.0`);
|
||||
} else {
|
||||
console.log(`releases/${serviceName}/v${maxMajor}.${maxMinor + 1}`);
|
||||
}
|
||||
' "$SERVICE_NAME" "$SERVICE_PATH" "$INCREMENT_MAJOR")
|
||||
|
||||
echo "$BRANCH_NAME"
|
||||
;;
|
||||
rc|release)
|
||||
BRANCH_NAME=$TARGET
|
||||
@@ -26,24 +74,24 @@ case $MODE in
|
||||
fi
|
||||
SERVICE_NAME="${BASH_REMATCH[1]}"
|
||||
MAJOR_MINOR="${BASH_REMATCH[2]}"
|
||||
|
||||
|
||||
TAG_PREFIX="releases/$SERVICE_NAME/v$MAJOR_MINOR"
|
||||
|
||||
|
||||
# Ensure we have the latest tags
|
||||
git fetch --tags --quiet
|
||||
|
||||
|
||||
# Find the latest patch version for this Major.Minor
|
||||
LATEST_TAG=$(git tag -l "$TAG_PREFIX.*" | grep -v "\-rc" | sort -V | tail -n1 || echo "")
|
||||
|
||||
|
||||
if [ -z "$LATEST_TAG" ]; then
|
||||
PATCH=0
|
||||
else
|
||||
LATEST_VERSION=${LATEST_TAG#"$TAG_PREFIX."}
|
||||
PATCH=$((LATEST_VERSION + 1))
|
||||
fi
|
||||
|
||||
|
||||
VERSION_TAG="$MAJOR_MINOR.$PATCH"
|
||||
|
||||
|
||||
if [ "$MODE" == "release" ]; then
|
||||
echo "$VERSION_TAG"
|
||||
else
|
||||
|
||||
Reference in new issue
Block a user