release-it 19.0.0-next.4 → 19.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/README.md +4 -3
- package/bin/release-it.js +0 -5
- package/lib/config.js +113 -103
- package/lib/index.js +2 -10
- package/lib/plugin/git/Git.js +2 -2
- package/lib/plugin/github/GitHub.js +2 -2
- package/lib/plugin/github/util.js +1 -0
- package/lib/plugin/gitlab/GitLab.js +2 -2
- package/lib/shell.js +6 -6
- package/lib/util.js +4 -0
- package/package.json +13 -14
- package/test/args.js +3 -3
- package/test/config.js +146 -71
- package/test/git.init.js +30 -30
- package/test/git.js +26 -26
- package/test/github.js +21 -21
- package/test/gitlab.js +27 -27
- package/test/npm.js +31 -31
- package/test/prompt.js +6 -5
- package/test/shell.js +5 -5
- package/test/spinner.js +8 -5
- package/test/stub/config/remote/.release-it.json +5 -0
- package/test/stub/config/remote/sub/.release-it.json +5 -0
- package/test/tasks.interactive.js +22 -15
- package/test/tasks.js +1 -1
- package/test/util/fetch.js +32 -0
- package/test/util/helpers.js +13 -8
- package/test/util/index.js +2 -1
- package/test/version.js +42 -42
package/test/npm.js
CHANGED
|
@@ -9,19 +9,19 @@ import { mkTmpDir, getArgs } from './util/helpers.js';
|
|
|
9
9
|
describe('npm', async () => {
|
|
10
10
|
test('should return npm package url', async () => {
|
|
11
11
|
const options = { npm: { name: 'my-cool-package' } };
|
|
12
|
-
const npmClient = factory(npm, { options });
|
|
12
|
+
const npmClient = await factory(npm, { options });
|
|
13
13
|
assert.equal(npmClient.getPackageUrl(), 'https://www.npmjs.com/package/my-cool-package');
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
test('should return npm package url (custom registry)', async () => {
|
|
17
17
|
const options = { npm: { name: 'my-cool-package', publishConfig: { registry: 'https://registry.example.org/' } } };
|
|
18
|
-
const npmClient = factory(npm, { options });
|
|
18
|
+
const npmClient = await factory(npm, { options });
|
|
19
19
|
assert.equal(npmClient.getPackageUrl(), 'https://registry.example.org/package/my-cool-package');
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
test('should return npm package url (custom publicPath)', async () => {
|
|
23
23
|
const options = { npm: { name: 'my-cool-package', publishConfig: { publicPath: '/custom/public-path' } } };
|
|
24
|
-
const npmClient = factory(npm, { options });
|
|
24
|
+
const npmClient = await factory(npm, { options });
|
|
25
25
|
assert.equal(npmClient.getPackageUrl(), 'https://www.npmjs.com/custom/public-path/my-cool-package');
|
|
26
26
|
});
|
|
27
27
|
|
|
@@ -32,46 +32,46 @@ describe('npm', async () => {
|
|
|
32
32
|
publishConfig: { registry: 'https://registry.example.org/', publicPath: '/custom/public-path' }
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
|
-
const npmClient = factory(npm, { options });
|
|
35
|
+
const npmClient = await factory(npm, { options });
|
|
36
36
|
assert.equal(npmClient.getPackageUrl(), 'https://registry.example.org/custom/public-path/my-cool-package');
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
test('should return default tag', async () => {
|
|
40
|
-
const npmClient = factory(npm);
|
|
40
|
+
const npmClient = await factory(npm);
|
|
41
41
|
const tag = await npmClient.resolveTag();
|
|
42
42
|
assert.equal(tag, 'latest');
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
test('should resolve default tag for pre-release', async t => {
|
|
46
|
-
const npmClient = factory(npm);
|
|
46
|
+
const npmClient = await factory(npm);
|
|
47
47
|
t.mock.method(npmClient, 'getRegistryPreReleaseTags', () => []);
|
|
48
48
|
const tag = await npmClient.resolveTag('1.0.0-0');
|
|
49
49
|
assert.equal(tag, 'next');
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
test('should guess tag from registry for pre-release', async t => {
|
|
53
|
-
const npmClient = factory(npm);
|
|
53
|
+
const npmClient = await factory(npm);
|
|
54
54
|
t.mock.method(npmClient, 'getRegistryPreReleaseTags', () => ['alpha']);
|
|
55
55
|
const tag = await npmClient.resolveTag('1.0.0-0');
|
|
56
56
|
assert.equal(tag, 'alpha');
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
test('should derive tag from pre-release version', async () => {
|
|
60
|
-
const npmClient = factory(npm);
|
|
60
|
+
const npmClient = await factory(npm);
|
|
61
61
|
const tag = await npmClient.resolveTag('1.0.2-alpha.3');
|
|
62
62
|
assert.equal(tag, 'alpha');
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
test('should use provided (default) tag even for pre-release', async t => {
|
|
66
66
|
const options = { npm: { tag: 'latest' } };
|
|
67
|
-
const npmClient = factory(npm, { options });
|
|
67
|
+
const npmClient = await factory(npm, { options });
|
|
68
68
|
t.mock.method(npmClient.shell, 'exec', () => Promise.resolve());
|
|
69
69
|
await npmClient.bump('1.0.0-next.0');
|
|
70
70
|
assert.equal(npmClient.getContext('tag'), 'latest');
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
test('should throw when `npm version` fails', async t => {
|
|
74
|
-
const npmClient = factory(npm);
|
|
74
|
+
const npmClient = await factory(npm);
|
|
75
75
|
t.mock.method(npmClient.shell, 'exec', () =>
|
|
76
76
|
Promise.reject(new Error('npm ERR! Version not changed, might want --allow-same-version'))
|
|
77
77
|
);
|
|
@@ -79,14 +79,14 @@ describe('npm', async () => {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
test('should return first pre-release tag from package in registry when resolving tag without pre-id', async t => {
|
|
82
|
-
const npmClient = factory(npm);
|
|
82
|
+
const npmClient = await factory(npm);
|
|
83
83
|
const response = { latest: '1.4.1', alpha: '2.0.0-alpha.1', beta: '2.0.0-beta.3' };
|
|
84
84
|
t.mock.method(npmClient.shell, 'exec', () => Promise.resolve(JSON.stringify(response)));
|
|
85
85
|
assert.equal(await npmClient.resolveTag('2.0.0-5'), 'alpha');
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
test('should return default pre-release tag when resolving tag without pre-id', async t => {
|
|
89
|
-
const npmClient = factory(npm);
|
|
89
|
+
const npmClient = await factory(npm);
|
|
90
90
|
const response = {
|
|
91
91
|
latest: '1.4.1'
|
|
92
92
|
};
|
|
@@ -95,19 +95,19 @@ describe('npm', async () => {
|
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
test('should handle erroneous output when resolving tag without pre-id', async t => {
|
|
98
|
-
const npmClient = factory(npm);
|
|
98
|
+
const npmClient = await factory(npm);
|
|
99
99
|
t.mock.method(npmClient.shell, 'exec', () => Promise.resolve(''));
|
|
100
100
|
assert.equal(await npmClient.resolveTag('2.0.0-0'), 'next');
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
test('should handle errored request when resolving tag without pre-id', async t => {
|
|
104
|
-
const npmClient = factory(npm);
|
|
104
|
+
const npmClient = await factory(npm);
|
|
105
105
|
t.mock.method(npmClient.shell, 'exec', () => Promise.resolve());
|
|
106
106
|
assert.equal(await npmClient.resolveTag('2.0.0-0'), 'next');
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
test('should add registry to commands when specified', async t => {
|
|
110
|
-
const npmClient = factory(npm);
|
|
110
|
+
const npmClient = await factory(npm);
|
|
111
111
|
npmClient.setContext({ publishConfig: { registry: 'registry.example.org' } });
|
|
112
112
|
const exec = t.mock.method(npmClient.shell, 'exec', command => {
|
|
113
113
|
if (command === 'npm whoami --registry registry.example.org') return Promise.resolve('john');
|
|
@@ -126,7 +126,7 @@ describe('npm', async () => {
|
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
test('should not throw when executing tasks', async t => {
|
|
129
|
-
const npmClient = factory(npm);
|
|
129
|
+
const npmClient = await factory(npm);
|
|
130
130
|
t.mock.method(npmClient.shell, 'exec', command => {
|
|
131
131
|
if (command === 'npm whoami') return Promise.resolve('john');
|
|
132
132
|
const re = /npm access (list collaborators --json|ls-collaborators) release-it/;
|
|
@@ -137,7 +137,7 @@ describe('npm', async () => {
|
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
test('should throw if npm is down', async t => {
|
|
140
|
-
const npmClient = factory(npm);
|
|
140
|
+
const npmClient = await factory(npm);
|
|
141
141
|
t.mock.method(npmClient.shell, 'exec', command => {
|
|
142
142
|
if (command === 'npm ping') return Promise.reject();
|
|
143
143
|
return Promise.resolve();
|
|
@@ -146,7 +146,7 @@ describe('npm', async () => {
|
|
|
146
146
|
});
|
|
147
147
|
|
|
148
148
|
test('should not throw if npm returns 400/404 for unsupported ping/whoami/access', async t => {
|
|
149
|
-
const npmClient = factory(npm);
|
|
149
|
+
const npmClient = await factory(npm);
|
|
150
150
|
const exec = t.mock.method(npmClient.shell, 'exec', () => Promise.resolve());
|
|
151
151
|
const pingError = "npm ERR! code E404\nnpm ERR! 404 Package '--ping' not found : ping";
|
|
152
152
|
const whoamiError = "npm ERR! code E404\nnpm ERR! 404 Package '--whoami' not found : whoami";
|
|
@@ -159,7 +159,7 @@ describe('npm', async () => {
|
|
|
159
159
|
});
|
|
160
160
|
|
|
161
161
|
test('should not throw if npm returns 400 for unsupported ping/whoami/access', async t => {
|
|
162
|
-
const npmClient = factory(npm);
|
|
162
|
+
const npmClient = await factory(npm);
|
|
163
163
|
const exec = t.mock.method(npmClient.shell, 'exec', () => Promise.resolve());
|
|
164
164
|
const pingError = 'npm ERR! code E400\nnpm ERR! 400 Bad Request - GET https://npm.example.org/-/ping?write=true';
|
|
165
165
|
const whoamiError = 'npm ERR! code E400\nnpm ERR! 400 Bad Request - GET https://npm.example.org/-/whoami';
|
|
@@ -172,14 +172,14 @@ describe('npm', async () => {
|
|
|
172
172
|
});
|
|
173
173
|
|
|
174
174
|
test('should throw if user is not authenticated', async t => {
|
|
175
|
-
const npmClient = factory(npm);
|
|
175
|
+
const npmClient = await factory(npm);
|
|
176
176
|
const exec = t.mock.method(npmClient.shell, 'exec', () => Promise.resolve());
|
|
177
177
|
exec.mock.mockImplementationOnce(() => Promise.reject(), 1);
|
|
178
178
|
await assert.rejects(runTasks(npmClient), { message: /^Not authenticated with npm/ });
|
|
179
179
|
});
|
|
180
180
|
|
|
181
181
|
test('should throw if user is not a collaborator (v9)', async t => {
|
|
182
|
-
const npmClient = factory(npm);
|
|
182
|
+
const npmClient = await factory(npm);
|
|
183
183
|
t.mock.method(npmClient.shell, 'exec', command => {
|
|
184
184
|
if (command === 'npm whoami') return Promise.resolve('ada');
|
|
185
185
|
if (command === 'npm --version') return Promise.resolve('9.2.0');
|
|
@@ -191,7 +191,7 @@ describe('npm', async () => {
|
|
|
191
191
|
});
|
|
192
192
|
|
|
193
193
|
test('should throw if user is not a collaborator (v8)', async t => {
|
|
194
|
-
const npmClient = factory(npm);
|
|
194
|
+
const npmClient = await factory(npm);
|
|
195
195
|
|
|
196
196
|
t.mock.method(npmClient.shell, 'exec', command => {
|
|
197
197
|
if (command === 'npm whoami') return Promise.resolve('ada');
|
|
@@ -205,7 +205,7 @@ describe('npm', async () => {
|
|
|
205
205
|
});
|
|
206
206
|
|
|
207
207
|
test('should not throw if user is not a collaborator on a new package', async t => {
|
|
208
|
-
const npmClient = factory(npm);
|
|
208
|
+
const npmClient = await factory(npm);
|
|
209
209
|
|
|
210
210
|
t.mock.method(npmClient.shell, 'exec', command => {
|
|
211
211
|
if (command === 'npm whoami') return Promise.resolve('ada');
|
|
@@ -220,7 +220,7 @@ describe('npm', async () => {
|
|
|
220
220
|
});
|
|
221
221
|
|
|
222
222
|
test('should handle 2FA and publish with OTP', async t => {
|
|
223
|
-
const npmClient = factory(npm);
|
|
223
|
+
const npmClient = await factory(npm);
|
|
224
224
|
npmClient.setContext({ name: 'pkg' });
|
|
225
225
|
|
|
226
226
|
const exec = t.mock.method(npmClient.shell, 'exec');
|
|
@@ -247,7 +247,7 @@ describe('npm', async () => {
|
|
|
247
247
|
});
|
|
248
248
|
|
|
249
249
|
test('should publish', async t => {
|
|
250
|
-
const npmClient = factory(npm);
|
|
250
|
+
const npmClient = await factory(npm);
|
|
251
251
|
const exec = t.mock.method(npmClient.shell, 'exec', command => {
|
|
252
252
|
if (command === 'npm whoami') return Promise.resolve('john');
|
|
253
253
|
const re = /npm access (list collaborators --json|ls-collaborators) release-it/;
|
|
@@ -260,7 +260,7 @@ describe('npm', async () => {
|
|
|
260
260
|
|
|
261
261
|
test('should use extra publish arguments', async t => {
|
|
262
262
|
const options = { npm: { skipChecks: true, publishArgs: '--registry=http://my-internal-registry.local' } };
|
|
263
|
-
const npmClient = factory(npm, { options });
|
|
263
|
+
const npmClient = await factory(npm, { options });
|
|
264
264
|
const exec = t.mock.method(npmClient.shell, 'exec', () => Promise.resolve());
|
|
265
265
|
await runTasks(npmClient);
|
|
266
266
|
assert.equal(
|
|
@@ -271,7 +271,7 @@ describe('npm', async () => {
|
|
|
271
271
|
|
|
272
272
|
test('should skip checks', async () => {
|
|
273
273
|
const options = { npm: { skipChecks: true } };
|
|
274
|
-
const npmClient = factory(npm, { options });
|
|
274
|
+
const npmClient = await factory(npm, { options });
|
|
275
275
|
await assert.doesNotReject(npmClient.init());
|
|
276
276
|
});
|
|
277
277
|
|
|
@@ -290,7 +290,7 @@ describe('npm', async () => {
|
|
|
290
290
|
})
|
|
291
291
|
);
|
|
292
292
|
const options = { npm };
|
|
293
|
-
const npmClient = factory(npm, { options });
|
|
293
|
+
const npmClient = await factory(npm, { options });
|
|
294
294
|
const exec = t.mock.method(npmClient.shell, 'exec', command => {
|
|
295
295
|
const cmd = 'npm whoami --registry https://gitlab.com/api/v4/projects/my-scope%2Fmy-pkg/packages/npm/';
|
|
296
296
|
if (command === cmd) return Promise.resolve('john');
|
|
@@ -316,7 +316,7 @@ describe('npm', async () => {
|
|
|
316
316
|
process.chdir(tmp);
|
|
317
317
|
writeFileSync(join(tmp, 'package.json'), JSON.stringify({ name: '@my-scope/my-pkg', version: '1.0.0' }));
|
|
318
318
|
const options = { npm };
|
|
319
|
-
const npmClient = factory(npm, { options });
|
|
319
|
+
const npmClient = await factory(npm, { options });
|
|
320
320
|
|
|
321
321
|
const exec = t.mock.method(npmClient.shell, 'exec', command => {
|
|
322
322
|
if (command === 'npm whoami') return Promise.resolve('john');
|
|
@@ -340,7 +340,7 @@ describe('npm', async () => {
|
|
|
340
340
|
|
|
341
341
|
test('should add allow-same-version argument', async t => {
|
|
342
342
|
const options = { npm: { skipChecks: true, allowSameVersion: true } };
|
|
343
|
-
const npmClient = factory(npm, { options });
|
|
343
|
+
const npmClient = await factory(npm, { options });
|
|
344
344
|
|
|
345
345
|
const exec = t.mock.method(npmClient.shell, 'exec', () => Promise.resolve());
|
|
346
346
|
|
|
@@ -351,7 +351,7 @@ describe('npm', async () => {
|
|
|
351
351
|
|
|
352
352
|
test('should add version arguments', async t => {
|
|
353
353
|
const options = { npm: { skipChecks: true, versionArgs: ['--workspaces-update=false', '--allow-same-version'] } };
|
|
354
|
-
const npmClient = factory(npm, { options });
|
|
354
|
+
const npmClient = await factory(npm, { options });
|
|
355
355
|
const exec = t.mock.method(npmClient.shell, 'exec', () => Promise.resolve());
|
|
356
356
|
await runTasks(npmClient);
|
|
357
357
|
const versionArgs = getArgs(exec, 'npm version');
|
package/test/prompt.js
CHANGED
|
@@ -17,7 +17,7 @@ test('should not create prompt if disabled', async t => {
|
|
|
17
17
|
const task = t.mock.fn();
|
|
18
18
|
const promptMock = t.mock.fn(yes);
|
|
19
19
|
const inquirer = { prompt: promptMock };
|
|
20
|
-
const prompt = factory(Prompt, { container: { inquirer } });
|
|
20
|
+
const prompt = await factory(Prompt, { container: { inquirer } });
|
|
21
21
|
prompt.register(prompts.git);
|
|
22
22
|
await prompt.show({ enabled: false, prompt: 'push', task });
|
|
23
23
|
assert.equal(promptMock.mock.callCount(), 0);
|
|
@@ -27,7 +27,7 @@ test('should not create prompt if disabled', async t => {
|
|
|
27
27
|
test('should create prompt', async t => {
|
|
28
28
|
const promptMock = t.mock.fn(yes);
|
|
29
29
|
const inquirer = { prompt: promptMock };
|
|
30
|
-
const prompt = factory(Prompt, { container: { inquirer } });
|
|
30
|
+
const prompt = await factory(Prompt, { container: { inquirer } });
|
|
31
31
|
prompt.register(prompts.git);
|
|
32
32
|
await prompt.show({ prompt: 'push' });
|
|
33
33
|
assert.equal(promptMock.mock.callCount(), 1);
|
|
@@ -57,9 +57,10 @@ test('should create prompt', async t => {
|
|
|
57
57
|
git: { tagName: 'v${version}' },
|
|
58
58
|
npm: { name: 'my-pkg', tag: 'next' }
|
|
59
59
|
});
|
|
60
|
+
await config.init();
|
|
60
61
|
config.setContext({ version: '1.0.0', tagName: '1.0.0' });
|
|
61
62
|
const inquirer = { prompt: promptMock };
|
|
62
|
-
const p = factory(Prompt, { container: { inquirer } });
|
|
63
|
+
const p = await factory(Prompt, { container: { inquirer } });
|
|
63
64
|
p.register(prompts[namespace], namespace);
|
|
64
65
|
await p.show({ namespace, prompt, context: config.getContext() });
|
|
65
66
|
assert.equal(promptMock.mock.callCount(), 1);
|
|
@@ -71,7 +72,7 @@ test('should execute task after positive answer', async t => {
|
|
|
71
72
|
const task = t.mock.fn();
|
|
72
73
|
const promptMock = t.mock.fn(yes);
|
|
73
74
|
const inquirer = { prompt: promptMock };
|
|
74
|
-
const prompt = factory(Prompt, { container: { inquirer } });
|
|
75
|
+
const prompt = await factory(Prompt, { container: { inquirer } });
|
|
75
76
|
prompt.register(prompts.git);
|
|
76
77
|
await prompt.show({ prompt: 'push', task });
|
|
77
78
|
assert.equal(promptMock.mock.callCount(), 1);
|
|
@@ -83,7 +84,7 @@ test('should not execute task after negative answer', async t => {
|
|
|
83
84
|
const task = t.mock.fn();
|
|
84
85
|
const promptMock = t.mock.fn(no);
|
|
85
86
|
const inquirer = { prompt: promptMock };
|
|
86
|
-
const prompt = factory(Prompt, { container: { inquirer } });
|
|
87
|
+
const prompt = await factory(Prompt, { container: { inquirer } });
|
|
87
88
|
prompt.register(prompts.git);
|
|
88
89
|
await prompt.show({ prompt: 'push', task });
|
|
89
90
|
assert.equal(promptMock.mock.callCount(), 1);
|
package/test/shell.js
CHANGED
|
@@ -4,10 +4,10 @@ import assert from 'node:assert/strict';
|
|
|
4
4
|
import Shell from '../lib/shell.js';
|
|
5
5
|
import { factory } from './util/index.js';
|
|
6
6
|
|
|
7
|
-
describe('shell', () => {
|
|
7
|
+
describe('shell', async () => {
|
|
8
8
|
const cwd = childProcess.execSync('pwd', { encoding: 'utf8' }).trim();
|
|
9
9
|
|
|
10
|
-
const shell = factory(Shell);
|
|
10
|
+
const shell = await factory(Shell);
|
|
11
11
|
|
|
12
12
|
test('exec', async () => {
|
|
13
13
|
assert.equal(await shell.exec('echo bar'), 'bar');
|
|
@@ -29,7 +29,7 @@ describe('shell', () => {
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
test('exec (dry-run/read-only)', async () => {
|
|
32
|
-
const shell = factory(Shell, { options: { 'dry-run': true } });
|
|
32
|
+
const shell = await factory(Shell, { options: { 'dry-run': true } });
|
|
33
33
|
{
|
|
34
34
|
const actual = await shell.exec('pwd', { write: false });
|
|
35
35
|
assert.equal(actual, cwd);
|
|
@@ -46,7 +46,7 @@ describe('shell', () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
test('exec (verbose)', async () => {
|
|
49
|
-
const shell = factory(Shell, { options: { verbose: true } });
|
|
49
|
+
const shell = await factory(Shell, { options: { verbose: true } });
|
|
50
50
|
const actual = await shell.exec('echo foo');
|
|
51
51
|
assert.equal(shell.log.exec.mock.calls[0].arguments[0], 'echo foo');
|
|
52
52
|
assert.equal(shell.log.exec.mock.callCount(), 1);
|
|
@@ -56,7 +56,7 @@ describe('shell', () => {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
test('should cache results of command execution', async () => {
|
|
59
|
-
const shell = factory(Shell);
|
|
59
|
+
const shell = await factory(Shell);
|
|
60
60
|
const result1 = await shell.exec('echo foo');
|
|
61
61
|
const result2 = await shell.exec('echo foo');
|
|
62
62
|
assert(result1 === result2);
|
package/test/spinner.js
CHANGED
|
@@ -3,12 +3,15 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import Spinner from '../lib/spinner.js';
|
|
4
4
|
import Config from '../lib/config.js';
|
|
5
5
|
|
|
6
|
-
const getConfig = options => {
|
|
6
|
+
const getConfig = async options => {
|
|
7
7
|
const testConfig = {
|
|
8
8
|
ci: false,
|
|
9
9
|
config: false
|
|
10
10
|
};
|
|
11
|
-
|
|
11
|
+
const config = new Config(Object.assign({}, testConfig, options));
|
|
12
|
+
await config.init();
|
|
13
|
+
|
|
14
|
+
return config;
|
|
12
15
|
};
|
|
13
16
|
|
|
14
17
|
test('should not show spinner and not execute task if disabled', async t => {
|
|
@@ -24,7 +27,7 @@ test('should show spinner and run task by default', async t => {
|
|
|
24
27
|
const ora = t.mock.fn();
|
|
25
28
|
const task = t.mock.fn(() => Promise.resolve());
|
|
26
29
|
const label = 'foo';
|
|
27
|
-
const config = getConfig({ ci: true });
|
|
30
|
+
const config = await getConfig({ ci: true });
|
|
28
31
|
const spinner = new Spinner({ container: { ora, config } });
|
|
29
32
|
await spinner.show({ task, label });
|
|
30
33
|
assert.equal(task.mock.callCount(), 1);
|
|
@@ -36,7 +39,7 @@ test('should show spinner and run task by default', async t => {
|
|
|
36
39
|
test('should run task, but not show spinner if interactive', async t => {
|
|
37
40
|
const ora = t.mock.fn();
|
|
38
41
|
const task = t.mock.fn(() => Promise.resolve());
|
|
39
|
-
const config = getConfig({ ci: false });
|
|
42
|
+
const config = await getConfig({ ci: false });
|
|
40
43
|
const spinner = new Spinner({ container: { ora, config } });
|
|
41
44
|
await spinner.show({ task });
|
|
42
45
|
assert.equal(task.mock.callCount(), 1);
|
|
@@ -46,7 +49,7 @@ test('should run task, but not show spinner if interactive', async t => {
|
|
|
46
49
|
test('should run task and show spinner if interactive, but external', async t => {
|
|
47
50
|
const ora = t.mock.fn();
|
|
48
51
|
const task = t.mock.fn(() => Promise.resolve());
|
|
49
|
-
const config = getConfig({ ci: false });
|
|
52
|
+
const config = await getConfig({ ci: false });
|
|
50
53
|
const spinner = new Spinner({ container: { ora, config } });
|
|
51
54
|
await spinner.show({ task, external: true });
|
|
52
55
|
assert.equal(task.mock.callCount(), 1);
|
|
@@ -14,13 +14,10 @@ import { interceptPublish as interceptGitLabPublish } from './stub/gitlab.js';
|
|
|
14
14
|
import { interceptCreate as interceptGitHubCreate } from './stub/github.js';
|
|
15
15
|
import { factory, LogStub, SpinnerStub } from './util/index.js';
|
|
16
16
|
import { mockFetch } from './util/mock.js';
|
|
17
|
+
import { createTarBlobByRawContents } from './util/fetch.js';
|
|
17
18
|
|
|
18
19
|
describe('tasks.interactive', () => {
|
|
19
|
-
const [mocker, github, gitlab
|
|
20
|
-
'https://api.github.com',
|
|
21
|
-
'https://gitlab.com/api/v4',
|
|
22
|
-
'https://raw.githubusercontent.com'
|
|
23
|
-
]);
|
|
20
|
+
const [mocker, github, gitlab] = mockFetch(['https://api.github.com', 'https://gitlab.com/api/v4']);
|
|
24
21
|
|
|
25
22
|
before(() => {
|
|
26
23
|
mocker.mockGlobal();
|
|
@@ -96,18 +93,28 @@ describe('tasks.interactive', () => {
|
|
|
96
93
|
|
|
97
94
|
const validationExtendedConfiguration = "echo 'extended_configuration'";
|
|
98
95
|
|
|
99
|
-
|
|
96
|
+
github.head('/repos/release-it/release-it-configuration/tarball/main', {
|
|
100
97
|
status: 200,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
headers: {}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
github.get('/repos/release-it/release-it-configuration/tarball/main', {
|
|
102
|
+
status: 200,
|
|
103
|
+
body: await new Response(
|
|
104
|
+
createTarBlobByRawContents({
|
|
105
|
+
'.release-it.json': JSON.stringify({
|
|
106
|
+
hooks: {
|
|
107
|
+
'before:init': validationExtendedConfiguration
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
).arrayBuffer()
|
|
106
112
|
});
|
|
107
113
|
|
|
108
114
|
const config = {
|
|
109
|
-
$schema: 'https://unpkg.com/release-it@
|
|
110
|
-
extends: 'github:release-it/release-it-configuration'
|
|
115
|
+
$schema: 'https://unpkg.com/release-it@19/schema/release-it.json',
|
|
116
|
+
extends: 'github:release-it/release-it-configuration',
|
|
117
|
+
config: true
|
|
111
118
|
};
|
|
112
119
|
|
|
113
120
|
const container = getContainer(config);
|
|
@@ -129,7 +136,7 @@ describe('tasks.interactive', () => {
|
|
|
129
136
|
renameSync('.git', 'foo');
|
|
130
137
|
|
|
131
138
|
const config = {
|
|
132
|
-
$schema: 'https://unpkg.com/release-it@
|
|
139
|
+
$schema: 'https://unpkg.com/release-it@19/schema/release-it.json',
|
|
133
140
|
extends: false
|
|
134
141
|
};
|
|
135
142
|
|
|
@@ -213,7 +220,7 @@ describe('tasks.interactive', () => {
|
|
|
213
220
|
childProcess.execSync('git tag 1.0.0', execOpts);
|
|
214
221
|
const sha = gitAdd('line', 'file', 'More file');
|
|
215
222
|
|
|
216
|
-
const git = factory(Git);
|
|
223
|
+
const git = await factory(Git);
|
|
217
224
|
const ref = (await git.getBranchName()) ?? 'HEAD';
|
|
218
225
|
|
|
219
226
|
interceptGitHubCreate(github, {
|
package/test/tasks.js
CHANGED
|
@@ -243,7 +243,7 @@ describe('tasks', () => {
|
|
|
243
243
|
childProcess.execSync('git tag v1.0.0', execOpts);
|
|
244
244
|
const sha = gitAdd('line', 'file', 'More file');
|
|
245
245
|
childProcess.execSync('git push --follow-tags', execOpts);
|
|
246
|
-
const git = factory(Git);
|
|
246
|
+
const git = await factory(Git);
|
|
247
247
|
const ref = (await git.getBranchName()) ?? 'HEAD';
|
|
248
248
|
|
|
249
249
|
interceptGitHubAuthentication(github);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { create as createTar } from 'tar';
|
|
3
|
+
import { appendFile, mkTmpDir } from './helpers.js';
|
|
4
|
+
|
|
5
|
+
export function createTarBlob(dir) {
|
|
6
|
+
const stream = new Readable({
|
|
7
|
+
read() {}
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
createTar(
|
|
11
|
+
{
|
|
12
|
+
gzip: true,
|
|
13
|
+
portable: true,
|
|
14
|
+
sync: false,
|
|
15
|
+
cwd: dir
|
|
16
|
+
},
|
|
17
|
+
['.']
|
|
18
|
+
)
|
|
19
|
+
.on('data', chunk => stream.push(chunk))
|
|
20
|
+
.on('end', () => stream.push(null));
|
|
21
|
+
|
|
22
|
+
return stream;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function createTarBlobByRawContents(contents) {
|
|
26
|
+
const dir = mkTmpDir();
|
|
27
|
+
for (const [key, value] of Object.entries(contents)) {
|
|
28
|
+
appendFile(value, key, dir);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return createTarBlob(dir);
|
|
32
|
+
}
|
package/test/util/helpers.js
CHANGED
|
@@ -12,13 +12,7 @@ const mkTmpDir = () => {
|
|
|
12
12
|
const readFile = file => promises.readFile(path.resolve(file), 'utf8');
|
|
13
13
|
|
|
14
14
|
const gitAdd = (content, filePath, message) => {
|
|
15
|
-
|
|
16
|
-
pathSegments.pop();
|
|
17
|
-
if (pathSegments.length) {
|
|
18
|
-
mkdirSync(path.resolve(pathSegments.join('/')), { mode: parseInt('0777', 8), recursive: true });
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
appendFileSync(filePath, content);
|
|
15
|
+
appendFile(content, filePath);
|
|
22
16
|
childProcess.execSync(`git add ${filePath}`, execOpts);
|
|
23
17
|
const stdout = childProcess.execSync(`git commit -m "${message}"`, { encoding: 'utf-8' });
|
|
24
18
|
const match = stdout.match(/\[.+([a-z0-9]{7})\]/);
|
|
@@ -32,4 +26,15 @@ const getArgs = (fn, prefix) =>
|
|
|
32
26
|
.filter(cmd => cmd.startsWith(prefix))
|
|
33
27
|
.map(cmd => cmd.trim());
|
|
34
28
|
|
|
35
|
-
|
|
29
|
+
const appendFile = (content, filePath, cwd) => {
|
|
30
|
+
filePath = path.resolve(cwd ?? '', filePath);
|
|
31
|
+
const dirPath = path.dirname(filePath);
|
|
32
|
+
|
|
33
|
+
if (dirPath) {
|
|
34
|
+
mkdirSync(dirPath, { mode: parseInt('0777', 8), recursive: true });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
appendFileSync(filePath, content);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { mkTmpDir, readFile, gitAdd, getArgs, appendFile };
|
package/test/util/index.js
CHANGED
|
@@ -36,11 +36,12 @@ export class SpinnerStub {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
export let factory = (Definition, { namespace, options = {}, container = {} } = {}) => {
|
|
39
|
+
export let factory = async (Definition, { namespace, options = {}, container = {} } = {}) => {
|
|
40
40
|
options = Object.assign({}, { ci: true, verbose: false, 'dry-run': false, debug: false }, options);
|
|
41
41
|
const ns = namespace || Definition.name.toLowerCase();
|
|
42
42
|
container.config = container.config || new Config(Object.assign({ config: false }, options));
|
|
43
43
|
container.log = new LogStub();
|
|
44
|
+
await container.config.init();
|
|
44
45
|
|
|
45
46
|
container.spinner = new SpinnerStub();
|
|
46
47
|
container.shell = container.shell || new ShellStub({ container });
|