1 | import { format } from "url";
|
2 | import { find, merge } from "lodash-es";
|
3 | import getStream from "get-stream";
|
4 | import intoStream from "into-stream";
|
5 | import { CommitParser } from "conventional-commits-parser";
|
6 | import writer from "./wrappers/conventional-changelog-writer.js";
|
7 | import { filterRevertedCommitsSync } from "conventional-commits-filter";
|
8 | import { readPackageUp } from "read-package-up";
|
9 | import debugFactory from "debug";
|
10 | import loadChangelogConfig from "./lib/load-changelog-config.js";
|
11 | import HOSTS_CONFIG from "./lib/hosts-config.js";
|
12 |
|
13 | const debug = debugFactory("semantic-release:release-notes-generator");
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | export 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 parser = new CommitParser({ referenceActions, issuePrefixes, ...parserOpts });
|
47 | const parsedCommits = filterRevertedCommitsSync(
|
48 | commits
|
49 | .filter(({ message, hash }) => {
|
50 | if (!message.trim()) {
|
51 | debug("Skip commit %s with empty message", hash);
|
52 | return false;
|
53 | }
|
54 |
|
55 | return true;
|
56 | })
|
57 | .map((rawCommit) => ({
|
58 | ...rawCommit,
|
59 | ...parser.parse(rawCommit.message),
|
60 | }))
|
61 | );
|
62 | const previousTag = lastRelease.gitTag || lastRelease.gitHead;
|
63 | const currentTag = nextRelease.gitTag || nextRelease.gitHead;
|
64 | const { host: hostConfig, linkCompare, linkReferences, commit: commitConfig, issue: issueConfig } = pluginConfig;
|
65 | const changelogContext = merge(
|
66 | {
|
67 | version: nextRelease.version,
|
68 | host: format({ protocol, hostname, port }),
|
69 | owner,
|
70 | repository,
|
71 | previousTag,
|
72 | currentTag,
|
73 | linkCompare: currentTag && previousTag,
|
74 | issue,
|
75 | commit,
|
76 | packageData: ((await readPackageUp({ normalize: false, cwd })) || {}).packageJson,
|
77 | },
|
78 | { host: hostConfig, linkCompare, linkReferences, commit: commitConfig, issue: issueConfig }
|
79 | );
|
80 |
|
81 | debug("version: %o", changelogContext.version);
|
82 | debug("host: %o", changelogContext.hostname);
|
83 | debug("owner: %o", changelogContext.owner);
|
84 | debug("repository: %o", changelogContext.repository);
|
85 | debug("previousTag: %o", changelogContext.previousTag);
|
86 | debug("currentTag: %o", changelogContext.currentTag);
|
87 | debug("host: %o", changelogContext.host);
|
88 | debug("linkReferences: %o", changelogContext.linkReferences);
|
89 | debug("issue: %o", changelogContext.issue);
|
90 | debug("commit: %o", changelogContext.commit);
|
91 |
|
92 | return getStream(intoStream.object(parsedCommits).pipe(writer(changelogContext, writerOpts)));
|
93 | }
|