release-it 19.0.0-next.0 → 19.0.0-next.2

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/test/gitlab.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import fs from 'node:fs';
2
- import test from 'ava';
3
- import sinon from 'sinon';
4
- import nock from 'nock';
2
+ import test, { before, after, afterEach, beforeEach, describe } from 'node:test';
3
+ import assert from 'node:assert/strict';
5
4
  import { Agent } from 'undici';
5
+ import { MockServer, FetchMocker } from 'mentoss';
6
6
  import Git from '../lib/plugin/git/Git.js';
7
7
  import GitLab from '../lib/plugin/gitlab/GitLab.js';
8
8
  import { GitlabTestServer } from './util/https-server/server.js';
@@ -16,402 +16,441 @@ import {
16
16
  interceptMilestones
17
17
  } from './stub/gitlab.js';
18
18
 
19
- const tokenHeader = 'Private-Token';
20
- const tokenRef = 'GITLAB_TOKEN';
19
+ describe('GitLab', () => {
20
+ const tokenHeader = 'Private-Token';
21
+ const tokenRef = 'GITLAB_TOKEN';
22
+ const certificateAuthorityFileRef = 'CI_SERVER_TLS_CA_FILE';
21
23
 
22
- test.serial('should validate token', async t => {
23
- const tokenRef = 'MY_GITLAB_TOKEN';
24
- const pushRepo = 'https://gitlab.com/user/repo';
25
- const options = { gitlab: { release: true, tokenRef, tokenHeader, pushRepo } };
26
- const gitlab = factory(GitLab, { options });
27
- delete process.env[tokenRef];
24
+ const api = new MockServer('https://gitlab.com/api/v4');
25
+ const example = new MockServer('https://gitlab.example.org/api/v4');
26
+ const local = new MockServer('https://localhost:3000/api/v4');
28
27
 
29
- await t.throwsAsync(gitlab.init(), {
30
- message: /^Environment variable "MY_GITLAB_TOKEN" is required for GitLab releases/
28
+ const mocker = new FetchMocker({
29
+ servers: [api, example, local]
31
30
  });
32
- process.env[tokenRef] = '123';
33
31
 
34
- interceptUser(undefined, { reqheaders: { 'private-token': '123' } });
35
- interceptCollaborator(undefined, { reqheaders: { 'private-token': '123' } });
36
- await t.notThrowsAsync(gitlab.init());
37
- });
32
+ before(() => {
33
+ mocker.mockGlobal();
34
+ });
38
35
 
39
- test.serial('should support CI Job token header', async t => {
40
- const tokenRef = 'CI_JOB_TOKEN';
41
- const tokenHeader = 'Job-Token';
42
- process.env[tokenRef] = 'j0b-t0k3n';
43
- const pushRepo = 'https://gitlab.com/user/repo';
44
- const options = { git: { pushRepo }, gitlab: { release: true, tokenRef, tokenHeader } };
45
- const gitlab = factory(GitLab, { options });
36
+ let originalEnv;
37
+ beforeEach(() => {
38
+ originalEnv = process.env;
39
+ process.env = { ...originalEnv };
46
40
 
47
- interceptPublish(undefined, { reqheaders: { 'job-token': '1' } });
41
+ process.env[tokenRef] = '123';
42
+ });
48
43
 
49
- await t.notThrowsAsync(gitlab.init());
44
+ afterEach(() => {
45
+ if (originalEnv !== undefined) process.env = originalEnv;
46
+ mocker.clearAll();
47
+ });
50
48
 
51
- delete process.env[tokenRef];
52
- });
49
+ after(() => {
50
+ mocker.unmockGlobal();
51
+ });
53
52
 
54
- test.serial('should upload assets and release', async t => {
55
- const pushRepo = 'https://gitlab.com/user/repo';
56
- const options = {
57
- git: { pushRepo },
58
- gitlab: {
59
- tokenRef,
60
- release: true,
61
- releaseName: 'Release ${version}',
62
- releaseNotes: 'echo Custom notes',
63
- assets: 'test/resources/file-v${version}.txt',
64
- milestones: ['${version}', '${latestVersion} UAT']
65
- }
66
- };
67
- const gitlab = factory(GitLab, { options });
68
- sinon.stub(gitlab, 'getLatestVersion').resolves('2.0.0');
69
-
70
- const git = factory(Git);
71
- const ref = (await git.getBranchName()) ?? 'HEAD';
72
-
73
- interceptUser();
74
- interceptCollaborator();
75
- interceptMilestones({
76
- query: { title: '2.0.1' },
77
- milestones: [
78
- {
79
- id: 17,
80
- iid: 3,
81
- title: '2.0.1'
82
- }
83
- ]
53
+ test('should validate token', async () => {
54
+ const tokenRef = 'MY_GITLAB_TOKEN';
55
+ const pushRepo = 'https://gitlab.com/user/repo';
56
+ const options = { gitlab: { release: true, tokenRef, tokenHeader, pushRepo } };
57
+ const gitlab = factory(GitLab, { options });
58
+ delete process.env[tokenRef];
59
+
60
+ await assert.rejects(gitlab.init(), /Environment variable "MY_GITLAB_TOKEN" is required for GitLab releases/);
61
+
62
+ process.env[tokenRef] = '123';
63
+
64
+ interceptUser(api, { headers: { 'private-token': '123' } });
65
+ interceptCollaborator(api, { headers: { 'private-token': '123' } });
66
+ await assert.doesNotReject(gitlab.init());
84
67
  });
85
- interceptMilestones({
86
- query: { title: '2.0.0 UAT' },
87
- milestones: [
88
- {
89
- id: 42,
90
- iid: 4,
91
- title: '2.0.0 UAT'
92
- }
93
- ]
68
+
69
+ test('should support CI Job token header', async () => {
70
+ const tokenRef = 'CI_JOB_TOKEN';
71
+ const tokenHeader = 'Job-Token';
72
+ process.env[tokenRef] = 'j0b-t0k3n';
73
+ const pushRepo = 'https://gitlab.com/user/repo';
74
+ const options = { git: { pushRepo }, gitlab: { release: true, tokenRef, tokenHeader } };
75
+ const gitlab = factory(GitLab, { options });
76
+
77
+ interceptPublish(api, { headers: { 'job-token': '1' } });
78
+
79
+ await assert.doesNotReject(gitlab.init());
80
+
81
+ delete process.env[tokenRef];
94
82
  });
95
- interceptAsset();
96
- interceptPublish({
97
- body: {
98
- name: 'Release 2.0.1',
99
- ref,
100
- tag_name: '2.0.1',
101
- tag_message: 'Release 2.0.1',
102
- description: 'Custom notes',
103
- assets: {
104
- links: [
105
- {
106
- name: 'file-v2.0.1.txt',
107
- url: `${pushRepo}/uploads/7e8bec1fe27cc46a4bc6a91b9e82a07c/file-v2.0.1.txt`
108
- }
109
- ]
110
- },
111
- milestones: ['2.0.1', '2.0.0 UAT']
112
- }
83
+
84
+ test('should upload assets and release', async t => {
85
+ const pushRepo = 'https://gitlab.com/user/repo';
86
+ const options = {
87
+ git: { pushRepo },
88
+ gitlab: {
89
+ tokenRef,
90
+ release: true,
91
+ releaseName: 'Release ${version}',
92
+ releaseNotes: 'echo Custom notes',
93
+ assets: 'test/resources/file-v${version}.txt',
94
+ milestones: ['${version}', '${latestVersion} UAT']
95
+ }
96
+ };
97
+ const gitlab = factory(GitLab, { options });
98
+ t.mock.method(gitlab, 'getLatestVersion', () => Promise.resolve('2.0.0'));
99
+
100
+ const git = factory(Git);
101
+ const ref = (await git.getBranchName()) ?? 'HEAD';
102
+
103
+ interceptUser(api);
104
+ interceptCollaborator(api);
105
+ interceptMilestones(api, { query: { title: '2.0.1' }, milestones: [{ id: 17, iid: 3, title: '2.0.1' }] });
106
+ interceptMilestones(api, { query: { title: '2.0.0 UAT' }, milestones: [{ id: 42, iid: 4, title: '2.0.0 UAT' }] });
107
+ interceptAsset(api);
108
+ interceptPublish(api, {
109
+ body: {
110
+ name: 'Release 2.0.1',
111
+ ref,
112
+ tag_name: '2.0.1',
113
+ tag_message: 'Release 2.0.1',
114
+ description: 'Custom notes',
115
+ assets: {
116
+ links: [
117
+ { name: 'file-v2.0.1.txt', url: `${pushRepo}/uploads/7e8bec1fe27cc46a4bc6a91b9e82a07c/file-v2.0.1.txt` }
118
+ ]
119
+ },
120
+ milestones: ['2.0.1', '2.0.0 UAT']
121
+ }
122
+ });
123
+
124
+ await runTasks(gitlab);
125
+
126
+ assert.equal(gitlab.assets[0].url, `${pushRepo}/uploads/7e8bec1fe27cc46a4bc6a91b9e82a07c/file-v2.0.1.txt`);
127
+ const { isReleased, releaseUrl } = gitlab.getContext();
128
+ assert(isReleased);
129
+ assert.equal(releaseUrl, `${pushRepo}/-/releases/2.0.1`);
113
130
  });
114
131
 
115
- await runTasks(gitlab);
132
+ test('should upload assets with ID-based URLs too', async t => {
133
+ const host = 'https://gitlab.com';
134
+ const pushRepo = `${host}/user/repo`;
135
+ const options = {
136
+ git: { pushRepo },
137
+ gitlab: {
138
+ tokenRef,
139
+ release: true,
140
+ assets: 'test/resources/file-v${version}.txt',
141
+ useIdsForUrls: true
142
+ }
143
+ };
116
144
 
117
- t.is(gitlab.assets[0].url, `${pushRepo}/uploads/7e8bec1fe27cc46a4bc6a91b9e82a07c/file-v2.0.1.txt`);
118
- const { isReleased, releaseUrl } = gitlab.getContext();
119
- t.true(isReleased);
120
- t.is(releaseUrl, `${pushRepo}/-/releases/2.0.1`);
121
- });
145
+ const gitlab = factory(GitLab, { options });
146
+ t.mock.method(gitlab, 'getLatestVersion', () => Promise.resolve('2.0.0'));
122
147
 
123
- test.serial('should upload assets with ID-based URLs too', async t => {
124
- const host = 'https://gitlab.com';
125
- const pushRepo = `${host}/user/repo`;
126
- const options = {
127
- git: { pushRepo },
128
- gitlab: {
129
- tokenRef,
130
- release: true,
131
- assets: 'test/resources/file-v${version}.txt',
132
- useIdsForUrls: true
133
- }
134
- };
135
- const gitlab = factory(GitLab, { options });
136
- sinon.stub(gitlab, 'getLatestVersion').resolves('2.0.0');
137
-
138
- interceptUser();
139
- interceptCollaborator();
140
- interceptAsset();
141
- interceptPublish();
142
-
143
- await runTasks(gitlab);
144
-
145
- t.is(gitlab.assets[0].url, `${host}/-/project/1234/uploads/7e8bec1fe27cc46a4bc6a91b9e82a07c/file-v2.0.1.txt`);
146
- });
148
+ interceptUser(api);
149
+ interceptCollaborator(api);
150
+ interceptAsset(api);
151
+ interceptPublish(api);
147
152
 
148
- test.serial('should upload assets to generic repo', async t => {
149
- const host = 'https://gitlab.com';
150
- const pushRepo = `${host}/user/repo`;
151
- const options = {
152
- git: { pushRepo },
153
- gitlab: {
154
- tokenRef,
155
- release: true,
156
- assets: 'test/resources/file-v${version}.txt',
157
- useGenericPackageRepositoryForAssets: true,
158
- genericPackageRepositoryName: 'release-it'
159
- }
160
- };
161
- const gitlab = factory(GitLab, { options });
162
- sinon.stub(gitlab, 'getLatestVersion').resolves('2.0.0');
163
-
164
- interceptUser();
165
- interceptCollaborator();
166
- interceptAssetGeneric();
167
- interceptPublish();
168
-
169
- await runTasks(gitlab);
170
-
171
- t.is(gitlab.assets[0].url, `${host}/api/v4/projects/user%2Frepo/packages/generic/release-it/2.0.1/file-v2.0.1.txt`);
172
- });
153
+ await runTasks(gitlab);
173
154
 
174
- test.serial('should throw when release milestone is missing', async t => {
175
- const pushRepo = 'https://gitlab.com/user/repo';
176
- const options = {
177
- git: { pushRepo },
178
- gitlab: {
179
- tokenRef,
180
- release: true,
181
- milestones: ['${version}', '${latestVersion} UAT']
182
- }
183
- };
184
- const gitlab = factory(GitLab, { options });
185
- sinon.stub(gitlab, 'getLatestVersion').resolves('2.0.0');
186
-
187
- interceptUser();
188
- interceptCollaborator();
189
- interceptMilestones({
190
- query: { title: '2.0.1' },
191
- milestones: [
192
- {
193
- id: 17,
194
- iid: 3,
195
- title: '2.0.1'
155
+ assert.equal(
156
+ gitlab.assets[0].url,
157
+ `${host}/-/project/1234/uploads/7e8bec1fe27cc46a4bc6a91b9e82a07c/file-v2.0.1.txt`
158
+ );
159
+ });
160
+
161
+ test('should upload assets to generic repo', async t => {
162
+ const host = 'https://gitlab.com';
163
+ const pushRepo = `${host}/user/repo`;
164
+ const options = {
165
+ git: { pushRepo },
166
+ gitlab: {
167
+ tokenRef,
168
+ release: true,
169
+ assets: 'test/resources/file-v${version}.txt',
170
+ useGenericPackageRepositoryForAssets: true,
171
+ genericPackageRepositoryName: 'release-it'
196
172
  }
197
- ]
173
+ };
174
+ const gitlab = factory(GitLab, { options });
175
+ t.mock.method(gitlab, 'getLatestVersion', () => Promise.resolve('2.0.0'));
176
+
177
+ interceptUser(api);
178
+ interceptCollaborator(api);
179
+ interceptAssetGeneric(api);
180
+ interceptPublish(api);
181
+
182
+ await runTasks(gitlab);
183
+
184
+ assert.equal(
185
+ gitlab.assets[0].url,
186
+ `${host}/api/v4/projects/user%2Frepo/packages/generic/release-it/2.0.1/file-v2.0.1.txt`
187
+ );
198
188
  });
199
- interceptMilestones({
200
- query: { title: '2.0.0 UAT' },
201
- milestones: []
189
+
190
+ test('should throw when release milestone is missing', async t => {
191
+ const pushRepo = 'https://gitlab.com/user/repo';
192
+ const options = {
193
+ git: { pushRepo },
194
+ gitlab: {
195
+ tokenRef,
196
+ release: true,
197
+ milestones: ['${version}', '${latestVersion} UAT']
198
+ }
199
+ };
200
+ const gitlab = factory(GitLab, { options });
201
+ t.mock.method(gitlab, 'getLatestVersion', () => Promise.resolve('2.0.0'));
202
+
203
+ interceptUser(api);
204
+ interceptCollaborator(api);
205
+ interceptMilestones(api, { query: { title: '2.0.1' }, milestones: [{ id: 17, iid: 3, title: '2.0.1' }] });
206
+ interceptMilestones(api, { query: { title: '2.0.0 UAT' }, milestones: [] });
207
+
208
+ await assert.rejects(
209
+ runTasks(gitlab),
210
+ /Missing one or more milestones in GitLab. Creating a GitLab release will fail./
211
+ );
202
212
  });
203
213
 
204
- await t.throwsAsync(runTasks(gitlab), {
205
- message: /^Missing one or more milestones in GitLab. Creating a GitLab release will fail./
214
+ test('should release to self-managed host', async t => {
215
+ const host = 'https://gitlab.example.org';
216
+ const options = {
217
+ git: { pushRepo: `${host}/user/repo` },
218
+ gitlab: { releaseName: 'Release ${version}', releaseNotes: 'echo readme', tokenRef }
219
+ };
220
+ const gitlab = factory(GitLab, { options });
221
+ t.mock.method(gitlab, 'getLatestVersion', () => Promise.resolve('1.0.0'));
222
+
223
+ interceptUser(example);
224
+ interceptCollaborator(example);
225
+ interceptPublish(example);
226
+
227
+ await runTasks(gitlab);
228
+
229
+ const { origin, baseUrl } = gitlab.getContext();
230
+ assert.equal(origin, host);
231
+ assert.equal(baseUrl, `${host}/api/v4`);
206
232
  });
207
- });
208
233
 
209
- test.serial('should release to self-managed host', async t => {
210
- const host = 'https://gitlab.example.org';
211
- const scope = nock(host);
212
- scope.post('/api/v4/projects/user%2Frepo/releases').reply(200, {});
213
- const options = {
214
- git: { pushRepo: `${host}/user/repo` },
215
- gitlab: { releaseName: 'Release ${version}', releaseNotes: 'echo readme', tokenRef }
216
- };
217
- const gitlab = factory(GitLab, { options });
218
- sinon.stub(gitlab, 'getLatestVersion').resolves('1.0.0');
219
-
220
- interceptUser({ host });
221
- interceptCollaborator({ host });
222
-
223
- await runTasks(gitlab);
224
-
225
- const { origin, baseUrl } = gitlab.getContext();
226
- t.is(origin, host);
227
- t.is(baseUrl, `${host}/api/v4`);
228
- });
234
+ test('should release to sub-grouped repo', async () => {
235
+ const options = { gitlab: { tokenRef }, git: { pushRepo: 'git@gitlab.com:group/sub-group/repo.git' } };
236
+ const gitlab = factory(GitLab, { options });
229
237
 
230
- test.serial('should release to sub-grouped repo', async t => {
231
- const scope = nock('https://gitlab.com');
232
- scope.post('/api/v4/projects/group%2Fsub-group%2Frepo/releases').reply(200, {});
233
- const options = { gitlab: { tokenRef }, git: { pushRepo: 'git@gitlab.com:group/sub-group/repo.git' } };
234
- const gitlab = factory(GitLab, { options });
238
+ interceptUser(api, { owner: 'sub-group' });
239
+ interceptCollaborator(api, { owner: 'sub-group', group: 'group' });
240
+ interceptPublish(api, { owner: 'group', project: 'sub-group%2Frepo' });
235
241
 
236
- interceptUser({ owner: 'sub-group' });
237
- interceptCollaborator({ owner: 'sub-group', group: 'group' });
242
+ await runTasks(gitlab);
238
243
 
239
- await runTasks(gitlab);
244
+ const { isReleased, releaseUrl } = gitlab.getContext();
245
+ assert(isReleased);
246
+ assert.match(releaseUrl, /https:\/\/gitlab.com\/group\/sub-group(\/|%2F)repo\/-\/releases\//);
247
+ });
240
248
 
241
- const { isReleased, releaseUrl } = gitlab.getContext();
242
- t.true(isReleased);
243
- t.regex(releaseUrl, /https:\/\/gitlab.com\/group\/sub-group\/repo\/-\/releases\//);
244
- });
249
+ test('should throw for unauthenticated user', async () => {
250
+ const host = 'https://gitlab.com';
251
+ const pushRepo = `${host}/user/repo`;
252
+ const options = { gitlab: { tokenRef, pushRepo, host } };
253
+ const gitlab = factory(GitLab, { options });
245
254
 
246
- test.serial('should throw for unauthenticated user', async t => {
247
- const host = 'https://gitlab.com';
248
- const pushRepo = `${host}/user/repo`;
249
- const options = { gitlab: { tokenRef, pushRepo, host } };
250
- const gitlab = factory(GitLab, { options });
251
- const scope = nock(host);
252
- scope.get(`/api/v4/user`).reply(401);
255
+ api.get('/user', { status: 401 });
253
256
 
254
- await t.throwsAsync(runTasks(gitlab), {
255
- message: /^Could not authenticate with GitLab using environment variable "GITLAB_TOKEN"/
257
+ await assert.rejects(
258
+ runTasks(gitlab),
259
+ /Could not authenticate with GitLab using environment variable "GITLAB_TOKEN"/
260
+ );
256
261
  });
257
- });
258
262
 
259
- test.serial('should throw for non-collaborator', async t => {
260
- const host = 'https://gitlab.com';
261
- const pushRepo = `${host}/john/repo`;
262
- const options = { gitlab: { tokenRef, pushRepo, host } };
263
- const gitlab = factory(GitLab, { options });
264
- const scope = nock(host);
265
- scope.get(`/api/v4/projects/john%2Frepo/members/all/1`).reply(200, { username: 'emma' });
266
- interceptUser({ owner: 'john' });
263
+ test('should throw for non-collaborator', async () => {
264
+ const host = 'https://gitlab.com';
265
+ const pushRepo = `${host}/john/repo`;
266
+ const options = { gitlab: { tokenRef, pushRepo, host } };
267
+ const gitlab = factory(GitLab, { options });
267
268
 
268
- await t.throwsAsync(runTasks(gitlab), { message: /^User john is not a collaborator for john\/repo/ });
269
- });
269
+ api.get(`/projects/john%2Frepo/members/all/1`, { status: 200, username: 'emma' });
270
+ interceptUser(api, { owner: 'john' });
270
271
 
271
- test.serial('should throw for insufficient access level', async t => {
272
- const host = 'https://gitlab.com';
273
- const pushRepo = `${host}/john/repo`;
274
- const options = { gitlab: { tokenRef, pushRepo, host } };
275
- const gitlab = factory(GitLab, { options });
276
- const scope = nock(host);
277
- scope.get(`/api/v4/projects/john%2Frepo/members/all/1`).reply(200, { username: 'john', access_level: 10 });
278
- interceptUser({ owner: 'john' });
272
+ await assert.rejects(runTasks(gitlab), /User john is not a collaborator for john\/repo/);
273
+ });
279
274
 
280
- await t.throwsAsync(runTasks(gitlab), { message: /^User john is not a collaborator for john\/repo/ });
281
- });
275
+ test('should throw for insufficient access level', async () => {
276
+ const host = 'https://gitlab.com';
277
+ const pushRepo = `${host}/john/repo`;
278
+ const options = { gitlab: { tokenRef, pushRepo, host } };
279
+ const gitlab = factory(GitLab, { options });
282
280
 
283
- test('should not make requests in dry run', async t => {
284
- const [host, owner, repo] = ['https://gitlab.example.org', 'user', 'repo'];
285
- const pushRepo = `${host}/${owner}/${repo}`;
286
- const options = { 'dry-run': true, git: { pushRepo }, gitlab: { releaseName: 'R', tokenRef } };
287
- const gitlab = factory(GitLab, { options });
288
- sinon.stub(gitlab, 'getLatestVersion').resolves('1.0.0');
281
+ api.get(`/projects/john%2Frepo/members/all/1`, { status: 200, username: 'john', access_level: 10 });
282
+ interceptUser(api, { owner: 'john' });
289
283
 
290
- await runTasks(gitlab);
284
+ await assert.rejects(runTasks(gitlab), /User john is not a collaborator for john\/repo/);
285
+ });
291
286
 
292
- const { isReleased, releaseUrl } = gitlab.getContext();
287
+ test('should not make requests in dry run', async t => {
288
+ const [host, owner, repo] = ['https://gitlab.example.org', 'user', 'repo'];
289
+ const pushRepo = `${host}/${owner}/${repo}`;
290
+ const options = { 'dry-run': true, git: { pushRepo }, gitlab: { releaseName: 'R', tokenRef } };
291
+ const gitlab = factory(GitLab, { options });
292
+ t.mock.method(gitlab, 'getLatestVersion', () => Promise.resolve('1.0.0'));
293
293
 
294
- t.is(gitlab.log.exec.args[2][0], 'gitlab releases#uploadAssets');
295
- t.is(gitlab.log.exec.args[3][0], 'gitlab releases#createRelease "R" (1.0.1)');
296
- t.true(isReleased);
297
- t.is(releaseUrl, `${pushRepo}/-/releases/1.0.1`);
298
- });
294
+ await runTasks(gitlab);
299
295
 
300
- test('should skip checks', async t => {
301
- const options = { gitlab: { tokenRef, skipChecks: true, release: true, milestones: ['v1.0.0'] } };
302
- const gitlab = factory(GitLab, { options });
296
+ const { isReleased, releaseUrl } = gitlab.getContext();
303
297
 
304
- await t.notThrowsAsync(gitlab.init());
305
- await t.notThrowsAsync(gitlab.beforeRelease());
298
+ assert.equal(gitlab.log.exec.mock.calls[2].arguments[0], 'gitlab releases#uploadAssets');
299
+ assert.equal(gitlab.log.exec.mock.calls[3].arguments[0], 'gitlab releases#createRelease "R" (1.0.1)');
300
+ assert(isReleased);
301
+ assert.equal(releaseUrl, `${pushRepo}/-/releases/1.0.1`);
302
+ });
306
303
 
307
- t.is(gitlab.log.exec.args.filter(entry => /checkReleaseMilestones/.test(entry[0])).length, 0);
308
- });
304
+ test('should skip checks', async () => {
305
+ const options = { gitlab: { tokenRef, skipChecks: true, release: true, milestones: ['v1.0.0'] } };
306
+ const gitlab = factory(GitLab, { options });
309
307
 
310
- test.serial('should not create fetch agent', t => {
311
- const options = { gitlab: {} };
312
- const gitlab = factory(GitLab, { options });
308
+ await assert.doesNotReject(gitlab.init());
309
+ await assert.doesNotReject(gitlab.beforeRelease());
313
310
 
314
- t.deepEqual(gitlab.certificateAuthorityOption, {});
315
- });
311
+ assert.equal(
312
+ gitlab.log.exec.mock.calls
313
+ .flatMap(call => call.arguments)
314
+ .filter(entry => /checkReleaseMilestones/.test(entry[0])).length,
315
+ 0
316
+ );
317
+ });
316
318
 
317
- test.serial('should create fetch agent if secure == false', t => {
318
- const options = { gitlab: { secure: false } };
319
- const gitlab = factory(GitLab, { options });
320
- const { dispatcher } = gitlab.certificateAuthorityOption;
319
+ test('should not create fetch agent', () => {
320
+ const options = { gitlab: {} };
321
+ const gitlab = factory(GitLab, { options });
321
322
 
322
- t.true(dispatcher instanceof Agent, "Fetch dispatcher should be an instance of undici's Agent class");
323
+ assert.deepEqual(gitlab.certificateAuthorityOption, {});
324
+ });
323
325
 
324
- const kOptions = Object.getOwnPropertySymbols(dispatcher).find(symbol => symbol.description === 'options');
325
- t.deepEqual(dispatcher[kOptions].connect, { rejectUnauthorized: false, ca: undefined });
326
- });
326
+ test('should create fetch agent if secure == false', () => {
327
+ const options = { gitlab: { secure: false } };
328
+ const gitlab = factory(GitLab, { options });
329
+ const { dispatcher } = gitlab.certificateAuthorityOption;
327
330
 
328
- test.serial('should create fetch agent if certificateAuthorityFile', t => {
329
- const sandbox = sinon.createSandbox();
330
- sandbox.stub(fs, 'readFileSync').returns('test certificate');
331
+ assert(dispatcher instanceof Agent, "Fetch dispatcher should be an instance of undici's Agent class");
331
332
 
332
- const options = { gitlab: { certificateAuthorityFile: 'cert.crt' } };
333
- const gitlab = factory(GitLab, { options });
334
- const { dispatcher } = gitlab.certificateAuthorityOption;
333
+ const kOptions = Object.getOwnPropertySymbols(dispatcher).find(symbol => symbol.description === 'options');
334
+ assert.deepEqual(dispatcher[kOptions].connect, { rejectUnauthorized: false, ca: undefined });
335
+ });
335
336
 
336
- t.true(dispatcher instanceof Agent, "Fetch dispatcher should be an instance of undici's Agent class");
337
+ test('should create fetch agent if certificateAuthorityFile', t => {
338
+ const readFileSync = t.mock.method(fs, 'readFileSync', () => 'test certificate');
337
339
 
338
- const kOptions = Object.getOwnPropertySymbols(dispatcher).find(symbol => symbol.description === 'options');
339
- t.deepEqual(dispatcher[kOptions].connect, { rejectUnauthorized: undefined, ca: 'test certificate' });
340
+ const options = { gitlab: { certificateAuthorityFile: 'cert.crt' } };
341
+ const gitlab = factory(GitLab, { options });
342
+ const { dispatcher } = gitlab.certificateAuthorityOption;
340
343
 
341
- sandbox.restore();
342
- });
344
+ assert(dispatcher instanceof Agent, "Fetch dispatcher should be an instance of undici's Agent class");
345
+
346
+ const kOptions = Object.getOwnPropertySymbols(dispatcher).find(symbol => symbol.description === 'options');
347
+ assert.deepEqual(dispatcher[kOptions].connect, { rejectUnauthorized: undefined, ca: 'test certificate' });
348
+
349
+ readFileSync.mock.restore();
350
+ });
351
+
352
+ test('should create fetch agent if CI_SERVER_TLS_CA_FILE env is set', t => {
353
+ const readFileSync = t.mock.method(fs, 'readFileSync', () => 'test certificate');
354
+ process.env[certificateAuthorityFileRef] = 'ca.crt';
355
+
356
+ const options = { gitlab: {} };
357
+ const gitlab = factory(GitLab, { options });
358
+ const { dispatcher } = gitlab.certificateAuthorityOption;
343
359
 
344
- test.serial('should throw for insecure connections to self-hosted instances', async t => {
345
- const host = 'https://localhost:3000';
360
+ assert(dispatcher instanceof Agent, "Fetch dispatcher should be an instance of undici's Agent class");
346
361
 
347
- const options = {
348
- git: { pushRepo: `${host}/user/repo` },
349
- gitlab: { host, tokenRef, origin: host }
350
- };
351
- const gitlab = factory(GitLab, { options });
352
- const server = new GitlabTestServer();
362
+ const kOptions = Object.getOwnPropertySymbols(dispatcher).find(symbol => symbol.description === 'options');
363
+ assert.deepEqual(dispatcher[kOptions].connect, { rejectUnauthorized: undefined, ca: 'test certificate' });
353
364
 
354
- t.teardown(async () => {
355
- nock.disableNetConnect();
356
- await server.stop();
365
+ readFileSync.mock.restore();
357
366
  });
358
367
 
359
- await server.run();
360
- nock.enableNetConnect();
368
+ test('should create fetch agent if certificateAuthorityFileRef env is set', t => {
369
+ const readFileSync = t.mock.method(fs, 'readFileSync', () => 'test certificate');
370
+ process.env['GITLAB_CA_FILE'] = 'custom-ca.crt';
361
371
 
362
- await t.throwsAsync(gitlab.init(), {
363
- message: /^Could not authenticate with GitLab using environment variable "GITLAB_TOKEN"/
372
+ const options = { gitlab: { certificateAuthorityFileRef: 'GITLAB_CA_FILE' } };
373
+ const gitlab = factory(GitLab, { options });
374
+ const { dispatcher } = gitlab.certificateAuthorityOption;
375
+
376
+ assert(dispatcher instanceof Agent, "Fetch dispatcher should be an instance of undici's Agent class");
377
+
378
+ const kOptions = Object.getOwnPropertySymbols(dispatcher).find(symbol => symbol.description === 'options');
379
+ assert.deepEqual(dispatcher[kOptions].connect, { rejectUnauthorized: undefined, ca: 'test certificate' });
380
+
381
+ readFileSync.mock.restore();
364
382
  });
365
- });
366
383
 
367
- test.serial('should succesfully connect to self-hosted instance if insecure connection allowed', async t => {
368
- const host = 'https://localhost:3000';
369
-
370
- const options = {
371
- git: { pushRepo: `${host}/user/repo` },
372
- gitlab: {
373
- host,
374
- tokenRef,
375
- origin: host,
376
- secure: false
377
- }
378
- };
379
- const gitlab = factory(GitLab, { options });
380
- const server = new GitlabTestServer();
381
-
382
- t.teardown(async () => {
383
- nock.disableNetConnect();
384
- await server.stop();
384
+ test('should throw for insecure connections to self-hosted instances', async t => {
385
+ const host = 'https://localhost:3000';
386
+
387
+ const options = {
388
+ git: { pushRepo: `${host}/user/repo` },
389
+ gitlab: { host, tokenRef, origin: host }
390
+ };
391
+ const gitlab = factory(GitLab, { options });
392
+ const server = new GitlabTestServer();
393
+
394
+ t.after(async () => {
395
+ await server.stop();
396
+ });
397
+
398
+ await server.run();
399
+
400
+ await assert.rejects(gitlab.init(), /Could not authenticate with GitLab using environment variable "GITLAB_TOKEN"/);
385
401
  });
386
402
 
387
- await server.run();
388
- nock.enableNetConnect();
403
+ test('should succesfully connect to self-hosted instance if insecure connection allowed', async t => {
404
+ const host = 'https://localhost:3000';
389
405
 
390
- await t.notThrowsAsync(gitlab.init());
391
- });
406
+ const options = {
407
+ git: { pushRepo: `${host}/user/repo` },
408
+ gitlab: {
409
+ host,
410
+ tokenRef,
411
+ origin: host,
412
+ secure: false
413
+ }
414
+ };
415
+ const gitlab = factory(GitLab, { options });
416
+ const server = new GitlabTestServer();
392
417
 
393
- test.serial('should succesfully connect to self-hosted instance with valid CA file', async t => {
394
- const host = 'https://localhost:3000';
395
-
396
- const options = {
397
- git: { pushRepo: `${host}/user/repo` },
398
- gitlab: {
399
- host,
400
- tokenRef,
401
- origin: host,
402
- certificateAuthorityFile: 'test/util/https-server/client/my-private-root-ca.cert.pem'
403
- }
404
- };
405
- const gitlab = factory(GitLab, { options });
406
- const server = new GitlabTestServer();
407
-
408
- t.teardown(async () => {
409
- nock.disableNetConnect();
410
- await server.stop();
418
+ t.after(async () => {
419
+ await server.stop();
420
+ });
421
+
422
+ await server.run();
423
+
424
+ interceptUser(local);
425
+ interceptCollaborator(local);
426
+
427
+ await assert.doesNotReject(gitlab.init());
411
428
  });
412
429
 
413
- await server.run();
414
- nock.enableNetConnect();
430
+ test('should succesfully connect to self-hosted instance with valid CA file', async t => {
431
+ const host = 'https://localhost:3000';
432
+
433
+ const options = {
434
+ git: { pushRepo: `${host}/user/repo` },
435
+ gitlab: {
436
+ host,
437
+ tokenRef,
438
+ origin: host,
439
+ certificateAuthorityFile: 'test/util/https-server/client/my-private-root-ca.cert.pem'
440
+ }
441
+ };
442
+ const gitlab = factory(GitLab, { options });
443
+ const server = new GitlabTestServer();
415
444
 
416
- await t.notThrowsAsync(gitlab.init());
445
+ t.after(async () => {
446
+ await server.stop();
447
+ });
448
+
449
+ await server.run();
450
+
451
+ interceptUser(local);
452
+ interceptCollaborator(local);
453
+
454
+ await assert.doesNotReject(gitlab.init());
455
+ });
417
456
  });