feat: Expect plugins to return Promises
BREAKING CHANGE: Each plugin is expected to return an async function or a Promise returning function. The callback parameter is not passed to plugins anymore.
This commit is contained in:
		
							parent
							
								
									d4c7605f68
								
							
						
					
					
						commit
						5bec59b26b
					
				| @ -210,8 +210,6 @@ module.exports = function (pluginConfig, config, callback) {} | |||||||
|   - `options`: `semantic-release` options like `debug`, or `branch` |   - `options`: `semantic-release` options like `debug`, or `branch` | ||||||
|   - `pkg`: Parsed `package.json` |   - `pkg`: Parsed `package.json` | ||||||
|   - For certain plugins the `config` object contains even more information. See below. |   - For certain plugins the `config` object contains even more information. See below. | ||||||
| - `callback`: If an error occurs pass it as first argument. Otherwise pass your result as second argument. |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| ### `analyzeCommits` | ### `analyzeCommits` | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| const {promisify, inspect} = require('util'); | const {inspect} = require('util'); | ||||||
| const {isString, isObject, isFunction, noop, cloneDeep} = require('lodash'); | const {isString, isObject, isFunction, noop, cloneDeep} = require('lodash'); | ||||||
| const importFrom = require('import-from'); | const importFrom = require('import-from'); | ||||||
| 
 | 
 | ||||||
