release-it 15.0.0-esm.2 → 15.0.0-esm.5

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 (50) hide show
  1. package/README.md +22 -16
  2. package/config/release-it.json +5 -1
  3. package/lib/config.js +7 -15
  4. package/lib/index.js +13 -21
  5. package/lib/log.js +1 -1
  6. package/lib/plugin/GitBase.js +2 -2
  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 +11 -4
  11. package/lib/plugin/github/GitHub.js +59 -15
  12. package/lib/plugin/gitlab/GitLab.js +69 -15
  13. package/lib/plugin/npm/npm.js +3 -2
  14. package/lib/plugin/version/Version.js +5 -5
  15. package/lib/shell.js +3 -3
  16. package/lib/spinner.js +3 -3
  17. package/lib/util.js +2 -2
  18. package/package.json +36 -42
  19. package/test/config.js +21 -28
  20. package/test/git.init.js +32 -7
  21. package/test/git.js +5 -2
  22. package/test/github.js +116 -19
  23. package/test/gitlab.js +69 -18
  24. package/test/log.js +1 -1
  25. package/test/npm.js +12 -3
  26. package/test/plugins.js +34 -22
  27. package/test/spinner.js +8 -11
  28. package/test/stub/config/default/.release-it.json +5 -0
  29. package/test/stub/config/invalid-config-rc +1 -0
  30. package/test/stub/config/invalid-config-txt +2 -0
  31. package/test/stub/config/merge/.release-it.json +5 -0
  32. package/test/stub/config/merge/package.json +7 -0
  33. package/test/stub/config/toml/.release-it.toml +2 -0
  34. package/test/stub/config/yaml/.release-it.yaml +2 -0
  35. package/test/stub/config/yml/.release-it.yml +2 -0
  36. package/test/stub/github.js +26 -10
  37. package/test/stub/gitlab.js +15 -7
  38. package/test/stub/shell.js +2 -2
  39. package/test/tasks.interactive.js +2 -3
  40. package/test/tasks.js +44 -4
  41. package/test/util/helpers.js +6 -6
  42. package/test/util/index.js +13 -18
  43. package/test/utils.js +1 -1
  44. package/test/version.js +14 -9
  45. package/config/.codecov.yml +0 -5
  46. package/config/deprecated.json +0 -1
  47. package/lib/deprecated.js +0 -22
  48. package/lib/metrics.js +0 -76
  49. package/test/deprecated.js +0 -11
  50. package/test/metrics.js +0 -17
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);
@@ -131,18 +141,20 @@ test.serial('should disable core plugins', async t => {
131
141
  t.deepEqual(result, {
132
142
  changelog: undefined,
133
143
  name: undefined,
134
- latestVersion: undefined,
144
+ latestVersion: '0.0.0',
135
145
  version: undefined
136
146
  });
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
@@ -4,16 +4,13 @@ import Spinner from '../lib/spinner.js';
4
4
  import Config from '../lib/config.js';
5
5
 
6
6
  test.beforeEach(t => {
7
- t.context.ora = {
8
- promise: sinon.spy()
9
- };
7
+ t.context.ora = sinon.spy();
10
8
  });
11
9
 
12
10
  const getConfig = options => {
13
11
  const testConfig = {
14
12
  ci: false,
15
- config: false,
16
- 'disable-metrics': true
13
+ config: false
17
14
  };
18
15
  return new Config(Object.assign({}, testConfig, options));
19
16
  };
@@ -24,7 +21,7 @@ test('should not show spinner and not execute task if disabled', async t => {
24
21
  const spinner = new Spinner({ container: { ora } });
25
22
  await spinner.show({ enabled: false, task });
26
23
  t.is(task.callCount, 0);
27
- t.is(ora.promise.callCount, 0);
24
+ t.is(ora.callCount, 0);
28
25
  });
29
26
 
30
27
  test('should show spinner and run task by default', async t => {
@@ -35,9 +32,9 @@ test('should show spinner and run task by default', async t => {
35
32
  const spinner = new Spinner({ container: { ora, config } });
36
33
  await spinner.show({ task, label });
37
34
  t.is(task.callCount, 1);
38
- t.is(ora.promise.callCount, 1);
39
- t.is(ora.promise.firstCall.args[0], task.firstCall.returnValue);
40
- t.is(ora.promise.firstCall.args[1], label);
35
+ t.is(ora.callCount, 1);
36
+ t.is(ora.firstCall.args[0], task.firstCall.returnValue);
37
+ t.is(ora.firstCall.args[1], label);
41
38
  });
42
39
 
43
40
  test('should run task, but not show spinner if interactive', async t => {
@@ -47,7 +44,7 @@ test('should run task, but not show spinner if interactive', async t => {
47
44
  const spinner = new Spinner({ container: { ora, config } });
48
45
  await spinner.show({ task });
49
46
  t.is(task.callCount, 1);
50
- t.is(ora.promise.callCount, 0);
47
+ t.is(ora.callCount, 0);
51
48
  });
52
49
 
53
50
  test('should run task and show spinner if interactive, but external', async t => {
@@ -57,5 +54,5 @@ test('should run task and show spinner if interactive, but external', async t =>
57
54
  const spinner = new Spinner({ container: { ora, config } });
58
55
  await spinner.show({ task, external: true });
59
56
  t.is(task.callCount, 1);
60
- t.is(ora.promise.callCount, 1);
57
+ t.is(ora.callCount, 1);
61
58
  });
@@ -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
@@ -1,16 +1,19 @@
1
1
  import nock from 'nock';
2
2
 
3
- const interceptAuthentication = ({ api = 'https://api.github.com', username = 'john' } = {}) =>
3
+ const interceptAuthentication = ({ api = 'https://api.github.com', username = 'john' } = {}) => {
4
4
  nock(api).get('/user').reply(200, {
5
5
  login: username
6
6
  });
7
+ };
7
8
 
8
9
  const interceptCollaborator = ({
9
10
  api = 'https://api.github.com',
10
11
  owner = 'user',
11
12
  project = 'repo',
12
13
  username = 'john'
13
- } = {}) => nock(api).get(`/repos/${owner}/${project}/collaborators/${username}`).reply(204);
14
+ } = {}) => {
15
+ nock(api).get(`/repos/${owner}/${project}/collaborators/${username}`).reply(204);
16
+ };
14
17
 
15
18
  const interceptListReleases = ({
16
19
  host = 'github.com',
@@ -18,7 +21,7 @@ const interceptListReleases = ({
18
21
  owner = 'user',
19
22
  project = 'repo',
20
23
  tag_name
21
- } = {}) =>
24
+ } = {}) => {
22
25
  nock(api)
23
26
  .get(`/repos/${owner}/${project}/releases?per_page=1&page=1`)
24
27
  .reply(200, [
@@ -34,16 +37,24 @@ const interceptListReleases = ({
34
37
  prerelease: false
35
38
  }
36
39
  ]);
40
+ };
37
41
 
38
42
  const interceptCreate = ({
39
43
  api = 'https://api.github.com',
40
44
  host = 'github.com',
41
45
  owner = 'user',
42
46
  project = 'repo',
43
- body: { tag_name, name = '', body = null, prerelease = false, draft = false }
44
- } = {}) =>
47
+ body: { tag_name, name = '', generate_release_notes = false, body = null, prerelease = false, draft = false }
48
+ } = {}) => {
45
49
  nock(api)
46
- .post(`/repos/${owner}/${project}/releases`, { tag_name, name, body, prerelease, draft })
50
+ .post(`/repos/${owner}/${project}/releases`, {
51
+ tag_name,
52
+ name,
53
+ body,
54
+ prerelease,
55
+ draft,
56
+ generate_release_notes
57
+ })
47
58
  .reply(() => {
48
59
  const id = 1;
49
60
  const responseBody = {
@@ -53,21 +64,23 @@ const interceptCreate = ({
53
64
  body,
54
65
  prerelease,
55
66
  draft,
67
+ generate_release_notes,
56
68
  upload_url: `https://uploads.${host}/repos/${owner}/${project}/releases/${id}/assets{?name,label}`,
57
69
  html_url: `https://${host}/${owner}/${project}/releases/tag/${tag_name}`
58
70
  };
59
71
  return [200, responseBody, { location: `${api}/repos/${owner}/${project}/releases/${id}` }];
60
72
  });
73
+ };
61
74
 
62
75
  const interceptUpdate = ({
63
76
  host = 'github.com',
64
77
  api = 'https://api.github.com',
65
78
  owner = 'user',
66
79
  project = 'repo',
67
- body: { tag_name, name = '', body = null, prerelease = false, draft = false }
68
- } = {}) =>
80
+ body: { tag_name, name = '', body = null, prerelease = false, draft = false, generate_release_notes = false }
81
+ } = {}) => {
69
82
  nock(api)
70
- .patch(`/repos/${owner}/${project}/releases/1`, { tag_name, name, body, draft, prerelease })
83
+ .patch(`/repos/${owner}/${project}/releases/1`, { tag_name, name, body, draft, prerelease, generate_release_notes })
71
84
  .reply(200, {
72
85
  id: 1,
73
86
  tag_name,
@@ -75,9 +88,11 @@ const interceptUpdate = ({
75
88
  body,
76
89
  prerelease,
77
90
  draft,
91
+ generate_release_notes,
78
92
  upload_url: `https://uploads.${host}/repos/${owner}/${project}/releases/1/assets{?name,label}`,
79
93
  html_url: `https://${host}/${owner}/${project}/releases/tag/${tag_name}`
80
94
  });
95
+ };
81
96
 
82
97
  const interceptAsset = ({
83
98
  api = 'https://api.github.com',
@@ -86,7 +101,7 @@ const interceptAsset = ({
86
101
  project = 'repo',
87
102
  tagName,
88
103
  body = {}
89
- } = {}) =>
104
+ } = {}) => {
90
105
  nock(`https://uploads.${host}`)
91
106
  .post(`/repos/${owner}/${project}/releases/1/assets`, body)
92
107
  .query(true)
@@ -103,6 +118,7 @@ const interceptAsset = ({
103
118
  browser_download_url: `https://${host}/${owner}/${project}/releases/download/${tagName}/${name}`
104
119
  };
105
120
  });
121
+ };
106
122
 
107
123
  export {
108
124
  interceptAuthentication,
@@ -11,16 +11,24 @@ export let interceptCollaborator = (
11
11
  .get(`/api/v4/projects/${group ? `${group}%2F` : ''}${owner}%2F${project}/members/all/${userId}`)
12
12
  .reply(200, { id: userId, username: owner, access_level: 30 });
13
13
 
14
- export let interceptCollaboratorFallback = (
15
- { host = 'https://gitlab.com', owner = 'user', project = 'repo', group, userId = 1 } = {},
14
+ export let interceptPublish = ({ host = 'https://gitlab.com', owner = 'user', project = 'repo', body } = {}, options) =>
15
+ nock(host, options).post(`/api/v4/projects/${owner}%2F${project}/releases`, body).reply(200, {});
16
+
17
+ export let interceptMilestones = (
18
+ { host = 'https://gitlab.com', owner = 'user', project = 'repo', query = {}, milestones = [] } = {},
16
19
  options
17
20
  ) =>
18
21
  nock(host, options)
19
- .get(`/api/v4/projects/${group ? `${group}%2F` : ''}${owner}%2F${project}/members/${userId}`)
20
- .reply(200, { id: userId, username: owner, access_level: 30 });
21
-
22
- export let interceptPublish = ({ host = 'https://gitlab.com', owner = 'user', project = 'repo', body } = {}, options) =>
23
- nock(host, options).post(`/api/v4/projects/${owner}%2F${project}/releases`, body).reply(200, {});
22
+ .get(`/api/v4/projects/${owner}%2F${project}/milestones`)
23
+ .query(
24
+ Object.assign(
25
+ {
26
+ include_parent_milestones: true
27
+ },
28
+ query
29
+ )
30
+ )
31
+ .reply(200, JSON.stringify(milestones));
24
32
 
25
33
  export let interceptAsset = ({ host = 'https://gitlab.com', owner = 'user', project = 'repo' } = {}) =>
26
34
  nock(host)
@@ -1,7 +1,7 @@
1
- import _debug from 'debug';
1
+ import util from 'node:util';
2
2
  import Shell from '../../lib/shell.js';
3
3
 
4
- const debug = _debug('release-it:shell-stub');
4
+ const debug = util.debug('release-it:shell-stub');
5
5
 
6
6
  class ShellStub extends Shell {
7
7
  exec(command) {
@@ -1,4 +1,4 @@
1
- import path from 'path';
1
+ import path from 'node:path';
2
2
  import test from 'ava';
3
3
  import sh from 'shelljs';
4
4
  import _ from 'lodash';
@@ -19,8 +19,7 @@ const sandbox = sinon.createSandbox();
19
19
 
20
20
  const testConfig = {
21
21
  ci: false,
22
- config: false,
23
- 'disable-metrics': true
22
+ config: false
24
23
  };
25
24
 
26
25
  const log = sandbox.createStubInstance(Log);
package/test/tasks.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 sh from 'shelljs';
4
4
  import _ from 'lodash';
@@ -30,8 +30,7 @@ const sandbox = sinon.createSandbox();
30
30
 
31
31
  const testConfig = {
32
32
  ci: true,
33
- config: false,
34
- 'disable-metrics': true
33
+ config: false
35
34
  };
36
35
 
37
36
  const log = sandbox.createStubInstance(Log);
@@ -358,7 +357,7 @@ test.serial('should initially publish non-private scoped npm package privately',
358
357
  test.serial('should use pkg.publishConfig.registry', async t => {
359
358
  const { target } = t.context;
360
359
  const pkgName = path.basename(target);
361
- const registry = 'https://my-registry.com';
360
+ const registry = 'https://my-registry.example.org';
362
361
 
363
362
  gitAdd(
364
363
  JSON.stringify({
@@ -397,6 +396,47 @@ test.serial('should propagate errors', async t => {
397
396
  t.is(log.error.callCount, 1);
398
397
  });
399
398
 
399
+ test.serial('should use custom changelog command with context', async t => {
400
+ const { bare } = t.context;
401
+ const project = path.basename(bare);
402
+ const owner = path.basename(path.dirname(bare));
403
+ sh.exec('git tag v1.0.0');
404
+ gitAdd('line', 'file', 'More file');
405
+
406
+ interceptGitHubAuthentication();
407
+ interceptGitHubCollaborator({ owner, project });
408
+ interceptGitHubCreate({
409
+ owner,
410
+ project,
411
+ body: {
412
+ tag_name: 'v1.1.0',
413
+ name: 'Release 1.1.0',
414
+ body: 'custom-changelog-generator --from=v1.0.0 --to=v1.1.0',
415
+ draft: false,
416
+ prerelease: false
417
+ }
418
+ });
419
+
420
+ const container = getContainer({
421
+ increment: 'minor',
422
+ github: {
423
+ release: true,
424
+ releaseNotes: 'echo custom-changelog-generator --from=${latestTag} --to=${tagName}',
425
+ pushRepo: `https://github.com/${owner}/${project}`
426
+ }
427
+ });
428
+
429
+ const exec = sinon.spy(container.shell, 'execStringCommand');
430
+
431
+ await runTasks({}, container);
432
+
433
+ const command = exec.args.find(([command]) => command.includes('custom-changelog-generator'));
434
+
435
+ t.is(command[0], 'echo custom-changelog-generator --from=v1.0.0 --to=v1.1.0');
436
+
437
+ exec.restore();
438
+ });
439
+
400
440
  {
401
441
  test.serial('should run all hooks', async t => {
402
442
  gitAdd(`{"name":"hooked","version":"1.0.0","type":"module"}`, 'package.json', 'Add package.json');
@@ -1,14 +1,14 @@
1
- import { promises as fs } from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
3
4
  import sh from 'shelljs';
4
- import tmp from 'tmp';
5
5
 
6
6
  const mkTmpDir = () => {
7
- const dir = tmp.dirSync({ prefix: 'release-it-' });
8
- return dir.name;
7
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'release-it-'));
8
+ return dir;
9
9
  };
10
10
 
11
- const readFile = file => fs.readFile(path.resolve(file), 'utf8');
11
+ const readFile = file => fs.promises.readFile(path.resolve(file), 'utf8');
12
12
 
13
13
  const gitAdd = (content, file, message) => {
14
14
  sh.ShellString(content).toEnd(file);