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.
Files changed (47) hide show
  1. package/README.md +24 -19
  2. package/config/release-it.json +2 -0
  3. package/lib/config.js +7 -15
  4. package/lib/index.js +27 -33
  5. package/lib/log.js +1 -1
  6. package/lib/plugin/GitBase.js +1 -1
  7. package/lib/plugin/GitRelease.js +1 -1
  8. package/lib/plugin/Plugin.js +1 -1
  9. package/lib/plugin/factory.js +5 -5
  10. package/lib/plugin/git/Git.js +3 -2
  11. package/lib/plugin/github/GitHub.js +6 -5
  12. package/lib/plugin/gitlab/GitLab.js +68 -14
  13. package/lib/plugin/npm/npm.js +3 -2
  14. package/lib/shell.js +2 -2
  15. package/lib/util.js +2 -2
  16. package/package.json +23 -30
  17. package/test/config.js +19 -26
  18. package/test/git.init.js +32 -7
  19. package/test/git.js +5 -2
  20. package/test/github.js +14 -15
  21. package/test/gitlab.js +69 -18
  22. package/test/log.js +1 -1
  23. package/test/npm.js +12 -3
  24. package/test/plugins.js +33 -21
  25. package/test/spinner.js +1 -2
  26. package/test/stub/config/default/.release-it.json +5 -0
  27. package/test/stub/config/invalid-config-rc +1 -0
  28. package/test/stub/config/invalid-config-txt +2 -0
  29. package/test/stub/config/merge/.release-it.json +5 -0
  30. package/test/stub/config/merge/package.json +7 -0
  31. package/test/stub/config/toml/.release-it.toml +2 -0
  32. package/test/stub/config/yaml/.release-it.yaml +2 -0
  33. package/test/stub/config/yml/.release-it.yml +2 -0
  34. package/test/stub/github.js +2 -2
  35. package/test/stub/gitlab.js +15 -7
  36. package/test/stub/shell.js +2 -2
  37. package/test/tasks.interactive.js +2 -3
  38. package/test/tasks.js +3 -4
  39. package/test/util/helpers.js +6 -6
  40. package/test/util/index.js +2 -1
  41. package/test/utils.js +1 -1
  42. package/config/.codecov.yml +0 -5
  43. package/config/deprecated.json +0 -1
  44. package/lib/deprecated.js +0 -22
  45. package/lib/metrics.js +0 -76
  46. package/test/deprecated.js +0 -11
  47. 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.afterEach(() => mock.restore()); // eslint-disable-line ava/no-inline-assertions
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
- mock({ '.release-it.yaml': 'foo:\n bar: 1' });
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
- mock({ '.release-it.yml': 'foo:\n bar: 1' });
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
- mock({ '.release-it.toml': '[foo]\nbar=1' });
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
- mock({ 'invalid-config-txt': 'foo\nbar\baz' });
86
- t.throws(() => new Config({ config: 'invalid-config-txt' }), { message: /Invalid configuration file at/ });
87
- mock.restore();
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
- mock({ 'invalid-config-rc': 'foo=bar' });
92
- t.throws(() => new Config({ config: 'invalid-config-rc' }), { message: /Invalid configuration file at/ });
93
- mock.restore();
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].[0-1][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(await spy.lastCall.returnValue, /Branch .?foo.? set up to track remote branch .?foo.? from .?upstream.?/);
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', body: '', prerelease: true, draft: true } });
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 generated release notes', async t => {
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://my-custom-host.org/api/v3', host: 'my-custom-host.org' };
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://my-custom-host.org:user/repo`,
232
- host: 'my-custom-host.org',
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://my-custom-host.org/user/repo/releases/tag/1.0.1`);
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://my-custom-host.org/api/v3', host: 'my-custom-host.org' };
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://my-custom-host.org/user/repo');
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://my-custom-host.org/user/repo/releases/tag/1.0.1');
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://my-custom-host.org:user/repo',
404
+ pushRepo: 'git://custom.example.org:user/repo',
406
405
  release: true,
407
406
  web: true,
408
- host: 'my-custom-host.org',
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://my-custom-host.org/user/repo/releases/new?tag=2.0.2&title=The+Launch&body=It+happened&prerelease=false'
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
@@ -1,4 +1,4 @@
1
- import { EOL } from 'os';
1
+ import { EOL } from 'node:os';
2
2
  import test from 'ava';
3
3
  import mockStdIo from 'mock-stdio';
4
4
  import stripAnsi from 'strip-ansi';
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://my-registry.com/' } } };
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://my-registry.com/package/my-cool-package');
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
- sh.ShellString(JSON.stringify({ name: 'project', version: '1.0.0', type: 'module' })).toEnd('package.json');
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('package.json');
59
- sh.exec(`npm install ${rootDir}`);
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
- sh.ShellString(JSON.stringify({ name: 'project', version: '1.0.0' })).toEnd('package.json');
118
- sh.exec(`npm install release-it@^14`);
119
- const content = "const { Plugin } = require('release-it'); module.exports = " + ReplacePlugin.toString();
120
- sh.ShellString(content).toEnd('replace-plugin.js');
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.js': {}
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
- sh.ShellString(JSON.stringify({ name: 'pkg-name', version: '1.0.0', type: 'module' })).toEnd('package.json');
141
- sh.exec(`npm install ${rootDir}`);
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
@@ -10,8 +10,7 @@ test.beforeEach(t => {
10
10
  const getConfig = options => {
11
11
  const testConfig = {
12
12
  ci: false,
13
- config: false,
14
- 'disable-metrics': true
13
+ config: false
15
14
  };
16
15
  return new Config(Object.assign({}, testConfig, options));
17
16
  };
@@ -0,0 +1,5 @@
1
+ {
2
+ "github": {
3
+ "release": true
4
+ }
5
+ }
@@ -0,0 +1 @@
1
+ foo=bar
@@ -0,0 +1,2 @@
1
+ foo
2
+ bar\baz
@@ -0,0 +1,5 @@
1
+ {
2
+ "github": {
3
+ "release": true
4
+ }
5
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "release-it": {
3
+ "git": {
4
+ "push": false
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,2 @@
1
+ [foo]
2
+ bar=1
@@ -0,0 +1,2 @@
1
+ foo:
2
+ bar: 1
@@ -0,0 +1,2 @@
1
+ foo:
2
+ bar: 1
@@ -44,7 +44,7 @@ const interceptCreate = ({
44
44
  host = 'github.com',
45
45
  owner = 'user',
46
46
  project = 'repo',
47
- body: { tag_name, name = '', body = '', prerelease = false, draft = false, generate_release_notes = false }
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 = '', prerelease = false, draft = false, generate_release_notes = false }
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 })