xrelease
Version:
xrelease (pronounced cross-release) helps you setup automated releases for your project for any language
69 lines • 2.71 kB
JavaScript
import { execa } from 'execa';
import fs from 'fs/promises';
export async function generateChangelog(version, template = 'conventional') {
try {
// Try to get the last tag
let commits;
try {
const { stdout: lastTag } = await execa('git', ['describe', '--tags', '--abbrev=0']);
// Get commits since last tag
const { stdout } = await execa('git', ['log', '--oneline', '--no-merges', `${lastTag}..HEAD`]);
commits = stdout;
}
catch (error) {
// If no tags exist, get all commits
const { stdout } = await execa('git', ['log', '--oneline', '--no-merges']);
commits = stdout;
}
// Generate changelog content
const date = new Date().toISOString().split('T')[0];
const header = `## [${version}] - ${date}\n\n`;
let content = '';
if (!commits.trim()) {
content = '* No changes\n\n';
}
else if (template === 'conventional') {
content = formatConventionalCommits(commits);
}
else {
content = formatSimpleCommits(commits);
}
const changelogContent = header + content;
try {
// Try to read existing changelog
const existingChangelog = await fs.readFile('CHANGELOG.md', 'utf-8');
const updatedChangelog = existingChangelog.replace(/^(# Changelog\n\n)?/, ''); // Remove existing header if present
await fs.writeFile('CHANGELOG.md', '# Changelog\n\n' + changelogContent + updatedChangelog);
}
catch (error) {
// If file doesn't exist, create new one
await fs.writeFile('CHANGELOG.md', '# Changelog\n\n' + changelogContent);
}
}
catch (error) {
if (error instanceof Error && error.message.includes('ENOENT')) {
throw new Error('Failed to update changelog file');
}
throw error;
}
}
function formatConventionalCommits(commits) {
const lines = commits.split('\n').filter(Boolean);
const formatted = lines.map((line) => {
const match = line.match(/^[a-f0-9]+ (feat|fix|docs|style|refactor|test|chore)(\([^)]+\))?: (.+)$/);
if (match) {
const [, type, , message] = match;
return `* ${type}: ${message}`;
}
return `* ${line.replace(/^[a-f0-9]+ /, '')}`;
});
return formatted.join('\n') + '\n\n';
}
function formatSimpleCommits(commits) {
return (commits
.split('\n')
.filter(Boolean)
.map((line) => `* ${line.replace(/^[a-f0-9]+ /, '')}`)
.join('\n') + '\n\n');
}
//# sourceMappingURL=generate-changelog.js.map