UNPKG

4.63 kBJavaScriptView Raw
1import { format } from "url";
2import { find, merge } from "lodash-es";
3import getStream from "get-stream";
4import intoStream from "into-stream";
5import { sync as parser } from "conventional-commits-parser";
6import writer from "./wrappers/conventional-changelog-writer.js";
7import filter from "conventional-commits-filter";
8import { readPackageUp } from "read-pkg-up";
9import debugFactory from "debug";
10import loadChangelogConfig from "./lib/load-changelog-config.js";
11import HOSTS_CONFIG from "./lib/hosts-config.js";
12
13const debug = debugFactory("semantic-release:release-notes-generator");
14
15/**
16 * Generate the changelog for all the commits in `options.commits`.
17 *
18 * @param {Object} pluginConfig The plugin configuration.
19 * @param {String} pluginConfig.preset conventional-changelog preset ('angular', 'atom', 'codemirror', 'ember', 'eslint', 'express', 'jquery', 'jscs', 'jshint').
20 * @param {String} pluginConfig.config Requireable npm package with a custom conventional-changelog preset
21 * @param {Object} pluginConfig.parserOpts Additional `conventional-changelog-parser` options that will overwrite ones loaded by `preset` or `config`.
22 * @param {Object} pluginConfig.writerOpts Additional `conventional-changelog-writer` options that will overwrite ones loaded by `preset` or `config`.
23 * @param {Object} context The semantic-release context.
24 * @param {Array<Object>} context.commits The commits to analyze.
25 * @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`.
26 * @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`.
27 * @param {Object} context.options.repositoryUrl The git repository URL.
28 *
29 * @returns {String} The changelog for all the commits in `context.commits`.
30 */
31export async function generateNotes(pluginConfig, context) {
32 const { commits, lastRelease, nextRelease, options, cwd } = context;
33 const repositoryUrl = options.repositoryUrl.replace(/\.git$/i, "");
34 const { parserOpts, writerOpts } = await loadChangelogConfig(pluginConfig, context);
35
36 const [match, auth, host, path] = /^(?!.+:\/\/)(?:(?<auth>.*)@)?(?<host>.*?):(?<path>.*)$/.exec(repositoryUrl) || [];
37 let { hostname, port, pathname, protocol } = new URL(
38 match ? `ssh://${auth ? `${auth}@` : ""}${host}/${path}` : repositoryUrl
39 );
40 port = protocol.includes("ssh") ? "" : port;
41 protocol = protocol && /http[^s]/.test(protocol) ? "http" : "https";
42 const [, owner, repository] = /^\/(?<owner>[^/]+)?\/?(?<repository>.+)?$/.exec(pathname);
43
44 const { issue, commit, referenceActions, issuePrefixes } =
45 find(HOSTS_CONFIG, (conf) => conf.hostname === hostname) || HOSTS_CONFIG.default;
46 const parsedCommits = filter(
47 commits
48 .filter(({ message, hash }) => {
49 if (!message.trim()) {
50 debug("Skip commit %s with empty message", hash);
51 return false;
52 }
53
54 return true;
55 })
56 .map((rawCommit) => ({
57 ...rawCommit,
58 ...parser(rawCommit.message, { referenceActions, issuePrefixes, ...parserOpts }),
59 }))
60 );
61 const previousTag = lastRelease.gitTag || lastRelease.gitHead;
62 const currentTag = nextRelease.gitTag || nextRelease.gitHead;
63 const { host: hostConfig, linkCompare, linkReferences, commit: commitConfig, issue: issueConfig } = pluginConfig;
64 const changelogContext = merge(
65 {
66 version: nextRelease.version,
67 host: format({ protocol, hostname, port }),
68 owner,
69 repository,
70 previousTag,
71 currentTag,
72 linkCompare: currentTag && previousTag,
73 issue,
74 commit,
75 packageData: ((await readPackageUp({ normalize: false, cwd })) || {}).packageJson,
76 },
77 { host: hostConfig, linkCompare, linkReferences, commit: commitConfig, issue: issueConfig }
78 );
79
80 debug("version: %o", changelogContext.version);
81 debug("host: %o", changelogContext.hostname);
82 debug("owner: %o", changelogContext.owner);
83 debug("repository: %o", changelogContext.repository);
84 debug("previousTag: %o", changelogContext.previousTag);
85 debug("currentTag: %o", changelogContext.currentTag);
86 debug("host: %o", changelogContext.host);
87 debug("linkReferences: %o", changelogContext.linkReferences);
88 debug("issue: %o", changelogContext.issue);
89 debug("commit: %o", changelogContext.commit);
90
91 return getStream(intoStream.object(parsedCommits).pipe(writer(changelogContext, writerOpts)));
92}