From 9064d398c02891dc7f52b516a40c9f4fa9315ec9 Mon Sep 17 00:00:00 2001 From: Bas van den Aakster Date: Sat, 13 Sep 2025 14:01:42 +0200 Subject: [PATCH] Implement intelligent version calculation based on branch comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### 🚀 Features - Version bumping now compares source branch vs target branch versions - Calculates proper increment from version differences between branches - Applies calculated increment to target branch version for new version ### 🔧 Improvements - Replaces branch name-based versioning with actual version analysis - Shows detailed version calculation in workflow logs - Validates that source version is higher than target version - Supports increments greater than 1 (e.g., patch increases by 2) ### 🧮 Version Calculation Logic - **Target (main)**: `1.2.3`, **Source (patch/dev)**: `1.2.5` - **Calculation**: patch increased by 2, so increment = 1 - **Result**: `1.2.4` (target version + minimum needed increment) ### 📊 Enhanced Validation - Fails if no version increase detected between branches - Ensures positive increments for version calculations - Detailed logging of version comparison and calculation steps 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/version-and-publish.yml | 97 ++++++++++++++++++----- 1 file changed, 77 insertions(+), 20 deletions(-) diff --git a/.github/workflows/version-and-publish.yml b/.github/workflows/version-and-publish.yml index 155007e..289d79f 100644 --- a/.github/workflows/version-and-publish.yml +++ b/.github/workflows/version-and-publish.yml @@ -53,21 +53,52 @@ jobs: - name: Run build run: pnpm build - - name: Determine version bump type + - name: Determine version bump from branch comparison id: version-type run: | - BRANCH_NAME="${{ github.ref_name }}" - if [[ "$BRANCH_NAME" =~ ^major/ ]]; then + # Get version from source branch (current) + SOURCE_VERSION=$(node -p "require('./package.json').version") + + # Get version from target branch (main) + git fetch origin main + TARGET_VERSION=$(git show origin/main:package.json | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8')).version") + + echo "📊 Source branch version: $SOURCE_VERSION" + echo "📊 Target branch version: $TARGET_VERSION" + + # Parse versions into components + IFS='.' read -r -a SOURCE_PARTS <<< "$SOURCE_VERSION" + IFS='.' read -r -a TARGET_PARTS <<< "$TARGET_VERSION" + + SOURCE_MAJOR=${SOURCE_PARTS[0]} + SOURCE_MINOR=${SOURCE_PARTS[1]} + SOURCE_PATCH=${SOURCE_PARTS[2]} + + TARGET_MAJOR=${TARGET_PARTS[0]} + TARGET_MINOR=${TARGET_PARTS[1]} + TARGET_PATCH=${TARGET_PARTS[2]} + + # Determine version bump type based on what changed + if [ "$SOURCE_MAJOR" -gt "$TARGET_MAJOR" ]; then echo "type=major" >> $GITHUB_OUTPUT - elif [[ "$BRANCH_NAME" =~ ^minor/ ]]; then + echo "🚀 Major version increase detected ($TARGET_MAJOR → $SOURCE_MAJOR)" + elif [ "$SOURCE_MINOR" -gt "$TARGET_MINOR" ]; then echo "type=minor" >> $GITHUB_OUTPUT - elif [[ "$BRANCH_NAME" =~ ^patch/ ]]; then + echo "✨ Minor version increase detected ($TARGET_MINOR → $SOURCE_MINOR)" + elif [ "$SOURCE_PATCH" -gt "$TARGET_PATCH" ]; then echo "type=patch" >> $GITHUB_OUTPUT + echo "🐛 Patch version increase detected ($TARGET_PATCH → $SOURCE_PATCH)" else echo "type=none" >> $GITHUB_OUTPUT + echo "⚠️ No version increase detected. Source version must be higher than target." + echo "Target: $TARGET_VERSION, Source: $SOURCE_VERSION" exit 1 fi + # Store versions for later use + echo "source-version=$SOURCE_VERSION" >> $GITHUB_OUTPUT + echo "target-version=$TARGET_VERSION" >> $GITHUB_OUTPUT + - name: Generate changelog with Claude id: changelog run: | @@ -133,55 +164,81 @@ jobs: git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" - - name: Create version bump script + - name: Create version calculation script run: | - # Create Node.js script to safely bump version - cat > bump-version.js << 'VERSION_SCRIPT_EOF' + # Create Node.js script to calculate proper version increment + cat > calculate-version.js << 'VERSION_SCRIPT_EOF' const fs = require('fs'); const path = require('path'); const versionType = process.argv[2]; + const targetVersion = process.argv[3]; + const sourceVersion = process.argv[4]; const packagePath = path.join(process.cwd(), 'package.json'); try { - const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8')); - const currentVersion = packageJson.version; - const [major, minor, patch] = currentVersion.split('.').map(Number); + // Parse versions + const [targetMajor, targetMinor, targetPatch] = targetVersion.split('.').map(Number); + const [sourceMajor, sourceMinor, sourcePatch] = sourceVersion.split('.').map(Number); let newVersion; + let increment; + switch (versionType) { case 'major': - newVersion = `${major + 1}.0.0`; + // Calculate major increment and reset minor/patch + increment = sourceMajor - targetMajor; + newVersion = `${targetMajor + increment}.0.0`; break; case 'minor': - newVersion = `${major}.${minor + 1}.0`; + // Keep major from target, calculate minor increment, reset patch + increment = sourceMinor - targetMinor; + newVersion = `${targetMajor}.${targetMinor + increment}.0`; break; case 'patch': - newVersion = `${major}.${minor}.${patch + 1}`; + // Keep major/minor from target, calculate patch increment + increment = sourcePatch - targetPatch; + newVersion = `${targetMajor}.${targetMinor}.${targetPatch + increment}`; break; default: throw new Error(`Invalid version type: ${versionType}`); } + // Ensure increment is positive + if (increment <= 0) { + throw new Error(`Invalid increment ${increment} for ${versionType} version`); + } + + // Update package.json + const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8')); packageJson.version = newVersion; fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2) + '\n'); - console.log(`${currentVersion}:${newVersion}`); + console.log(`${targetVersion}:${newVersion}:${increment}`); } catch (error) { - console.error('Error bumping version:', error.message); + console.error('Error calculating version:', error.message); process.exit(1); } VERSION_SCRIPT_EOF - - name: Bump version and create merge branch + - name: Calculate new version and create merge branch id: prepare run: | VERSION_TYPE="${{ steps.version-type.outputs.type }}" + TARGET_VERSION="${{ steps.version-type.outputs.target-version }}" + SOURCE_VERSION="${{ steps.version-type.outputs.source-version }}" - # Bump version using our safe Node.js script - VERSION_OUTPUT=$(node bump-version.js $VERSION_TYPE) + # Calculate new version using target + calculated increment + VERSION_OUTPUT=$(node calculate-version.js $VERSION_TYPE $TARGET_VERSION $SOURCE_VERSION) CURRENT_VERSION=$(echo $VERSION_OUTPUT | cut -d: -f1) NEW_VERSION=$(echo $VERSION_OUTPUT | cut -d: -f2) + INCREMENT=$(echo $VERSION_OUTPUT | cut -d: -f3) + + echo "📊 Version calculation:" + echo " Target (main): $CURRENT_VERSION" + echo " Source (branch): $SOURCE_VERSION" + echo " New version: $NEW_VERSION" + echo " Increment: +$INCREMENT ($VERSION_TYPE)" echo "current-version=$CURRENT_VERSION" >> $GITHUB_OUTPUT echo "new-version=$NEW_VERSION" >> $GITHUB_OUTPUT @@ -208,7 +265,7 @@ jobs: fi # Clean up temporary files - rm -f bump-version.js + rm -f calculate-version.js # Commit version bump and changes git add -A