release-it 19.0.0-next.1 → 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 +34 -2
- package/lib/index.js +26 -9
- package/lib/log.js +4 -4
- package/lib/plugin/github/GitHub.js +2 -6
- package/lib/plugin/github/util.js +1 -1
- package/lib/plugin/gitlab/GitLab.js +4 -1
- package/lib/plugin/npm/npm.js +4 -0
- package/package.json +13 -19
- 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 -164
- package/test/tasks.js +394 -412
- package/test/util/helpers.js +4 -3
- package/test/util/index.js +34 -7
- package/test/utils.js +33 -32
- package/test/version.js +192 -176
- package/test/util/setup.js +0 -3
|
@@ -1,216 +1,269 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { renameSync } from 'node:fs';
|
|
3
3
|
import childProcess from 'node:child_process';
|
|
4
|
-
import test from '
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import Spinner from '../lib/spinner.js';
|
|
4
|
+
import test, { afterEach, after, before, beforeEach, describe, mock } from 'node:test';
|
|
5
|
+
import assert from 'node:assert/strict';
|
|
6
|
+
import { MockServer, FetchMocker } from 'mentoss';
|
|
8
7
|
import Prompt from '../lib/prompt.js';
|
|
9
8
|
import Config from '../lib/config.js';
|
|
10
9
|
import runTasks from '../lib/index.js';
|
|
11
10
|
import Git from '../lib/plugin/git/Git.js';
|
|
12
11
|
import { execOpts } from '../lib/util.js';
|
|
13
|
-
import { mkTmpDir, gitAdd } from './util/helpers.js';
|
|
12
|
+
import { mkTmpDir, gitAdd, getArgs } from './util/helpers.js';
|
|
14
13
|
import ShellStub from './stub/shell.js';
|
|
15
14
|
import { interceptPublish as interceptGitLabPublish } from './stub/gitlab.js';
|
|
16
15
|
import { interceptCreate as interceptGitHubCreate } from './stub/github.js';
|
|
17
|
-
import { factory } from './util/index.js';
|
|
16
|
+
import { factory, LogStub, SpinnerStub } from './util/index.js';
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
describe('tasks.interactive', () => {
|
|
19
|
+
const github = new MockServer('https://api.github.com');
|
|
20
|
+
const gitlab = new MockServer('https://gitlab.com/api/v4');
|
|
21
|
+
const githubusercontent = new MockServer('https://raw.githubusercontent.com');
|
|
20
22
|
|
|
21
|
-
const
|
|
23
|
+
const mocker = new FetchMocker({
|
|
24
|
+
servers: [github, gitlab, githubusercontent]
|
|
25
|
+
});
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
+
before(() => {
|
|
28
|
+
mocker.mockGlobal();
|
|
29
|
+
});
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
mocker.clearAll();
|
|
33
|
+
prompt.mock.resetCalls();
|
|
34
|
+
log.resetCalls();
|
|
35
|
+
});
|
|
31
36
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const getContainer = (options, inquirer = defaultInquirer) => {
|
|
40
|
-
const config = new Config(Object.assign({}, testConfig, options));
|
|
41
|
-
const shell = new ShellStub({ container: { log, config } });
|
|
42
|
-
const prompt = new Prompt({ container: { inquirer } });
|
|
43
|
-
return {
|
|
44
|
-
log,
|
|
45
|
-
spinner,
|
|
46
|
-
config,
|
|
47
|
-
shell,
|
|
48
|
-
prompt
|
|
37
|
+
after(() => {
|
|
38
|
+
mocker.unmockGlobal();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const testConfig = {
|
|
42
|
+
ci: false,
|
|
43
|
+
config: false
|
|
49
44
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
45
|
+
|
|
46
|
+
const getHooks = plugins => {
|
|
47
|
+
const hooks = {};
|
|
48
|
+
['before', 'after'].forEach(prefix => {
|
|
49
|
+
plugins.forEach(ns => {
|
|
50
|
+
['init', 'beforeBump', 'bump', 'beforeRelease', 'release', 'afterRelease'].forEach(lifecycle => {
|
|
51
|
+
hooks[`${prefix}:${lifecycle}`] = `echo ${prefix}:${lifecycle}`;
|
|
52
|
+
hooks[`${prefix}:${ns}:${lifecycle}`] = `echo ${prefix}:${ns}:${lifecycle}`;
|
|
53
|
+
});
|
|
59
54
|
});
|
|
60
55
|
});
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
};
|
|
56
|
+
return hooks;
|
|
57
|
+
};
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
});
|
|
59
|
+
const log = new LogStub();
|
|
60
|
+
const spinner = new SpinnerStub();
|
|
68
61
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
childProcess.execSync(`git init --bare .`, execOpts);
|
|
74
|
-
childProcess.execSync(`git clone ${bare} ${target}`, execOpts);
|
|
75
|
-
process.chdir(target);
|
|
76
|
-
gitAdd('line', 'file', 'Add file');
|
|
77
|
-
t.context = { bare, target };
|
|
78
|
-
});
|
|
62
|
+
const prompt = mock.fn(([options]) => {
|
|
63
|
+
const answer = options.type === 'list' ? options.choices[0].value : options.name === 'version' ? '0.0.1' : true;
|
|
64
|
+
return { [options.name]: answer };
|
|
65
|
+
});
|
|
79
66
|
|
|
80
|
-
|
|
81
|
-
sandbox.resetHistory();
|
|
82
|
-
});
|
|
67
|
+
const defaultInquirer = { prompt };
|
|
83
68
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
});
|
|
69
|
+
const getContainer = (options, inquirer = defaultInquirer) => {
|
|
70
|
+
const config = new Config(Object.assign({}, testConfig, options));
|
|
71
|
+
const shell = new ShellStub({ container: { log, config } });
|
|
72
|
+
const prompt = new Prompt({ container: { inquirer } });
|
|
73
|
+
return { log, spinner, config, shell, prompt };
|
|
74
|
+
};
|
|
91
75
|
|
|
92
|
-
|
|
93
|
-
|
|
76
|
+
let bare;
|
|
77
|
+
let target;
|
|
78
|
+
beforeEach(async () => {
|
|
79
|
+
bare = mkTmpDir();
|
|
80
|
+
target = mkTmpDir();
|
|
81
|
+
process.chdir(bare);
|
|
82
|
+
childProcess.execSync(`git init --bare .`, execOpts);
|
|
83
|
+
childProcess.execSync(`git clone ${bare} ${target}`, execOpts);
|
|
84
|
+
process.chdir(target);
|
|
85
|
+
gitAdd('line', 'file', 'Add file');
|
|
86
|
+
});
|
|
94
87
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
88
|
+
test('should run tasks without throwing errors', async () => {
|
|
89
|
+
renameSync('.git', 'foo');
|
|
90
|
+
const { name, latestVersion, version } = await runTasks({}, getContainer());
|
|
91
|
+
assert.equal(version, '0.0.1');
|
|
92
|
+
assert(log.obtrusive.mock.calls[0].arguments[0].includes(`release ${name} (currently at ${latestVersion})`));
|
|
93
|
+
assert.match(log.log.mock.calls.at(-1).arguments[0], /Done \(in [0-9]+s\.\)/);
|
|
101
94
|
});
|
|
102
95
|
|
|
103
|
-
|
|
96
|
+
test('should run tasks using extended configuration', async t => {
|
|
97
|
+
renameSync('.git', 'foo');
|
|
104
98
|
|
|
105
|
-
|
|
99
|
+
const validationExtendedConfiguration = "echo 'extended_configuration'";
|
|
106
100
|
|
|
107
|
-
|
|
101
|
+
githubusercontent.get('/release-it/release-it-configuration/HEAD/.release-it.json', {
|
|
102
|
+
status: 200,
|
|
103
|
+
body: {
|
|
104
|
+
hooks: {
|
|
105
|
+
'before:init': validationExtendedConfiguration
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
const config = {
|
|
111
|
+
$schema: 'https://unpkg.com/release-it@18/schema/release-it.json',
|
|
112
|
+
extends: 'github:release-it/release-it-configuration'
|
|
113
|
+
};
|
|
111
114
|
|
|
112
|
-
|
|
113
|
-
t.false(commands.includes('echo after:github:release'));
|
|
114
|
-
t.false(commands.includes('echo after:gitlab:release'));
|
|
115
|
-
t.false(commands.includes('echo after:npm:release'));
|
|
116
|
-
});
|
|
115
|
+
const container = getContainer(config);
|
|
117
116
|
|
|
118
|
-
|
|
119
|
-
const { target } = t.context;
|
|
120
|
-
const pkgName = path.basename(target);
|
|
121
|
-
gitAdd(`{"name":"${pkgName}","version":"1.0.0"}`, 'package.json', 'Add package.json');
|
|
122
|
-
childProcess.execSync('git tag 1.0.0', execOpts);
|
|
117
|
+
const exec = t.mock.method(container.shell, 'execFormattedCommand');
|
|
123
118
|
|
|
124
|
-
|
|
125
|
-
const inquirer = { prompt: sandbox.stub().callsFake(([options]) => ({ [options.name]: false })) };
|
|
119
|
+
const { name, latestVersion, version } = await runTasks({}, container);
|
|
126
120
|
|
|
127
|
-
|
|
128
|
-
{
|
|
129
|
-
increment: 'minor',
|
|
130
|
-
hooks,
|
|
131
|
-
github: { release: true, skipChecks: true },
|
|
132
|
-
gitlab: { release: true, skipChecks: true },
|
|
133
|
-
npm: { publish: true, skipChecks: true }
|
|
134
|
-
},
|
|
135
|
-
inquirer
|
|
136
|
-
);
|
|
121
|
+
const commands = getArgs(exec, 'echo');
|
|
137
122
|
|
|
138
|
-
|
|
123
|
+
assert(commands.includes(validationExtendedConfiguration));
|
|
139
124
|
|
|
140
|
-
|
|
125
|
+
assert.equal(version, '0.0.1');
|
|
126
|
+
assert(log.obtrusive.mock.calls[0].arguments[0].includes(`release ${name} (currently at ${latestVersion})`));
|
|
127
|
+
assert.match(log.log.mock.calls.at(-1).arguments[0], /Done \(in [0-9]+s\.\)/);
|
|
128
|
+
});
|
|
141
129
|
|
|
142
|
-
|
|
130
|
+
test('should run tasks not using extended configuration as it is not a string', async () => {
|
|
131
|
+
renameSync('.git', 'foo');
|
|
143
132
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
133
|
+
const config = {
|
|
134
|
+
$schema: 'https://unpkg.com/release-it@18/schema/release-it.json',
|
|
135
|
+
extends: false
|
|
136
|
+
};
|
|
148
137
|
|
|
149
|
-
|
|
150
|
-
t.false(commands.includes('echo after:github:release'));
|
|
151
|
-
t.false(commands.includes('echo after:gitlab:release'));
|
|
152
|
-
t.false(commands.includes('echo after:npm:release'));
|
|
138
|
+
const container = getContainer(config);
|
|
153
139
|
|
|
154
|
-
|
|
155
|
-
});
|
|
140
|
+
const { name, latestVersion, version } = await runTasks({}, container);
|
|
156
141
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const pkgName = path.basename(target);
|
|
161
|
-
const owner = path.basename(path.dirname(bare));
|
|
162
|
-
gitAdd(`{"name":"${pkgName}","version":"1.0.0"}`, 'package.json', 'Add package.json');
|
|
163
|
-
childProcess.execSync('git tag 1.0.0', execOpts);
|
|
164
|
-
const sha = gitAdd('line', 'file', 'More file');
|
|
165
|
-
|
|
166
|
-
const git = factory(Git);
|
|
167
|
-
const ref = (await git.getBranchName()) ?? 'HEAD';
|
|
168
|
-
|
|
169
|
-
interceptGitHubCreate({
|
|
170
|
-
owner,
|
|
171
|
-
project,
|
|
172
|
-
body: { tag_name: '1.1.0', name: 'Release 1.1.0', body: `* More file (${sha})` }
|
|
142
|
+
assert.equal(version, '0.0.1');
|
|
143
|
+
assert(log.obtrusive.mock.calls[0].arguments[0].includes(`release ${name} (currently at ${latestVersion})`));
|
|
144
|
+
assert.match(log.log.mock.calls.at(-1).arguments[0], /Done \(in [0-9]+s\.\)/);
|
|
173
145
|
});
|
|
174
146
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
});
|
|
147
|
+
test('should not run hooks for disabled release-cycle methods', async t => {
|
|
148
|
+
const hooks = getHooks(['version', 'git', 'github', 'gitlab', 'npm']);
|
|
149
|
+
|
|
150
|
+
const container = getContainer({
|
|
151
|
+
hooks,
|
|
152
|
+
git: { push: false },
|
|
153
|
+
github: { release: false },
|
|
154
|
+
gitlab: { release: false },
|
|
155
|
+
npm: { publish: false }
|
|
156
|
+
});
|
|
186
157
|
|
|
187
|
-
|
|
158
|
+
const exec = t.mock.method(container.shell, 'execFormattedCommand');
|
|
188
159
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
160
|
+
await runTasks({}, container);
|
|
161
|
+
|
|
162
|
+
const commands = getArgs(exec, 'echo');
|
|
163
|
+
|
|
164
|
+
assert(commands.includes('echo before:init'));
|
|
165
|
+
assert(commands.includes('echo after:afterRelease'));
|
|
166
|
+
|
|
167
|
+
assert(!commands.includes('echo after:git:release'));
|
|
168
|
+
assert(!commands.includes('echo after:github:release'));
|
|
169
|
+
assert(!commands.includes('echo after:gitlab:release'));
|
|
170
|
+
assert(!commands.includes('echo after:npm:release'));
|
|
195
171
|
});
|
|
196
172
|
|
|
197
|
-
|
|
173
|
+
test('should not run hooks for cancelled release-cycle methods', async t => {
|
|
174
|
+
const pkgName = path.basename(target);
|
|
175
|
+
gitAdd(`{"name":"${pkgName}","version":"1.0.0"}`, 'package.json', 'Add package.json');
|
|
176
|
+
childProcess.execSync('git tag 1.0.0', execOpts);
|
|
177
|
+
|
|
178
|
+
const hooks = getHooks(['version', 'git', 'github', 'gitlab', 'npm']);
|
|
179
|
+
const prompt = mock.fn(([options]) => ({ [options.name]: false }));
|
|
180
|
+
const inquirer = { prompt };
|
|
181
|
+
|
|
182
|
+
const container = getContainer(
|
|
183
|
+
{
|
|
184
|
+
increment: 'minor',
|
|
185
|
+
hooks,
|
|
186
|
+
github: { release: true, skipChecks: true },
|
|
187
|
+
gitlab: { release: true, skipChecks: true },
|
|
188
|
+
npm: { publish: true, skipChecks: true }
|
|
189
|
+
},
|
|
190
|
+
inquirer
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
const exec = t.mock.method(container.shell, 'execFormattedCommand');
|
|
194
|
+
|
|
195
|
+
await runTasks({}, container);
|
|
196
|
+
|
|
197
|
+
const commands = getArgs(exec, 'echo');
|
|
198
|
+
|
|
199
|
+
assert(commands.includes('echo before:init'));
|
|
200
|
+
assert(commands.includes('echo after:afterRelease'));
|
|
201
|
+
assert(commands.includes('echo after:git:bump'));
|
|
202
|
+
assert(commands.includes('echo after:npm:bump'));
|
|
203
|
+
|
|
204
|
+
assert(!commands.includes('echo after:git:release'));
|
|
205
|
+
assert(!commands.includes('echo after:github:release'));
|
|
206
|
+
assert(!commands.includes('echo after:gitlab:release'));
|
|
207
|
+
assert(!commands.includes('echo after:npm:release'));
|
|
208
|
+
});
|
|
198
209
|
|
|
199
|
-
|
|
210
|
+
test('should run "after:*:release" plugin hooks', async t => {
|
|
211
|
+
const project = path.basename(bare);
|
|
212
|
+
const pkgName = path.basename(target);
|
|
213
|
+
const owner = path.basename(path.dirname(bare));
|
|
214
|
+
gitAdd(`{"name":"${pkgName}","version":"1.0.0"}`, 'package.json', 'Add package.json');
|
|
215
|
+
childProcess.execSync('git tag 1.0.0', execOpts);
|
|
216
|
+
const sha = gitAdd('line', 'file', 'More file');
|
|
217
|
+
|
|
218
|
+
const git = factory(Git);
|
|
219
|
+
const ref = (await git.getBranchName()) ?? 'HEAD';
|
|
220
|
+
|
|
221
|
+
interceptGitHubCreate(github, {
|
|
222
|
+
owner,
|
|
223
|
+
project,
|
|
224
|
+
body: { tag_name: '1.1.0', name: 'Release 1.1.0', body: `* More file (${sha})` }
|
|
225
|
+
});
|
|
200
226
|
|
|
201
|
-
|
|
227
|
+
interceptGitLabPublish(gitlab, {
|
|
228
|
+
owner,
|
|
229
|
+
project,
|
|
230
|
+
body: {
|
|
231
|
+
name: 'Release 1.1.0',
|
|
232
|
+
ref,
|
|
233
|
+
tag_name: '1.1.0',
|
|
234
|
+
tag_message: 'Release 1.1.0',
|
|
235
|
+
description: `* More file (${sha})`
|
|
236
|
+
}
|
|
237
|
+
});
|
|
202
238
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
239
|
+
const hooks = getHooks(['version', 'git', 'github', 'gitlab', 'npm']);
|
|
240
|
+
|
|
241
|
+
const container = getContainer({
|
|
242
|
+
increment: 'minor',
|
|
243
|
+
hooks,
|
|
244
|
+
github: { release: true, pushRepo: `https://github.com/${owner}/${project}`, skipChecks: true },
|
|
245
|
+
gitlab: { release: true, pushRepo: `https://gitlab.com/${owner}/${project}`, skipChecks: true },
|
|
246
|
+
npm: { name: pkgName, skipChecks: true }
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
const exec = t.mock.method(container.shell, 'execFormattedCommand');
|
|
210
250
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
251
|
+
await runTasks({}, container);
|
|
252
|
+
|
|
253
|
+
const commands = getArgs(exec, 'echo');
|
|
254
|
+
|
|
255
|
+
assert(commands.includes('echo after:git:bump'));
|
|
256
|
+
assert(commands.includes('echo after:npm:bump'));
|
|
257
|
+
assert(commands.includes('echo after:git:release'));
|
|
258
|
+
assert(commands.includes('echo after:github:release'));
|
|
259
|
+
assert(commands.includes('echo after:gitlab:release'));
|
|
260
|
+
assert(commands.includes('echo after:npm:release'));
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test('should show only version prompt', async () => {
|
|
264
|
+
const config = { ci: false, 'only-version': true };
|
|
265
|
+
await runTasks({}, getContainer(config));
|
|
266
|
+
assert.equal(prompt.mock.callCount(), 1);
|
|
267
|
+
assert.equal(prompt.mock.calls[0].arguments[0][0].name, 'incrementList');
|
|
268
|
+
});
|
|
216
269
|
});
|