semantic-release 19.0.5 → 20.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/semantic-release.js +15 -14
- package/cli.js +11 -11
- package/docs/extending/plugins-list.md +4 -0
- package/docs/support/troubleshooting.md +2 -2
- package/docs/usage/ci-configuration.md +1 -1
- package/docs/usage/configuration.md +3 -3
- package/index.js +28 -25
- package/lib/branches/expand.js +5 -5
- package/lib/branches/get-tags.js +10 -7
- package/lib/branches/index.js +11 -11
- package/lib/branches/normalize.js +13 -16
- package/lib/definitions/branches.js +6 -8
- package/lib/definitions/constants.js +9 -21
- package/lib/definitions/errors.js +120 -54
- package/lib/definitions/plugins.js +6 -6
- package/lib/get-commits.js +6 -4
- package/lib/get-config.js +25 -16
- package/lib/get-error.js +4 -4
- package/lib/get-git-auth-url.js +9 -7
- package/lib/get-last-release.js +6 -6
- package/lib/get-logger.js +6 -4
- package/lib/get-next-version.js +5 -5
- package/lib/get-release-to-add.js +7 -7
- package/lib/git.js +26 -46
- package/lib/hide-sensitive.js +4 -4
- package/lib/plugins/index.js +36 -26
- package/lib/plugins/normalize.js +11 -9
- package/lib/plugins/pipeline.js +7 -7
- package/lib/plugins/utils.js +14 -10
- package/lib/utils.js +19 -37
- package/lib/verify.js +6 -6
- package/package.json +40 -31
package/lib/git.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import gitLogParser from 'git-log-parser';
|
|
2
|
+
import getStream from 'get-stream';
|
|
3
|
+
import {execa} from 'execa';
|
|
4
|
+
import debugGit from 'debug';
|
|
5
|
+
import {GIT_NOTE_REF} from './definitions/constants.js';
|
|
6
|
+
|
|
7
|
+
const debug = debugGit('semantic-release:git');
|
|
6
8
|
|
|
7
9
|
Object.assign(gitLogParser.fields, {hash: 'H', message: 'B', gitTags: 'd', committerDate: {key: 'ci', type: Date}});
|
|
8
10
|
|
|
@@ -14,7 +16,7 @@ Object.assign(gitLogParser.fields, {hash: 'H', message: 'B', gitTags: 'd', commi
|
|
|
14
16
|
*
|
|
15
17
|
* @return {String} The commit sha of the tag in parameter or `null`.
|
|
16
18
|
*/
|
|
17
|
-
async function getTagHead(tagName, execaOptions) {
|
|
19
|
+
export async function getTagHead(tagName, execaOptions) {
|
|
18
20
|
return (await execa('git', ['rev-list', '-1', tagName], execaOptions)).stdout;
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -27,7 +29,7 @@ async function getTagHead(tagName, execaOptions) {
|
|
|
27
29
|
* @return {Array<String>} List of git tags.
|
|
28
30
|
* @throws {Error} If the `git` command fails.
|
|
29
31
|
*/
|
|
30
|
-
async function getTags(branch, execaOptions) {
|
|
32
|
+
export async function getTags(branch, execaOptions) {
|
|
31
33
|
return (await execa('git', ['tag', '--merged', branch], execaOptions)).stdout
|
|
32
34
|
.split('\n')
|
|
33
35
|
.map((tag) => tag.trim())
|
|
@@ -42,7 +44,7 @@ async function getTags(branch, execaOptions) {
|
|
|
42
44
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
|
43
45
|
* @return {Promise<Array<Object>>} The list of commits between `from` and `to`.
|
|
44
46
|
*/
|
|
45
|
-
async function getCommits(from, to, execaOptions) {
|
|
47
|
+
export async function getCommits(from, to, execaOptions) {
|
|
46
48
|
return (
|
|
47
49
|
await getStream.array(
|
|
48
50
|
gitLogParser.parse(
|
|
@@ -62,7 +64,7 @@ async function getCommits(from, to, execaOptions) {
|
|
|
62
64
|
* @return {Array<String>} List of git branches.
|
|
63
65
|
* @throws {Error} If the `git` command fails.
|
|
64
66
|
*/
|
|
65
|
-
async function getBranches(repositoryUrl, execaOptions) {
|
|
67
|
+
export async function getBranches(repositoryUrl, execaOptions) {
|
|
66
68
|
return (await execa('git', ['ls-remote', '--heads', repositoryUrl], execaOptions)).stdout
|
|
67
69
|
.split('\n')
|
|
68
70
|
.filter(Boolean)
|
|
@@ -77,7 +79,7 @@ async function getBranches(repositoryUrl, execaOptions) {
|
|
|
77
79
|
*
|
|
78
80
|
* @return {Boolean} `true` if the reference exists, falsy otherwise.
|
|
79
81
|
*/
|
|
80
|
-
async function isRefExists(ref, execaOptions) {
|
|
82
|
+
export async function isRefExists(ref, execaOptions) {
|
|
81
83
|
try {
|
|
82
84
|
return (await execa('git', ['rev-parse', '--verify', ref], execaOptions)).exitCode === 0;
|
|
83
85
|
} catch (error) {
|
|
@@ -99,7 +101,7 @@ async function isRefExists(ref, execaOptions) {
|
|
|
99
101
|
* @param {String} branch The repository branch to fetch.
|
|
100
102
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
|
101
103
|
*/
|
|
102
|
-
async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
|
|
104
|
+
export async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
|
|
103
105
|
const isDetachedHead =
|
|
104
106
|
(await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {...execaOptions, reject: false})).stdout === 'HEAD';
|
|
105
107
|
|
|
@@ -137,7 +139,7 @@ async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
|
|
|
137
139
|
* @param {String} repositoryUrl The remote repository URL.
|
|
138
140
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
|
139
141
|
*/
|
|
140
|
-
async function fetchNotes(repositoryUrl, execaOptions) {
|
|
142
|
+
export async function fetchNotes(repositoryUrl, execaOptions) {
|
|
141
143
|
try {
|
|
142
144
|
await execa(
|
|
143
145
|
'git',
|
|
@@ -159,7 +161,7 @@ async function fetchNotes(repositoryUrl, execaOptions) {
|
|
|
159
161
|
*
|
|
160
162
|
* @return {String} the sha of the HEAD commit.
|
|
161
163
|
*/
|
|
162
|
-
async function getGitHead(execaOptions) {
|
|
164
|
+
export async function getGitHead(execaOptions) {
|
|
163
165
|
return (await execa('git', ['rev-parse', 'HEAD'], execaOptions)).stdout;
|
|
164
166
|
}
|
|
165
167
|
|
|
@@ -170,7 +172,7 @@ async function getGitHead(execaOptions) {
|
|
|
170
172
|
*
|
|
171
173
|
* @return {string} The value of the remote git URL.
|
|
172
174
|
*/
|
|
173
|
-
async function repoUrl(execaOptions) {
|
|
175
|
+
export async function repoUrl(execaOptions) {
|
|
174
176
|
try {
|
|
175
177
|
return (await execa('git', ['config', '--get', 'remote.origin.url'], execaOptions)).stdout;
|
|
176
178
|
} catch (error) {
|
|
@@ -185,7 +187,7 @@ async function repoUrl(execaOptions) {
|
|
|
185
187
|
*
|
|
186
188
|
* @return {Boolean} `true` if the current working directory is in a git repository, falsy otherwise.
|
|
187
189
|
*/
|
|
188
|
-
async function isGitRepo(execaOptions) {
|
|
190
|
+
export async function isGitRepo(execaOptions) {
|
|
189
191
|
try {
|
|
190
192
|
return (await execa('git', ['rev-parse', '--git-dir'], execaOptions)).exitCode === 0;
|
|
191
193
|
} catch (error) {
|
|
@@ -202,7 +204,7 @@ async function isGitRepo(execaOptions) {
|
|
|
202
204
|
*
|
|
203
205
|
* @throws {Error} if not authorized to push.
|
|
204
206
|
*/
|
|
205
|
-
async function verifyAuth(repositoryUrl, branch, execaOptions) {
|
|
207
|
+
export async function verifyAuth(repositoryUrl, branch, execaOptions) {
|
|
206
208
|
try {
|
|
207
209
|
await execa('git', ['push', '--dry-run', '--no-verify', repositoryUrl, `HEAD:${branch}`], execaOptions);
|
|
208
210
|
} catch (error) {
|
|
@@ -220,7 +222,7 @@ async function verifyAuth(repositoryUrl, branch, execaOptions) {
|
|
|
220
222
|
*
|
|
221
223
|
* @throws {Error} if the tag creation failed.
|
|
222
224
|
*/
|
|
223
|
-
async function tag(tagName, ref, execaOptions) {
|
|
225
|
+
export async function tag(tagName, ref, execaOptions) {
|
|
224
226
|
await execa('git', ['tag', tagName, ref], execaOptions);
|
|
225
227
|
}
|
|
226
228
|
|
|
@@ -232,7 +234,7 @@ async function tag(tagName, ref, execaOptions) {
|
|
|
232
234
|
*
|
|
233
235
|
* @throws {Error} if the push failed.
|
|
234
236
|
*/
|
|
235
|
-
async function push(repositoryUrl, execaOptions) {
|
|
237
|
+
export async function push(repositoryUrl, execaOptions) {
|
|
236
238
|
await execa('git', ['push', '--tags', repositoryUrl], execaOptions);
|
|
237
239
|
}
|
|
238
240
|
|
|
@@ -244,7 +246,7 @@ async function push(repositoryUrl, execaOptions) {
|
|
|
244
246
|
*
|
|
245
247
|
* @throws {Error} if the push failed.
|
|
246
248
|
*/
|
|
247
|
-
async function pushNotes(repositoryUrl, execaOptions) {
|
|
249
|
+
export async function pushNotes(repositoryUrl, execaOptions) {
|
|
248
250
|
await execa('git', ['push', repositoryUrl, `refs/notes/${GIT_NOTE_REF}`], execaOptions);
|
|
249
251
|
}
|
|
250
252
|
|
|
@@ -256,7 +258,7 @@ async function pushNotes(repositoryUrl, execaOptions) {
|
|
|
256
258
|
*
|
|
257
259
|
* @return {Boolean} `true` if valid, falsy otherwise.
|
|
258
260
|
*/
|
|
259
|
-
async function verifyTagName(tagName, execaOptions) {
|
|
261
|
+
export async function verifyTagName(tagName, execaOptions) {
|
|
260
262
|
try {
|
|
261
263
|
return (await execa('git', ['check-ref-format', `refs/tags/${tagName}`], execaOptions)).exitCode === 0;
|
|
262
264
|
} catch (error) {
|
|
@@ -272,7 +274,7 @@ async function verifyTagName(tagName, execaOptions) {
|
|
|
272
274
|
*
|
|
273
275
|
* @return {Boolean} `true` if valid, falsy otherwise.
|
|
274
276
|
*/
|
|
275
|
-
async function verifyBranchName(branch, execaOptions) {
|
|
277
|
+
export async function verifyBranchName(branch, execaOptions) {
|
|
276
278
|
try {
|
|
277
279
|
return (await execa('git', ['check-ref-format', `refs/heads/${branch}`], execaOptions)).exitCode === 0;
|
|
278
280
|
} catch (error) {
|
|
@@ -289,7 +291,7 @@ async function verifyBranchName(branch, execaOptions) {
|
|
|
289
291
|
*
|
|
290
292
|
* @return {Boolean} `true` is the HEAD of the current local branch is the same as the HEAD of the remote branch, falsy otherwise.
|
|
291
293
|
*/
|
|
292
|
-
async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
|
|
294
|
+
export async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
|
|
293
295
|
return (
|
|
294
296
|
(await getGitHead(execaOptions)) ===
|
|
295
297
|
(await execa('git', ['ls-remote', '--heads', repositoryUrl, branch], execaOptions)).stdout.match(/^(?<ref>\w+)?/)[1]
|
|
@@ -304,7 +306,7 @@ async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
|
|
|
304
306
|
*
|
|
305
307
|
* @return {Object} the parsed JSON note if there is one, an empty object otherwise.
|
|
306
308
|
*/
|
|
307
|
-
async function getNote(ref, execaOptions) {
|
|
309
|
+
export async function getNote(ref, execaOptions) {
|
|
308
310
|
try {
|
|
309
311
|
return JSON.parse((await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOptions)).stdout);
|
|
310
312
|
} catch (error) {
|
|
@@ -324,28 +326,6 @@ async function getNote(ref, execaOptions) {
|
|
|
324
326
|
* @param {String} ref The Git reference to add the note to.
|
|
325
327
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
|
326
328
|
*/
|
|
327
|
-
async function addNote(note, ref, execaOptions) {
|
|
329
|
+
export async function addNote(note, ref, execaOptions) {
|
|
328
330
|
await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-f', '-m', JSON.stringify(note), ref], execaOptions);
|
|
329
331
|
}
|
|
330
|
-
|
|
331
|
-
module.exports = {
|
|
332
|
-
getTagHead,
|
|
333
|
-
getTags,
|
|
334
|
-
getCommits,
|
|
335
|
-
getBranches,
|
|
336
|
-
isRefExists,
|
|
337
|
-
fetch,
|
|
338
|
-
fetchNotes,
|
|
339
|
-
getGitHead,
|
|
340
|
-
repoUrl,
|
|
341
|
-
isGitRepo,
|
|
342
|
-
verifyAuth,
|
|
343
|
-
tag,
|
|
344
|
-
push,
|
|
345
|
-
pushNotes,
|
|
346
|
-
verifyTagName,
|
|
347
|
-
isBranchUpToDate,
|
|
348
|
-
verifyBranchName,
|
|
349
|
-
getNote,
|
|
350
|
-
addNote,
|
|
351
|
-
};
|
package/lib/hide-sensitive.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import {escapeRegExp, isString, size} from 'lodash-es';
|
|
2
|
+
import {SECRET_MIN_SIZE, SECRET_REPLACEMENT} from './definitions/constants.js';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
export default (env) => {
|
|
5
5
|
const toReplace = Object.keys(env).filter((envVar) => {
|
|
6
6
|
// https://github.com/semantic-release/semantic-release/issues/1558
|
|
7
7
|
if (envVar === 'GOPRIVATE') {
|
|
@@ -17,4 +17,4 @@ module.exports = (env) => {
|
|
|
17
17
|
);
|
|
18
18
|
return (output) =>
|
|
19
19
|
output && isString(output) && toReplace.length > 0 ? output.toString().replace(regexp, SECRET_REPLACEMENT) : output;
|
|
20
|
-
}
|
|
20
|
+
}
|
package/lib/plugins/index.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import {castArray, identity, isNil, isPlainObject, isString, omit} from 'lodash-es';
|
|
2
|
+
import AggregateError from 'aggregate-error';
|
|
3
|
+
import getError from '../get-error.js';
|
|
4
|
+
import PLUGINS_DEFINITIONS from '../definitions/plugins.js';
|
|
5
|
+
import {loadPlugin, parseConfig, validatePlugin, validateStep} from './utils.js';
|
|
6
|
+
import pipeline from './pipeline.js';
|
|
7
|
+
import normalize from './normalize.js';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
export default async (context, pluginsPath) => {
|
|
10
10
|
let {options, logger} = context;
|
|
11
11
|
const errors = [];
|
|
12
12
|
|
|
13
13
|
const plugins = options.plugins
|
|
14
|
-
? castArray(options.plugins).reduce((
|
|
14
|
+
? await castArray(options.plugins).reduce(async (eventualPluginsList, plugin) => {
|
|
15
|
+
const pluginsList = await eventualPluginsList;
|
|
15
16
|
if (validatePlugin(plugin)) {
|
|
16
17
|
const [name, config] = parseConfig(plugin);
|
|
17
|
-
plugin = isString(name) ? loadPlugin(context, name, pluginsPath) : name;
|
|
18
|
+
plugin = isString(name) ? await loadPlugin(context, name, pluginsPath) : name;
|
|
18
19
|
|
|
19
20
|
if (isPlainObject(plugin)) {
|
|
20
21
|
Object.entries(plugin).forEach(([type, func]) => {
|
|
@@ -24,7 +25,7 @@ module.exports = (context, pluginsPath) => {
|
|
|
24
25
|
writable: false,
|
|
25
26
|
enumerable: true,
|
|
26
27
|
});
|
|
27
|
-
|
|
28
|
+
pluginsList[type] = [...(pluginsList[type] || []), [func, config]];
|
|
28
29
|
}
|
|
29
30
|
});
|
|
30
31
|
} else {
|
|
@@ -34,7 +35,7 @@ module.exports = (context, pluginsPath) => {
|
|
|
34
35
|
errors.push(getError('EPLUGINSCONF', {plugin}));
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
return
|
|
38
|
+
return pluginsList;
|
|
38
39
|
}, {})
|
|
39
40
|
: [];
|
|
40
41
|
|
|
@@ -44,9 +45,13 @@ module.exports = (context, pluginsPath) => {
|
|
|
44
45
|
|
|
45
46
|
options = {...plugins, ...options};
|
|
46
47
|
|
|
47
|
-
const
|
|
48
|
-
(
|
|
48
|
+
const pluginsConfig = await Object.entries(PLUGINS_DEFINITIONS).reduce(
|
|
49
|
+
async (
|
|
50
|
+
eventualPluginsConfigAccumulator,
|
|
51
|
+
[type, {required, default: def, pipelineConfig, postprocess = identity, preprocess = identity}]
|
|
52
|
+
) => {
|
|
49
53
|
let pluginOptions;
|
|
54
|
+
const pluginsConfigAccumulator = await eventualPluginsConfigAccumulator;
|
|
50
55
|
|
|
51
56
|
if (isNil(options[type]) && def) {
|
|
52
57
|
pluginOptions = def;
|
|
@@ -60,28 +65,33 @@ module.exports = (context, pluginsPath) => {
|
|
|
60
65
|
|
|
61
66
|
if (!validateStep({required}, options[type])) {
|
|
62
67
|
errors.push(getError('EPLUGINCONF', {type, required, pluginConf: options[type]}));
|
|
63
|
-
return
|
|
68
|
+
return pluginsConfigAccumulator;
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
pluginOptions = options[type];
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
const steps =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
const steps = await Promise.all(
|
|
75
|
+
castArray(pluginOptions).map(async (pluginOpt) =>
|
|
76
|
+
normalize(
|
|
77
|
+
{...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS), 'plugins')},
|
|
78
|
+
type,
|
|
79
|
+
pluginOpt,
|
|
80
|
+
pluginsPath
|
|
81
|
+
)
|
|
75
82
|
)
|
|
76
83
|
);
|
|
77
84
|
|
|
78
|
-
|
|
85
|
+
pluginsConfigAccumulator[type] = async (input) =>
|
|
79
86
|
postprocess(
|
|
80
|
-
await pipeline(
|
|
87
|
+
await pipeline(
|
|
88
|
+
steps,
|
|
89
|
+
pipelineConfig && pipelineConfig(pluginsConfigAccumulator, logger)
|
|
90
|
+
)(await preprocess(input)),
|
|
81
91
|
input
|
|
82
92
|
);
|
|
83
93
|
|
|
84
|
-
return
|
|
94
|
+
return pluginsConfigAccumulator;
|
|
85
95
|
},
|
|
86
96
|
plugins
|
|
87
97
|
);
|
|
@@ -89,5 +99,5 @@ module.exports = (context, pluginsPath) => {
|
|
|
89
99
|
throw new AggregateError(errors);
|
|
90
100
|
}
|
|
91
101
|
|
|
92
|
-
return
|
|
93
|
-
}
|
|
102
|
+
return pluginsConfig;
|
|
103
|
+
}
|
package/lib/plugins/normalize.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import {cloneDeep, isFunction, isPlainObject, noop, omit} from 'lodash-es';
|
|
2
|
+
import debugPlugins from 'debug';
|
|
3
|
+
import getError from '../get-error.js';
|
|
4
|
+
import {extractErrors} from '../utils.js';
|
|
5
|
+
import PLUGINS_DEFINITIONS from '../definitions/plugins.js';
|
|
6
|
+
import {loadPlugin, parseConfig} from './utils.js';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const debug = debugPlugins('semantic-release:plugins');
|
|
9
|
+
|
|
10
|
+
export default async (context, type, pluginOpt, pluginsPath) => {
|
|
9
11
|
const {stdout, stderr, options, logger} = context;
|
|
10
12
|
if (!pluginOpt) {
|
|
11
13
|
return noop;
|
|
@@ -13,7 +15,7 @@ module.exports = (context, type, pluginOpt, pluginsPath) => {
|
|
|
13
15
|
|
|
14
16
|
const [name, config] = parseConfig(pluginOpt);
|
|
15
17
|
const pluginName = name.pluginName ? name.pluginName : isFunction(name) ? `[Function: ${name.name}]` : name;
|
|
16
|
-
const plugin = loadPlugin(context, name, pluginsPath);
|
|
18
|
+
const plugin = await loadPlugin(context, name, pluginsPath);
|
|
17
19
|
|
|
18
20
|
debug(`options for ${pluginName}/${type}: %O`, config);
|
|
19
21
|
|
|
@@ -64,4 +66,4 @@ module.exports = (context, type, pluginOpt, pluginsPath) => {
|
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
return validator;
|
|
67
|
-
}
|
|
69
|
+
}
|
package/lib/plugins/pipeline.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {identity} from 'lodash-es';
|
|
2
|
+
import pReduce from 'p-reduce';
|
|
3
|
+
import AggregateError from 'aggregate-error';
|
|
4
|
+
import {extractErrors} from '../utils.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* A Function that execute a list of function sequencially. If at least one Function ins the pipeline throws an Error or rejects, the pipeline function rejects as well.
|
|
@@ -23,9 +23,9 @@ const {extractErrors} = require('../utils');
|
|
|
23
23
|
* @param {Function} [options.getNextInput=identity] Function called after each step is executed, with the last step input and the current current step result; the returned value will be used as the input of the next step.
|
|
24
24
|
* @param {Function} [options.transform=identity] Function called after each step is executed, with the current step result, the step function and the last step input; the returned value will be saved in the pipeline results.
|
|
25
25
|
*
|
|
26
|
-
* @return {Pipeline} A Function that execute the `steps`
|
|
26
|
+
* @return {Pipeline} A Function that execute the `steps` sequentially
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
export default (steps, {settleAll = false, getNextInput = identity, transform = identity} = {}) => async (input) => {
|
|
29
29
|
const results = [];
|
|
30
30
|
const errors = [];
|
|
31
31
|
await pReduce(
|
|
@@ -55,4 +55,4 @@ module.exports = (steps, {settleAll = false, getNextInput = identity, transform
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
return results;
|
|
58
|
-
}
|
|
58
|
+
}
|
package/lib/plugins/utils.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {dirname} from 'node:path';
|
|
2
|
+
import {fileURLToPath} from 'node:url';
|
|
3
|
+
import {castArray, isArray, isFunction, isNil, isPlainObject, isString} from 'lodash-es';
|
|
4
|
+
import resolveFrom from 'resolve-from';
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
4
7
|
|
|
5
8
|
const validateSteps = (conf) => {
|
|
6
9
|
return conf.every((conf) => {
|
|
@@ -24,7 +27,7 @@ const validateSteps = (conf) => {
|
|
|
24
27
|
});
|
|
25
28
|
};
|
|
26
29
|
|
|
27
|
-
function validatePlugin(conf) {
|
|
30
|
+
export function validatePlugin(conf) {
|
|
28
31
|
return (
|
|
29
32
|
isString(conf) ||
|
|
30
33
|
(isArray(conf) &&
|
|
@@ -35,7 +38,7 @@ function validatePlugin(conf) {
|
|
|
35
38
|
);
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
function validateStep({required}, conf) {
|
|
41
|
+
export function validateStep({required}, conf) {
|
|
39
42
|
conf = castArray(conf).filter(Boolean);
|
|
40
43
|
if (required) {
|
|
41
44
|
return conf.length >= 1 && validateSteps(conf);
|
|
@@ -44,14 +47,17 @@ function validateStep({required}, conf) {
|
|
|
44
47
|
return conf.length === 0 || validateSteps(conf);
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
function loadPlugin({cwd}, name, pluginsPath) {
|
|
50
|
+
export async function loadPlugin({cwd}, name, pluginsPath) {
|
|
48
51
|
const basePath = pluginsPath[name]
|
|
49
52
|
? dirname(resolveFrom.silent(__dirname, pluginsPath[name]) || resolveFrom(cwd, pluginsPath[name]))
|
|
50
53
|
: __dirname;
|
|
51
|
-
|
|
54
|
+
|
|
55
|
+
// See https://github.com/mysticatea/eslint-plugin-node/issues/250
|
|
56
|
+
// eslint-disable-next-line node/no-unsupported-features/es-syntax
|
|
57
|
+
return isFunction(name) ? name : (await import(resolveFrom.silent(basePath, name) || resolveFrom(cwd, name))).default;
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
function parseConfig(plugin) {
|
|
60
|
+
export function parseConfig(plugin) {
|
|
55
61
|
let path;
|
|
56
62
|
let config;
|
|
57
63
|
if (isArray(plugin)) {
|
|
@@ -64,5 +70,3 @@ function parseConfig(plugin) {
|
|
|
64
70
|
|
|
65
71
|
return [path, config || {}];
|
|
66
72
|
}
|
|
67
|
-
|
|
68
|
-
module.exports = {validatePlugin, validateStep, loadPlugin, parseConfig};
|
package/lib/utils.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {isFunction, template, union} from 'lodash-es';
|
|
2
|
+
import semver from 'semver';
|
|
3
|
+
import hideSensitive from './hide-sensitive.js';
|
|
4
4
|
|
|
5
|
-
function extractErrors(err) {
|
|
6
|
-
return err &&
|
|
5
|
+
export function extractErrors(err) {
|
|
6
|
+
return err && err.errors ? [...err.errors] : [err];
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
function hideSensitiveValues(env, objs) {
|
|
9
|
+
export function hideSensitiveValues(env, objs) {
|
|
10
10
|
const hideFunction = hideSensitive(env);
|
|
11
11
|
return objs.map((object) => {
|
|
12
12
|
Object.getOwnPropertyNames(object).forEach((prop) => {
|
|
@@ -18,19 +18,19 @@ function hideSensitiveValues(env, objs) {
|
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
function tagsToVersions(tags) {
|
|
21
|
+
export function tagsToVersions(tags) {
|
|
22
22
|
return tags.map(({version}) => version);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function isMajorRange(range) {
|
|
25
|
+
export function isMajorRange(range) {
|
|
26
26
|
return /^\d+\.x(?:\.x)?$/i.test(range);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function isMaintenanceRange(range) {
|
|
29
|
+
export function isMaintenanceRange(range) {
|
|
30
30
|
return /^\d+\.(?:\d+|x)(?:\.x)?$/i.test(range);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
function getUpperBound(range) {
|
|
33
|
+
export function getUpperBound(range) {
|
|
34
34
|
const result = semver.valid(range)
|
|
35
35
|
? range
|
|
36
36
|
: ((semver.validRange(range) || '').match(/<(?<upperBound>\d+\.\d+\.\d+(-\d+)?)$/) || [])[1];
|
|
@@ -41,27 +41,27 @@ function getUpperBound(range) {
|
|
|
41
41
|
: result;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function getLowerBound(range) {
|
|
44
|
+
export function getLowerBound(range) {
|
|
45
45
|
return ((semver.validRange(range) || '').match(/(?<lowerBound>\d+\.\d+\.\d+)/) || [])[1];
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
function highest(version1, version2) {
|
|
48
|
+
export function highest(version1, version2) {
|
|
49
49
|
return version1 && version2 ? (semver.gt(version1, version2) ? version1 : version2) : version1 || version2;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function lowest(version1, version2) {
|
|
52
|
+
export function lowest(version1, version2) {
|
|
53
53
|
return version1 && version2 ? (semver.lt(version1, version2) ? version1 : version2) : version1 || version2;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
function getLatestVersion(versions, {withPrerelease} = {}) {
|
|
56
|
+
export function getLatestVersion(versions, {withPrerelease} = {}) {
|
|
57
57
|
return versions.filter((version) => withPrerelease || !semver.prerelease(version)).sort(semver.rcompare)[0];
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
function getEarliestVersion(versions, {withPrerelease} = {}) {
|
|
60
|
+
export function getEarliestVersion(versions, {withPrerelease} = {}) {
|
|
61
61
|
return versions.filter((version) => withPrerelease || !semver.prerelease(version)).sort(semver.compare)[0];
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
function getFirstVersion(versions, lowerBranches) {
|
|
64
|
+
export function getFirstVersion(versions, lowerBranches) {
|
|
65
65
|
const lowerVersion = union(...lowerBranches.map(({tags}) => tagsToVersions(tags))).sort(semver.rcompare);
|
|
66
66
|
if (lowerVersion[0]) {
|
|
67
67
|
return versions.sort(semver.compare).find((version) => semver.gt(version, lowerVersion[0]));
|
|
@@ -70,32 +70,14 @@ function getFirstVersion(versions, lowerBranches) {
|
|
|
70
70
|
return getEarliestVersion(versions);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
function getRange(min, max) {
|
|
73
|
+
export function getRange(min, max) {
|
|
74
74
|
return `>=${min}${max ? ` <${max}` : ''}`;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
function makeTag(tagFormat, version) {
|
|
77
|
+
export function makeTag(tagFormat, version) {
|
|
78
78
|
return template(tagFormat)({version});
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
function isSameChannel(channel, otherChannel) {
|
|
81
|
+
export function isSameChannel(channel, otherChannel) {
|
|
82
82
|
return channel === otherChannel || (!channel && !otherChannel);
|
|
83
83
|
}
|
|
84
|
-
|
|
85
|
-
module.exports = {
|
|
86
|
-
extractErrors,
|
|
87
|
-
hideSensitiveValues,
|
|
88
|
-
tagsToVersions,
|
|
89
|
-
isMajorRange,
|
|
90
|
-
isMaintenanceRange,
|
|
91
|
-
getUpperBound,
|
|
92
|
-
getLowerBound,
|
|
93
|
-
highest,
|
|
94
|
-
lowest,
|
|
95
|
-
getLatestVersion,
|
|
96
|
-
getEarliestVersion,
|
|
97
|
-
getFirstVersion,
|
|
98
|
-
getRange,
|
|
99
|
-
makeTag,
|
|
100
|
-
isSameChannel,
|
|
101
|
-
};
|
package/lib/verify.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {isPlainObject, isString, template} from 'lodash-es';
|
|
2
|
+
import AggregateError from 'aggregate-error';
|
|
3
|
+
import {isGitRepo, verifyTagName} from './git.js';
|
|
4
|
+
import getError from './get-error.js';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
export default async (context) => {
|
|
7
7
|
const {
|
|
8
8
|
cwd,
|
|
9
9
|
env,
|
|
@@ -40,4 +40,4 @@ module.exports = async (context) => {
|
|
|
40
40
|
if (errors.length > 0) {
|
|
41
41
|
throw new AggregateError(errors);
|
|
42
42
|
}
|
|
43
|
-
}
|
|
43
|
+
}
|