Skip to content

Fix/version workflow #14

Fix/version workflow

Fix/version workflow #14

# Ensures package.json and CHANGELOG.md are bumped when merging to release branch (master/main).
# Runs only on PRs targeting master or main (e.g. development → master).
name: Check Version Bump
on:
pull_request:
branches:
- master
- main
- development
jobs:
version-bump:
name: Version & Changelog bump
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22.x'
- name: Check version bump
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
set -e
# Skip version bump check when only test/docs/config files changed (no production code)
if [ -n "$BASE_SHA" ]; then
CHANGED=$(git diff --name-only "$BASE_SHA" HEAD 2>/dev/null || true)
PROD_CHANGES=$(echo "$CHANGED" | grep -v -e '^test/' -e '^package\.json$' -e '^CHANGELOG\.md$' -e '^\.github/' -e '^README' -e '^\.' -e '^docs/' -e '^jest\.config' -e '^\.eslintrc' -e '^\.prettierrc' || true)
PROD_CHANGES=$(echo "$PROD_CHANGES" | sed '/^$/d')
if [ -z "$PROD_CHANGES" ]; then
echo "Only test/docs/config files changed. Skipping version bump check."
exit 0
fi
# Skip when only comments changed in production files (//, /*, *, */, #)
if git diff "$BASE_SHA" HEAD | node -e "
const lines = require('fs').readFileSync(0,'utf8').split('\n').filter(l=>l.startsWith('+')||l.startsWith('-'));
const isComment = (s) => { const t=(s||'').slice(1).replace(/^\s+|\s+$/g,''); return !t || /^\/\//.test(t) || /^\/\*/.test(t) || /^\*\//.test(t) || /^\s*\*/.test(t) || /^#/.test(t); };
const hasCode = lines.some(l => !isComment(l));
process.exit(hasCode ? 1 : 0);
" 2>/dev/null; then
echo "Only comments changed in code. Skipping version bump check."
exit 0
fi
fi
PKG_VERSION=$(node -p "require('./package.json').version.replace(/^v/, '')")
if [ -z "$PKG_VERSION" ]; then
echo "::error::Could not read version from package.json"
exit 1
fi
git fetch --tags --force 2>/dev/null || true
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || true)
if [ -z "$LATEST_TAG" ]; then
echo "No existing tags found. Skipping version-bump check (first release)."
exit 0
fi
LATEST_VERSION="${LATEST_TAG#v}"
LATEST_VERSION="${LATEST_VERSION%%-*}"
if [ "$(printf '%s\n' "$LATEST_VERSION" "$PKG_VERSION" | sort -V | tail -1)" != "$PKG_VERSION" ]; then
echo "::error::Version bump required: package.json version ($PKG_VERSION) is not greater than latest tag ($LATEST_TAG). Please bump the version in package.json."
exit 1
fi
if [ "$PKG_VERSION" = "$LATEST_VERSION" ]; then
echo "::error::Version bump required: package.json version ($PKG_VERSION) equals latest tag ($LATEST_TAG). Please bump the version in package.json."
exit 1
fi
CHANGELOG_VERSION=$(sed -nE 's/^## \[v?([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' CHANGELOG.md | head -1)
if [ -z "$CHANGELOG_VERSION" ]; then
echo "::error::Could not find a version entry in CHANGELOG.md (expected line like '## [v1.0.0](...)')."
exit 1
fi
if [ "$CHANGELOG_VERSION" != "$PKG_VERSION" ]; then
echo "::error::CHANGELOG version mismatch: CHANGELOG.md top version ($CHANGELOG_VERSION) does not match package.json version ($PKG_VERSION). Please add or update the CHANGELOG entry for $PKG_VERSION."
exit 1
fi
echo "Version bump check passed: package.json and CHANGELOG.md are at $PKG_VERSION (latest tag: $LATEST_TAG)."