Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
const { exec } = require('child_process');
const verbData = {
chore: {
label: 'Chores',
renderOrder: 4,
},
feat: {
label: 'New Features',
renderOrder: 0,
},
fix: {
label: 'Fixes',
renderOrder: 1,
},
improv: {
label: 'Improvements',
renderOrder: 2,
},
perf: {
label: 'Performance Fixes',
renderOrder: 3,
},
refactor: {
label: 'Refactoring',
},
style: {
label: 'Style Changes',
},
test: {
label: 'Tests',
},
};
const verbs = Object.keys(verbData);
const commitFormat = `^(${verbs.join('|')})(\\((\\w+)\\))?:\\s*(.+)$`;
const capitalize = str => str.charAt(0).toUpperCase() + str.slice(1);
exec(`git log $(git describe --tags --abbrev=0)..HEAD --pretty=format:'%B'`, (err, linesAsBuffer, stderr) => {
if (err) {
console.log('\x1b[33m%s\x1b[0m', 'Error retrieving commits:');
console.log('\x1b[33m%s\x1b[0m', stderr);
process.exit(1);
}
const lines = linesAsBuffer.toString().split('\n').reverse();
const releaseInfo = lines
.map(line => line.trim())
.filter(Boolean)
.map(line => line.split('\n').join(' '))
.map(line => new RegExp(commitFormat, 'gi').exec(line))
.filter(Boolean)
.map(matchedResults => ({
verb: matchedResults[1],
scope: matchedResults[3] || 'miscellaneous',
body: matchedResults[4],
}))
.reduce((result, current) => {
// verb -> scope -> body
result[current.verb] = result[current.verb] || {};
const scopesByVerb = result[current.verb];
scopesByVerb[current.scope] = scopesByVerb[current.scope] || [];
const scopeItems = scopesByVerb[current.scope];
scopeItems.push(current.body);
return result;
}, {});
const releaseNotes = Object.entries(verbData)
.filter(([key, info]) => info.renderOrder !== undefined)
.sort(([key1, info1], [key2, info2]) => info1.renderOrder - info2.renderOrder)
.filter(([key, info]) => releaseInfo[key])
.map(([key, info]) => [
key,
info,
Object.entries(releaseInfo[key]).sort()
])
.reduce((result, [key, info, scopes]) => {
result.push(`## ${info.label}`);
scopes.forEach(([name, commits]) => {
result.push(`### ${capitalize(name)}`);
commits.forEach(commit => result.push(`* ${commit}`));
});
return result;
}, [])
.map(line => line
// Now escape the multiline string for output to GitHub Actions.
.replace(/"/gi, '\\"')
.replace(/'/gi, `'\\''`) // The wonders of bash...
.replace(/%/gi, '%25')
.replace(/\n/gi, '\\n')
.replace(/\r/gi, '\\r')
)
.join('\\n')
;
console.log(`::set-output name=release_notes::${releaseNotes}`);
process.exit(0);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment