release-it 15.0.0-esm.4 → 15.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 +24 -19
- package/config/release-it.json +2 -0
- package/lib/config.js +7 -15
- package/lib/index.js +27 -33
- package/lib/log.js +1 -1
- package/lib/plugin/GitBase.js +1 -1
- package/lib/plugin/GitRelease.js +1 -1
- package/lib/plugin/Plugin.js +1 -1
- package/lib/plugin/factory.js +5 -5
- package/lib/plugin/git/Git.js +3 -2
- package/lib/plugin/github/GitHub.js +6 -5
- package/lib/plugin/gitlab/GitLab.js +68 -14
- package/lib/plugin/npm/npm.js +3 -2
- package/lib/shell.js +2 -2
- package/lib/util.js +2 -2
- package/package.json +23 -30
- package/test/config.js +19 -26
- package/test/git.init.js +32 -7
- package/test/git.js +5 -2
- package/test/github.js +14 -15
- package/test/gitlab.js +69 -18
- package/test/log.js +1 -1
- package/test/npm.js +12 -3
- package/test/plugins.js +33 -21
- package/test/spinner.js +1 -2
- package/test/stub/config/default/.release-it.json +5 -0
- package/test/stub/config/invalid-config-rc +1 -0
- package/test/stub/config/invalid-config-txt +2 -0
- package/test/stub/config/merge/.release-it.json +5 -0
- package/test/stub/config/merge/package.json +7 -0
- package/test/stub/config/toml/.release-it.toml +2 -0
- package/test/stub/config/yaml/.release-it.yaml +2 -0
- package/test/stub/config/yml/.release-it.yml +2 -0
- package/test/stub/github.js +2 -2
- package/test/stub/gitlab.js +15 -7
- package/test/stub/shell.js +2 -2
- package/test/tasks.interactive.js +2 -3
- package/test/tasks.js +3 -4
- package/test/util/helpers.js +6 -6
- package/test/util/index.js +2 -1
- package/test/utils.js +1 -1
- package/config/.codecov.yml +0 -5
- package/config/deprecated.json +0 -1
- package/lib/deprecated.js +0 -22
- package/lib/metrics.js +0 -76
- package/test/deprecated.js +0 -11
- package/test/metrics.js +0 -17
package/test/config.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import mock from 'mock-fs';
|
|
3
2
|
import isCI from 'is-ci';
|
|
4
3
|
import Config from '../lib/config.js';
|
|
5
4
|
import { readJSON } from '../lib/util.js';
|
|
6
5
|
|
|
7
6
|
const defaultConfig = readJSON(new URL('../config/release-it.json', import.meta.url));
|
|
7
|
+
const projectConfig = readJSON(new URL('../.release-it.json', import.meta.url));
|
|
8
8
|
|
|
9
9
|
const localConfig = { github: { release: true } };
|
|
10
10
|
|
|
11
|
-
test
|
|
12
|
-
|
|
13
|
-
test('should contain default values', t => {
|
|
14
|
-
mock({ '../.release-it.json': JSON.stringify(localConfig) });
|
|
11
|
+
test("should read this project's own configuration", t => {
|
|
15
12
|
const config = new Config();
|
|
16
13
|
t.deepEqual(config.constructorConfig, {});
|
|
14
|
+
t.deepEqual(config.localConfig, projectConfig);
|
|
15
|
+
t.deepEqual(config.defaultConfig, defaultConfig);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('should contain default values', t => {
|
|
19
|
+
const config = new Config({ configDir: './test/stub/config/default' });
|
|
20
|
+
t.deepEqual(config.constructorConfig, { configDir: './test/stub/config/default' });
|
|
17
21
|
t.deepEqual(config.localConfig, localConfig);
|
|
18
22
|
t.deepEqual(config.defaultConfig, defaultConfig);
|
|
19
|
-
mock.restore();
|
|
20
23
|
});
|
|
21
24
|
|
|
22
25
|
test('should merge provided options', t => {
|
|
23
|
-
mock({
|
|
24
|
-
'package.json': JSON.stringify({ 'release-it': { git: { push: false } } }),
|
|
25
|
-
'../.release-it.json': JSON.stringify(localConfig)
|
|
26
|
-
});
|
|
27
26
|
const config = new Config({
|
|
27
|
+
configDir: './test/stub/config/merge',
|
|
28
28
|
increment: '1.0.0',
|
|
29
29
|
verbose: true,
|
|
30
30
|
github: {
|
|
@@ -37,7 +37,6 @@ test('should merge provided options', t => {
|
|
|
37
37
|
t.is(options.increment, '1.0.0');
|
|
38
38
|
t.is(options.git.push, false);
|
|
39
39
|
t.is(options.github.release, true);
|
|
40
|
-
mock.restore();
|
|
41
40
|
});
|
|
42
41
|
|
|
43
42
|
test('should set CI mode', t => {
|
|
@@ -57,24 +56,18 @@ test('should override --no-npm.publish', t => {
|
|
|
57
56
|
});
|
|
58
57
|
|
|
59
58
|
test('should read YAML config', t => {
|
|
60
|
-
|
|
61
|
-
const config = new Config({ config: '.release-it.yaml' });
|
|
59
|
+
const config = new Config({ configDir: './test/stub/config/yaml' });
|
|
62
60
|
t.deepEqual(config.options.foo, { bar: 1 });
|
|
63
|
-
mock.restore();
|
|
64
61
|
});
|
|
65
62
|
|
|
66
63
|
test('should read YML config', t => {
|
|
67
|
-
|
|
68
|
-
const config = new Config({ config: '.release-it.yml' });
|
|
64
|
+
const config = new Config({ configDir: './test/stub/config/yml' });
|
|
69
65
|
t.deepEqual(config.options.foo, { bar: 1 });
|
|
70
|
-
mock.restore();
|
|
71
66
|
});
|
|
72
67
|
|
|
73
68
|
test('should read TOML config', t => {
|
|
74
|
-
|
|
75
|
-
const config = new Config({ config: '.release-it.toml' });
|
|
69
|
+
const config = new Config({ configDir: './test/stub/config/toml' });
|
|
76
70
|
t.deepEqual(config.options.foo, { bar: 1 });
|
|
77
|
-
mock.restore();
|
|
78
71
|
});
|
|
79
72
|
|
|
80
73
|
test('should throw if provided config file is not found', t => {
|
|
@@ -82,15 +75,15 @@ test('should throw if provided config file is not found', t => {
|
|
|
82
75
|
});
|
|
83
76
|
|
|
84
77
|
test('should throw if provided config file is invalid (cosmiconfig exception)', t => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
t.throws(() => new Config({ config: './test/stub/config/invalid-config-txt' }), {
|
|
79
|
+
message: /Invalid configuration file at/
|
|
80
|
+
});
|
|
88
81
|
});
|
|
89
82
|
|
|
90
83
|
test('should throw if provided config file is invalid (no object)', t => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
t.throws(() => new Config({ config: './test/stub/config/invalid-config-rc' }), {
|
|
85
|
+
message: /Invalid configuration file at/
|
|
86
|
+
});
|
|
94
87
|
});
|
|
95
88
|
|
|
96
89
|
test('should not set default increment (for CI mode)', t => {
|
package/test/git.init.js
CHANGED
|
@@ -26,6 +26,19 @@ test.serial('should throw if on wrong branch', async t => {
|
|
|
26
26
|
await t.throwsAsync(gitClient.init(), { message: /^Must be on branch dev/ });
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
test.serial('should not throw if required branch matches', async t => {
|
|
30
|
+
const options = { git: { requireBranch: 'ma?*' } };
|
|
31
|
+
const gitClient = factory(Git, { options });
|
|
32
|
+
await t.notThrowsAsync(gitClient.init());
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test.serial('should not throw if one of required branch matches', async t => {
|
|
36
|
+
const options = { git: { requireBranch: ['release/*', 'hotfix/*'] } };
|
|
37
|
+
const gitClient = factory(Git, { options });
|
|
38
|
+
sh.exec('git checkout -b release/v1');
|
|
39
|
+
await t.notThrowsAsync(gitClient.init());
|
|
40
|
+
});
|
|
41
|
+
|
|
29
42
|
test.serial('should throw if there is no remote Git url', async t => {
|
|
30
43
|
const gitClient = factory(Git, { options: { git } });
|
|
31
44
|
sh.exec('git remote remove origin');
|
|
@@ -143,19 +156,13 @@ test.serial('should get the latest custom tag after fetch when tagName is config
|
|
|
143
156
|
test.serial('should get the latest tag based on tagMatch', async t => {
|
|
144
157
|
const shell = factory(Shell);
|
|
145
158
|
const gitClient = factory(Git, {
|
|
146
|
-
options: { git: { tagMatch: '[0-9][0-9]
|
|
159
|
+
options: { git: { tagMatch: '[0-9][0-9]\\.[0-1][0-9]\\.[0-9]*' } },
|
|
147
160
|
container: { shell }
|
|
148
161
|
});
|
|
149
|
-
const { bare, target } = t.context;
|
|
150
|
-
const other = mkTmpDir();
|
|
151
|
-
sh.exec('git push');
|
|
152
|
-
sh.exec(`git clone ${bare} ${other}`);
|
|
153
|
-
sh.pushd('-q', other);
|
|
154
162
|
sh.exec('git tag 1.0.0');
|
|
155
163
|
sh.exec('git tag 21.04.3');
|
|
156
164
|
sh.exec('git tag 1.0.1');
|
|
157
165
|
sh.exec('git push --tags');
|
|
158
|
-
sh.pushd('-q', target);
|
|
159
166
|
await gitClient.init();
|
|
160
167
|
t.is(gitClient.config.getContext('latestTag'), '21.04.3');
|
|
161
168
|
});
|
|
@@ -169,3 +176,21 @@ test.serial('should generate correct changelog', async t => {
|
|
|
169
176
|
const changelog = await gitClient.getChangelog();
|
|
170
177
|
t.regex(changelog, /\* Add file \(\w{7}\)\n\* Add file \(\w{7}\)/);
|
|
171
178
|
});
|
|
179
|
+
|
|
180
|
+
test.serial('should get the full changelog since latest major tag', async t => {
|
|
181
|
+
const shell = factory(Shell);
|
|
182
|
+
const gitClient = factory(Git, {
|
|
183
|
+
options: { git: { tagMatch: '[0-9]\\.[0-9]\\.[0-9]', changelog: git.changelog } },
|
|
184
|
+
container: { shell }
|
|
185
|
+
});
|
|
186
|
+
sh.exec('git tag 1.0.0');
|
|
187
|
+
gitAdd('line', 'file', 'Add file');
|
|
188
|
+
sh.exec('git tag 2.0.0-rc.0');
|
|
189
|
+
gitAdd('line', 'file', 'Add file');
|
|
190
|
+
sh.exec('git tag 2.0.0-rc.1');
|
|
191
|
+
gitAdd('line', 'file', 'Add file');
|
|
192
|
+
await gitClient.init();
|
|
193
|
+
t.is(gitClient.config.getContext('latestTag'), '1.0.0');
|
|
194
|
+
const changelog = await gitClient.getChangelog();
|
|
195
|
+
t.regex(changelog, /\* Add file \(\w{7}\)\n\* Add file \(\w{7}\)\n\* Add file \(\w{7}\)/);
|
|
196
|
+
});
|
package/test/git.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EOL } from 'os';
|
|
1
|
+
import { EOL } from 'node:os';
|
|
2
2
|
import test from 'ava';
|
|
3
3
|
import sinon from 'sinon';
|
|
4
4
|
import sh from 'shelljs';
|
|
@@ -228,7 +228,10 @@ test.serial('should push to remote name (not "origin")', async t => {
|
|
|
228
228
|
gitAdd('line', 'file', 'Add file');
|
|
229
229
|
await gitClient.push();
|
|
230
230
|
t.deepEqual(spy.lastCall.args[0], ['git', 'push', '--set-upstream', 'upstream', 'foo']);
|
|
231
|
-
t.regex(
|
|
231
|
+
t.regex(
|
|
232
|
+
await spy.lastCall.returnValue,
|
|
233
|
+
/branch .?foo.? set up to track (remote branch .?foo.? from .?upstream.?|.?upstream\/foo.?)/i
|
|
234
|
+
);
|
|
232
235
|
}
|
|
233
236
|
spy.restore();
|
|
234
237
|
});
|
package/test/github.js
CHANGED
|
@@ -91,7 +91,7 @@ test('should create a pre-release and draft release notes', async t => {
|
|
|
91
91
|
|
|
92
92
|
interceptAuthentication();
|
|
93
93
|
interceptCollaborator();
|
|
94
|
-
interceptCreate({ body: { tag_name: '2.0.2', name: 'Release 2.0.2',
|
|
94
|
+
interceptCreate({ body: { tag_name: '2.0.2', name: 'Release 2.0.2', prerelease: true, draft: true } });
|
|
95
95
|
|
|
96
96
|
await runTasks(github);
|
|
97
97
|
|
|
@@ -101,7 +101,7 @@ test('should create a pre-release and draft release notes', async t => {
|
|
|
101
101
|
exec.restore();
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
test('should create auto
|
|
104
|
+
test('should create auto-generated release notes', async t => {
|
|
105
105
|
const options = {
|
|
106
106
|
git,
|
|
107
107
|
github: {
|
|
@@ -118,9 +118,7 @@ test('should create auto generated release notes', async t => {
|
|
|
118
118
|
|
|
119
119
|
interceptAuthentication();
|
|
120
120
|
interceptCollaborator();
|
|
121
|
-
interceptCreate({
|
|
122
|
-
body: { tag_name: '2.0.2', name: 'Release 2.0.2', draft: false, prerelease: false, generate_release_notes: true }
|
|
123
|
-
});
|
|
121
|
+
interceptCreate({ body: { tag_name: '2.0.2', name: 'Release 2.0.2', generate_release_notes: true, body: '' } });
|
|
124
122
|
|
|
125
123
|
await runTasks(github);
|
|
126
124
|
|
|
@@ -220,7 +218,7 @@ test('should release to enterprise host', async t => {
|
|
|
220
218
|
});
|
|
221
219
|
|
|
222
220
|
test('should release to alternative host and proxy', async t => {
|
|
223
|
-
const remote = { api: 'https://
|
|
221
|
+
const remote = { api: 'https://custom.example.org/api/v3', host: 'custom.example.org' };
|
|
224
222
|
interceptAuthentication(remote);
|
|
225
223
|
interceptCollaborator(remote);
|
|
226
224
|
interceptCreate(Object.assign({ body: { tag_name: '1.0.1' } }, remote));
|
|
@@ -228,8 +226,8 @@ test('should release to alternative host and proxy', async t => {
|
|
|
228
226
|
git,
|
|
229
227
|
github: {
|
|
230
228
|
tokenRef,
|
|
231
|
-
pushRepo: `git://
|
|
232
|
-
host: '
|
|
229
|
+
pushRepo: `git://custom.example.org:user/repo`,
|
|
230
|
+
host: 'custom.example.org',
|
|
233
231
|
proxy: 'http://proxy:8080'
|
|
234
232
|
}
|
|
235
233
|
};
|
|
@@ -242,25 +240,26 @@ test('should release to alternative host and proxy', async t => {
|
|
|
242
240
|
|
|
243
241
|
const { isReleased, releaseUrl } = github.getContext();
|
|
244
242
|
t.true(isReleased);
|
|
245
|
-
t.is(releaseUrl, `https://
|
|
243
|
+
t.is(releaseUrl, `https://custom.example.org/user/repo/releases/tag/1.0.1`);
|
|
244
|
+
t.is(github.options.proxy, 'http://proxy:8080');
|
|
246
245
|
exec.restore();
|
|
247
246
|
});
|
|
248
247
|
|
|
249
248
|
test('should release to git.pushRepo', async t => {
|
|
250
|
-
const remote = { api: 'https://
|
|
249
|
+
const remote = { api: 'https://custom.example.org/api/v3', host: 'custom.example.org' };
|
|
251
250
|
interceptCreate(Object.assign({ body: { tag_name: '1.0.1' } }, remote));
|
|
252
251
|
const options = { git: { pushRepo: 'upstream', changelog: '' }, github: { tokenRef, skipChecks: true } };
|
|
253
252
|
const github = factory(GitHub, { options });
|
|
254
253
|
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
255
254
|
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
256
255
|
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('1.0.0');
|
|
257
|
-
exec.withArgs('git remote get-url upstream').resolves('https://
|
|
256
|
+
exec.withArgs('git remote get-url upstream').resolves('https://custom.example.org/user/repo');
|
|
258
257
|
|
|
259
258
|
await runTasks(github);
|
|
260
259
|
|
|
261
260
|
const { isReleased, releaseUrl } = github.getContext();
|
|
262
261
|
t.true(isReleased);
|
|
263
|
-
t.is(releaseUrl, 'https://
|
|
262
|
+
t.is(releaseUrl, 'https://custom.example.org/user/repo/releases/tag/1.0.1');
|
|
264
263
|
exec.restore();
|
|
265
264
|
});
|
|
266
265
|
|
|
@@ -402,10 +401,10 @@ test('should generate GitHub web release url for enterprise host', async t => {
|
|
|
402
401
|
const options = {
|
|
403
402
|
git,
|
|
404
403
|
github: {
|
|
405
|
-
pushRepo: 'git://
|
|
404
|
+
pushRepo: 'git://custom.example.org:user/repo',
|
|
406
405
|
release: true,
|
|
407
406
|
web: true,
|
|
408
|
-
host: '
|
|
407
|
+
host: 'custom.example.org',
|
|
409
408
|
releaseName: 'The Launch',
|
|
410
409
|
releaseNotes: 'echo It happened'
|
|
411
410
|
}
|
|
@@ -421,7 +420,7 @@ test('should generate GitHub web release url for enterprise host', async t => {
|
|
|
421
420
|
t.true(isReleased);
|
|
422
421
|
t.is(
|
|
423
422
|
releaseUrl,
|
|
424
|
-
'https://
|
|
423
|
+
'https://custom.example.org/user/repo/releases/new?tag=2.0.2&title=The+Launch&body=It+happened&prerelease=false'
|
|
425
424
|
);
|
|
426
425
|
exec.restore();
|
|
427
426
|
});
|
package/test/gitlab.js
CHANGED
|
@@ -6,9 +6,9 @@ import { factory, runTasks } from './util/index.js';
|
|
|
6
6
|
import {
|
|
7
7
|
interceptUser,
|
|
8
8
|
interceptCollaborator,
|
|
9
|
-
interceptCollaboratorFallback,
|
|
10
9
|
interceptPublish,
|
|
11
|
-
interceptAsset
|
|
10
|
+
interceptAsset,
|
|
11
|
+
interceptMilestones
|
|
12
12
|
} from './stub/gitlab.js';
|
|
13
13
|
|
|
14
14
|
const tokenHeader = 'Private-Token';
|
|
@@ -55,7 +55,8 @@ test.serial('should upload assets and release', async t => {
|
|
|
55
55
|
release: true,
|
|
56
56
|
releaseName: 'Release ${version}',
|
|
57
57
|
releaseNotes: 'echo Custom notes',
|
|
58
|
-
assets: 'test/resources/file-v${version}.txt'
|
|
58
|
+
assets: 'test/resources/file-v${version}.txt',
|
|
59
|
+
milestones: ['${version}', '${latestVersion} UAT']
|
|
59
60
|
}
|
|
60
61
|
};
|
|
61
62
|
const gitlab = factory(GitLab, { options });
|
|
@@ -63,6 +64,26 @@ test.serial('should upload assets and release', async t => {
|
|
|
63
64
|
|
|
64
65
|
interceptUser();
|
|
65
66
|
interceptCollaborator();
|
|
67
|
+
interceptMilestones({
|
|
68
|
+
query: { title: '2.0.1' },
|
|
69
|
+
milestones: [
|
|
70
|
+
{
|
|
71
|
+
id: 17,
|
|
72
|
+
iid: 3,
|
|
73
|
+
title: '2.0.1'
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
interceptMilestones({
|
|
78
|
+
query: { title: '2.0.0 UAT' },
|
|
79
|
+
milestones: [
|
|
80
|
+
{
|
|
81
|
+
id: 42,
|
|
82
|
+
iid: 4,
|
|
83
|
+
title: '2.0.0 UAT'
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
});
|
|
66
87
|
interceptAsset();
|
|
67
88
|
interceptPublish({
|
|
68
89
|
body: {
|
|
@@ -76,7 +97,8 @@ test.serial('should upload assets and release', async t => {
|
|
|
76
97
|
url: `${pushRepo}/uploads/7e8bec1fe27cc46a4bc6a91b9e82a07c/file-v2.0.1.txt`
|
|
77
98
|
}
|
|
78
99
|
]
|
|
79
|
-
}
|
|
100
|
+
},
|
|
101
|
+
milestones: ['2.0.1', '2.0.0 UAT']
|
|
80
102
|
}
|
|
81
103
|
});
|
|
82
104
|
|
|
@@ -88,6 +110,41 @@ test.serial('should upload assets and release', async t => {
|
|
|
88
110
|
t.is(releaseUrl, `${pushRepo}/-/releases`);
|
|
89
111
|
});
|
|
90
112
|
|
|
113
|
+
test.serial('should throw when release milestone is missing', async t => {
|
|
114
|
+
const pushRepo = 'https://gitlab.com/user/repo';
|
|
115
|
+
const options = {
|
|
116
|
+
git: { pushRepo },
|
|
117
|
+
gitlab: {
|
|
118
|
+
tokenRef,
|
|
119
|
+
release: true,
|
|
120
|
+
milestones: ['${version}', '${latestVersion} UAT']
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const gitlab = factory(GitLab, { options });
|
|
124
|
+
sinon.stub(gitlab, 'getLatestVersion').resolves('2.0.0');
|
|
125
|
+
|
|
126
|
+
interceptUser();
|
|
127
|
+
interceptCollaborator();
|
|
128
|
+
interceptMilestones({
|
|
129
|
+
query: { title: '2.0.1' },
|
|
130
|
+
milestones: [
|
|
131
|
+
{
|
|
132
|
+
id: 17,
|
|
133
|
+
iid: 3,
|
|
134
|
+
title: '2.0.1'
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
});
|
|
138
|
+
interceptMilestones({
|
|
139
|
+
query: { title: '2.0.0 UAT' },
|
|
140
|
+
milestones: []
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
await t.throwsAsync(runTasks(gitlab), {
|
|
144
|
+
message: /^Missing one or more milestones in GitLab. Creating a GitLab release will fail./
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
91
148
|
test.serial('should release to self-managed host', async t => {
|
|
92
149
|
const host = 'https://gitlab.example.org';
|
|
93
150
|
const scope = nock(host);
|
|
@@ -162,19 +219,6 @@ test.serial('should throw for insufficient access level', async t => {
|
|
|
162
219
|
await t.throwsAsync(runTasks(gitlab), { message: /^User john is not a collaborator for john\/repo/ });
|
|
163
220
|
});
|
|
164
221
|
|
|
165
|
-
test.serial('should fallback for gitlab < v12.4', async t => {
|
|
166
|
-
const host = 'https://gitlab.com';
|
|
167
|
-
const pushRepo = `${host}/user/repo`;
|
|
168
|
-
const options = { gitlab: { tokenRef, pushRepo, host } };
|
|
169
|
-
const gitlab = factory(GitLab, { options });
|
|
170
|
-
const scope = nock(host);
|
|
171
|
-
scope.get(`/api/v4/projects/user%2Frepo/members/all/1`).reply(404);
|
|
172
|
-
interceptUser();
|
|
173
|
-
interceptCollaboratorFallback();
|
|
174
|
-
|
|
175
|
-
await t.notThrowsAsync(gitlab.init());
|
|
176
|
-
});
|
|
177
|
-
|
|
178
222
|
test('should not make requests in dry run', async t => {
|
|
179
223
|
const [host, owner, repo] = ['https://gitlab.example.org', 'user', 'repo'];
|
|
180
224
|
const pushRepo = `${host}/${owner}/${repo}`;
|
|
@@ -195,7 +239,14 @@ test('should not make requests in dry run', async t => {
|
|
|
195
239
|
});
|
|
196
240
|
|
|
197
241
|
test('should skip checks', async t => {
|
|
198
|
-
const options = { gitlab: { tokenRef, skipChecks: true } };
|
|
242
|
+
const options = { gitlab: { tokenRef, skipChecks: true, release: true, milestones: ['v1.0.0'] } };
|
|
199
243
|
const gitlab = factory(GitLab, { options });
|
|
244
|
+
const spy = sinon.spy(gitlab, 'client', ['get']);
|
|
245
|
+
|
|
200
246
|
await t.notThrowsAsync(gitlab.init());
|
|
247
|
+
await t.notThrowsAsync(gitlab.beforeRelease());
|
|
248
|
+
|
|
249
|
+
t.is(spy.get.callCount, 0);
|
|
250
|
+
|
|
251
|
+
t.is(gitlab.log.exec.args.filter(entry => /checkReleaseMilestones/.test(entry[0])).length, 0);
|
|
201
252
|
});
|
package/test/log.js
CHANGED
package/test/npm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import path from 'path';
|
|
1
|
+
import path from 'node:path';
|
|
2
2
|
import test from 'ava';
|
|
3
3
|
import sinon from 'sinon';
|
|
4
4
|
import mock from 'mock-fs';
|
|
@@ -13,9 +13,9 @@ test('should return npm package url', t => {
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
test('should return npm package url (custom registry)', t => {
|
|
16
|
-
const options = { npm: { name: 'my-cool-package', publishConfig: { registry: 'https://
|
|
16
|
+
const options = { npm: { name: 'my-cool-package', publishConfig: { registry: 'https://registry.example.org/' } } };
|
|
17
17
|
const npmClient = factory(npm, { options });
|
|
18
|
-
t.is(npmClient.getPackageUrl(), 'https://
|
|
18
|
+
t.is(npmClient.getPackageUrl(), 'https://registry.example.org/package/my-cool-package');
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
test('should return default tag', async t => {
|
|
@@ -347,3 +347,12 @@ test('should not publish when `npm version` fails', async t => {
|
|
|
347
347
|
|
|
348
348
|
exec.restore();
|
|
349
349
|
});
|
|
350
|
+
|
|
351
|
+
test('should add allow-same-version argument', async t => {
|
|
352
|
+
const options = { npm: { skipChecks: true, allowSameVersion: true } };
|
|
353
|
+
const npmClient = factory(npm, { options });
|
|
354
|
+
const exec = sinon.stub(npmClient.shell, 'exec').resolves();
|
|
355
|
+
await runTasks(npmClient);
|
|
356
|
+
const version = exec.args.filter(arg => arg[0].startsWith('npm version'));
|
|
357
|
+
t.regex(version[0][0], / --allow-same-version/);
|
|
358
|
+
});
|
package/test/plugins.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
1
2
|
import test from 'ava';
|
|
2
3
|
import sh from 'shelljs';
|
|
3
4
|
import sinon from 'sinon';
|
|
@@ -12,16 +13,13 @@ import ContextPlugin from './stub/plugin-context.js';
|
|
|
12
13
|
import { mkTmpDir } from './util/helpers.js';
|
|
13
14
|
import ShellStub from './stub/shell.js';
|
|
14
15
|
|
|
15
|
-
const rootDir = new URL('..', import.meta.url);
|
|
16
|
-
|
|
17
16
|
const noop = Promise.resolve();
|
|
18
17
|
|
|
19
18
|
const sandbox = sinon.createSandbox();
|
|
20
19
|
|
|
21
20
|
const testConfig = {
|
|
22
21
|
ci: true,
|
|
23
|
-
config: false
|
|
24
|
-
'disable-metrics': true
|
|
22
|
+
config: false
|
|
25
23
|
};
|
|
26
24
|
|
|
27
25
|
const log = sandbox.createStubInstance(Log);
|
|
@@ -39,6 +37,11 @@ const getContainer = options => {
|
|
|
39
37
|
};
|
|
40
38
|
};
|
|
41
39
|
|
|
40
|
+
test.serial.before(t => {
|
|
41
|
+
t.timeout(60 * 1000);
|
|
42
|
+
sh.exec('npm link');
|
|
43
|
+
});
|
|
44
|
+
|
|
42
45
|
test.serial.beforeEach(t => {
|
|
43
46
|
const dir = mkTmpDir();
|
|
44
47
|
sh.pushd('-q', dir);
|
|
@@ -50,23 +53,28 @@ test.serial.afterEach(() => {
|
|
|
50
53
|
});
|
|
51
54
|
|
|
52
55
|
test.serial('should instantiate plugins and execute all release-cycle methods', async t => {
|
|
53
|
-
|
|
54
|
-
sh.exec(`npm install ${rootDir}`);
|
|
56
|
+
const { dir } = t.context;
|
|
55
57
|
|
|
56
58
|
const pluginDir = mkTmpDir();
|
|
57
59
|
sh.pushd('-q', pluginDir);
|
|
58
|
-
sh.ShellString(JSON.stringify({ name: 'my-plugin', version: '1.0.0', type: 'module' })).toEnd(
|
|
59
|
-
|
|
60
|
+
sh.ShellString(JSON.stringify({ name: 'my-plugin', version: '1.0.0', type: 'module' })).toEnd(
|
|
61
|
+
join(pluginDir, 'package.json')
|
|
62
|
+
);
|
|
63
|
+
sh.exec(`npm link release-it`);
|
|
60
64
|
const content = "import { Plugin } from 'release-it'; " + MyPlugin.toString() + '; export default MyPlugin;';
|
|
61
|
-
sh.ShellString(content).toEnd('index.js');
|
|
62
|
-
sh.popd();
|
|
65
|
+
sh.ShellString(content).toEnd(join(pluginDir, 'index.js'));
|
|
63
66
|
|
|
67
|
+
sh.pushd('-q', dir);
|
|
64
68
|
sh.mkdir('-p', 'my/plugin');
|
|
65
69
|
sh.pushd('-q', 'my/plugin');
|
|
66
|
-
sh.ShellString(content).toEnd('index.js');
|
|
67
|
-
sh.popd();
|
|
70
|
+
sh.ShellString(content).toEnd(join(dir, 'my', 'plugin', 'index.js'));
|
|
68
71
|
|
|
72
|
+
sh.pushd('-q', dir);
|
|
73
|
+
sh.ShellString(JSON.stringify({ name: 'project', version: '1.0.0', type: 'module' })).toEnd(
|
|
74
|
+
join(dir, 'package.json')
|
|
75
|
+
);
|
|
69
76
|
sh.exec(`npm install ${pluginDir}`);
|
|
77
|
+
sh.exec(`npm link release-it`);
|
|
70
78
|
|
|
71
79
|
const config = {
|
|
72
80
|
plugins: {
|
|
@@ -114,14 +122,16 @@ test.serial('should instantiate plugins and execute all release-cycle methods',
|
|
|
114
122
|
});
|
|
115
123
|
|
|
116
124
|
test.serial('should disable core plugins', async t => {
|
|
117
|
-
|
|
118
|
-
sh.
|
|
119
|
-
const content =
|
|
120
|
-
|
|
125
|
+
const { dir } = t.context;
|
|
126
|
+
sh.ShellString(JSON.stringify({ name: 'project', version: '1.0.0' })).toEnd(join(dir, 'package.json'));
|
|
127
|
+
const content =
|
|
128
|
+
"import { Plugin } from 'release-it'; " + ReplacePlugin.toString() + '; export default ReplacePlugin;';
|
|
129
|
+
sh.ShellString(content).toEnd(join(dir, 'replace-plugin.mjs'));
|
|
130
|
+
sh.exec(`npm link release-it`);
|
|
121
131
|
|
|
122
132
|
const config = {
|
|
123
133
|
plugins: {
|
|
124
|
-
'./replace-plugin.
|
|
134
|
+
'./replace-plugin.mjs': {}
|
|
125
135
|
}
|
|
126
136
|
};
|
|
127
137
|
const container = getContainer(config);
|
|
@@ -137,12 +147,14 @@ test.serial('should disable core plugins', async t => {
|
|
|
137
147
|
});
|
|
138
148
|
|
|
139
149
|
test.serial('should expose context to execute commands', async t => {
|
|
140
|
-
|
|
141
|
-
sh.
|
|
142
|
-
|
|
150
|
+
const { dir } = t.context;
|
|
151
|
+
sh.ShellString(JSON.stringify({ name: 'pkg-name', version: '1.0.0', type: 'module' })).toEnd(
|
|
152
|
+
join(dir, 'package.json')
|
|
153
|
+
);
|
|
143
154
|
const content =
|
|
144
155
|
"import { Plugin } from 'release-it'; " + ContextPlugin.toString() + '; export default ContextPlugin;';
|
|
145
|
-
sh.ShellString(content).toEnd('context-plugin.js');
|
|
156
|
+
sh.ShellString(content).toEnd(join(dir, 'context-plugin.js'));
|
|
157
|
+
sh.exec(`npm link release-it`);
|
|
146
158
|
|
|
147
159
|
const repo = parseGitUrl('https://github.com/user/pkg');
|
|
148
160
|
|
package/test/spinner.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
foo=bar
|
package/test/stub/github.js
CHANGED
|
@@ -44,7 +44,7 @@ const interceptCreate = ({
|
|
|
44
44
|
host = 'github.com',
|
|
45
45
|
owner = 'user',
|
|
46
46
|
project = 'repo',
|
|
47
|
-
body: { tag_name, name = '',
|
|
47
|
+
body: { tag_name, name = '', generate_release_notes = false, body = null, prerelease = false, draft = false }
|
|
48
48
|
} = {}) => {
|
|
49
49
|
nock(api)
|
|
50
50
|
.post(`/repos/${owner}/${project}/releases`, {
|
|
@@ -77,7 +77,7 @@ const interceptUpdate = ({
|
|
|
77
77
|
api = 'https://api.github.com',
|
|
78
78
|
owner = 'user',
|
|
79
79
|
project = 'repo',
|
|
80
|
-
body: { tag_name, name = '', body =
|
|
80
|
+
body: { tag_name, name = '', body = null, prerelease = false, draft = false, generate_release_notes = false }
|
|
81
81
|
} = {}) => {
|
|
82
82
|
nock(api)
|
|
83
83
|
.patch(`/repos/${owner}/${project}/releases/1`, { tag_name, name, body, draft, prerelease, generate_release_notes })
|