UNPKG

4.61 kBJavaScriptView Raw
1const {format} = require('url');
2const {find, merge} = require('lodash');
3const getStream = require('get-stream');
4const intoStream = require('into-stream');
5const parser = require('conventional-commits-parser').sync;
6const writer = require('conventional-changelog-writer');
7const filter = require('conventional-commits-filter');
8const readPkgUp = require('read-pkg-up');
9const debug = require('debug')('semantic-release:release-notes-generator');
10const loadChangelogConfig = require('./lib/load-changelog-config');
11const HOSTS_CONFIG = require('./lib/hosts-config');
12
13/**
14 * Generate the changelog for all the commits in `options.commits`.
15 *
16 * @param {Object} pluginConfig The plugin configuration.
17 * @param {String} pluginConfig.preset conventional-changelog preset ('angular', 'atom', 'codemirror', 'ember', 'eslint', 'express', 'jquery', 'jscs', 'jshint').
18 * @param {String} pluginConfig.config Requierable npm package with a custom conventional-changelog preset
19 * @param {Object} pluginConfig.parserOpts Additional `conventional-changelog-parser` options that will overwrite ones loaded by `preset` or `config`.
20 * @param {Object} pluginConfig.writerOpts Additional `conventional-changelog-writer` options that will overwrite ones loaded by `preset` or `config`.
21 * @param {Object} context The semantic-release context.
22 * @param {Array<Object>} context.commits The commits to analyze.
23 * @param {Object} context.lastRelease The last release with `gitHead` corresponding to the commit hash used to make the last release and `gitTag` corresponding to the git tag associated with `gitHead`.
24 * @param {Object} context.nextRelease The next release with `gitHead` corresponding to the commit hash used to make the release, the release `version` and `gitTag` corresponding to the git tag associated with `gitHead`.
25 * @param {Object} context.options.repositoryUrl The git repository URL.
26 *
27 * @returns {String} The changelog for all the commits in `context.commits`.
28 */
29async 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
92module.exports = {generateNotes};