quality-mcp
Version:
An MCP server that analyzes to your codebase, with plugin support for DCD and Simian. 🏍️ "The only Zen you find on the tops of mountains is the Zen you bring up there."
112 lines (90 loc) • 3.45 kB
JavaScript
import { execSync } from 'child_process';
import { existsSync, writeFileSync, readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import semver from 'semver';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const SENTINEL_FILE = '.version-bump-sentinel';
// Check if this is a version bump commit to avoid recursion
if (existsSync(SENTINEL_FILE)) {
console.log('Version bump commit detected, skipping to avoid recursion');
execSync(`rm ${SENTINEL_FILE}`, { stdio: 'inherit' });
process.exit(0);
}
try {
// Get the latest commit message
const commitMsg = execSync('git log -1 --pretty=%B', { encoding: 'utf8' }).trim();
// Get only the first line (the subject line)
const firstLine = commitMsg.split('\n')[0].trim();
// Parse conventional commit format
const conventionalCommitRegex =
/^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: (.+)$/;
const match = firstLine.match(conventionalCommitRegex);
if (!match) {
console.log('Non-conventional commit detected, skipping version bump');
process.exit(0);
}
const type = match[1];
// Determine version bump type
let bumpType = 'patch'; // default
if (type === 'feat') {
bumpType = 'minor';
} else if (
type === 'fix' ||
type === 'docs' ||
type === 'style' ||
type === 'refactor' ||
type === 'perf' ||
type === 'test'
) {
bumpType = 'patch';
}
// chore, build, ci, revert also get patch bumps
// Read current package.json
const packageJsonPath = join(__dirname, '..', 'package.json');
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
const currentVersion = packageJson.version;
// Check if version was already changed in this commit
let previousVersion = '0.0.0';
try {
const previousPackageJson = execSync('git show HEAD~1:package.json', { encoding: 'utf8' });
previousVersion = JSON.parse(previousPackageJson).version;
} catch {
// First commit or can't get previous version
previousVersion = '0.0.0';
}
if (currentVersion !== previousVersion) {
console.log(`Version already bumped from ${previousVersion} to ${currentVersion}, skipping`);
process.exit(0);
}
// Calculate new version
const newVersion = semver.inc(currentVersion, bumpType);
if (!newVersion) {
console.error('Failed to increment version');
process.exit(1);
}
console.log(`Bumping version from ${currentVersion} to ${newVersion} (${bumpType})`);
// Create sentinel file to mark this as a version bump commit
writeFileSync(SENTINEL_FILE, newVersion);
// Update package.json with new version
packageJson.version = newVersion;
writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
// Stage the changes
execSync('git add package.json', { stdio: 'inherit' });
// Amend the commit to include the version bump
execSync('git commit --amend --no-edit', { stdio: 'inherit' });
console.log(`✅ Version bumped to ${newVersion} and included in commit`);
} catch (error) {
console.error('Error during version bumping:', error.message);
// Clean up sentinel file if it exists
try {
if (existsSync(SENTINEL_FILE)) {
execSync(`rm ${SENTINEL_FILE}`, { stdio: 'inherit' });
}
} catch {
// Sentinel file might already be gone, that's okay
}
process.exit(1);
}