This tutorial explains how the version management system works in the Proxy Smart project. The system is designed to keep all package.json files synchronized across the monorepo and automate versioning for different release types.
The version management system consists of:
- Central Script:
scripts/version.js- Main version management logic - Git Hooks:
.githooks/pre-commit- Automatic version synchronization - GitHub Actions: Automated version validation and release workflows
- NPM Scripts: Convenient commands for version operations
The project is a monorepo with multiple packages:
├── package.json # Root package (master version)
├── backend/package.json # Backend service
├── ui/package.json # Frontend React application
├── infra/package.json # CDK infrastructure
└── scripts/package.json # Build & CI scripts
All packages must maintain version consistency, with the root package.json serving as the source of truth.
The system supports semantic versioning with pre-release identifiers:
X.Y.Z[-suffix[.build[.sha]]]
- X.Y.Z: Standard semantic version (major.minor.patch)
- suffix: Release type (alpha, beta, or RELEASE for production)
- build: Build number for non-production releases (YYYYMMDDHHMM format)
- sha: Short commit SHA for non-production releases
Examples:
1.2.3-RELEASE- Production release1.2.3-alpha.202508031914.823869b- Alpha release1.2.3-beta.202508031915.a1b2c3d- Beta release
The central script provides all version management functionality:
- findPackageFiles(): Automatically discovers all package.json files
- updateVersion(): Updates version across all packages
- checkConsistency(): Validates version consistency
- incrementVersion(): Handles semantic version bumping
- getBaseVersion(): Extracts base version without suffixes
| Command | Description | Example |
|---|---|---|
sync |
Synchronize all packages to root version | node scripts/version.js sync |
bump [type] |
Increment version (patch/minor/major) | node scripts/version.js bump minor |
set <version> |
Set specific version | node scripts/version.js set 1.2.3 |
check |
Validate version consistency | node scripts/version.js check |
base |
Get base version (no suffixes) | node scripts/version.js base |
The project provides convenient NPM scripts in the root package.json:
{
"scripts": {
"version:sync": "node scripts/version.js sync",
"version:bump": "node scripts/version.js bump",
"version:bump:minor": "node scripts/version.js bump minor",
"version:bump:major": "node scripts/version.js bump major",
"version:set": "node scripts/version.js set",
"version:check": "node scripts/version.js check",
"version:base": "node scripts/version.js base",
"precommit": "bun run version:sync"
}
}# Check current version consistency
bun run version:check
# Sync all packages to root version
bun run version:sync
# Bump patch version (1.2.3 → 1.2.4)
bun run version:bump
# Bump minor version (1.2.3 → 1.3.0)
bun run version:bump:minor
# Bump major version (1.2.3 → 2.0.0)
bun run version:bump:major
# Set specific version
bun run version:set 2.1.0
# Get base version without suffixes
bun run version:baseThe .githooks/pre-commit hook automatically runs before each commit:
#!/bin/bash
echo "Checking version consistency..."
node scripts/version.js sync
git add **/package.json
echo "✅ Version consistency ensured"This ensures that all commits maintain version consistency across packages.
To enable git hooks:
# Run the setup script
node scripts/setup-hooks.js
# Or manually configure
git config core.hooksPath .githooksAutomatically validates version consistency on pull requests:
on:
pull_request:
branches: [main, develop, test]What it does:
- Checks that all package.json files have consistent versions
- Fails the PR if versions are inconsistent
- Provides clear feedback on version mismatches
Reusable workflow for version operations:
Inputs:
operation: 'validate' or 'update'release_type: 'alpha', 'beta', or 'production'should_bump_version: Whether to increment versionversion_suffix: Version suffix to apply
Outputs:
current_version: Version before changesnew_version: Version after changesbase_version: Base version without suffixesbuild_number: Build number for non-productionshort_sha: Commit SHAis_consistent: Whether versions are consistent
Allows manual version bumping through GitHub Actions:
Triggers:
- Manual workflow dispatch
- Configurable version type (minor/major)
- Optional custom version
- Target branch selection
Process:
- Validates inputs
- Calculates new version
- Updates all package.json files
- Updates README badge
- Commits and pushes changes
The project uses a three-stage promotion model:
develop (alpha) ──auto-PR──▶ test (beta) ──manual-PR──▶ main (production)
Each branch has its own version suffix. When code is pushed, the release workflow creates a version-stamped tag and GitHub Release automatically.
Alpha releases are created automatically on every push to develop:
- Trigger: Push to
developbranch (excluding bot commits) - Workflow:
release-alpha.yml→release-orchestrator.yml→version-operations.yml - Version Logic: Current base version + alpha suffix with build number + short SHA
- Format:
X.Y.Z-alpha.YYYYMMDDHHMM.SHA - Example:
0.0.2-alpha.202603231607.00c7934f
Beta releases are created when code merges from develop into test:
- Trigger: Push to
testbranch (excluding bot commits) - Workflow:
release-beta.yml→release-orchestrator.yml→version-operations.yml - Version Logic: Current base version + beta suffix with build number + short SHA
- Format:
X.Y.Z-beta.YYYYMMDDHHMM.SHA - Deploy: Beta releases trigger deployment to the staging VPS via
deploy-beta.yml
Production releases are created when code merges from test into main:
- Trigger: Push to
mainbranch - Workflow:
release-production.yml→release-orchestrator.yml→version-operations.yml - Version Logic: Base version with RELEASE suffix
- Format:
X.Y.Z-RELEASE
When code is pushed to develop, the create-pr.yml workflow automatically:
- Creates (or updates) a PR from
develop→test - Enables GitHub auto-merge on the PR
- The PR merges automatically once all required checks pass
Similarly, when code merges to test, a PR from test → main is created — but this one requires manual review before merge.
Because each branch has different version suffixes (alpha vs beta vs production), the 5 package.json files always conflict between branches. The create-pr.yml workflow resolves this automatically:
- Detection: The workflow checks if the source branch is behind the target (
commits_behind != 0) - Merge: It merges the target branch into the source using
git merge -X ours(keeping the source's versions) - Rationale: The source's version strings are ephemeral anyway —
version-operations.ymlwill immediately re-stamp the correct stage version after merge - Bot commit: The merge commit includes
[proxy-smart-releaser]to prevent re-triggering release workflows
Example flow for develop → test:
1. develop has: 0.0.2-alpha.202603231607.00c7934f
2. test has: 0.0.2-beta.202603231553.5d372300
3. Workflow merges origin/test into develop with -X ours
4. Push → PR becomes conflict-free → auto-merge
5. version-operations re-stamps test as 0.0.2-beta.{new-build}.{new-sha}
Bot-generated commits are filtered to prevent infinite loops:
| Commit message contains | Alpha Release | Create PR | Compliance Tests |
|---|---|---|---|
proxy-smart-releaser |
Skipped | Skipped | Skipped (push only) |
🔄 Update version |
Skipped | Skipped | Skipped (push only) |
🤖 Update client APIs |
Skipped | Skipped | Skipped (push only) |
These workflows still run when triggered via workflow_dispatch, workflow_call, or schedule.
- Always ensure versions are consistent before committing
- Use
bun run version:checkregularly - Let the pre-commit hook handle synchronization
- Use semantic versioning principles:
- Patch: Bug fixes, non-breaking changes
- Minor: New features, backwards compatible
- Major: Breaking changes
- Use
bun run version:setfor hotfixes or specific versions - Always validate with
bun run version:checkafter manual changes - Document reason for manual version changes
- Development: Work on feature branches, merge to
develop(auto alpha versions) - Staging: Auto-PR promotes
develop→test(auto-merge, beta versions, VPS deploy) - Production: PR promotes
test→main(manual review, production versions) - Hotfixes: Direct to
mainwith manual version bump
-
Version Inconsistency Error
❌ backend/package.json: 1.2.3 (expected: 1.2.4)
Solution: Run
bun run version:sync -
Git Hook Not Working
# Re-setup hooks node scripts/setup-hooks.js -
CI/CD Version Validation Failure
- Check all package.json files manually
- Run
bun run version:checklocally - Sync versions and commit changes
# Check which packages exist
node scripts/version.js sync --dry-run
# Manually inspect versions
find . -name "package.json" -not -path "*/node_modules/*" -exec echo {} \; -exec jq -r '.version' {} \;
# Reset all versions to root
bun run version:syncFor special releases, you can set custom versions:
# Release candidate
bun run version:set 2.0.0-rc.1
# Custom suffix
bun run version:set 1.5.0-hotfix.1
# Production release
bun run version:set 1.2.3-RELEASEYou can import and use the version script functions:
import {
getCurrentVersion,
updateVersion,
checkConsistency
} from './scripts/version.js';
const currentVersion = getCurrentVersion();
const isConsistent = checkConsistency();The version management system is deeply integrated with the CI/CD pipeline:
- Pre-commit Hook: Synchronizes all package.json files before every commit
- PR Validation:
version-check.ymlensures version consistency on pull requests - Auto-Release: Push to
develop/test/maintriggers stage-specific release workflows - Auto-PR:
create-pr.ymlpromotes code through branches with conflict resolution - Auto-Merge:
develop→testPRs merge automatically after checks pass - Changelog: AI-powered changelog generation from commit history (OpenAI)
- Compliance: SMART Inferno compliance tests run on real code merges
- Deploy: Beta releases deploy to the staging VPS automatically
This version management system provides:
- Consistency: All packages stay synchronized
- Automation: Minimal manual intervention required
- Flexibility: Supports various release types and workflows
- Reliability: Git hooks and CI/CD validation prevent errors
- Transparency: Clear versioning scheme for all environments
By following this system, you can maintain clean, consistent versioning across the entire monorepo while supporting complex release workflows.