1 | const {castArray, pickBy, isNil, isString, isPlainObject} = require('lodash');
|
2 | const readPkgUp = require('read-pkg-up');
|
3 | const {cosmiconfig} = require('cosmiconfig');
|
4 | const resolveFrom = require('resolve-from');
|
5 | const debug = require('debug')('semantic-release:config');
|
6 | const {repoUrl} = require('./git');
|
7 | const PLUGINS_DEFINITIONS = require('./definitions/plugins');
|
8 | const plugins = require('./plugins');
|
9 | const {validatePlugin, parseConfig} = require('./plugins/utils');
|
10 |
|
11 | const CONFIG_NAME = 'release';
|
12 | const CONFIG_FILES = [
|
13 | 'package.json',
|
14 | `.${CONFIG_NAME}rc`,
|
15 | `.${CONFIG_NAME}rc.json`,
|
16 | `.${CONFIG_NAME}rc.yaml`,
|
17 | `.${CONFIG_NAME}rc.yml`,
|
18 | `.${CONFIG_NAME}rc.js`,
|
19 | `${CONFIG_NAME}.config.js`,
|
20 | ];
|
21 |
|
22 | module.exports = async (context, cliOptions) => {
|
23 | const {cwd, env} = context;
|
24 | const {config, filepath} = (await cosmiconfig(CONFIG_NAME, {searchPlaces: CONFIG_FILES}).search(cwd)) || {};
|
25 |
|
26 | debug('load config from: %s', filepath);
|
27 |
|
28 |
|
29 | let options = {...config, ...cliOptions};
|
30 |
|
31 | const pluginsPath = {};
|
32 | let extendPaths;
|
33 | ({extends: extendPaths, ...options} = options);
|
34 | if (extendPaths) {
|
35 |
|
36 | options = {
|
37 | ...castArray(extendPaths).reduce((result, extendPath) => {
|
38 | const extendsOptions = require(resolveFrom.silent(__dirname, extendPath) || resolveFrom(cwd, extendPath));
|
39 |
|
40 |
|
41 |
|
42 | Object.entries(extendsOptions)
|
43 | .filter(([, value]) => Boolean(value))
|
44 | .reduce((pluginsPath, [option, value]) => {
|
45 | castArray(value).forEach((plugin) => {
|
46 | if (option === 'plugins' && validatePlugin(plugin)) {
|
47 | pluginsPath[parseConfig(plugin)[0]] = extendPath;
|
48 | } else if (
|
49 | PLUGINS_DEFINITIONS[option] &&
|
50 | (isString(plugin) || (isPlainObject(plugin) && isString(plugin.path)))
|
51 | ) {
|
52 | pluginsPath[isString(plugin) ? plugin : plugin.path] = extendPath;
|
53 | }
|
54 | });
|
55 | return pluginsPath;
|
56 | }, pluginsPath);
|
57 |
|
58 | return {...result, ...extendsOptions};
|
59 | }, {}),
|
60 | ...options,
|
61 | };
|
62 | }
|
63 |
|
64 |
|
65 | options = {
|
66 | branches: [
|
67 | '+([0-9])?(.{+([0-9]),x}).x',
|
68 | 'master',
|
69 | 'next',
|
70 | 'next-major',
|
71 | {name: 'beta', prerelease: true},
|
72 | {name: 'alpha', prerelease: true},
|
73 | ],
|
74 | repositoryUrl: (await pkgRepoUrl({normalize: false, cwd})) || (await repoUrl({cwd, env})),
|
75 | tagFormat: `v\${version}`,
|
76 | plugins: [
|
77 | '@semantic-release/commit-analyzer',
|
78 | '@semantic-release/release-notes-generator',
|
79 | '@semantic-release/npm',
|
80 | '@semantic-release/github',
|
81 | ],
|
82 |
|
83 | ...pickBy(options, (option) => !isNil(option)),
|
84 | ...(options.branches ? {branches: castArray(options.branches)} : {}),
|
85 | };
|
86 |
|
87 | if (options.ci === false) {
|
88 | options.noCi = true;
|
89 | }
|
90 |
|
91 | debug('options values: %O', options);
|
92 |
|
93 | return {options, plugins: await plugins({...context, options}, pluginsPath)};
|
94 | };
|
95 |
|
96 | async function pkgRepoUrl(options) {
|
97 | const {packageJson} = (await readPkgUp(options)) || {};
|
98 | return packageJson && (isPlainObject(packageJson.repository) ? packageJson.repository.url : packageJson.repository);
|
99 | }
|