UNPKG

3.41 kBJavaScriptView Raw
1import { isUndefined } from "lodash-es";
2import { sync as parser } from "conventional-commits-parser";
3import filter from "conventional-commits-filter";
4import debugFactory from "debug";
5import loadParserConfig from "./lib/load-parser-config.js";
6import loadReleaseRules from "./lib/load-release-rules.js";
7import analyzeCommit from "./lib/analyze-commit.js";
8import compareReleaseTypes from "./lib/compare-release-types.js";
9import RELEASE_TYPES from "./lib/default-release-types.js";
10import DEFAULT_RELEASE_RULES from "./lib/default-release-rules.js";
11
12const debug = debugFactory("semantic-release:commit-analyzer");
13
14/**
15 * Determine the type of release to create based on a list of commits.
16 *
17 * @param {Object} pluginConfig The plugin configuration.
18 * @param {String} pluginConfig.preset conventional-changelog preset ('angular', 'atom', 'codemirror', 'ember', 'eslint', 'express', 'jquery', 'jscs', 'jshint')
19 * @param {String} pluginConfig.config Requireable npm package with a custom conventional-changelog preset
20 * @param {String|Array} pluginConfig.releaseRules A `String` to load an external module or an `Array` of rules.
21 * @param {Object} pluginConfig.parserOpts Additional `conventional-changelog-parser` options that will overwrite ones loaded by `preset` or `config`.
22 * @param {Object} context The semantic-release context.
23 * @param {Array<Object>} context.commits The commits to analyze.
24 * @param {String} context.cwd The current working directory.
25 *
26 * @returns {String|null} the type of release to create based on the list of commits or `null` if no release has to be done.
27 */
28export async function analyzeCommits(pluginConfig, context) {
29 const { commits, logger } = context;
30 const releaseRules = loadReleaseRules(pluginConfig, context);
31 const config = await loadParserConfig(pluginConfig, context);
32 let releaseType = null;
33
34 filter(
35 commits
36 .filter(({ message, hash }) => {
37 if (!message.trim()) {
38 debug("Skip commit %s with empty message", hash);
39 return false;
40 }
41
42 return true;
43 })
44 .map(({ message, ...commitProps }) => ({ rawMsg: message, message, ...commitProps, ...parser(message, config) }))
45 ).every(({ rawMsg, ...commit }) => {
46 logger.log(`Analyzing commit: %s`, rawMsg);
47 let commitReleaseType;
48
49 // Determine release type based on custom releaseRules
50 if (releaseRules) {
51 debug("Analyzing with custom rules");
52 commitReleaseType = analyzeCommit(releaseRules, commit);
53 }
54
55 // If no custom releaseRules or none matched the commit, try with default releaseRules
56 if (isUndefined(commitReleaseType)) {
57 debug("Analyzing with default rules");
58 commitReleaseType = analyzeCommit(DEFAULT_RELEASE_RULES, commit);
59 }
60
61 if (commitReleaseType) {
62 logger.log("The release type for the commit is %s", commitReleaseType);
63 } else {
64 logger.log("The commit should not trigger a release");
65 }
66
67 // Set releaseType if commit's release type is higher
68 if (commitReleaseType && compareReleaseTypes(releaseType, commitReleaseType)) {
69 releaseType = commitReleaseType;
70 }
71
72 // Break loop if releaseType is the highest
73 if (releaseType === RELEASE_TYPES[0]) {
74 return false;
75 }
76
77 return true;
78 });
79 logger.log("Analysis of %s commits complete: %s release", commits.length, releaseType || "no");
80
81 return releaseType;
82}