1 | const {format} = require('url');
|
2 | const {find, merge} = require('lodash');
|
3 | const getStream = require('get-stream');
|
4 | const intoStream = require('into-stream');
|
5 | const parser = require('conventional-commits-parser').sync;
|
6 | const writer = require('conventional-changelog-writer');
|
7 | const filter = require('conventional-commits-filter');
|
8 | const readPkgUp = require('read-pkg-up');
|
9 | const debug = require('debug')('semantic-release:release-notes-generator');
|
10 | const loadChangelogConfig = require('./lib/load-changelog-config');
|
11 | const HOSTS_CONFIG = require('./lib/hosts-config');
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | async function generateNotes(pluginConfig, context) {
|
30 | const {commits, lastRelease, nextRelease, options, cwd} = context;
|
31 | const repositoryUrl = options.repositoryUrl.replace(/\.git$/i, '');
|
32 | const {parserOpts, writerOpts} = await loadChangelogConfig(pluginConfig, context);
|
33 |
|
34 | const [match, auth, host, path] = /^(?!.+:\/\/)(?:(?<auth>.*)@)?(?<host>.*?):(?<path>.*)$/.exec(repositoryUrl) || [];
|
35 | let {hostname, port, pathname, protocol} = new URL(
|
36 | match ? `ssh://${auth ? `${auth}@` : ''}${host}/${path}` : repositoryUrl
|
37 | );
|
38 | port = protocol.includes('ssh') ? '' : port;
|
39 | protocol = protocol && /http[^s]/.test(protocol) ? 'http' : 'https';
|
40 | const [, owner, repository] = /^\/(?<owner>[^/]+)?\/?(?<repository>.+)?$/.exec(pathname);
|
41 |
|
42 | const {issue, commit, referenceActions, issuePrefixes} =
|
43 | find(HOSTS_CONFIG, conf => conf.hostname === hostname) || HOSTS_CONFIG.default;
|
44 | const parsedCommits = filter(
|
45 | commits
|
46 | .filter(({message, hash}) => {
|
47 | if (!message.trim()) {
|
48 | debug('Skip commit %s with empty message', hash);
|
49 | return false;
|
50 | }
|
51 |
|
52 | return true;
|
53 | })
|
54 | .map(rawCommit => ({
|
55 | ...rawCommit,
|
56 | ...parser(rawCommit.message, {referenceActions, issuePrefixes, ...parserOpts}),
|
57 | }))
|
58 | );
|
59 | const previousTag = lastRelease.gitTag || lastRelease.gitHead;
|
60 | const currentTag = nextRelease.gitTag || nextRelease.gitHead;
|
61 | const {host: hostConfig, linkCompare, linkReferences, commit: commitConfig, issue: issueConfig} = pluginConfig;
|
62 | const changelogContext = merge(
|
63 | {
|
64 | version: nextRelease.version,
|
65 | host: format({protocol, hostname, port}),
|
66 | owner,
|
67 | repository,
|
68 | previousTag,
|
69 | currentTag,
|
70 | linkCompare: currentTag && previousTag,
|
71 | issue,
|
72 | commit,
|
73 | packageData: ((await readPkgUp({normalize: false, cwd})) || {}).packageJson,
|
74 | },
|
75 | {host: hostConfig, linkCompare, linkReferences, commit: commitConfig, issue: issueConfig}
|
76 | );
|
77 |
|
78 | debug('version: %o', changelogContext.version);
|
79 | debug('host: %o', changelogContext.hostname);
|
80 | debug('owner: %o', changelogContext.owner);
|
81 | debug('repository: %o', changelogContext.repository);
|
82 | debug('previousTag: %o', changelogContext.previousTag);
|
83 | debug('currentTag: %o', changelogContext.currentTag);
|
84 | debug('host: %o', changelogContext.host);
|
85 | debug('linkReferences: %o', changelogContext.linkReferences);
|
86 | debug('issue: %o', changelogContext.issue);
|
87 | debug('commit: %o', changelogContext.commit);
|
88 |
|
89 | return getStream(intoStream.object(parsedCommits).pipe(writer(changelogContext, writerOpts)));
|
90 | }
|
91 |
|
92 | module.exports = {generateNotes};
|