release-it 17.5.0 → 18.0.0-next.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.
@@ -63,6 +63,7 @@
63
63
  "tokenRef": "GITLAB_TOKEN",
64
64
  "tokenHeader": "Private-Token",
65
65
  "certificateAuthorityFile": null,
66
+ "secure": null,
66
67
  "assets": null,
67
68
  "origin": null,
68
69
  "skipChecks": false
@@ -2,7 +2,6 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import open from 'open';
4
4
  import { Octokit } from '@octokit/rest';
5
- import fetch from 'node-fetch';
6
5
  import { globby } from 'globby';
7
6
  import mime from 'mime-types';
8
7
  import _ from 'lodash';
@@ -177,8 +176,7 @@ class GitHub extends Release {
177
176
  userAgent: `release-it/${pkg.version}`,
178
177
  log: this.config.isDebug ? console : null,
179
178
  request: {
180
- timeout,
181
- fetch
179
+ timeout
182
180
  }
183
181
  };
184
182
 
@@ -1,8 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import got from 'got';
4
3
  import { globby } from 'globby';
5
- import { FormData, fileFromSync } from 'node-fetch';
6
4
  import _ from 'lodash';
7
5
  import Release from '../GitRelease.js';
8
6
  import { format, e } from '../../util.js';
@@ -17,26 +15,17 @@ class GitLab extends Release {
17
15
  super(...args);
18
16
  this.registerPrompts(prompts);
19
17
  this.assets = [];
20
- const { certificateAuthorityFile } = this.options;
21
- this.certificateAuthorityOption = certificateAuthorityFile
22
- ? { https: { certificateAuthority: fs.readFileSync(certificateAuthorityFile) } }
23
- : {};
24
- }
18
+ const { certificateAuthorityFile, secure } = this.options;
25
19
 
26
- get client() {
27
- if (this._client) return this._client;
28
- const { tokenHeader } = this.options;
29
- const { baseUrl } = this.getContext();
30
- this._client = got.extend({
31
- prefixUrl: baseUrl,
32
- method: 'POST',
33
- headers: {
34
- 'user-agent': 'webpro/release-it',
35
- [tokenHeader]: this.token
36
- },
37
- ...this.certificateAuthorityOption
38
- });
39
- return this._client;
20
+ const httpsOptions = {
21
+ certificateAuthority: certificateAuthorityFile ? fs.readFileSync(certificateAuthorityFile) : undefined,
22
+ rejectUnauthorized: typeof secure === 'boolean' ? secure : undefined
23
+ };
24
+
25
+ // Remove keys with undefined values
26
+ const https = _.pickBy(httpsOptions, value => value !== undefined);
27
+
28
+ this.certificateAuthorityOption = _.isEmpty(https) ? {} : { https };
40
29
  }
41
30
 
