Repository: semantic-release/semantic-release
Pull request #473 (2017-10-18 20:35:03)

Handle errors when verifyConditions and verifyRelease are a pipeline
The plugin module for `verifyConditions` and `verifyRelease` was returning:
- A `Promise` returning function if multiple plugins are defined
- The plugin itself (a function with callback) when there is only one plugin in the chain

The rest of the code expected `verifyConditions` and `verifyRelease` to be a function with callback and was promisifying it.
If there was multiple plugins in the pipeline that that was resulting in promisifying a promise and the errors returned were not caught and node was warning with ` UnhandledPromiseRejectionWarning: Unhandled promise rejection`.

With this fix the plugin module always return a `Promise` returning function for `verifyConditions` and `verifyRelease` and the rest of the code doesn't promisify them anymore.

See #406

gr2m: Thanks @pvdlg great work 👍 

Patch:
diff --git a/src/index.js b/src/index.js
index 01b53aa..d27e425 100644
--- a/src/index.js
+++ b/src/index.js
@@ -75,7 +75,7 @@ module.exports = async () => {
     log.verbose('pre', 'Running pre-script.');
     log.verbose('pre', 'Veriying conditions.');
     try {
-      await promisify(plugins.verifyConditions)(config);
+      await plugins.verifyConditions(config);
     } catch (err) {
       log[options.debug ? 'warn' : 'error']('pre', err.message);
       if (!options.debug) process.exit(1);
diff --git a/src/lib/plugins.js b/src/lib/plugins.js
index 58831de..0cdc50c 100644
--- a/src/lib/plugins.js
+++ b/src/lib/plugins.js
@@ -10,20 +10,21 @@ module.exports = options => {
   };
   ['verifyConditions', 'verifyRelease'].forEach(plugin => {
     if (!Array.isArray(options[plugin])) {
-      plugins[plugin] = normalize(
-        options[plugin],
-        plugin === 'verifyConditions' ? '@semantic-release/condition-travis' : './plugin-noop'
+      plugins[plugin] = promisify(
+        normalize(
+          options[plugin],
+          plugin === 'verifyConditions' ? '@semantic-release/condition-travis' : './plugin-noop'
+        )
       );
-      return;
+    } else {
+      plugins[plugin] = async pluginOptions => {
+        return pSeries(
+          options[plugin].map(step => {
+            return () => promisify(normalize(step, './plugin-noop'))(pluginOptions);
+          })
+        );
+      };
     }
-
-    plugins[plugin] = async pluginOptions => {
-      return pSeries(
-        options[plugin].map(step => {
-          return () => promisify(normalize(step, './plugin-noop'))(pluginOptions);
-        })
-      );
-    };
   });
 
   return plugins;
diff --git a/src/pre.js b/src/pre.js
index f8d1d1c..46e05b2 100644
--- a/src/pre.js
+++ b/src/pre.js
@@ -17,7 +17,7 @@ module.exports = async config => {
     version: type === 'initial' ? '1.0.0' : semver.inc(lastRelease.version, type),
   };
 
-  await promisify(verifyRelease)(assign({commits, lastRelease, nextRelease}, config));
+  await verifyRelease(assign({commits, lastRelease, nextRelease}, config));
 
   return nextRelease;
 };


Test patch:
diff --git a/test/pre.test.js b/test/pre.test.js
index ea2ffec..01db4d2 100644
--- a/test/pre.test.js
+++ b/test/pre.test.js
@@ -44,7 +44,7 @@ test.serial('Increase version', async t => {
     plugins: {
       getLastRelease: callbackify(getLastRelease),
       analyzeCommits: callbackify(analyzeCommits),
-      verifyRelease: callbackify(verifyRelease),
+      verifyRelease: verifyRelease,
     },
   });
 
@@ -89,7 +89,7 @@ test.serial('Initial version', async t => {
     plugins: {
       getLastRelease: callbackify(getLastRelease),
       analyzeCommits: callbackify(analyzeCommits),
-      verifyRelease: callbackify(verifyRelease),
+      verifyRelease: verifyRelease,
     },
   });
 
@@ -137,7 +137,7 @@ test.serial('Throws error if verifyRelease fails', async t => {
       plugins: {
         getLastRelease: callbackify(getLastRelease),
         analyzeCommits: callbackify(analyzeCommits),
-        verifyRelease: callbackify(verifyRelease),
+        verifyRelease: verifyRelease,
       },
     })
   );