/
changelog.js
75 lines (63 loc) · 2.37 KB
/
changelog.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Generates docs/CHANGELOG.md
// Run this right after the npm version command.
const { EOL } = require('os');
const shell = require('shelljs');
const tempy = require('tempy');
shell.config.silent = true;
const P = EOL + EOL;
const CURRENT_TAG = shell
.exec('git tag --sort=v:refname')
.tail({ '-n': 1 })
.stdout.trim();
const PREVIOUS_TAG = shell
.exec('git tag --sort=v:refname')
.tail({ '-n': 2 })
.head({ '-n': 1 })
.stdout.trim();
/** This is a “major” release if the version is 0.x.0 or x.0.0 */
const IS_MAJOR = /^v?(0\.\d+\.0|\d+.0.0)$/.test(CURRENT_TAG);
const FILE = tempy.file();
/** Tests for a `feat` commit type. */
const isFeature = (s) => /feat(\(\w+\))?:/.test(s);
/** Tests for commit types that don’t need adding to the CHANGELOG (like `docs` or `chore`). */
const isUninformative = (s) =>
/(test|style|chore|docs|ci)(\([\w-]+\))?:/.test(s);
/** Tests if this commit just bumped the version (via `npm version`). */
const isVersionBump = (s) => /^\w+\s\d+\.\d+\.\d+$/.test(s);
const changes = shell
.exec(`git log --oneline "${PREVIOUS_TAG}"..`)
.split(EOL)
.filter((line) => !isUninformative(line) && !isVersionBump(line));
/**
* Format an array of commit details and concatenate into a string.
* @param {string[]} changes
*/
const formatChanges = (changes) =>
changes
.map((line) =>
line
// Strip standalone commit types ('feat:', 'fix:', etc.)
.replace(/[a-z]+: /, '')
// Format scoped commit types ('feat(foo):' => 'foo:', etc.)
.replace(/[a-z]+\((\w+)\)/, '$1')
// Linkify commit refs.
.replace(
/^(\w+)/,
'* [[$1](https://github.com/boardgameio/boardgame.io/commit/$1)]'
)
// Linkify PR references.
.replace(
/\(#(\d{3,})\)/,
'([#$1](https://github.com/boardgameio/boardgame.io/pull/$1))'
)
)
.join(EOL);
const features = formatChanges(changes.filter((line) => isFeature(line)));
const others = formatChanges(changes.filter((line) => !isFeature(line)));
let NOTES = (IS_MAJOR ? '## ' : '### ') + CURRENT_TAG + P;
if (features.length > 0) NOTES += '#### Features' + P + features + P;
if (others.length > 0) NOTES += '#### Bugfixes' + P + others + P;
shell.ShellString(NOTES).toEnd(FILE);
shell.echo(NOTES);
shell.cat('docs/documentation/CHANGELOG.md').toEnd(FILE);
shell.cp(FILE, 'docs/documentation/CHANGELOG.md');