42
31
  async init() {
@@ -172,8 +161,28 @@ class GitLab extends Release {
172
161
  const { baseUrl } = this.getContext();
173
162
  this.debug(Object.assign({ url: `${baseUrl}/${endpoint}` }, options));
174
163
  const method = (options.method || 'POST').toLowerCase();
175
- const response = await this.client[method](endpoint, options);
176
- const body = typeof response.body === 'string' ? JSON.parse(response.body) : response.body || {};
164
+ const { tokenHeader } = this.options;
165
+ const url = `${baseUrl}/${endpoint}${options.searchParams ? `?${new URLSearchParams(options.searchParams)}` : ''}`;
166
+ const headers = {
167
+ 'user-agent': 'webpro/release-it',
168
+ [tokenHeader]: this.token
169
+ };
170
+ const requestOptions = {
171
+ method,
172
+ headers,
173
+ ...this.certificateAuthorityOption
174
+ };
175
+
176
+ const response = await fetch(
177
+ url,
178
+ options.json || options.body
179
+ ? {
180
+ ...requestOptions,
181
+ body: options.json ? JSON.stringify(options.json) : options.body
182
+ }
183
+ : requestOptions
184
+ );
185
+ const body = await response.json();
177
186
  this.debug(body);
178
187
  return body;
179
188
  }
@@ -232,7 +241,8 @@ class GitLab extends Release {
232
241
  const endpoint = `projects/${id}/uploads`;
233
242
 
234
243
  const body = new FormData();
235
- body.set('file', fileFromSync(filePath));
244
+ const rawData = await fs.promises.readFile(filePath);
245
+ body.set('file', new Blob([rawData]), name);
236
246
  const options = { body };
237
247
 
238
248
  try {
package/lib/prompt.js CHANGED
@@ -19,7 +19,7 @@ class Prompt {
19
19
  name: promptName,
20
20
  message: prompt.message(context),
21
21
  choices: 'choices' in prompt && prompt.choices(context),
22
- transformer: 'transformer' in prompt && prompt.transformer(context)
22
+ transformer: 'transformer' in prompt ? prompt.transformer(context) : undefined
23
23
  });
24
24
 
25
25
  const answers = await this.createPrompt([options]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-it",
3
- "version": "17.5.0",
3
+ "version": "18.0.0-next.0",
4
4
  "description": "Generic CLI tool to automate versioning and package publishing-related tasks.",
5
5
  "keywords": [
6
6
  "build",
@@ -79,64 +79,62 @@
79
79
  "license": "MIT",
80
80
  "dependencies": {
81
81
  "@iarna/toml": "2.2.5",
82
- "@octokit/rest": "20.1.1",
82
+ "@octokit/rest": "21.0.2",
83
83
  "async-retry": "1.3.3",
84
84
  "chalk": "5.3.0",
85
85
  "cosmiconfig": "9.0.0",
86
- "execa": "8.0.1",
87
- "git-url-parse": "14.0.0",
86
+ "execa": "9.3.1",
87
+ "git-url-parse": "15.0.0",
88
88
  "globby": "14.0.2",
89
- "got": "13.0.0",
90
- "inquirer": "9.3.2",
89
+ "inquirer": "10.1.8",
91
90
  "is-ci": "3.0.1",
92
91
  "issue-parser": "7.0.1",
93
92
  "lodash": "4.17.21",
94
93
  "mime-types": "2.1.35",
95
94
  "new-github-release-url": "2.0.0",
96
- "node-fetch": "3.3.2",
97
95
  "open": "10.1.0",
98
96
  "ora": "8.0.1",
99
- "os-name": "5.1.0",
97
+ "os-name": "6.0.0",
100
98
  "proxy-agent": "6.4.0",
101
- "semver": "7.6.2",
99
+ "semver": "7.6.3",
102
100
  "shelljs": "0.8.5",
103
- "update-notifier": "7.0.0",
101
+ "update-notifier": "7.2.0",
104
102
  "url-join": "5.0.0",
105
103
  "wildcard-match": "5.1.3",
106
104
  "yargs-parser": "21.1.1"
107
105
  },
108
106
  "devDependencies": {
109
- "@eslint/compat": "1.1.0",
107
+ "@eslint/compat": "1.1.1",
110
108
  "@eslint/eslintrc": "3.1.0",
111
- "@eslint/js": "9.6.0",
112
- "@octokit/request-error": "5.1.0",
113
- "@types/node": "20.14.9",
109
+ "@eslint/js": "9.9.1",
110
+ "@octokit/request-error": "6.1.4",
111
+ "@types/node": "20.14.10",
114
112
  "ava": "6.1.3",
115
- "eslint": "9.6.0",
113
+ "eslint": "9.9.1",
116
114
  "eslint-config-prettier": "9.1.0",
117
115
  "eslint-plugin-ava": "15.0.1",
118
- "eslint-plugin-import": "2.29.1",
119
- "eslint-plugin-prettier": "5.1.3",
116
+ "eslint-plugin-import-x": "3.1.0",
117
+ "eslint-plugin-prettier": "5.2.1",
120
118
  "fs-monkey": "1.0.6",
121
- "globals": "15.7.0",
119
+ "globals": "15.9.0",
122
120
  "installed-check": "9.3.0",
123
- "knip": "5.23.2",
124
- "memfs": "4.9.3",
121
+ "knip": "5.27.3",
122
+ "memfs": "4.11.1",
125
123
  "mock-stdio": "1.0.3",
126
- "nock": "13.5.4",
127
- "prettier": "3.3.2",
124
+ "nock": "14.0.0-beta.8",
125
+ "prettier": "3.3.3",
128
126
  "remark-cli": "12.0.1",
129
127
  "remark-preset-webpro": "1.1.0",
130
128
  "sinon": "18.0.0",
131
129
  "strip-ansi": "7.1.0",
132
- "typescript": "5.5.2"
130
+ "typescript": "5.5.4"
133
131
  },
134
132
  "overrides": {
135
133
  "pac-resolver": "7.0.1",
136
134
  "socks": "2.8.3"
137
135
  },
138
136
  "engines": {
139
- "node": "^18.18.0 || ^20.9.0 || ^22.0.0"
137
+ "node": "^20.9.0 || ^22.0.0"
140
138
  },
141
139
  "remarkConfig": {
142
140
  "plugins": [
package/schema/git.json CHANGED
@@ -14,7 +14,11 @@
14
14
  "default": true
15
15
  },
16
16
  "requireBranch": {
17
- "type": "boolean",
17
+ "oneOf": [
18
+ { "type": "boolean", "enum": [false] },
19
+ { "type": "string" },
20
+ { "type": "array", "items": { "type": "string" } }
21
+ ],
18
22
  "default": false
19
23
  },
20
24
  "requireUpstream": {
@@ -46,6 +46,9 @@
46
46
  "certificateAuthorityFile": {
47
47
  "default": null
48
48
  },
49
+ "secure": {
50
+ "default": null
51
+ },
49
52
  "assets": {
50
53
  "default": null
51
54
  },
package/test/gitlab.js CHANGED
@@ -1,3 +1,4 @@
1
+ import fs from 'node:fs';
1
2
  import test from 'ava';
2
3
  import sinon from 'sinon';
3
4
  import nock from 'nock';
@@ -225,28 +226,70 @@ test('should not make requests in dry run', async t => {
225
226
  const options = { 'dry-run': true, git: { pushRepo }, gitlab: { releaseName: 'R', tokenRef } };
226
227
  const gitlab = factory(GitLab, { options });
227
228
  sinon.stub(gitlab, 'getLatestVersion').resolves('1.0.0');
228
- const spy = sinon.spy(gitlab, 'client', ['get']);
229
229
 
230
230
  await runTasks(gitlab);
231
231
 
232
232
  const { isReleased, releaseUrl } = gitlab.getContext();
233
- t.is(spy.get.callCount, 0);
233
+
234
234
  t.is(gitlab.log.exec.args[2][0], 'gitlab releases#uploadAssets');
235
235
  t.is(gitlab.log.exec.args[3][0], 'gitlab releases#createRelease "R" (1.0.1)');
236
236
  t.true(isReleased);
237
237
  t.is(releaseUrl, `${pushRepo}/-/releases`);
238
- spy.get.restore();
239
238
  });
240
239
 
241
240
  test('should skip checks', async t => {
242
241
  const options = { gitlab: { tokenRef, skipChecks: true, release: true, milestones: ['v1.0.0'] } };
243
242
  const gitlab = factory(GitLab, { options });
244
- const spy = sinon.spy(gitlab, 'client', ['get']);
245
243
 
246
244
  await t.notThrowsAsync(gitlab.init());
247
245
  await t.notThrowsAsync(gitlab.beforeRelease());
248
246
 
249
- t.is(spy.get.callCount, 0);
250
-
251
247
  t.is(gitlab.log.exec.args.filter(entry => /checkReleaseMilestones/.test(entry[0])).length, 0);
252
248
  });
249
+
250
+ test('should handle certificate authority options', t => {
251
+ const sandbox = sinon.createSandbox();
252
+ sandbox.stub(fs, 'readFileSync').returns('test certificate');
253
+
254
+ {
255
+ const options = { gitlab: {} };
256
+ const gitlab = factory(GitLab, { options });
257
+ t.deepEqual(gitlab.certificateAuthorityOption, {});
258
+ }
259
+
260
+ {
261
+ const options = { gitlab: { certificateAuthorityFile: 'cert.crt' } };
262
+ const gitlab = factory(GitLab, { options });
263
+ t.deepEqual(gitlab.certificateAuthorityOption, { https: { certificateAuthority: 'test certificate' } });
264
+ }
265
+
266
+ {
267
+ const options = { gitlab: { secure: false } };
268
+ const gitlab = factory(GitLab, { options });
269
+ t.deepEqual(gitlab.certificateAuthorityOption, { https: { rejectUnauthorized: false } });
270
+ }
271
+
272
+ {
273
+ const options = { gitlab: { secure: true } };
274
+ const gitlab = factory(GitLab, { options });
275
+ t.deepEqual(gitlab.certificateAuthorityOption, { https: { rejectUnauthorized: true } });
276
+ }
277
+
278
+ {
279
+ const options = { gitlab: { certificateAuthorityFile: 'cert.crt', secure: true } };
280
+ const gitlab = factory(GitLab, { options });
281
+ t.deepEqual(gitlab.certificateAuthorityOption, {
282
+ https: { certificateAuthority: 'test certificate', rejectUnauthorized: true }
283
+ });
284
+ }
285
+
286
+ {
287
+ const options = { gitlab: { certificateAuthorityFile: 'cert.crt', secure: false } };
288
+ const gitlab = factory(GitLab, { options });
289
+ t.deepEqual(gitlab.certificateAuthorityOption, {
290
+ https: { certificateAuthority: 'test certificate', rejectUnauthorized: false }
291
+ });
292
+ }
293
+
294
+ sandbox.restore();
295
+ });
package/test/prompt.js CHANGED
@@ -42,7 +42,7 @@ test('should create prompt', async t => {
42
42
  message: 'Push?',
43
43
  name: 'push',
44
44
  choices: false,
45
- transformer: false,
45
+ transformer: undefined,
46
46
  default: true
47
47
  });
48
48
  });
package/types/config.d.ts CHANGED
@@ -170,6 +170,9 @@ export interface Config {
170
170
 
171
171
  /** @default null */
172
172
  certificateAuthorityFile?: any;
173
+
174
+ /** @default null */
175
+ secure?: boolean;
173
176
 
174
177
  /** @default null */
175
178
  assets?: any;