Repository: semantic-release/semantic-release
Pull request #520 (2017-11-23 00:23:58)

Use default plugin if the path property is missing from a single plugin configuration
Fix regression introduced in #515

The configuration is now using the default plugin '@semantic-release/commit-analyzer' with passing a parameter instead of throwing an error.
```json
"release": {
  "analyzeCommits": {
    "param": "value"
  }
}
```

codecov[bot]: # [Codecov](https://codecov.io/gh/semantic-release/semantic-release/pull/520?src=pr&el=h1) Report
> Merging [#520](https://codecov.io/gh/semantic-release/semantic-release/pull/520?src=pr&el=desc) into [caribou](https://codecov.io/gh/semantic-release/semantic-release/commit/facdadaddb9d1816c77d5719812734549a74899b?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/semantic-release/semantic-release/pull/520/graphs/tree.svg?width=650&height=150&src=pr&token=hENTgPdVFG)](https://codecov.io/gh/semantic-release/semantic-release/pull/520?src=pr&el=tree)

```diff
@@          Coverage Diff           @@
##           caribou   #520   +/-   ##
======================================
  Coverage      100%   100%           
======================================
  Files           13     13           
  Lines          248    245    -3     
  Branches        47     48    +1     
======================================
- Hits           248    245    -3
```


| [Impacted Files](https://codecov.io/gh/semantic-release/semantic-release/pull/520?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [lib/plugins/definitions.js](https://codecov.io/gh/semantic-release/semantic-release/pull/520?src=pr&el=tree#diff-bGliL3BsdWdpbnMvZGVmaW5pdGlvbnMuanM=) | `100% <ø> (ø)` | :arrow_up: |
| [lib/plugins/index.js](https://codecov.io/gh/semantic-release/semantic-release/pull/520?src=pr&el=tree#diff-bGliL3BsdWdpbnMvaW5kZXguanM=) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/semantic-release/semantic-release/pull/520?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/semantic-release/semantic-release/pull/520?src=pr&el=footer). Last update [facdada...deee205](https://codecov.io/gh/semantic-release/semantic-release/pull/520?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/lib/plugins/definitions.js b/lib/plugins/definitions.js
index 32b547a..60909d5 100644
--- a/lib/plugins/definitions.js
+++ b/lib/plugins/definitions.js
@@ -1,17 +1,12 @@
 const {isString, isObject, isFunction, isArray} = require('lodash');
 const semver = require('semver');
-const conditionTravis = require('@semantic-release/condition-travis');
-const commitAnalyzer = require('@semantic-release/commit-analyzer');
-const releaseNotesGenerator = require('@semantic-release/release-notes-generator');
-const npm = require('@semantic-release/npm');
-const github = require('@semantic-release/github');
 
 const RELEASE_TYPE = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'];
 const validatePluginConfig = conf => isString(conf) || isString(conf.path) || isFunction(conf);
 
 module.exports = {
   verifyConditions: {
-    default: [npm.verifyConditions, github.verifyConditions, conditionTravis],
+    default: ['@semantic-release/npm', '@semantic-release/github', '@semantic-release/condition-travis'],
     config: {
       validator: conf => !conf || (isArray(conf) ? conf : [conf]).every(conf => validatePluginConfig(conf)),
       message:
@@ -19,7 +14,7 @@ module.exports = {
     },
   },
   getLastRelease: {
-    default: npm.getLastRelease,
+    default: '@semantic-release/npm',
     config: {
       validator: conf => Boolean(conf) && validatePluginConfig(conf),
       message:
@@ -35,7 +30,7 @@ module.exports = {
     },
   },
   analyzeCommits: {
-    default: commitAnalyzer,
+    default: '@semantic-release/commit-analyzer',
     config: {
       validator: conf => Boolean(conf) && validatePluginConfig(conf),
       message:
@@ -55,7 +50,7 @@ module.exports = {
     },
   },
   generateNotes: {
-    default: releaseNotesGenerator,
+    default: '@semantic-release/release-notes-generator',
     config: {
       validator: conf => !conf || validatePluginConfig(conf),
       message:
@@ -67,7 +62,7 @@ module.exports = {
     },
   },
   publish: {
-    default: [npm.publish, github.publish],
+    default: ['@semantic-release/npm', '@semantic-release/github'],
     config: {
       validator: conf => Boolean(conf) && (isArray(conf) ? conf : [conf]).every(conf => validatePluginConfig(conf)),
       message:
diff --git a/lib/plugins/index.js b/lib/plugins/index.js
index 1ff266f..70bc69d 100644
--- a/lib/plugins/index.js
+++ b/lib/plugins/index.js
@@ -1,4 +1,4 @@
-const {isArray} = require('lodash');
+const {isArray, isObject} = require('lodash');
 const DEFINITIONS = require('./definitions');
 const pipeline = require('./pipeline');
 const normalize = require('./normalize');
@@ -8,6 +8,10 @@ module.exports = (options, logger) =>
     const {config, output, default: def} = DEFINITIONS[pluginType];
     let pluginConfs;
     if (options[pluginType]) {
+      // If an object is passed and the path is missing, set the default one for single plugins
+      if (isObject(options[pluginType]) && !options[pluginType].path && !isArray(def)) {
+        options[pluginType].path = def;
+      }
       if (config && !config.validator(options[pluginType])) {
         throw new Error(config.message);
       }


Test patch:
diff --git a/test/plugins/plugins.test.js b/test/plugins/plugins.test.js
index 41b8abc..a4525cf 100644
--- a/test/plugins/plugins.test.js
+++ b/test/plugins/plugins.test.js
@@ -9,8 +9,8 @@ test.beforeEach(t => {
 });
 
 test('Export default plugins', t => {
-  // Call the plugin module
   const plugins = getPlugins({}, t.context.logger);
+
   // Verify the module returns a function for each plugin
   t.is(typeof plugins.verifyConditions, 'function');
   t.is(typeof plugins.getLastRelease, 'function');
@@ -21,7 +21,6 @@ test('Export default plugins', t => {
 });
 
 test('Export plugins based on config', t => {
-  // Call the plugin module
   const plugins = getPlugins(
     {
       verifyConditions: ['./test/fixtures/plugin-noop', {path: './test/fixtures/plugin-noop'}],
@@ -31,6 +30,7 @@ test('Export plugins based on config', t => {
     },
     t.context.logger
   );
+
   // Verify the module returns a function for each plugin
   t.is(typeof plugins.verifyConditions, 'function');
   t.is(typeof plugins.getLastRelease, 'function');
@@ -40,8 +40,26 @@ test('Export plugins based on config', t => {
   t.is(typeof plugins.publish, 'function');
 });
 
-test('Throw an error if plugin configuration is invalid', t => {
+test('Use default when only options are passed for a single plugin', t => {
+  const plugins = getPlugins({getLastRelease: {}, analyzeCommits: {}}, t.context.logger);
+
+  // Verify the module returns a function for each plugin
+  t.is(typeof plugins.getLastRelease, 'function');
+  t.is(typeof plugins.analyzeCommits, 'function');
+});
+
+test('Throw an error if plugin configuration is missing a path for plugin pipeline', t => {
   const error = t.throws(() => getPlugins({verifyConditions: {}}, t.context.logger));
+
+  t.is(
+    error.message,
+    'The "verifyConditions" plugin, if defined, must be a single or an array of plugins definition. A plugin definition is either a string or an object with a path property.'
+  );
+});
+
+test('Throw an error if an array of plugin configuration is missing a path for plugin pipeline', t => {
+  const error = t.throws(() => getPlugins({verifyConditions: [{path: '@semantic-release/npm'}, {}]}, t.context.logger));
+
   t.is(
     error.message,
     'The "verifyConditions" plugin, if defined, must be a single or an array of plugins definition. A plugin definition is either a string or an object with a path property.'