release-it 19.2.3 → 20.0.0-0
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/log.js +1 -1
- package/lib/plugin/factory.js +1 -1
- package/lib/plugin/git/Git.js +7 -0
- package/lib/plugin/github/GitHub.js +1 -1
- package/lib/plugin/npm/npm.js +1 -0
- package/lib/prompt.js +18 -11
- package/package.json +26 -25
- package/test/git.js +33 -0
- package/test/log.js +8 -0
- package/test/prompt.js +20 -28
- package/test/tasks.interactive.js +12 -12
- package/test/tasks.js +1 -1
package/lib/log.js
CHANGED
package/lib/plugin/factory.js
CHANGED
package/lib/plugin/git/Git.js
CHANGED
|
@@ -209,6 +209,13 @@ class Git extends GitBase {
|
|
|
209
209
|
this.disableRollback();
|
|
210
210
|
return push;
|
|
211
211
|
} catch (error) {
|
|
212
|
+
if (this.config.getContext('isReleased')) {
|
|
213
|
+
this.disableRollback();
|
|
214
|
+
this.log.error(error.message || error);
|
|
215
|
+
this.log.warn('The package might have been released, but git push failed.');
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
212
219
|
try {
|
|
213
220
|
await this.rollbackTagPush();
|
|
214
221
|
} catch (tagError) {
|
|
@@ -453,7 +453,7 @@ class GitHub extends Release {
|
|
|
453
453
|
const { commit: template, excludeMatches = [] } = releaseNotes;
|
|
454
454
|
const commits = await this.getCommits();
|
|
455
455
|
|
|
456
|
-
if (this.options.commit) commits.pop();
|
|
456
|
+
if (this.options.commit || !this.config.isIncrement) commits.pop();
|
|
457
457
|
|
|
458
458
|
return commits
|
|
459
459
|
.map(commit => {
|
package/lib/plugin/npm/npm.js
CHANGED
package/lib/prompt.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { confirm, input, select } from '@inquirer/prompts';
|
|
2
|
+
|
|
3
|
+
const types = { confirm, input, list: select };
|
|
2
4
|
|
|
3
5
|
class Prompt {
|
|
4
6
|
constructor({ container }) {
|
|
5
|
-
this.createPrompt =
|
|
7
|
+
this.createPrompt = container.createPrompt;
|
|
6
8
|
this.prompts = {};
|
|
7
9
|
}
|
|
8
10
|
|
|
@@ -15,18 +17,23 @@ class Prompt {
|
|
|
15
17
|
if (!enabled) return false;
|
|
16
18
|
|
|
17
19
|
const prompt = this.prompts[namespace][promptName];
|
|
18
|
-
const options =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const options = {
|
|
21
|
+
message: prompt.message(context)
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if ('default' in prompt) options.default = prompt.default;
|
|
25
|
+
if ('choices' in prompt) options.choices = prompt.choices(context);
|
|
26
|
+
if ('transformer' in prompt) options.transformer = prompt.transformer(context);
|
|
27
|
+
if ('validate' in prompt) options.validate = prompt.validate;
|
|
28
|
+
if ('pageSize' in prompt) options.pageSize = prompt.pageSize;
|
|
24
29
|
|
|
25
|
-
const
|
|
30
|
+
const answer = await (this.createPrompt
|
|
31
|
+
? this.createPrompt(prompt.type, options)
|
|
32
|
+
: types[prompt.type](options));
|
|
26
33
|
|
|
27
|
-
const doExecute = prompt.type === 'confirm' ?
|
|
34
|
+
const doExecute = prompt.type === 'confirm' ? answer : true;
|
|
28
35
|
|
|
29
|
-
return doExecute && task ? await task(
|
|
36
|
+
return doExecute && task ? await task(answer) : false;
|
|
30
37
|
}
|
|
31
38
|
}
|
|
32
39
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-it",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "20.0.0-0",
|
|
4
4
|
"description": "Generic CLI tool to automate versioning and package publishing-related tasks.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"build",
|
|
@@ -78,53 +78,54 @@
|
|
|
78
78
|
},
|
|
79
79
|
"license": "MIT",
|
|
80
80
|
"dependencies": {
|
|
81
|
+
"@inquirer/prompts": "8.3.2",
|
|
81
82
|
"@nodeutils/defaults-deep": "1.1.0",
|
|
82
83
|
"@octokit/rest": "22.0.1",
|
|
83
84
|
"@phun-ky/typeof": "2.0.3",
|
|
84
85
|
"async-retry": "1.3.3",
|
|
85
86
|
"c12": "3.3.3",
|
|
86
|
-
"ci-info": "^4.
|
|
87
|
-
"eta": "4.5.
|
|
87
|
+
"ci-info": "^4.4.0",
|
|
88
|
+
"eta": "4.5.1",
|
|
88
89
|
"git-url-parse": "16.1.0",
|
|
89
|
-
"inquirer": "12.11.1",
|
|
90
90
|
"issue-parser": "7.0.1",
|
|
91
91
|
"lodash.merge": "4.6.2",
|
|
92
92
|
"mime-types": "3.0.2",
|
|
93
93
|
"new-github-release-url": "2.0.0",
|
|
94
|
-
"open": "
|
|
95
|
-
"ora": "9.
|
|
96
|
-
"os-name": "
|
|
97
|
-
"proxy-agent": "
|
|
98
|
-
"semver": "7.7.
|
|
94
|
+
"open": "11.0.0",
|
|
95
|
+
"ora": "9.3.0",
|
|
96
|
+
"os-name": "7.0.0",
|
|
97
|
+
"proxy-agent": "7.0.0",
|
|
98
|
+
"semver": "7.7.4",
|
|
99
99
|
"tinyglobby": "0.2.15",
|
|
100
|
-
"undici": "
|
|
100
|
+
"undici": "7.24.5",
|
|
101
101
|
"url-join": "5.0.0",
|
|
102
102
|
"wildcard-match": "5.1.4",
|
|
103
|
-
"yargs-parser": "
|
|
103
|
+
"yargs-parser": "22.0.0"
|
|
104
104
|
},
|
|
105
105
|
"devDependencies": {
|
|
106
|
-
"@eslint/js": "
|
|
106
|
+
"@eslint/js": "10.0.1",
|
|
107
107
|
"@octokit/request-error": "7.1.0",
|
|
108
|
-
"@types/node": "
|
|
109
|
-
"eslint": "
|
|
110
|
-
"eslint-plugin-import-x": "4.16.
|
|
111
|
-
"globals": "
|
|
112
|
-
"installed-check": "
|
|
113
|
-
"knip": "
|
|
114
|
-
"mentoss": "0.
|
|
108
|
+
"@types/node": "24.10.9",
|
|
109
|
+
"eslint": "10.1.0",
|
|
110
|
+
"eslint-plugin-import-x": "4.16.2",
|
|
111
|
+
"globals": "17.4.0",
|
|
112
|
+
"installed-check": "10.0.1",
|
|
113
|
+
"knip": "6.0.5",
|
|
114
|
+
"mentoss": "0.13.0",
|
|
115
115
|
"mock-stdio": "1.0.3",
|
|
116
|
-
"prettier": "3.
|
|
116
|
+
"prettier": "3.8.1",
|
|
117
117
|
"remark-cli": "12.0.1",
|
|
118
|
-
"remark-preset-webpro": "2.1.
|
|
119
|
-
"tar": "7.5.
|
|
120
|
-
"typescript": "
|
|
118
|
+
"remark-preset-webpro": "2.1.1",
|
|
119
|
+
"tar": "7.5.13",
|
|
120
|
+
"typescript": "6.0.2"
|
|
121
121
|
},
|
|
122
122
|
"overrides": {
|
|
123
123
|
"pac-resolver": "7.0.1",
|
|
124
|
-
"socks": "2.8.3"
|
|
124
|
+
"socks": "2.8.3",
|
|
125
|
+
"glob": "13.0.0"
|
|
125
126
|
},
|
|
126
127
|
"engines": {
|
|
127
|
-
"node": "^20.
|
|
128
|
+
"node": "^20.19.0 || ^22.13.0 || >=24.0.0"
|
|
128
129
|
},
|
|
129
130
|
"remarkConfig": {
|
|
130
131
|
"plugins": [
|
package/test/git.js
CHANGED
|
@@ -348,6 +348,39 @@ describe('git', () => {
|
|
|
348
348
|
assert.equal(exec.mock.calls[15].arguments[0], 'git push origin --delete v1.2.4');
|
|
349
349
|
});
|
|
350
350
|
|
|
351
|
+
test('should skip rollback when push fails but package is already published', async t => {
|
|
352
|
+
childProcess.execSync('git init', execOpts);
|
|
353
|
+
childProcess.execSync(`git remote add origin file://foo`, execOpts);
|
|
354
|
+
sh.exec(`git remote update`, execOpts);
|
|
355
|
+
const version = '1.2.3';
|
|
356
|
+
gitAdd(`{"version":"${version}"}`, 'package.json', 'Add package.json');
|
|
357
|
+
const options = { git: { requireCleanWorkingDir: true, commit: true, tag: true, tagName: 'v${version}' } };
|
|
358
|
+
const gitClient = await factory(Git, { options });
|
|
359
|
+
const exec = t.mock.method(gitClient.shell, 'execFormattedCommand');
|
|
360
|
+
const warn = t.mock.method(gitClient.log, 'warn');
|
|
361
|
+
sh.exec(`git push`, execOpts);
|
|
362
|
+
sh.exec(`git checkout HEAD~1`, execOpts);
|
|
363
|
+
gitAdd('line', 'file', 'Add file');
|
|
364
|
+
|
|
365
|
+
await gitClient.init();
|
|
366
|
+
|
|
367
|
+
childProcess.execSync('npm --no-git-tag-version version patch', execOpts);
|
|
368
|
+
|
|
369
|
+
gitClient.bump('1.2.4');
|
|
370
|
+
await gitClient.beforeRelease();
|
|
371
|
+
await gitClient.stage('package.json');
|
|
372
|
+
await gitClient.commit({ message: 'Add this' });
|
|
373
|
+
await gitClient.tag();
|
|
374
|
+
|
|
375
|
+
gitClient.config.setContext({ isReleased: true });
|
|
376
|
+
|
|
377
|
+
await gitClient.push();
|
|
378
|
+
|
|
379
|
+
const execCalls = exec.mock.calls.map(c => c.arguments[0]);
|
|
380
|
+
assert.equal(execCalls.includes('git push origin --delete v1.2.4'), false);
|
|
381
|
+
assert(warn.mock.calls.some(c => /git push failed/.test(c.arguments[0])));
|
|
382
|
+
});
|
|
383
|
+
|
|
351
384
|
test('should not touch existing history when rolling back', async t => {
|
|
352
385
|
childProcess.execSync('git init', execOpts);
|
|
353
386
|
const version = '1.2.3';
|
package/test/log.js
CHANGED
|
@@ -24,6 +24,14 @@ describe('log', () => {
|
|
|
24
24
|
assert.equal(stripVTControlCharacters(stderr), 'ERROR foo\n');
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
+
test('should print info', () => {
|
|
28
|
+
const log = new Log();
|
|
29
|
+
mockStdIo.start();
|
|
30
|
+
log.info('foo');
|
|
31
|
+
const { stderr } = mockStdIo.end();
|
|
32
|
+
assert.equal(stripVTControlCharacters(stderr), 'foo\n');
|
|
33
|
+
});
|
|
34
|
+
|
|
27
35
|
test('should print a warning', () => {
|
|
28
36
|
const log = new Log();
|
|
29
37
|
mockStdIo.start();
|
package/test/prompt.js
CHANGED
|
@@ -10,33 +10,28 @@ import { factory } from './util/index.js';
|
|
|
10
10
|
|
|
11
11
|
const prompts = { git, github, gitlab, npm };
|
|
12
12
|
|
|
13
|
-
const yes = (
|
|
14
|
-
const no = (
|
|
13
|
+
const yes = () => Promise.resolve(true);
|
|
14
|
+
const no = () => Promise.resolve(false);
|
|
15
15
|
|
|
16
16
|
test('should not create prompt if disabled', async t => {
|
|
17
17
|
const task = t.mock.fn();
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const prompt = await factory(Prompt, { container: { inquirer } });
|
|
18
|
+
const createPrompt = t.mock.fn(yes);
|
|
19
|
+
const prompt = await factory(Prompt, { container: { createPrompt } });
|
|
21
20
|
prompt.register(prompts.git);
|
|
22
21
|
await prompt.show({ enabled: false, prompt: 'push', task });
|
|
23
|
-
assert.equal(
|
|
22
|
+
assert.equal(createPrompt.mock.callCount(), 0);
|
|
24
23
|
assert.equal(task.mock.callCount(), 0);
|
|
25
24
|
});
|
|
26
25
|
|
|
27
26
|
test('should create prompt', async t => {
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const prompt = await factory(Prompt, { container: { inquirer } });
|
|
27
|
+
const createPrompt = t.mock.fn(yes);
|
|
28
|
+
const prompt = await factory(Prompt, { container: { createPrompt } });
|
|
31
29
|
prompt.register(prompts.git);
|
|
32
30
|
await prompt.show({ prompt: 'push' });
|
|
33
|
-
assert.equal(
|
|
34
|
-
assert.
|
|
35
|
-
|
|
31
|
+
assert.equal(createPrompt.mock.callCount(), 1);
|
|
32
|
+
assert.equal(createPrompt.mock.calls[0].arguments[0], 'confirm');
|
|
33
|
+
assert.deepEqual(createPrompt.mock.calls[0].arguments[1], {
|
|
36
34
|
message: 'Push?',
|
|
37
|
-
name: 'push',
|
|
38
|
-
choices: false,
|
|
39
|
-
transformer: undefined,
|
|
40
35
|
default: true
|
|
41
36
|
});
|
|
42
37
|
});
|
|
@@ -51,7 +46,7 @@ test('should create prompt', async t => {
|
|
|
51
46
|
['npm', 'otp', 'Please enter OTP for npm:']
|
|
52
47
|
].map(async ([namespace, prompt, message]) => {
|
|
53
48
|
test(`should create prompt and render template message (${namespace}.${prompt})`, async t => {
|
|
54
|
-
const
|
|
49
|
+
const createPrompt = t.mock.fn(yes);
|
|
55
50
|
const config = new Config({
|
|
56
51
|
isPreRelease: true,
|
|
57
52
|
git: { tagName: 'v${version}' },
|
|
@@ -59,34 +54,31 @@ test('should create prompt', async t => {
|
|
|
59
54
|
});
|
|
60
55
|
await config.init();
|
|
61
56
|
config.setContext({ version: '1.0.0', tagName: '1.0.0' });
|
|
62
|
-
const
|
|
63
|
-
const p = await factory(Prompt, { container: { inquirer } });
|
|
57
|
+
const p = await factory(Prompt, { container: { createPrompt } });
|
|
64
58
|
p.register(prompts[namespace], namespace);
|
|
65
59
|
await p.show({ namespace, prompt, context: config.getContext() });
|
|
66
|
-
assert.equal(
|
|
67
|
-
assert.equal(
|
|
60
|
+
assert.equal(createPrompt.mock.callCount(), 1);
|
|
61
|
+
assert.equal(createPrompt.mock.calls[0].arguments[1].message, message);
|
|
68
62
|
});
|
|
69
63
|
});
|
|
70
64
|
|
|
71
65
|
test('should execute task after positive answer', async t => {
|
|
72
66
|
const task = t.mock.fn();
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const prompt = await factory(Prompt, { container: { inquirer } });
|
|
67
|
+
const createPrompt = t.mock.fn(yes);
|
|
68
|
+
const prompt = await factory(Prompt, { container: { createPrompt } });
|
|
76
69
|
prompt.register(prompts.git);
|
|
77
70
|
await prompt.show({ prompt: 'push', task });
|
|
78
|
-
assert.equal(
|
|
71
|
+
assert.equal(createPrompt.mock.callCount(), 1);
|
|
79
72
|
assert.equal(task.mock.callCount(), 1);
|
|
80
73
|
assert.equal(task.mock.calls[0].arguments[0], true);
|
|
81
74
|
});
|
|
82
75
|
|
|
83
76
|
test('should not execute task after negative answer', async t => {
|
|
84
77
|
const task = t.mock.fn();
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
const prompt = await factory(Prompt, { container: { inquirer } });
|
|
78
|
+
const createPrompt = t.mock.fn(no);
|
|
79
|
+
const prompt = await factory(Prompt, { container: { createPrompt } });
|
|
88
80
|
prompt.register(prompts.git);
|
|
89
81
|
await prompt.show({ prompt: 'push', task });
|
|
90
|
-
assert.equal(
|
|
82
|
+
assert.equal(createPrompt.mock.callCount(), 1);
|
|
91
83
|
assert.equal(task.mock.callCount(), 0);
|
|
92
84
|
});
|
|
@@ -25,7 +25,7 @@ describe('tasks.interactive', () => {
|
|
|
25
25
|
|
|
26
26
|
afterEach(() => {
|
|
27
27
|
mocker.clearAll();
|
|
28
|
-
|
|
28
|
+
createPrompt.mock.resetCalls();
|
|
29
29
|
log.resetCalls();
|
|
30
30
|
});
|
|
31
31
|
|
|
@@ -54,17 +54,18 @@ describe('tasks.interactive', () => {
|
|
|
54
54
|
const log = new LogStub();
|
|
55
55
|
const spinner = new SpinnerStub();
|
|
56
56
|
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
const createPrompt = mock.fn((type, options) => {
|
|
58
|
+
if (type === 'list') return options.choices[0].value;
|
|
59
|
+
if (type === 'input') return '0.0.1';
|
|
60
|
+
return true;
|
|
60
61
|
});
|
|
61
62
|
|
|
62
|
-
const
|
|
63
|
+
const defaultCreatePrompt = createPrompt;
|
|
63
64
|
|
|
64
|
-
const getContainer = (options,
|
|
65
|
+
const getContainer = (options, promptFn = defaultCreatePrompt) => {
|
|
65
66
|
const config = new Config(Object.assign({}, testConfig, options));
|
|
66
67
|
const shell = new ShellStub({ container: { log, config } });
|
|
67
|
-
const prompt = new Prompt({ container: {
|
|
68
|
+
const prompt = new Prompt({ container: { createPrompt: promptFn } });
|
|
68
69
|
return { log, spinner, config, shell, prompt };
|
|
69
70
|
};
|
|
70
71
|
|
|
@@ -181,8 +182,7 @@ describe('tasks.interactive', () => {
|
|
|
181
182
|
childProcess.execSync('git tag 1.0.0', execOpts);
|
|
182
183
|
|
|
183
184
|
const hooks = getHooks(['version', 'git', 'github', 'gitlab', 'npm']);
|
|
184
|
-
const
|
|
185
|
-
const inquirer = { prompt };
|
|
185
|
+
const rejectAll = mock.fn(() => false);
|
|
186
186
|
|
|
187
187
|
const container = getContainer(
|
|
188
188
|
{
|
|
@@ -192,7 +192,7 @@ describe('tasks.interactive', () => {
|
|
|
192
192
|
gitlab: { release: true, skipChecks: true },
|
|
193
193
|
npm: { publish: true, skipChecks: true }
|
|
194
194
|
},
|
|
195
|
-
|
|
195
|
+
rejectAll
|
|
196
196
|
);
|
|
197
197
|
|
|
198
198
|
const exec = t.mock.method(container.shell, 'execFormattedCommand');
|
|
@@ -268,7 +268,7 @@ describe('tasks.interactive', () => {
|
|
|
268
268
|
test('should show only version prompt', async () => {
|
|
269
269
|
const config = { ci: false, 'only-version': true };
|
|
270
270
|
await runTasks({}, getContainer(config));
|
|
271
|
-
assert.equal(
|
|
272
|
-
assert.equal(
|
|
271
|
+
assert.equal(createPrompt.mock.callCount(), 1);
|
|
272
|
+
assert.equal(createPrompt.mock.calls[0].arguments[0], 'list');
|
|
273
273
|
});
|
|
274
274
|
});
|
package/test/tasks.js
CHANGED
|
@@ -34,7 +34,7 @@ describe('tasks', () => {
|
|
|
34
34
|
'https://gitlab.com/api/v4'
|
|
35
35
|
]);
|
|
36
36
|
|
|
37
|
-
const npmMajorVersion = semver.major(process.env.npm_config_user_agent
|
|
37
|
+
const npmMajorVersion = semver.major(process.env.npm_config_user_agent?.match(/npm\/([^ ]+)/)?.[1] ?? '10.0.0');
|
|
38
38
|
|
|
39
39
|
const testConfig = {
|
|
40
40
|
ci: true,
|