Skip to content

Commit 9dc87e0

Browse files
sheerloxtravi
andauthored
feat: add support for ESM presets (#537)
Co-authored-by: Matt Travi <programmer@travi.org>
1 parent 96b93b7 commit 9dc87e0

7 files changed

+52
-31
lines changed

index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ const debug = debugFactory("semantic-release:commit-analyzer");
2323
* @param {Array<Object>} context.commits The commits to analyze.
2424
* @param {String} context.cwd The current working directory.
2525
*
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.
26+
* @returns {Promise<String|null>} the type of release to create based on the list of commits or `null` if no release has to be done.
2727
*/
2828
export async function analyzeCommits(pluginConfig, context) {
2929
const { commits, logger } = context;
30-
const releaseRules = loadReleaseRules(pluginConfig, context);
30+
const releaseRules = await loadReleaseRules(pluginConfig, context);
3131
const config = await loadParserConfig(pluginConfig, context);
3232
let releaseType = null;
3333

lib/load-parser-config.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { dirname } from "node:path";
22
import { fileURLToPath } from "node:url";
3-
import { promisify } from "node:util";
4-
import { isPlainObject } from "lodash-es";
5-
import importFrom from "import-from";
3+
import importFrom from "import-from-esm";
64
import conventionalChangelogAngular from "conventional-changelog-angular";
75

86
/**
@@ -14,6 +12,7 @@ import conventionalChangelogAngular from "conventional-changelog-angular";
1412
* @param {Object} pluginConfig.parserOpts Additional `conventional-changelog-parser` options that will overwrite ones loaded by `preset` or `config`.
1513
* @param {Object} context The semantic-release context.
1614
* @param {String} context.cwd The current working directory.
15+
*
1716
* @return {Promise<Object>} a `Promise` that resolve to the `conventional-changelog-parser` options.
1817
*/
1918
export default async ({ preset, config, parserOpts, presetConfig }, { cwd }) => {
@@ -22,9 +21,11 @@ export default async ({ preset, config, parserOpts, presetConfig }, { cwd }) =>
2221

2322
if (preset) {
2423
const presetPackage = `conventional-changelog-${preset.toLowerCase()}`;
25-
loadedConfig = await (importFrom.silent(__dirname, presetPackage) || importFrom(cwd, presetPackage))(presetConfig);
24+
loadedConfig = await (
25+
(await importFrom.silent(__dirname, presetPackage)) || (await importFrom(cwd, presetPackage))
26+
)(presetConfig);
2627
} else if (config) {
27-
loadedConfig = await (importFrom.silent(__dirname, config) || importFrom(cwd, config))();
28+
loadedConfig = await ((await importFrom.silent(__dirname, config)) || (await importFrom(cwd, config)))();
2829
} else {
2930
loadedConfig = await conventionalChangelogAngular();
3031
}

lib/load-release-rules.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { dirname } from "node:path";
22
import { fileURLToPath } from "node:url";
33
import { isUndefined } from "lodash-es";
4-
import importFrom from "import-from";
4+
import importFrom from "import-from-esm";
55
import RELEASE_TYPES from "./default-release-types.js";
66

77
/**
@@ -15,16 +15,16 @@ import RELEASE_TYPES from "./default-release-types.js";
1515
* @param {Object} context The semantic-release context.
1616
* @param {String} context.cwd The current working directory.
1717
*
18-
* @return {Array} the loaded and validated `releaseRules`.
18+
* @return {Promise<Array>} the loaded and validated `releaseRules`.
1919
*/
20-
export default ({ releaseRules }, { cwd }) => {
20+
export default async ({ releaseRules }, { cwd }) => {
2121
let loadedReleaseRules;
2222
const __dirname = dirname(fileURLToPath(import.meta.url));
2323

2424
if (releaseRules) {
2525
loadedReleaseRules =
2626
typeof releaseRules === "string"
27-
? importFrom.silent(__dirname, releaseRules) || importFrom(cwd, releaseRules)
27+
? (await importFrom.silent(__dirname, releaseRules)) || (await importFrom(cwd, releaseRules))
2828
: releaseRules;
2929

3030
if (!Array.isArray(loadedReleaseRules)) {

package-lock.json

+10-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"conventional-commits-filter": "^4.0.0",
2222
"conventional-commits-parser": "^5.0.0",
2323
"debug": "^4.0.0",
24-
"import-from": "^4.0.0",
24+
"import-from-esm": "^1.0.3",
2525
"lodash-es": "^4.17.21",
2626
"micromatch": "^4.0.2"
2727
},

test/load-parser-config.test.js

+11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import test from "ava";
2+
import importFrom from "import-from-esm";
3+
import sinon from "sinon";
24
import loadParserConfig from "../lib/load-parser-config.js";
35

46
const cwd = process.cwd();
@@ -100,3 +102,12 @@ test('Throw error if "config" doesn`t exist', async (t) => {
100102
test('Throw error if "preset" doesn`t exist', async (t) => {
101103
await t.throwsAsync(loadParserConfig({ preset: "unknown-preset" }, { cwd }), { code: "MODULE_NOT_FOUND" });
102104
});
105+
106+
test.serial("Load preset and config correctly when importFrom.silent fails", async (t) => {
107+
sinon.stub(importFrom, "silent").returns(undefined);
108+
109+
await loadPreset(t, "angular");
110+
await loadConfig(t, "angular");
111+
112+
sinon.restore();
113+
});

test/load-release-rules.test.js

+18-18
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,26 @@ import testReleaseRules from "./fixtures/release-rules.cjs";
44

55
const cwd = process.cwd();
66

7-
test('Accept a "releaseRules" option', (t) => {
8-
const releaseRules = loadReleaseRules({ releaseRules: testReleaseRules }, { cwd });
7+
test('Accept a "releaseRules" option', async (t) => {
8+
const releaseRules = await loadReleaseRules({ releaseRules: testReleaseRules }, { cwd });
99

1010
t.deepEqual(releaseRules, testReleaseRules);
1111
});
1212

13-
test('Accept a "releaseRules" option that reference a requireable module', (t) => {
14-
const releaseRules = loadReleaseRules({ releaseRules: "./test/fixtures/release-rules.cjs" }, { cwd });
13+
test('Accept a "releaseRules" option that reference a requireable module', async (t) => {
14+
const releaseRules = await loadReleaseRules({ releaseRules: "./test/fixtures/release-rules.cjs" }, { cwd });
1515

1616
t.deepEqual(releaseRules, testReleaseRules);
1717
});
1818

19-
test('Return undefined if "releaseRules" not set', (t) => {
20-
const releaseRules = loadReleaseRules({}, { cwd });
19+
test('Return undefined if "releaseRules" not set', async (t) => {
20+
const releaseRules = await loadReleaseRules({}, { cwd });
2121

2222
t.is(releaseRules, undefined);
2323
});
2424

25-
test('Preserve release rules set to "false" or "null"', (t) => {
26-
const releaseRules = loadReleaseRules(
25+
test('Preserve release rules set to "false" or "null"', async (t) => {
26+
const releaseRules = await loadReleaseRules(
2727
{
2828
releaseRules: [
2929
{ type: "feat", release: false },
@@ -39,32 +39,32 @@ test('Preserve release rules set to "false" or "null"', (t) => {
3939
]);
4040
});
4141

42-
test('Throw error if "releaseRules" reference invalid commit type', (t) => {
43-
t.throws(() => loadReleaseRules({ releaseRules: [{ tag: "Update", release: "invalid" }] }, { cwd }), {
42+
test('Throw error if "releaseRules" reference invalid commit type', async (t) => {
43+
await t.throwsAsync(loadReleaseRules({ releaseRules: [{ tag: "Update", release: "invalid" }] }, { cwd }), {
4444
message: /Error in commit-analyzer configuration: "invalid" is not a valid release type\. Valid values are:\[?.*]/,
4545
});
4646
});
4747

48-
test('Throw error if a rule in "releaseRules" does not have a release type', (t) => {
49-
t.throws(() => loadReleaseRules({ releaseRules: [{ tag: "Update" }] }, { cwd }), {
48+
test('Throw error if a rule in "releaseRules" does not have a release type', async (t) => {
49+
await t.throwsAsync(loadReleaseRules({ releaseRules: [{ tag: "Update" }] }, { cwd }), {
5050
message: /Error in commit-analyzer configuration: rules must be an object with a "release" property/,
5151
});
5252
});
5353

54-
test('Throw error if "releaseRules" is not an Array or a String', (t) => {
55-
t.throws(() => loadReleaseRules({ releaseRules: {} }, { cwd }), {
54+
test('Throw error if "releaseRules" is not an Array or a String', async (t) => {
55+
await t.throwsAsync(loadReleaseRules({ releaseRules: {} }, { cwd }), {
5656
message: /Error in commit-analyzer configuration: "releaseRules" must be an array of rules/,
5757
});
5858
});
5959

60-
test('Throw error if "releaseRules" option reference a requirable module that is not an Array or a String', (t) => {
61-
t.throws(() => loadReleaseRules({ releaseRules: "./test/fixtures/release-rules-invalid.cjs" }, { cwd }), {
60+
test('Throw error if "releaseRules" option reference a requirable module that is not an Array or a String', async (t) => {
61+
await t.throwsAsync(loadReleaseRules({ releaseRules: "./test/fixtures/release-rules-invalid.cjs" }, { cwd }), {
6262
message: /Error in commit-analyzer configuration: "releaseRules" must be an array of rules/,
6363
});
6464
});
6565

66-
test('Throw error if "releaseRules" contains an undefined rule', (t) => {
67-
t.throws(() => loadReleaseRules({ releaseRules: [{ type: "feat", release: "minor" }, undefined] }, { cwd }), {
66+
test('Throw error if "releaseRules" contains an undefined rule', async (t) => {
67+
await t.throwsAsync(loadReleaseRules({ releaseRules: [{ type: "feat", release: "minor" }, undefined] }, { cwd }), {
6868
message: /Error in commit-analyzer configuration: rules must be an object with a "release" property/,
6969
});
7070
});

0 commit comments

Comments
 (0)