| @ -14,9 +14,9 @@ module.exports = (pluginType, pluginConfig, logger, validator) => { | |||||||
| 
 | 
 | ||||||
|   let func; |   let func; | ||||||
|   if (isFunction(plugin)) { |   if (isFunction(plugin)) { | ||||||
|     func = promisify(plugin.bind(null, cloneDeep(config))); |     func = plugin.bind(null, cloneDeep(config)); | ||||||
|   } else if (isObject(plugin) && plugin[pluginType] && isFunction(plugin[pluginType])) { |   } else if (isObject(plugin) && plugin[pluginType] && isFunction(plugin[pluginType])) { | ||||||
|     func = promisify(plugin[pluginType].bind(null, cloneDeep(config))); |     func = plugin[pluginType].bind(null, cloneDeep(config)); | ||||||
|   } else { |   } else { | ||||||
|     throw new Error( |     throw new Error( | ||||||
|       `The ${pluginType} plugin must be a function, or an object with a function in the property ${pluginType}.` |       `The ${pluginType} plugin must be a function, or an object with a function in the property ${pluginType}.` | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								test/fixtures/multi-plugin.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								test/fixtures/multi-plugin.js
									
									
									
									
										vendored
									
									
								
							| @ -1,21 +1,8 @@ | |||||||
| module.exports = { | module.exports = { | ||||||
|   verifyConditions(config, options, cb) { |   verifyConditions: () => {}, | ||||||
|     cb(); |   getLastRelease: () => {}, | ||||||
|   }, |   analyzeCommits: () => {}, | ||||||
| 
 |   verifyRelease: () => {}, | ||||||
|   getLastRelease(config, options, cb) { |   generateNotes: () => {}, | ||||||
|     cb(); |   publish: () => {}, | ||||||
|   }, |  | ||||||
|   analyzeCommits(config, options, cb) { |  | ||||||
|     cb(); |  | ||||||
|   }, |  | ||||||
|   verifyRelease(config, options, cb) { |  | ||||||
|     cb(); |  | ||||||
|   }, |  | ||||||
|   generateNotes(config, options, cb) { |  | ||||||
|     cb(); |  | ||||||
|   }, |  | ||||||
|   publish(config, options, cb) { |  | ||||||
|     cb(); |  | ||||||
|   }, |  | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								test/fixtures/plugin-error-inherited.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								test/fixtures/plugin-error-inherited.js
									
									
									
									
										vendored
									
									
								
							| @ -9,6 +9,6 @@ class InheritedError extends SemanticReleaseError { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = function(config, options, cb) { | module.exports = () => { | ||||||
|   cb(new InheritedError('Inherited error', 'EINHERITED')); |   throw new InheritedError('Inherited error', 'EINHERITED'); | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								test/fixtures/plugin-error.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								test/fixtures/plugin-error.js
									
									
									
									
										vendored
									
									
								
							| @ -1,5 +1,5 @@ | |||||||
| module.exports = function(config, options, cb) { | module.exports = () => { | ||||||
|   const error = new Error('a'); |   const error = new Error('a'); | ||||||
|   error.errorProperty = 'errorProperty'; |   error.errorProperty = 'errorProperty'; | ||||||
|   cb(error); |   throw error; | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								test/fixtures/plugin-noop.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								test/fixtures/plugin-noop.js
									
									
									
									
										vendored
									
									
								
							| @ -1,3 +1 @@ | |||||||
| module.exports = (config, options, cb) => { | module.exports = () => {}; | ||||||
|   cb(null); |  | ||||||
| }; |  | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								test/fixtures/plugin-result-config.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								test/fixtures/plugin-result-config.js
									
									
									
									
										vendored
									
									
								
							| @ -1,3 +1 @@ | |||||||
| module.exports = function(pluginConfig, options, cb) { | module.exports = (pluginConfig, options) => ({pluginConfig, options}); | ||||||
|   cb(null, {pluginConfig, options}); |  | ||||||
| }; |  | ||||||
|  | |||||||
| @ -1,4 +1,3 @@ | |||||||
| import {callbackify} from 'util'; |  | ||||||
| import test from 'ava'; | import test from 'ava'; | ||||||
| import {writeJson} from 'fs-extra'; | import {writeJson} from 'fs-extra'; | ||||||
| import proxyquire from 'proxyquire'; | import proxyquire from 'proxyquire'; | ||||||
| @ -57,12 +56,12 @@ test.serial('Plugins are called with expected values', async t => { | |||||||
| 
 | 
 | ||||||
|   const options = { |   const options = { | ||||||
|     branch: 'master', |     branch: 'master', | ||||||
|     verifyConditions: [callbackify(verifyConditions1), callbackify(verifyConditions2)], |     verifyConditions: [verifyConditions1, verifyConditions2], | ||||||
|     getLastRelease: callbackify(getLastRelease), |     getLastRelease, | ||||||
|     analyzeCommits: callbackify(analyzeCommits), |     analyzeCommits, | ||||||
|     verifyRelease: callbackify(verifyRelease), |     verifyRelease, | ||||||
|     generateNotes: callbackify(generateNotes), |     generateNotes, | ||||||
|     publish: callbackify(publish), |     publish, | ||||||
|   }; |   }; | ||||||
|   const pkg = {name, version: '0.0.0-dev'}; |   const pkg = {name, version: '0.0.0-dev'}; | ||||||
|   normalizeData(pkg); |   normalizeData(pkg); | ||||||
| @ -140,12 +139,12 @@ test.serial('Use new gitHead, and recreate release notes if a publish plugin cre | |||||||
| 
 | 
 | ||||||
|   const options = { |   const options = { | ||||||
|     branch: 'master', |     branch: 'master', | ||||||
|     verifyConditions: callbackify(stub().resolves()), |     verifyConditions: stub().resolves(), | ||||||
|     getLastRelease: callbackify(stub().resolves(lastRelease)), |     getLastRelease: stub().resolves(lastRelease), | ||||||
|     analyzeCommits: callbackify(stub().resolves(nextRelease.type)), |     analyzeCommits: stub().resolves(nextRelease.type), | ||||||
|     verifyRelease: callbackify(stub().resolves()), |     verifyRelease: stub().resolves(), | ||||||
|     generateNotes: callbackify(generateNotes), |     generateNotes, | ||||||
|     publish: [callbackify(publish1), callbackify(publish2)], |     publish: [publish1, publish2], | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   await writeJson('./package.json', {}); |   await writeJson('./package.json', {}); | ||||||
| @ -188,12 +187,12 @@ test.serial('Dry-run skips verifyConditions and publish', async t => { | |||||||
|   const options = { |   const options = { | ||||||
|     dryRun: true, |     dryRun: true, | ||||||
|     branch: 'master', |     branch: 'master', | ||||||
|     verifyConditions: callbackify(verifyConditions), |     verifyConditions, | ||||||
|     getLastRelease: callbackify(getLastRelease), |     getLastRelease, | ||||||
|     analyzeCommits: callbackify(analyzeCommits), |     analyzeCommits, | ||||||
|     verifyRelease: callbackify(verifyRelease), |     verifyRelease, | ||||||
|     generateNotes: callbackify(generateNotes), |     generateNotes, | ||||||
|     publish: callbackify(publish), |     publish, | ||||||
|   }; |   }; | ||||||
|   const pkg = {name, version: '0.0.0-dev'}; |   const pkg = {name, version: '0.0.0-dev'}; | ||||||
|   normalizeData(pkg); |   normalizeData(pkg); | ||||||
|  | |||||||
| @ -1,4 +1,3 @@ | |||||||
| import {callbackify} from 'util'; |  | ||||||
| import test from 'ava'; | import test from 'ava'; | ||||||
| import {noop} from 'lodash'; | import {noop} from 'lodash'; | ||||||
| import {stub, match} from 'sinon'; | import {stub, match} from 'sinon'; | ||||||
| @ -39,7 +38,7 @@ test('Normalize and load plugin that retuns multiple functions', t => { | |||||||
| 
 | 
 | ||||||
| test('Wrap plugin in a function that validate the output of the plugin', async t => { | test('Wrap plugin in a function that validate the output of the plugin', async t => { | ||||||
|   const pluginFunction = stub().resolves(1); |   const pluginFunction = stub().resolves(1); | ||||||
|   const plugin = normalize('', callbackify(pluginFunction), t.context.logger, { |   const plugin = normalize('', pluginFunction, t.context.logger, { | ||||||
|     validator: output => output === 1, |     validator: output => output === 1, | ||||||
|     message: 'The output must be 1', |     message: 'The output must be 1', | ||||||
|   }); |   }); | ||||||
| @ -53,7 +52,7 @@ test('Wrap plugin in a function that validate the output of the plugin', async t | |||||||
| 
 | 
 | ||||||
| test('Plugin is called with "pluginConfig" (omitting "path") and input', async t => { | test('Plugin is called with "pluginConfig" (omitting "path") and input', async t => { | ||||||
|   const pluginFunction = stub().resolves(); |   const pluginFunction = stub().resolves(); | ||||||
|   const conf = {path: callbackify(pluginFunction), conf: 'confValue'}; |   const conf = {path: pluginFunction, conf: 'confValue'}; | ||||||
|   const plugin = normalize('', conf, t.context.logger); |   const plugin = normalize('', conf, t.context.logger); | ||||||
|   await plugin('param'); |   await plugin('param'); | ||||||
| 
 | 
 | ||||||
| @ -61,9 +60,8 @@ test('Plugin is called with "pluginConfig" (omitting "path") and input', async t | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Prevent plugins to modify "pluginConfig"', async t => { | test('Prevent plugins to modify "pluginConfig"', async t => { | ||||||
|   const pluginFunction = stub().callsFake((pluginConfig, options, cb) => { |   const pluginFunction = stub().callsFake(pluginConfig => { | ||||||
|     pluginConfig.conf.subConf = 'otherConf'; |     pluginConfig.conf.subConf = 'otherConf'; | ||||||
|     cb(); |  | ||||||
|   }); |   }); | ||||||
|   const conf = {path: pluginFunction, conf: {subConf: 'originalConf'}}; |   const conf = {path: pluginFunction, conf: {subConf: 'originalConf'}}; | ||||||
|   const plugin = normalize('', conf, t.context.logger); |   const plugin = normalize('', conf, t.context.logger); | ||||||
| @ -73,9 +71,8 @@ test('Prevent plugins to modify "pluginConfig"', async t => { | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Prevent plugins to modify its input', async t => { | test('Prevent plugins to modify its input', async t => { | ||||||
|   const pluginFunction = stub().callsFake((pluginConfig, options, cb) => { |   const pluginFunction = stub().callsFake((pluginConfig, options) => { | ||||||
|     options.param.subParam = 'otherParam'; |     options.param.subParam = 'otherParam'; | ||||||
|     cb(); |  | ||||||
|   }); |   }); | ||||||
|   const input = {param: {subParam: 'originalSubParam'}}; |   const input = {param: {subParam: 'originalSubParam'}}; | ||||||
|   const plugin = normalize('', pluginFunction, t.context.logger); |   const plugin = normalize('', pluginFunction, t.context.logger); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user