release-it 19.0.0-next.0 → 19.0.0-next.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/lib/cli.js +2 -5
- package/lib/config.js +42 -7
- package/lib/index.js +30 -14
- package/lib/log.js +12 -11
- package/lib/plugin/GitBase.js +2 -1
- package/lib/plugin/GitRelease.js +5 -5
- package/lib/plugin/Plugin.js +6 -4
- package/lib/plugin/factory.js +11 -11
- package/lib/plugin/git/Git.js +5 -6
- package/lib/plugin/github/GitHub.js +13 -16
- package/lib/plugin/github/util.js +1 -1
- package/lib/plugin/gitlab/GitLab.js +6 -4
- package/lib/plugin/npm/npm.js +4 -0
- package/lib/util.js +71 -42
- package/package.json +27 -29
- package/schema/gitlab.json +4 -0
- package/schema/release-it.json +4 -0
- package/test/cli.js +6 -5
- package/test/config.js +232 -122
- package/test/git.init.js +220 -218
- package/test/git.js +359 -364
- package/test/github.js +565 -480
- package/test/gitlab.js +374 -335
- package/test/log.js +141 -138
- package/test/npm.js +315 -373
- package/test/plugin-name.js +7 -6
- package/test/plugins.js +200 -211
- package/test/prompt.js +26 -32
- package/test/shell.js +63 -60
- package/test/spinner.js +20 -24
- package/test/stub/github.js +113 -123
- package/test/stub/gitlab.js +74 -52
- package/test/tasks.interactive.js +217 -165
- package/test/tasks.js +394 -413
- package/test/util/helpers.js +4 -3
- package/test/util/index.js +35 -11
- package/test/utils.js +33 -32
- package/test/version.js +192 -176
- package/test/util/setup.js +0 -3
package/lib/cli.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { readJSON } from './util.js';
|
|
2
|
-
import Log from './log.js';
|
|
3
2
|
import runTasks from './index.js';
|
|
4
3
|
|
|
5
4
|
const pkg = readJSON(new URL('../package.json', import.meta.url));
|
|
6
5
|
|
|
7
|
-
const log = new Log();
|
|
8
|
-
|
|
9
6
|
const helpText = `Release It! v${pkg.version}
|
|
10
7
|
|
|
11
8
|
Usage: release-it <increment> [options]
|
|
@@ -27,10 +24,10 @@ const helpText = `Release It! v${pkg.version}
|
|
|
27
24
|
For more details, please see https://github.com/release-it/release-it`;
|
|
28
25
|
|
|
29
26
|
/** @internal */
|
|
30
|
-
export const version = () =>
|
|
27
|
+
export const version = () => console.log(`v${pkg.version}`);
|
|
31
28
|
|
|
32
29
|
/** @internal */
|
|
33
|
-
export const help = () =>
|
|
30
|
+
export const help = () => console.log(helpText);
|
|
34
31
|
|
|
35
32
|
export default async options => {
|
|
36
33
|
if (options.version) {
|
package/lib/config.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import util from 'node:util';
|
|
2
2
|
import { cosmiconfigSync } from 'cosmiconfig';
|
|
3
3
|
import parseToml from '@iarna/toml/parse-string.js';
|
|
4
|
-
import _ from 'lodash';
|
|
5
4
|
import { isCI } from 'ci-info';
|
|
6
|
-
import
|
|
5
|
+
import defaultsDeep from '@nodeutils/defaults-deep';
|
|
6
|
+
import { isObjectStrict } from '@phun-ky/typeof';
|
|
7
|
+
import merge from 'lodash.merge';
|
|
8
|
+
import get from 'lodash.get';
|
|
9
|
+
import { e, getSystemInfo, readJSON } from './util.js';
|
|
7
10
|
|
|
8
11
|
const debug = util.debug('release-it:config');
|
|
9
12
|
const defaultConfig = readJSON(new URL('../config/release-it.json', import.meta.url));
|
|
@@ -35,7 +38,34 @@ const getLocalConfig = ({ file, dir = process.cwd() }) => {
|
|
|
35
38
|
throw new Error(`Invalid configuration file at ${result.filepath}`);
|
|
36
39
|
}
|
|
37
40
|
debug({ cosmiconfig: result });
|
|
38
|
-
return result &&
|
|
41
|
+
return result && isObjectStrict(result.config) ? result.config : localConfig;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const fetchConfigurationFromGitHub = async configuration => {
|
|
45
|
+
const docs = 'https://github.com/release-it/release-it/blob/main/docs/configuration.md';
|
|
46
|
+
|
|
47
|
+
const regex = /^github:([^/]+)\/([^#:]+)(?::([^#]+))?(?:#(.+))?$/;
|
|
48
|
+
const match = configuration.match(regex);
|
|
49
|
+
|
|
50
|
+
if (!match) {
|
|
51
|
+
throw e(`Invalid Extended Configuration from GitHub: ${configuration}`, docs);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const [, owner, repo, file = '.release-it.json', tag] = match;
|
|
55
|
+
const ref = tag ? `refs/tags/${tag}` : 'HEAD';
|
|
56
|
+
const url = new URL(`https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${file}`);
|
|
57
|
+
|
|
58
|
+
const response = await fetch(url);
|
|
59
|
+
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
throw e(`Failed to fetch ${url}: ${response.statusText}`, docs);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return response.json();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const getRemoteConfiguration = async configuration => {
|
|
68
|
+
return fetchConfigurationFromGitHub(configuration);
|
|
39
69
|
};
|
|
40
70
|
|
|
41
71
|
class Config {
|
|
@@ -72,7 +102,7 @@ class Config {
|
|
|
72
102
|
}
|
|
73
103
|
|
|
74
104
|
mergeOptions() {
|
|
75
|
-
return
|
|
105
|
+
return defaultsDeep(
|
|
76
106
|
{},
|
|
77
107
|
this.constructorConfig,
|
|
78
108
|
{
|
|
@@ -83,14 +113,17 @@ class Config {
|
|
|
83
113
|
);
|
|
84
114
|
}
|
|
85
115
|
|
|
116
|
+
mergeRemoteOptions(remoteConfiguration) {
|
|
117
|
+
return merge({}, this.options, remoteConfiguration);
|
|
118
|
+
}
|
|
86
119
|
getContext(path) {
|
|
87
|
-
const context =
|
|
88
|
-
return path ?
|
|
120
|
+
const context = merge({}, this.options, this.contextOptions);
|
|
121
|
+
return path ? get(context, path) : context;
|
|
89
122
|
}
|
|
90
123
|
|
|
91
124
|
setContext(options) {
|
|
92
125
|
debug(options);
|
|
93
|
-
|
|
126
|
+
merge(this.contextOptions, options);
|
|
94
127
|
}
|
|
95
128
|
|
|
96
129
|
setCI(value = true) {
|
|
@@ -138,4 +171,6 @@ class Config {
|
|
|
138
171
|
}
|
|
139
172
|
}
|
|
140
173
|
|
|
174
|
+
export { getRemoteConfiguration };
|
|
175
|
+
|
|
141
176
|
export default Config;
|
package/lib/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
1
|
import { getPlugins } from './plugin/factory.js';
|
|
3
2
|
import Logger from './log.js';
|
|
4
|
-
import Config from './config.js';
|
|
3
|
+
import Config, { getRemoteConfiguration } from './config.js';
|
|
5
4
|
import Shell from './shell.js';
|
|
6
5
|
import Prompt from './prompt.js';
|
|
7
6
|
import Spinner from './spinner.js';
|
|
8
|
-
import { reduceUntil, parseVersion } from './util.js';
|
|
7
|
+
import { reduceUntil, parseVersion, castArray } from './util.js';
|
|
9
8
|
|
|
10
9
|
const runTasks = async (opts, di) => {
|
|
11
10
|
let container = {};
|
|
@@ -14,6 +13,15 @@ const runTasks = async (opts, di) => {
|
|
|
14
13
|
Object.assign(container, di);
|
|
15
14
|
container.config = container.config || new Config(opts);
|
|
16
15
|
|
|
16
|
+
if (typeof container.config.options?.extends === 'string') {
|
|
17
|
+
/**
|
|
18
|
+
* If the configuration has an 'extends' property, fetch the remote configuration
|
|
19
|
+
* and merge it into the local configuration options.
|
|
20
|
+
*/
|
|
21
|
+
const remoteConfiguration = await getRemoteConfiguration(container.config.options.extends);
|
|
22
|
+
container.config.options = container.config.mergeRemoteOptions(remoteConfiguration);
|
|
23
|
+
}
|
|
24
|
+
|
|
17
25
|
const { config } = container;
|
|
18
26
|
const { isCI, isVerbose, verbosityLevel, isDryRun, isChangelog, isReleaseVersion } = config;
|
|
19
27
|
|
|
@@ -33,20 +41,20 @@ const runTasks = async (opts, di) => {
|
|
|
33
41
|
if (!scripts || !scripts.length) return;
|
|
34
42
|
const context = config.getContext();
|
|
35
43
|
const external = true;
|
|
36
|
-
for (const script of
|
|
44
|
+
for (const script of castArray(scripts)) {
|
|
37
45
|
const task = () => shell.exec(script, { external }, context);
|
|
38
46
|
await spinner.show({ task, label: script, context, external });
|
|
39
47
|
}
|
|
40
48
|
};
|
|
41
49
|
|
|
42
50
|
const runLifeCycleHook = async (plugin, name, ...args) => {
|
|
43
|
-
if (plugin ===
|
|
51
|
+
if (plugin === plugins.at(0)) await runHook('before', name);
|
|
44
52
|
await runHook('before', plugin.namespace, name);
|
|
45
53
|
const willHookRun = (await plugin[name](...args)) !== false;
|
|
46
54
|
if (willHookRun) {
|
|
47
55
|
await runHook('after', plugin.namespace, name);
|
|
48
56
|
}
|
|
49
|
-
if (plugin ===
|
|
57
|
+
if (plugin === plugins.at(-1)) await runHook('after', name);
|
|
50
58
|
};
|
|
51
59
|
|
|
52
60
|
const [internal, external] = await getPlugins(config, container);
|
|
@@ -63,8 +71,13 @@ const runTasks = async (opts, di) => {
|
|
|
63
71
|
const changelog = await reduceUntil(plugins, plugin => plugin.getChangelog(latestVersion));
|
|
64
72
|
|
|
65
73
|
if (isChangelog) {
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
if (changelog) {
|
|
75
|
+
console.log(changelog);
|
|
76
|
+
process.exit(0);
|
|
77
|
+
} else {
|
|
78
|
+
log.warn('No changelog found');
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
68
81
|
}
|
|
69
82
|
|
|
70
83
|
const incrementBase = { latestVersion, increment, isPreRelease, preReleaseId, preReleaseBase };
|
|
@@ -96,13 +109,14 @@ const runTasks = async (opts, di) => {
|
|
|
96
109
|
version = version || (await reduceUntil(plugins, plugin => plugin.getIncrementedVersion(incrementBase)));
|
|
97
110
|
}
|
|
98
111
|
|
|
99
|
-
if (!version) {
|
|
100
|
-
log.obtrusive(`No new version to release`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
112
|
if (isReleaseVersion) {
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
if (version) {
|
|
114
|
+
console.log(version);
|
|
115
|
+
process.exit(0);
|
|
116
|
+
} else {
|
|
117
|
+
log.warn(`No new version to release`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
106
120
|
}
|
|
107
121
|
|
|
108
122
|
if (version) {
|
|
@@ -126,6 +140,8 @@ const runTasks = async (opts, di) => {
|
|
|
126
140
|
await runLifeCycleHook(plugin, hook);
|
|
127
141
|
}
|
|
128
142
|
}
|
|
143
|
+
} else {
|
|
144
|
+
log.obtrusive(`No new version to release`);
|
|
129
145
|
}
|
|
130
146
|
|
|
131
147
|
log.log(`🏁 Done (in ${Math.floor(process.uptime())}s.)`);
|
package/lib/log.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { EOL } from 'node:os';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
const { isObject, last, filter, isString, lowerCase, upperFirst, isArray } = _;
|
|
3
|
+
import { isObjectLoose } from '@phun-ky/typeof';
|
|
4
|
+
import { upperFirst } from './util.js';
|
|
6
5
|
|
|
7
6
|
class Logger {
|
|
8
7
|
constructor({ isCI = true, isVerbose = false, verbosityLevel = 0, isDryRun = false } = {}) {
|
|
@@ -25,27 +24,29 @@ class Logger {
|
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
info(...args) {
|
|
28
|
-
|
|
27
|
+
console.error(chalk.grey(...args));
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
warn(...args) {
|
|
32
|
-
|
|
31
|
+
console.error(chalk.yellow('WARNING'), ...args);
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
verbose(...args) {
|
|
36
|
-
const { isExternal } =
|
|
35
|
+
const { isExternal } = isObjectLoose(args.at(-1)) ? args.at(-1) : {};
|
|
37
36
|
if (this.shouldLog(isExternal)) {
|
|
38
|
-
|
|
37
|
+
console.error(...args.filter(str => typeof str === 'string'));
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
exec(...args) {
|
|
43
|
-
const { isDryRun: isExecutedInDryRun, isExternal, isCached } =
|
|
42
|
+
const { isDryRun: isExecutedInDryRun, isExternal, isCached } = isObjectLoose(args.at(-1)) ? args.at(-1) : {};
|
|
44
43
|
if (this.shouldLog(isExternal) || this.isDryRun) {
|
|
45
44
|
const prefix = isExecutedInDryRun == null ? '$' : '!';
|
|
46
|
-
const command = args
|
|
45
|
+
const command = args
|
|
46
|
+
.map(cmd => (typeof cmd === 'string' ? cmd : Array.isArray(cmd) ? cmd.join(' ') : ''))
|
|
47
|
+
.join(' ');
|
|
47
48
|
const message = [prefix, command, isCached ? '[cached]' : ''].join(' ').trim();
|
|
48
|
-
|
|
49
|
+
console.error(message);
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -61,7 +62,7 @@ class Logger {
|
|
|
61
62
|
const body = text.replace(new RegExp(EOL + EOL, 'g'), EOL);
|
|
62
63
|
this.obtrusive(`${header}:${EOL}${body}`);
|
|
63
64
|
} else {
|
|
64
|
-
this.obtrusive(`Empty ${
|
|
65
|
+
this.obtrusive(`Empty ${title.toLowerCase()}`);
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
}
|
package/lib/plugin/GitBase.js
CHANGED
package/lib/plugin/GitRelease.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { readJSON } from '../util.js';
|
|
1
|
+
import { pick, readJSON } from '../util.js';
|
|
3
2
|
import GitBase from './GitBase.js';
|
|
4
3
|
|
|
5
4
|
const defaultConfig = readJSON(new URL('../../config/release-it.json', import.meta.url));
|
|
@@ -12,7 +11,7 @@ class GitRelease extends GitBase {
|
|
|
12
11
|
getInitialOptions(options) {
|
|
13
12
|
const baseOptions = super.getInitialOptions(...arguments);
|
|
14
13
|
const git = options.git || defaultConfig.git;
|
|
15
|
-
const gitOptions =
|
|
14
|
+
const gitOptions = pick(git, [
|
|
16
15
|
'tagExclude',
|
|
17
16
|
'tagName',
|
|
18
17
|
'tagMatch',
|
|
@@ -21,12 +20,13 @@ class GitRelease extends GitBase {
|
|
|
21
20
|
'changelog',
|
|
22
21
|
'commit'
|
|
23
22
|
]);
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
return Object.assign({}, gitOptions, baseOptions);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
get token() {
|
|
28
28
|
const { tokenRef } = this.options;
|
|
29
|
-
return
|
|
29
|
+
return process.env[tokenRef] || null;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async beforeRelease() {
|
package/lib/plugin/Plugin.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { debug } from 'node:util';
|
|
2
|
-
import
|
|
2
|
+
import merge from 'lodash.merge';
|
|
3
|
+
import get from 'lodash.get';
|
|
3
4
|
|
|
4
5
|
class Plugin {
|
|
5
6
|
static isEnabled() {
|
|
@@ -40,12 +41,13 @@ class Plugin {
|
|
|
40
41
|
afterRelease() {}
|
|
41
42
|
|
|
42
43
|
getContext(path) {
|
|
43
|
-
const context =
|
|
44
|
-
|
|
44
|
+
const context = merge({}, this.options, this.context);
|
|
45
|
+
|
|
46
|
+
return path ? get(context, path) : context;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
setContext(context) {
|
|
48
|
-
|
|
50
|
+
merge(this.context, context);
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
exec(command, { options, context = {} } = {}) {
|
package/lib/plugin/factory.js
CHANGED
|
@@ -2,7 +2,7 @@ import url from 'node:url';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import util from 'node:util';
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
5
|
-
import
|
|
5
|
+
import { castArray } from '../util.js';
|
|
6
6
|
import Version from './version/Version.js';
|
|
7
7
|
import Git from './git/Git.js';
|
|
8
8
|
import GitLab from './gitlab/GitLab.js';
|
|
@@ -54,23 +54,23 @@ export const getPluginName = pluginName => {
|
|
|
54
54
|
export let getPlugins = async (config, container) => {
|
|
55
55
|
const context = config.getContext();
|
|
56
56
|
const disabledPlugins = [];
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
context.plugins
|
|
60
|
-
async (result, pluginConfig, pluginName) => {
|
|
57
|
+
const enabledExternalPlugins = [];
|
|
58
|
+
if (context.plugins) {
|
|
59
|
+
for (const [pluginName, pluginConfig] of Object.entries(context.plugins)) {
|
|
61
60
|
const [name, Plugin] = await load(pluginName);
|
|
62
61
|
const [namespace, options] = pluginConfig.length === 2 ? pluginConfig : [name, pluginConfig];
|
|
62
|
+
|
|
63
63
|
config.setContext({ [namespace]: options });
|
|
64
|
+
|
|
64
65
|
if (await Plugin.isEnabled(options)) {
|
|
65
66
|
const instance = new Plugin({ namespace, options: config.getContext(), container });
|
|
66
67
|
debug({ namespace, options: instance.options });
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
enabledExternalPlugins.push(instance);
|
|
69
|
+
|
|
70
|
+
disabledPlugins.push(...pluginNames.filter(p => castArray(Plugin.disablePlugin(options)).includes(p)));
|
|
69
71
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
[]
|
|
73
|
-
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
74
|
|
|
75
75
|
const enabledPlugins = await pluginNames.reduce(async (result, plugin) => {
|
|
76
76
|
if (plugin in plugins && !disabledPlugins.includes(plugin)) {
|
package/lib/plugin/git/Git.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { EOL } from 'node:os';
|
|
2
|
-
import _ from 'lodash';
|
|
3
2
|
import { execa } from 'execa';
|
|
4
3
|
import matcher from 'wildcard-match';
|
|
5
|
-
import { format, e, fixArgs } from '../../util.js';
|
|
4
|
+
import { format, e, fixArgs, once, castArray } from '../../util.js';
|
|
6
5
|
import GitBase from '../GitBase.js';
|
|
7
6
|
import prompts from './prompts.js';
|
|
8
7
|
|
|
@@ -64,7 +63,7 @@ class Git extends GitBase {
|
|
|
64
63
|
}
|
|
65
64
|
|
|
66
65
|
enableRollback() {
|
|
67
|
-
this.rollbackOnce =
|
|
66
|
+
this.rollbackOnce = once(this.rollback.bind(this));
|
|
68
67
|
process.on('SIGINT', this.rollbackOnce);
|
|
69
68
|
process.on('exit', this.rollbackOnce);
|
|
70
69
|
}
|
|
@@ -96,7 +95,7 @@ class Git extends GitBase {
|
|
|
96
95
|
|
|
97
96
|
async isRequiredBranch() {
|
|
98
97
|
const branch = await this.getBranchName();
|
|
99
|
-
const requiredBranches =
|
|
98
|
+
const requiredBranches = castArray(this.options.requireBranch);
|
|
100
99
|
const [branches, negated] = requiredBranches.reduce(
|
|
101
100
|
([p, n], b) => (b.startsWith('!') ? [p, [...n, b.slice(1)]] : [[...p, b], n]),
|
|
102
101
|
[[], []]
|
|
@@ -151,7 +150,7 @@ class Git extends GitBase {
|
|
|
151
150
|
|
|
152
151
|
stage(file) {
|
|
153
152
|
if (!file || !file.length) return noop;
|
|
154
|
-
const files =
|
|
153
|
+
const files = castArray(file);
|
|
155
154
|
return this.exec(['git', 'add', ...files]).catch(err => {
|
|
156
155
|
this.log.warn(`Could not stage ${files}`);
|
|
157
156
|
this.debug(err);
|
|
@@ -164,7 +163,7 @@ class Git extends GitBase {
|
|
|
164
163
|
}
|
|
165
164
|
|
|
166
165
|
reset(file) {
|
|
167
|
-
const files =
|
|
166
|
+
const files = castArray(file);
|
|
168
167
|
return this.exec(['git', 'checkout', 'HEAD', '--', ...files]).catch(err => {
|
|
169
168
|
this.log.warn(`Could not reset ${files}`);
|
|
170
169
|
this.debug(err);
|
|
@@ -4,19 +4,14 @@ import open from 'open';
|
|
|
4
4
|
import { Octokit } from '@octokit/rest';
|
|
5
5
|
import { globby } from 'globby';
|
|
6
6
|
import mime from 'mime-types';
|
|
7
|
-
import _ from 'lodash';
|
|
8
7
|
import retry from 'async-retry';
|
|
9
8
|
import newGithubReleaseUrl from 'new-github-release-url';
|
|
10
9
|
import { ProxyAgent } from 'proxy-agent';
|
|
11
|
-
import { format, parseVersion, readJSON, e } from '../../util.js';
|
|
10
|
+
import { format, parseVersion, readJSON, e, castArray } from '../../util.js';
|
|
12
11
|
import Release from '../GitRelease.js';
|
|
13
12
|
import prompts from './prompts.js';
|
|
14
13
|
import { getCommitsFromChangelog, getResolvedIssuesFromChangelog, searchQueries } from './util.js';
|
|
15
14
|
|
|
16
|
-
/**
|
|
17
|
-
* @typedef {import('@octokit/rest').RestEndpointMethodTypes['repos']['createRelease']['parameters']} CreateReleaseOptions
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
15
|
/**
|
|
21
16
|
* @typedef {import('@octokit/rest').RestEndpointMethodTypes['repos']['createRelease']['parameters']} CreateReleaseOptions
|
|
22
17
|
*/
|
|
@@ -34,7 +29,7 @@ const parseErrormsg = err => {
|
|
|
34
29
|
if (err instanceof Error) {
|
|
35
30
|
const { status, message } = err;
|
|
36
31
|
const headers = err.response ? err.response.headers : {};
|
|
37
|
-
msg = `${
|
|
32
|
+
msg = `${headers?.status || status} (${message})`;
|
|
38
33
|
}
|
|
39
34
|
return msg;
|
|
40
35
|
};
|
|
@@ -166,7 +161,7 @@ class GitHub extends Release {
|
|
|
166
161
|
const githubError = new Error(message);
|
|
167
162
|
this.log.verbose(err.errors);
|
|
168
163
|
this.debug(err);
|
|
169
|
-
if (!
|
|
164
|
+
if (!RETRY_CODES.includes(err.status)) {
|
|
170
165
|
return bail(githubError);
|
|
171
166
|
}
|
|
172
167
|
throw githubError;
|
|
@@ -175,7 +170,8 @@ class GitHub extends Release {
|
|
|
175
170
|
get client() {
|
|
176
171
|
if (this._client) return this._client;
|
|
177
172
|
const { proxy, timeout } = this.options;
|
|
178
|
-
const
|
|
173
|
+
const repo = this.getContext('repo');
|
|
174
|
+
const host = this.options.host || repo.host;
|
|
179
175
|
const isGitHub = host === 'github.com';
|
|
180
176
|
const baseUrl = `https://${isGitHub ? 'api.github.com' : host}${isGitHub ? '' : '/api/v3'}`;
|
|
181
177
|
const options = {
|
|
@@ -226,6 +222,7 @@ class GitHub extends Release {
|
|
|
226
222
|
const { isPreRelease } = parseVersion(version);
|
|
227
223
|
const name = format(releaseName, this.config.getContext());
|
|
228
224
|
const releaseNotesObject = this.options.releaseNotes;
|
|
225
|
+
|
|
229
226
|
const body = autoGenerate
|
|
230
227
|
? isUpdate
|
|
231
228
|
? null
|
|
@@ -331,7 +328,7 @@ class GitHub extends Release {
|
|
|
331
328
|
const context = this.config.getContext();
|
|
332
329
|
const { isDryRun } = this.config;
|
|
333
330
|
|
|
334
|
-
const patterns =
|
|
331
|
+
const patterns = castArray(assets).map(pattern => format(pattern, context));
|
|
335
332
|
|
|
336
333
|
this.log.exec('octokit repos.uploadReleaseAssets', patterns, { isDryRun });
|
|
337
334
|
|
|
@@ -356,9 +353,9 @@ class GitHub extends Release {
|
|
|
356
353
|
}
|
|
357
354
|
|
|
358
355
|
async generateWebUrl() {
|
|
359
|
-
const
|
|
356
|
+
const repo = this.getContext('repo');
|
|
357
|
+
const host = this.options.host || repo.host;
|
|
360
358
|
const isGitHub = host === 'github.com';
|
|
361
|
-
|
|
362
359
|
const options = await this.getOctokitReleaseOptions();
|
|
363
360
|
const url = newGithubReleaseUrl({
|
|
364
361
|
user: options.owner,
|
|
@@ -410,7 +407,7 @@ class GitHub extends Release {
|
|
|
410
407
|
|
|
411
408
|
async commentOnResolvedItems() {
|
|
412
409
|
const { isDryRun } = this.config;
|
|
413
|
-
const { owner, project: repo } = this.getContext('repo');
|
|
410
|
+
const { host, owner, project: repo } = this.getContext('repo');
|
|
414
411
|
const changelog = await this.getChangelog();
|
|
415
412
|
const { comments } = this.options;
|
|
416
413
|
const { submit, issue, pr } = comments ?? {};
|
|
@@ -422,13 +419,13 @@ class GitHub extends Release {
|
|
|
422
419
|
const searchResults = await Promise.all(searchQueries(this.client, owner, repo, shas));
|
|
423
420
|
const mergedPullRequests = searchResults.flatMap(items => items.map(item => ({ type: 'pr', number: item.number })));
|
|
424
421
|
|
|
425
|
-
const
|
|
426
|
-
const resolvedIssues = getResolvedIssuesFromChangelog(
|
|
422
|
+
const hostURL = 'https://' + (this.options.host || host);
|
|
423
|
+
const resolvedIssues = getResolvedIssuesFromChangelog(hostURL, owner, repo, changelog);
|
|
427
424
|
|
|
428
425
|
for (const item of [...resolvedIssues, ...mergedPullRequests]) {
|
|
429
426
|
const { type, number } = item;
|
|
430
427
|
const comment = format(format(type === 'pr' ? pr : issue, context), context);
|
|
431
|
-
const url = `${
|
|
428
|
+
const url = `${hostURL}/${owner}/${repo}/${type === 'pr' ? 'pull' : 'issues'}/${number}`;
|
|
432
429
|
|
|
433
430
|
if (isDryRun) {
|
|
434
431
|
this.log.exec(`octokit issues.createComment (${url})`, { isDryRun });
|
|
@@ -18,7 +18,7 @@ export const getSearchQueries = (base, commits, separator = '+') => {
|
|
|
18
18
|
|
|
19
19
|
export const searchQueries = (client, owner, repo, shas) =>
|
|
20
20
|
getSearchQueries(`repo:${owner}/${repo}+type:pr+is:merged`, shas).map(
|
|
21
|
-
async q => (await client.search.issuesAndPullRequests({ q })).data.items
|
|
21
|
+
async q => (await client.search.issuesAndPullRequests({ q, advanced_search: true })).data.items
|
|
22
22
|
);
|
|
23
23
|
|
|
24
24
|
export const getCommitsFromChangelog = changelog => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fs, { promises } from 'node:fs'; // import fs here so it can be stubbed in tests
|
|
3
3
|
import { globby } from 'globby';
|
|
4
|
-
import _ from 'lodash';
|
|
5
4
|
import { Agent } from 'undici';
|
|
6
5
|
import Release from '../GitRelease.js';
|
|
7
|
-
import { format, e } from '../../util.js';
|
|
6
|
+
import { format, e, castArray } from '../../util.js';
|
|
8
7
|
import prompts from './prompts.js';
|
|
9
8
|
|
|
10
9
|
const docs = 'https://git.io/release-it-gitlab';
|
|
@@ -16,7 +15,10 @@ class GitLab extends Release {
|
|
|
16
15
|
super(...args);
|
|
17
16
|
this.registerPrompts(prompts);
|
|
18
17
|
this.assets = [];
|
|
19
|
-
const {
|
|
18
|
+
const { secure } = this.options;
|
|
19
|
+
const certificateAuthorityFileRef = this.options.certificateAuthorityFileRef || 'CI_SERVER_TLS_CA_FILE';
|
|
20
|
+
const certificateAuthorityFile =
|
|
21
|
+
this.options.certificateAuthorityFile || process.env[certificateAuthorityFileRef] || null;
|
|
20
22
|
this.certificateAuthorityOption = {};
|
|
21
23
|
|
|
22
24
|
const needsCustomAgent = Boolean(secure === false || certificateAuthorityFile);
|
|
@@ -309,7 +311,7 @@ class GitLab extends Release {
|
|
|
309
311
|
const { isDryRun } = this.config;
|
|
310
312
|
const context = this.config.getContext();
|
|
311
313
|
|
|
312
|
-
const patterns =
|
|
314
|
+
const patterns = castArray(assets).map(pattern => format(pattern, context));
|
|
313
315
|
|
|
314
316
|
this.log.exec('gitlab releases#uploadAssets', patterns, { isDryRun });
|
|
315
317
|
|
package/lib/plugin/npm/npm.js
CHANGED
|
@@ -256,6 +256,10 @@ class npm extends Plugin {
|
|
|
256
256
|
})
|
|
257
257
|
.catch(err => {
|
|
258
258
|
this.debug(err);
|
|
259
|
+
if (this.config.isDryRun && /publish over the previously published version/.test(err)) {
|
|
260
|
+
return Promise.resolve();
|
|
261
|
+
}
|
|
262
|
+
|
|
259
263
|
if (/one-time pass/.test(err)) {
|
|
260
264
|
if (otp != null) {
|
|
261
265
|
this.log.warn('The provided OTP is incorrect or has expired.');
|