1 | const {isPlainObject, isFunction, noop, cloneDeep, omit} = require('lodash');
|
2 | const debug = require('debug')('semantic-release:plugins');
|
3 | const getError = require('../get-error');
|
4 | const {extractErrors} = require('../utils');
|
5 | const PLUGINS_DEFINITIONS = require('../definitions/plugins');
|
6 | const {loadPlugin, parseConfig} = require('./utils');
|
7 |
|
8 | module.exports = (context, type, pluginOpt, pluginsPath) => {
|
9 | const {stdout, stderr, options, logger} = context;
|
10 | if (!pluginOpt) {
|
11 | return noop;
|
12 | }
|
13 |
|
14 | const [name, config] = parseConfig(pluginOpt);
|
15 | const pluginName = name.pluginName ? name.pluginName : isFunction(name) ? `[Function: ${name.name}]` : name;
|
16 | const plugin = loadPlugin(context, name, pluginsPath);
|
17 |
|
18 | debug(`options for ${pluginName}/${type}: %O`, config);
|
19 |
|
20 | let func;
|
21 | if (isFunction(plugin)) {
|
22 | func = plugin.bind(null, cloneDeep({...options, ...config}));
|
23 | } else if (isPlainObject(plugin) && plugin[type] && isFunction(plugin[type])) {
|
24 | func = plugin[type].bind(null, cloneDeep({...options, ...config}));
|
25 | } else {
|
26 | throw getError('EPLUGIN', {type, pluginName});
|
27 | }
|
28 |
|
29 | const validator = async (input) => {
|
30 | const {dryRun, outputValidator} = PLUGINS_DEFINITIONS[type] || {};
|
31 | try {
|
32 | if (!input.options.dryRun || dryRun) {
|
33 | logger.log(`Start step "${type}" of plugin "${pluginName}"`);
|
34 | const result = await func({
|
35 | ...cloneDeep(omit(input, ['stdout', 'stderr', 'logger'])),
|
36 | stdout,
|
37 | stderr,
|
38 | logger: logger.scope(logger.scopeName, pluginName),
|
39 | });
|
40 | if (outputValidator && !outputValidator(result)) {
|
41 | throw getError(`E${type.toUpperCase()}OUTPUT`, {result, pluginName});
|
42 | }
|
43 |
|
44 | logger.success(`Completed step "${type}" of plugin "${pluginName}"`);
|
45 | return result;
|
46 | }
|
47 |
|
48 | logger.warn(`Skip step "${type}" of plugin "${pluginName}" in dry-run mode`);
|
49 | } catch (error) {
|
50 | logger.error(`Failed step "${type}" of plugin "${pluginName}"`);
|
51 | extractErrors(error).forEach((err) => Object.assign(err, {pluginName}));
|
52 | throw error;
|
53 | }
|
54 | };
|
55 |
|
56 | Reflect.defineProperty(validator, 'pluginName', {value: pluginName, writable: false, enumerable: true});
|
57 |
|
58 | if (!isFunction(pluginOpt)) {
|
59 | if (pluginsPath[name]) {
|
60 | logger.success(`Loaded plugin "${type}" from "${pluginName}" in shareable config "${pluginsPath[name]}"`);
|
61 | } else {
|
62 | logger.success(`Loaded plugin "${type}" from "${pluginName}"`);
|
63 | }
|
64 | }
|
65 |
|
66 | return validator;
|
67 | };
|