Repository: semantic-release/semantic-release
Pull request #1815 (2021-02-22 22:12:48)

feat(config): Use cosmiconfig defaults to support .cjs config files
This change adds support for `*.cjs` config files by removing the explicit use of `searchPlaces` options and relying and the default search places generated by `cosmicconfig`.  As per the docs for [`cosmicconfig`][cc], the defaults include all the extensions/formats previously supported by semantic-release in addition to the new .cjs variants.

Resolves [#1814][issue].

[issue]: https://github.com/semantic-release/semantic-release/issues/1814
[cc]: https://github.com/davidtheclark/cosmiconfig#searchplaces

travi: thank you for investigating and tracking down these details. i did dig a little bit to try to understand why they were defined explicitly before, but even the version that resulted in the addition appears to have supported similar defaults. from what i can tell this change aligns with the original intent fro before that change too.

Patch:
diff --git a/lib/get-config.js b/lib/get-config.js
index c54acfe..1f16962 100644
--- a/lib/get-config.js
+++ b/lib/get-config.js
@@ -9,19 +9,10 @@ const plugins = require('./plugins');
 const {validatePlugin, parseConfig} = require('./plugins/utils');
 
 const CONFIG_NAME = 'release';
-const CONFIG_FILES = [
-  'package.json',
-  `.${CONFIG_NAME}rc`,
-  `.${CONFIG_NAME}rc.json`,
-  `.${CONFIG_NAME}rc.yaml`,
-  `.${CONFIG_NAME}rc.yml`,
-  `.${CONFIG_NAME}rc.js`,
-  `${CONFIG_NAME}.config.js`,
-];
 
 module.exports = async (context, cliOptions) => {
   const {cwd, env} = context;
-  const {config, filepath} = (await cosmiconfig(CONFIG_NAME, {searchPlaces: CONFIG_FILES}).search(cwd)) || {};
+  const {config, filepath} = (await cosmiconfig(CONFIG_NAME).search(cwd)) || {};
 
   debug('load config from: %s', filepath);
 


Test patch:
diff --git a/test/get-config.test.js b/test/get-config.test.js
index ecec2b3..94f32bd 100644
--- a/test/get-config.test.js
+++ b/test/get-config.test.js
@@ -191,6 +191,28 @@ test('Read options from .releaserc.js', async (t) => {
   t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
 });
 
+test('Read options from .releaserc.cjs', async (t) => {
+  // Create a git repository, set the current working directory at the root of the repo
+  const {cwd} = await gitRepo();
+  const options = {
+    analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
+    branches: ['test_branch'],
+    repositoryUrl: 'https://host.null/owner/module.git',
+    tagFormat: `v\${version}`,
+    plugins: false,
+  };
+  // Create .releaserc.cjs in repository root
+  await writeFile(path.resolve(cwd, '.releaserc.cjs'), `module.exports = ${JSON.stringify(options)}`);
+
+  const {options: result} = await t.context.getConfig({cwd});
+
+  const expected = {...options, branches: ['test_branch']};
+  // Verify the options contains the plugin config from .releaserc.cjs
+  t.deepEqual(result, expected);
+  // Verify the plugins module is called with the plugin options from .releaserc.cjs
+  t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
+});
+
 test('Read options from release.config.js', async (t) => {
   // Create a git repository, set the current working directory at the root of the repo
   const {cwd} = await gitRepo();
@@ -213,6 +235,28 @@ test('Read options from release.config.js', async (t) => {
   t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
 });
 
+test('Read options from release.config.cjs', async (t) => {
+  // Create a git repository, set the current working directory at the root of the repo
+  const {cwd} = await gitRepo();
+  const options = {
+    analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
+    branches: ['test_branch'],
+    repositoryUrl: 'https://host.null/owner/module.git',
+    tagFormat: `v\${version}`,
+    plugins: false,
+  };
+  // Create release.config.cjs in repository root
+  await writeFile(path.resolve(cwd, 'release.config.cjs'), `module.exports = ${JSON.stringify(options)}`);
+
+  const {options: result} = await t.context.getConfig({cwd});
+
+  const expected = {...options, branches: ['test_branch']};
+  // Verify the options contains the plugin config from release.config.cjs
+  t.deepEqual(result, expected);
+  // Verify the plugins module is called with the plugin options from release.config.cjs
+  t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
+});
+
 test('Prioritise CLI/API parameters over file configuration and git repo', async (t) => {
   // Create a git repository, set the current working directory at the root of the repo
   let {cwd, repositoryUrl} = await gitRepo();