release-it 15.5.0 → 15.6.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.
@@ -11,6 +11,7 @@
11
11
  "commitMessage": "Release ${version}",
12
12
  "commitArgs": [],
13
13
  "tag": true,
14
+ "tagExclude": null,
14
15
  "tagName": null,
15
16
  "tagMatch": null,
16
17
  "tagAnnotation": "Release ${version}",
@@ -93,7 +93,8 @@ class GitBase extends Plugin {
93
93
  getLatestTagName() {
94
94
  const context = Object.assign({}, this.config.getContext(), { version: '*' });
95
95
  const match = format(this.options.tagMatch || this.options.tagName || '${version}', context);
96
- return this.exec(`git describe --tags --match=${match} --abbrev=0`, { options }).then(
96
+ const exclude = this.options.tagExclude ? ` --exclude=${format(this.options.tagExclude, context)}` : '';
97
+ return this.exec(`git describe --tags --match=${match} --abbrev=0${exclude}`, { options }).then(
97
98
  stdout => stdout || null,
98
99
  () => null
99
100
  );
@@ -12,7 +12,7 @@ class GitRelease extends GitBase {
12
12
  getInitialOptions(options) {
13
13
  const baseOptions = super.getInitialOptions(...arguments);
14
14
  const git = options.git || defaultConfig.git;
15
- const gitOptions = _.pick(git, ['tagName', 'tagMatch', 'pushRepo', 'changelog']);
15
+ const gitOptions = _.pick(git, ['tagExclude', 'tagName', 'tagMatch', 'pushRepo', 'changelog']);
16
16
  return _.defaults(baseOptions, gitOptions);
17
17
  }
18
18
 
@@ -65,7 +65,8 @@ class Plugin {
65
65
  step(options) {
66
66
  const context = Object.assign({}, this.config.getContext(), { [this.namespace]: this.getContext() });
67
67
  const opts = Object.assign({}, options, { context });
68
- return this.config.isCI ? this.spinner.show(opts) : this.showPrompt(opts);
68
+ const isException = this.config.isPromptOnlyVersion && ['incrementList', 'publish', 'otp'].includes(opts.prompt);
69
+ return this.config.isCI && !isException ? this.spinner.show(opts) : this.showPrompt(opts);
69
70
  }
70
71
  }
71
72
 
@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import got from 'got';
4
4
  import { globby } from 'globby';
5
- import FormData from 'form-data';
5
+ import { FormData, fileFromSync } from 'node-fetch';
6
6
  import allSettled from 'promise.allsettled';
7
7
  import _ from 'lodash';
8
8
  import Release from '../GitRelease.js';
@@ -232,7 +232,7 @@ class GitLab extends Release {
232
232
  const endpoint = `projects/${id}/uploads`;
233
233
 
234
234
  const body = new FormData();
235
- body.append('file', fs.createReadStream(filePath));
235
+ body.set('file', fileFromSync(filePath));
236
236
  const options = { body };
237
237
 
238
238
  try {
@@ -92,7 +92,8 @@ class npm extends Plugin {
92
92
  release() {
93
93
  if (this.options.publish === false) return false;
94
94
  const publish = () => this.publish({ otpCallback });
95
- const otpCallback = this.config.isCI ? null : task => this.step({ prompt: 'otp', task });
95
+ const otpCallback =
96
+ this.config.isCI && !this.config.isPromptOnlyVersion ? null : task => this.step({ prompt: 'otp', task });
96
97
  return this.step({ task: publish, label: 'npm publish', prompt: 'publish' });
97
98
  }
98
99
 
@@ -131,34 +132,43 @@ class npm extends Plugin {
131
132
  );
132
133
  }
133
134
 
134
- isCollaborator() {
135
+ async isCollaborator() {
135
136
  const registry = this.getRegistry();
136
137
  const registryArg = registry ? ` --registry ${registry}` : '';
137
138
  const name = this.getName();
138
139
  const { username } = this.getContext();
139
140
  if (username === undefined) return true;
140
141
  if (username === null) return false;
141
- return this.exec(`npm access ls-collaborators ${name}${registryArg}`, { options }).then(
142
- output => {
143
- try {
144
- const collaborators = JSON.parse(output);
145
- const permissions = collaborators[username];
146
- return permissions && permissions.includes('write');
147
- } catch (err) {
148
- this.debug(err);
149
- return false;
150
- }
151
- },
152
- err => {
142
+
143
+ try {
144
+ let npmVersion = await this.exec('npm --version', { options });
145
+
146
+ let accessCommand;
147
+ if (semver.gt(npmVersion, '9.0.0')) {
148
+ accessCommand = 'npm access list collaborators --json';
149
+ } else {
150
+ accessCommand = 'npm access ls-collaborators';
151
+ }
152
+
153
+ const output = await this.exec(`${accessCommand} ${name}${registryArg}`, { options });
154
+
155
+ try {
156
+ const collaborators = JSON.parse(output);
157
+ const permissions = collaborators[username];
158
+ return permissions && permissions.includes('write');
159
+ } catch (err) {
153
160
  this.debug(err);
154
- if (/code E400/.test(err)) {
155
- this.log.warn('Ignoring response from unsupported `npm access` command.');
156
- } else {
157
- this.log.warn(`Unable to verify if user ${username} is a collaborator for ${name}.`);
158
- }
159
- return true;
161
+ return false;
160
162
  }
161
- );
163
+ } catch (err) {
164
+ this.debug(err);
165
+ if (/code E400/.test(err)) {
166
+ this.log.warn('Ignoring response from unsupported `npm access` command.');
167
+ } else {
168
+ this.log.warn(`Unable to verify if user ${username} is a collaborator for ${name}.`);
169
+ }
170
+ return true;
171
+ }
162
172
  }
163
173
 
164
174
  async getLatestRegistryVersion() {
package/lib/util.js CHANGED
@@ -20,8 +20,6 @@ const getSystemInfo = () => {
20
20
  };
21
21
  };
22
22
 
23
- const clean = args => args.filter(arg => arg != null);
24
-
25
23
  const format = (template = '', context = {}) => {
26
24
  try {
27
25
  return _.template(template)(context);
@@ -95,7 +93,6 @@ const e = (message, docs) => new Error(docs ? `${message}${EOL}Documentation: ${
95
93
 
96
94
  export {
97
95
  getSystemInfo,
98
- clean,
99
96
  format,
100
97
  truncateLines,
101
98
  rejectAfter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-it",
3
- "version": "15.5.0",
3
+ "version": "15.6.0",
4
4
  "description": "Generic CLI tool to automate versioning and package publishing related tasks.",
5
5
  "keywords": [
6
6
  "build",
@@ -60,27 +60,26 @@
60
60
  "license": "MIT",
61
61
  "dependencies": {
62
62
  "@iarna/toml": "2.2.5",
63
- "@octokit/rest": "19.0.4",
63
+ "@octokit/rest": "19.0.5",
64
64
  "async-retry": "1.3.3",
65
- "chalk": "5.0.1",
66
- "cosmiconfig": "7.0.1",
65
+ "chalk": "5.1.2",
66
+ "cosmiconfig": "8.0.0",
67
67
  "execa": "6.1.0",
68
- "form-data": "4.0.0",
69
68
  "git-url-parse": "13.1.0",
70
69
  "globby": "13.1.2",
71
- "got": "12.5.1",
72
- "inquirer": "9.1.2",
70
+ "got": "12.5.3",
71
+ "inquirer": "9.1.4",
73
72
  "is-ci": "3.0.1",
74
73
  "lodash": "4.17.21",
75
74
  "mime-types": "2.1.35",
76
75
  "new-github-release-url": "2.0.0",
77
- "node-fetch": "3.2.10",
76
+ "node-fetch": "3.3.0",
78
77
  "open": "8.4.0",
79
78
  "ora": "6.1.2",
80
79
  "os-name": "5.0.1",
81
- "promise.allsettled": "1.0.5",
80
+ "promise.allsettled": "1.0.6",
82
81
  "proxy-agent": "5.0.0",
83
- "semver": "7.3.7",
82
+ "semver": "7.3.8",
84
83
  "shelljs": "0.8.5",
85
84
  "update-notifier": "6.0.2",
86
85
  "url-join": "5.0.0",
@@ -88,19 +87,19 @@
88
87
  "yargs-parser": "21.1.1"
89
88
  },
90
89
  "devDependencies": {
91
- "@octokit/request-error": "3.0.1",
92
- "ava": "4.3.3",
93
- "eslint": "8.24.0",
90
+ "@octokit/request-error": "3.0.2",
91
+ "ava": "5.1.0",
92
+ "eslint": "8.28.0",
94
93
  "eslint-config-prettier": "8.5.0",
95
94
  "eslint-plugin-ava": "13.2.0",
96
95
  "eslint-plugin-import": "2.26.0",
97
96
  "eslint-plugin-prettier": "4.2.1",
98
- "mock-fs": "5.1.4",
97
+ "mock-fs": "5.2.0",
99
98
  "mock-stdio": "1.0.3",
100
99
  "nock": "13.2.9",
101
100
  "nyc": "15.1.0",
102
- "prettier": "2.7.1",
103
- "sinon": "14.0.1",
101
+ "prettier": "2.8.0",
102
+ "sinon": "15.0.0",
104
103
  "strip-ansi": "7.0.1"
105
104
  },
106
105
  "engines": {
package/test/git.init.js CHANGED
@@ -167,6 +167,23 @@ test.serial('should get the latest tag based on tagMatch', async t => {
167
167
  t.is(gitClient.config.getContext('latestTag'), '21.04.3');
168
168
  });
169
169
 
170
+ test.serial('should get the latest tag based on tagExclude', async t => {
171
+ const shell = factory(Shell);
172
+ const gitClient = factory(Git, {
173
+ options: { git: { tagExclude: '*[-]*' } },
174
+ container: { shell }
175
+ });
176
+ sh.exec('git tag 1.0.0');
177
+ sh.exec('git commit --allow-empty -m "commit 1"');
178
+ sh.exec('git tag 1.0.1-rc.0');
179
+ sh.exec('git tag 1.0.1');
180
+ sh.exec('git commit --allow-empty -m "commit 2"');
181
+ sh.exec('git tag 1.1.0-rc.0');
182
+ sh.exec('git push --tags');
183
+ await gitClient.init();
184
+ t.is(gitClient.config.getContext('latestTag'), '1.0.1');
185
+ });
186
+
170
187
  test.serial('should generate correct changelog', async t => {
171
188
  const gitClient = factory(Git, { options: { git } });
172
189
  sh.exec('git tag 1.0.0');
package/test/npm.js CHANGED
@@ -182,10 +182,21 @@ test('should throw if user is not authenticated', async t => {
182
182
  exec.restore();
183
183
  });
184
184
 
185
- test('should throw if user is not a collaborator', async t => {
185
+ test('should throw if user is not a collaborator (v9)', async t => {
186
186
  const npmClient = factory(npm);
187
187
  const exec = sinon.stub(npmClient.shell, 'exec').resolves();
188
188
  exec.withArgs('npm whoami').resolves('ada');
189
+ exec.withArgs('npm --version').resolves('9.2.0');
190
+ exec.withArgs('npm access list collaborators --json release-it').resolves(JSON.stringify({ john: ['write'] }));
191
+ await t.throwsAsync(runTasks(npmClient), { message: /^User ada is not a collaborator for release-it/ });
192
+ exec.restore();
193
+ });
194
+
195
+ test('should throw if user is not a collaborator (v8)', async t => {
196
+ const npmClient = factory(npm);
197
+ const exec = sinon.stub(npmClient.shell, 'exec').resolves();
198
+ exec.withArgs('npm whoami').resolves('ada');
199
+ exec.withArgs('npm --version').resolves('8.2.0');
189
200
  exec.withArgs('npm access ls-collaborators release-it').resolves(JSON.stringify({ john: ['write'] }));
190
201
  await t.throwsAsync(runTasks(npmClient), { message: /^User ada is not a collaborator for release-it/ });
191
202
  exec.restore();
@@ -307,7 +318,7 @@ test('should publish to a different/scoped registry', async t => {
307
318
  'npm ping --registry https://gitlab.com/api/v4/projects/my-scope%2Fmy-pkg/packages/npm/',
308
319
  'npm whoami --registry https://gitlab.com/api/v4/projects/my-scope%2Fmy-pkg/packages/npm/',
309
320
  'npm show @my-scope/my-pkg@latest version --registry https://gitlab.com/api/v4/projects/my-scope%2Fmy-pkg/packages/npm/',
310
- 'npm access ls-collaborators @my-scope/my-pkg --registry https://gitlab.com/api/v4/projects/my-scope%2Fmy-pkg/packages/npm/',
321
+ 'npm --version',
311
322
  'npm version 1.0.1 --no-git-tag-version',
312
323
  'npm publish . --tag latest'
313
324
  ]);
@@ -341,7 +352,7 @@ test('should not publish when `npm version` fails', async t => {
341
352
  'npm ping',
342
353
  'npm whoami',
343
354
  'npm show @my-scope/my-pkg@latest version',
344
- 'npm access ls-collaborators @my-scope/my-pkg',
355
+ 'npm --version',
345
356
  'npm version 1.0.1 --no-git-tag-version'
346
357
  ]);
347
358
 
package/test/tasks.js CHANGED
@@ -128,7 +128,7 @@ test.serial('should use pkg.version (in sub dir) w/o tagging repo', async t => {
128
128
  const { stdout } = sh.exec('git describe --tags --match=* --abbrev=0');
129
129
  t.is(stdout.trim(), '1.0.0');
130
130
  const npmArgs = getArgs(exec.args, 'npm');
131
- t.is(npmArgs[4], 'npm version 1.3.0 --no-git-tag-version');
131
+ t.is(npmArgs[5], 'npm version 1.3.0 --no-git-tag-version');
132
132
  exec.restore();
133
133
  });
134
134
 
@@ -174,6 +174,7 @@ test.serial('should release all the things (basic)', async t => {
174
174
  'npm ping',
175
175
  'npm whoami',
176
176
  `npm show ${pkgName}@latest version`,
177
+ 'npm --version',
177
178
  `npm access ls-collaborators ${pkgName}`,
178
179
  'npm version 1.0.1 --no-git-tag-version',
179
180
  'npm publish . --tag latest'
@@ -307,6 +308,7 @@ test.serial('should release all the things (pre-release, github, gitlab)', async
307
308
  'npm ping',
308
309
  'npm whoami',
309
310
  `npm show ${pkgName}@latest version`,
311
+ 'npm --version',
310
312
  `npm access ls-collaborators ${pkgName}`,
311
313
  'npm version 1.1.0-alpha.0 --no-git-tag-version',
312
314
  'npm publish . --tag alpha'
@@ -346,6 +348,7 @@ test.serial('should publish pre-release without pre-id with different npm.tag',
346
348
  'npm ping',
347
349
  'npm whoami',
348
350
  `npm show ${pkgName}@latest version`,
351
+ 'npm --version',
349
352
  `npm access ls-collaborators ${pkgName}`,
350
353
  'npm version 2.0.0-0 --no-git-tag-version',
351
354
  'npm publish . --tag next'
@@ -393,7 +396,7 @@ test.serial('should initially publish non-private scoped npm package privately',
393
396
  await runTasks({}, container);
394
397
 
395
398
  const npmArgs = getArgs(container.shell.exec.args, 'npm');
396
- t.is(npmArgs[5], 'npm publish . --tag latest');
399
+ t.is(npmArgs[6], 'npm publish . --tag latest');
397
400
  exec.restore();
398
401
  });
399
402