-
-
Notifications
You must be signed in to change notification settings - Fork 31
/
update-changelog.ts
121 lines (102 loc) · 4.66 KB
/
update-changelog.ts
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import conventionalChangelogCore, { Context } from 'conventional-changelog-core';
import { Options as WriterOptions } from 'conventional-changelog-writer';
import fs from 'fs-extra';
import getStream from 'get-stream';
import log from 'npmlog';
import { BLANK_LINE, CHANGELOG_HEADER, EOL } from './constants';
import { GetChangelogConfig } from './get-changelog-config';
import { makeBumpOnlyFilter } from './make-bump-only-filter';
import { readExistingChangelog } from './read-existing-changelog';
import { ChangelogConfig, ChangelogType, UpdateChangelogOption } from '../models';
import { Package } from '../package';
import { setConfigChangelogCommitClientLogin, setConfigChangelogCommitGitAuthor } from './writer-opts-transform';
/**
* Update changelog with the commits of the new release
* @param {Package} pkg
* @param {ChangelogType} type
* @param {UpdateChangelogOption} commandOptions
*/
export async function updateChangelog(pkg: Package, type: ChangelogType, updateOptions: UpdateChangelogOption) {
log.silly(type, 'for %s at %s', pkg.name, pkg.location);
const {
changelogPreset,
changelogIncludeCommitsGitAuthor,
changelogIncludeCommitsClientLogin,
changelogHeaderMessage = '',
changelogVersionMessage = '',
commitsSinceLastRelease,
rootPath,
tagPrefix = 'v',
version,
} = updateOptions;
const config = await GetChangelogConfig.getChangelogConfig(changelogPreset, rootPath);
const options = {} as { config: ChangelogConfig; lernaPackage: string; tagPrefix: string; pkg: { path: string } };
const context = {} as Context; // pass as positional because cc-core's merge-config is wack
const writerOpts = {} as WriterOptions;
// cc-core mutates input :P
if (config.conventionalChangelog) {
// "new" preset API
options.config = Object.assign({}, config.conventionalChangelog) as ChangelogConfig;
} else {
// "old" preset API
options.config = Object.assign({}, config) as ChangelogConfig;
}
// NOTE: must pass as positional argument due to weird bug in merge-config
const gitRawCommitsOpts = Object.assign({}, options.config.gitRawCommitsOpts);
// are we including commit author name/email or remote client login name
if (changelogIncludeCommitsGitAuthor || changelogIncludeCommitsGitAuthor === '') {
setConfigChangelogCommitGitAuthor(config, gitRawCommitsOpts, writerOpts, changelogIncludeCommitsGitAuthor);
} else if (
(changelogIncludeCommitsClientLogin || changelogIncludeCommitsClientLogin === '') &&
commitsSinceLastRelease
) {
// prettier-ignore
setConfigChangelogCommitClientLogin(config, gitRawCommitsOpts, writerOpts, commitsSinceLastRelease, changelogIncludeCommitsClientLogin);
}
if (type === 'root') {
context.version = version;
// preserve tagPrefix because cc-core can't find the currentTag otherwise
context.currentTag = `${tagPrefix}${version}`;
// root changelogs are only enabled in fixed mode, and need the proper tag prefix
options.tagPrefix = tagPrefix;
} else {
// "fixed" or "independent"
gitRawCommitsOpts.path = pkg.location;
options.pkg = { path: pkg.manifestLocation };
if (type === 'independent') {
options.lernaPackage = pkg.name;
} else {
// only fixed mode can have a custom tag prefix
options.tagPrefix = tagPrefix;
// preserve tagPrefix because cc-core can't find the currentTag otherwise
context.currentTag = `${tagPrefix}${pkg.version}`;
context.version = pkg.version; // TODO investigate why Lerna doesn't have this line
}
}
// generate the markdown for the upcoming release.
const changelogStream = conventionalChangelogCore(options, context, gitRawCommitsOpts, undefined, writerOpts);
return Promise.all([
// prettier-ignore
getStream(changelogStream).then(makeBumpOnlyFilter(pkg)),
readExistingChangelog(pkg),
]).then(([inputEntry, [changelogFileLoc, changelogContents]]) => {
let newEntry = inputEntry;
log.silly(type, 'writing new entry: %j', newEntry);
const changelogVersion = type === 'root' ? changelogVersionMessage : '';
const changelogHeader = CHANGELOG_HEADER.replace(
/%s/g,
type === 'root' ? (changelogHeaderMessage?.length > 0 ? changelogHeaderMessage + EOL : '') : ''
);
const content = [changelogHeader, changelogVersion, newEntry, changelogContents]
.join(BLANK_LINE)
.trim()
.replace(/[\r\n]{2,}/gm, '\n\n'); // conventional-changelog adds way too many extra line breaks, let's remove a few of them
return fs.writeFile(changelogFileLoc, content + EOL).then(() => {
log.verbose(type, 'wrote', changelogFileLoc);
return {
logPath: changelogFileLoc,
newEntry,
};
});
});
}