post-merge
Version:
A reusable library for handling post-merge operations including version bumping and git tagging
152 lines • 6.05 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.readPackageInfo = readPackageInfo;
exports.hasPrereleaseSuffix = hasPrereleaseSuffix;
exports.determineVersionStrategy = determineVersionStrategy;
exports.bumpVersion = bumpVersion;
const child_process_1 = require("child_process");
const util_1 = require("util");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const execAsync = (0, util_1.promisify)(child_process_1.exec);
/**
* Reads package.json and returns package information
*/
async function readPackageInfo(packageJsonPath) {
const fullPath = path.resolve(packageJsonPath);
if (!fs.existsSync(fullPath)) {
throw new Error(`package.json not found at: ${fullPath}`);
}
const content = fs.readFileSync(fullPath, 'utf8');
const packageData = JSON.parse(content);
return {
name: packageData.name,
version: packageData.version
};
}
/**
* Checks if a version has a prerelease suffix
*/
function hasPrereleaseSuffix(version, prereleaseId = 'release') {
const prereleasePattern = new RegExp(`-${prereleaseId}\\.[0-9]+`);
return prereleasePattern.test(version);
}
/**
* Counts feature commits between the last tag and HEAD
*/
async function countFeatureCommits() {
try {
// Get the last tag
let lastTag;
try {
const { stdout: tagOutput } = await execAsync('git describe --tags --abbrev=0');
lastTag = tagOutput.trim();
}
catch (_a) {
// No tags found, use last 20 commits
const { stdout } = await execAsync('git log --oneline -n 20');
const commits = stdout.split('\n').filter(line => line.trim());
const featureCommits = commits.filter(commit => {
const message = commit.toLowerCase();
return message.includes(' feat:') || message.includes(' feat(') ||
message.includes(' feature:') || message.includes(' feature(');
});
return featureCommits.length;
}
// Get commits between last tag and HEAD
const { stdout } = await execAsync(`git log ${lastTag}..HEAD --oneline`);
const commits = stdout.split('\n').filter(line => line.trim());
const featureCommits = commits.filter(commit => {
const message = commit.toLowerCase();
return message.includes(' feat:') || message.includes(' feat(') ||
message.includes(' feature:') || message.includes(' feature(');
});
console.log(`Analyzing commits between ${lastTag} and HEAD: found ${commits.length} commits total`);
return featureCommits.length;
}
catch (error) {
console.warn('Failed to read git history:', error);
return 0;
}
}
/**
* Determines the version bump strategy based on current version and commit history
*/
async function determineVersionStrategy(currentVersion, prereleaseId = 'release') {
if (!hasPrereleaseSuffix(currentVersion, prereleaseId)) {
return 'patch';
}
// Check commits between last tag and HEAD for feature commits
const featureCount = await countFeatureCommits();
console.log(`Found ${featureCount} feature commits between last tag and HEAD`);
// If at least 1 feature commit, use mixed strategy (bump patch and reset prerelease)
if (featureCount >= 1) {
return 'mixed';
}
return 'prerelease';
}
/**
* Bumps the package version using npm version command
*/
async function bumpVersion(strategy, prereleaseId = 'release') {
const currentPackage = await readPackageInfo('./package.json');
const currentVersion = currentPackage.version;
let command;
if (strategy === 'prerelease') {
command = `npm version prerelease --preid=${prereleaseId} --no-git-tag-version`;
}
else if (strategy === 'mixed') {
command = `npm version patch --no-git-tag-version`;
await execAsync(command);
// Then add prerelease suffix back with .0
command = `npm version prerelease --preid=${prereleaseId} --no-git-tag-version`;
}
else {
command = `npm version patch --no-git-tag-version`;
}
console.log(`Bumping version using strategy: ${strategy}`);
console.log(`Current version: ${currentVersion}`);
await execAsync(command);
const updatedPackage = await readPackageInfo('./package.json');
const newVersion = updatedPackage.version;
console.log(`New version: ${newVersion}`);
return {
currentVersion,
newVersion,
isPrerelease: strategy === 'prerelease'
};
}
//# sourceMappingURL=version-utils.js.map
;