@backstage/integration 1.15.1-next.0 → 1.15.1
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/CHANGELOG.md +20 -0
- package/dist/ScmIntegrations.cjs.js +110 -0
- package/dist/ScmIntegrations.cjs.js.map +1 -0
- package/dist/awsCodeCommit/AwsCodeCommitIntegration.cjs.js +58 -0
- package/dist/awsCodeCommit/AwsCodeCommitIntegration.cjs.js.map +1 -0
- package/dist/awsCodeCommit/config.cjs.js +26 -0
- package/dist/awsCodeCommit/config.cjs.js.map +1 -0
- package/dist/awsS3/AwsS3Integration.cjs.js +38 -0
- package/dist/awsS3/AwsS3Integration.cjs.js.map +1 -0
- package/dist/awsS3/config.cjs.js +53 -0
- package/dist/awsS3/config.cjs.js.map +1 -0
- package/dist/azure/AzureIntegration.cjs.js +62 -0
- package/dist/azure/AzureIntegration.cjs.js.map +1 -0
- package/dist/azure/AzureUrl.cjs.js +189 -0
- package/dist/azure/AzureUrl.cjs.js.map +1 -0
- package/dist/azure/CachedAzureDevOpsCredentialsProvider.cjs.js +76 -0
- package/dist/azure/CachedAzureDevOpsCredentialsProvider.cjs.js.map +1 -0
- package/dist/azure/DefaultAzureDevOpsCredentialsProvider.cjs.js +75 -0
- package/dist/azure/DefaultAzureDevOpsCredentialsProvider.cjs.js.map +1 -0
- package/dist/azure/config.cjs.js +153 -0
- package/dist/azure/config.cjs.js.map +1 -0
- package/dist/azure/core.cjs.js +18 -0
- package/dist/azure/core.cjs.js.map +1 -0
- package/dist/azure/deprecated.cjs.js +26 -0
- package/dist/azure/deprecated.cjs.js.map +1 -0
- package/dist/bitbucket/BitbucketIntegration.cjs.js +65 -0
- package/dist/bitbucket/BitbucketIntegration.cjs.js.map +1 -0
- package/dist/bitbucket/config.cjs.js +47 -0
- package/dist/bitbucket/config.cjs.js.map +1 -0
- package/dist/bitbucket/core.cjs.js +95 -0
- package/dist/bitbucket/core.cjs.js.map +1 -0
- package/dist/bitbucketCloud/BitbucketCloudIntegration.cjs.js +54 -0
- package/dist/bitbucketCloud/BitbucketCloudIntegration.cjs.js.map +1 -0
- package/dist/bitbucketCloud/config.cjs.js +30 -0
- package/dist/bitbucketCloud/config.cjs.js.map +1 -0
- package/dist/bitbucketCloud/core.cjs.js +78 -0
- package/dist/bitbucketCloud/core.cjs.js.map +1 -0
- package/dist/bitbucketServer/BitbucketServerIntegration.cjs.js +48 -0
- package/dist/bitbucketServer/BitbucketServerIntegration.cjs.js.map +1 -0
- package/dist/bitbucketServer/config.cjs.js +36 -0
- package/dist/bitbucketServer/config.cjs.js.map +1 -0
- package/dist/bitbucketServer/core.cjs.js +73 -0
- package/dist/bitbucketServer/core.cjs.js.map +1 -0
- package/dist/gerrit/GerritIntegration.cjs.js +52 -0
- package/dist/gerrit/GerritIntegration.cjs.js.map +1 -0
- package/dist/gerrit/config.cjs.js +60 -0
- package/dist/gerrit/config.cjs.js.map +1 -0
- package/dist/gerrit/core.cjs.js +179 -0
- package/dist/gerrit/core.cjs.js.map +1 -0
- package/dist/gitea/GiteaIntegration.cjs.js +34 -0
- package/dist/gitea/GiteaIntegration.cjs.js.map +1 -0
- package/dist/gitea/config.cjs.js +34 -0
- package/dist/gitea/config.cjs.js.map +1 -0
- package/dist/gitea/core.cjs.js +59 -0
- package/dist/gitea/core.cjs.js.map +1 -0
- package/dist/github/DefaultGithubCredentialsProvider.cjs.js +54 -0
- package/dist/github/DefaultGithubCredentialsProvider.cjs.js.map +1 -0
- package/dist/github/GithubIntegration.cjs.js +51 -0
- package/dist/github/GithubIntegration.cjs.js.map +1 -0
- package/dist/github/SingleInstanceGithubCredentialsProvider.cjs.js +211 -0
- package/dist/github/SingleInstanceGithubCredentialsProvider.cjs.js.map +1 -0
- package/dist/github/config.cjs.js +55 -0
- package/dist/github/config.cjs.js.map +1 -0
- package/dist/github/core.cjs.js +46 -0
- package/dist/github/core.cjs.js.map +1 -0
- package/dist/gitlab/DefaultGitlabCredentialsProvider.cjs.js +30 -0
- package/dist/gitlab/DefaultGitlabCredentialsProvider.cjs.js.map +1 -0
- package/dist/gitlab/GitLabIntegration.cjs.js +41 -0
- package/dist/gitlab/GitLabIntegration.cjs.js.map +1 -0
- package/dist/gitlab/SingleInstanceGitlabCredentialsProvider.cjs.js +24 -0
- package/dist/gitlab/SingleInstanceGitlabCredentialsProvider.cjs.js.map +1 -0
- package/dist/gitlab/config.cjs.js +60 -0
- package/dist/gitlab/config.cjs.js.map +1 -0
- package/dist/gitlab/core.cjs.js +84 -0
- package/dist/gitlab/core.cjs.js.map +1 -0
- package/dist/googleGcs/config.cjs.js +16 -0
- package/dist/googleGcs/config.cjs.js.map +1 -0
- package/dist/harness/HarnessIntegration.cjs.js +34 -0
- package/dist/harness/HarnessIntegration.cjs.js.map +1 -0
- package/dist/harness/config.cjs.js +22 -0
- package/dist/harness/config.cjs.js.map +1 -0
- package/dist/harness/core.cjs.js +101 -0
- package/dist/harness/core.cjs.js.map +1 -0
- package/dist/helpers.cjs.js +71 -0
- package/dist/helpers.cjs.js.map +1 -0
- package/dist/index.cjs.js +124 -2451
- package/dist/index.cjs.js.map +1 -1
- package/package.json +6 -6
package/dist/index.cjs.js
CHANGED
|
@@ -1,2454 +1,127 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
var
|
|
14
|
-
var
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
config.getOptionalConfigArray("integrations.awsS3") ?? []
|
|
128
|
-
);
|
|
129
|
-
return basicIntegrations(
|
|
130
|
-
configs.map((c) => new AwsS3Integration(c)),
|
|
131
|
-
(i) => i.config.host
|
|
132
|
-
);
|
|
133
|
-
};
|
|
134
|
-
get type() {
|
|
135
|
-
return "awsS3";
|
|
136
|
-
}
|
|
137
|
-
get title() {
|
|
138
|
-
return this.integrationConfig.host;
|
|
139
|
-
}
|
|
140
|
-
get config() {
|
|
141
|
-
return this.integrationConfig;
|
|
142
|
-
}
|
|
143
|
-
resolveUrl(options) {
|
|
144
|
-
const resolved = defaultScmResolveUrl(options);
|
|
145
|
-
return resolved;
|
|
146
|
-
}
|
|
147
|
-
resolveEditUrl(url) {
|
|
148
|
-
return url;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const AMAZON_AWS_CODECOMMIT_HOST = "console.aws.amazon.com";
|
|
153
|
-
function readAwsCodeCommitIntegrationConfig(config) {
|
|
154
|
-
const accessKeyId = config.getOptionalString("accessKeyId");
|
|
155
|
-
const secretAccessKey = config.getOptionalString("secretAccessKey")?.trim();
|
|
156
|
-
const roleArn = config.getOptionalString("roleArn");
|
|
157
|
-
const externalId = config.getOptionalString("externalId");
|
|
158
|
-
const region = config.getString("region");
|
|
159
|
-
const host = config.getOptionalString("host") || `${region}.${AMAZON_AWS_CODECOMMIT_HOST}`;
|
|
160
|
-
return {
|
|
161
|
-
host,
|
|
162
|
-
accessKeyId,
|
|
163
|
-
secretAccessKey,
|
|
164
|
-
roleArn,
|
|
165
|
-
externalId,
|
|
166
|
-
region
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
function readAwsCodeCommitIntegrationConfigs(configs) {
|
|
170
|
-
return configs.map(readAwsCodeCommitIntegrationConfig);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
class AwsCodeCommitIntegration {
|
|
174
|
-
constructor(integrationConfig) {
|
|
175
|
-
this.integrationConfig = integrationConfig;
|
|
176
|
-
}
|
|
177
|
-
static factory = ({
|
|
178
|
-
config
|
|
179
|
-
}) => {
|
|
180
|
-
const configs = readAwsCodeCommitIntegrationConfigs(
|
|
181
|
-
config.getOptionalConfigArray("integrations.awsCodeCommit") ?? []
|
|
182
|
-
);
|
|
183
|
-
return basicIntegrations(
|
|
184
|
-
configs.map((c) => new AwsCodeCommitIntegration(c)),
|
|
185
|
-
(i) => i.config.host
|
|
186
|
-
);
|
|
187
|
-
};
|
|
188
|
-
get type() {
|
|
189
|
-
return "awsCodeCommit";
|
|
190
|
-
}
|
|
191
|
-
get config() {
|
|
192
|
-
return this.integrationConfig;
|
|
193
|
-
}
|
|
194
|
-
get title() {
|
|
195
|
-
return this.integrationConfig.host;
|
|
196
|
-
}
|
|
197
|
-
resolveUrl(options) {
|
|
198
|
-
const resolved = defaultScmResolveUrl(options);
|
|
199
|
-
return resolved;
|
|
200
|
-
}
|
|
201
|
-
resolveEditUrl(url) {
|
|
202
|
-
const parsedUrl = new URL(url);
|
|
203
|
-
const pathMatch = parsedUrl.pathname.match(
|
|
204
|
-
/^\/codesuite\/codecommit\/repositories\/([^\/]+)\//
|
|
205
|
-
);
|
|
206
|
-
if (!pathMatch) {
|
|
207
|
-
throw new Error(``);
|
|
208
|
-
}
|
|
209
|
-
const [, repositoryName] = pathMatch;
|
|
210
|
-
return replaceCodeCommitUrlType(url, repositoryName);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
function replaceCodeCommitUrlType(url, repositoryName, type) {
|
|
214
|
-
const newString = `files/edit` ;
|
|
215
|
-
return url.replace(
|
|
216
|
-
new RegExp(
|
|
217
|
-
`/codesuite/codecommit/repositories/${repositoryName}/(browse|files/edit)/`
|
|
218
|
-
),
|
|
219
|
-
`/codesuite/codecommit/repositories/${repositoryName}/${newString}/`
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const VERSION_PREFIX_GIT_BRANCH = "GB";
|
|
224
|
-
class AzureUrl {
|
|
225
|
-
/**
|
|
226
|
-
* Parses an azure URL as copied from the browser address bar.
|
|
227
|
-
*
|
|
228
|
-
* Throws an error if the URL is not a valid azure repo URL.
|
|
229
|
-
*/
|
|
230
|
-
static fromRepoUrl(repoUrl) {
|
|
231
|
-
const url = new URL(repoUrl);
|
|
232
|
-
let owner;
|
|
233
|
-
let project;
|
|
234
|
-
let repo;
|
|
235
|
-
const parts = url.pathname.split("/").map((part) => decodeURIComponent(part));
|
|
236
|
-
if (parts[2] === "_git") {
|
|
237
|
-
owner = parts[1];
|
|
238
|
-
project = repo = parts[3];
|
|
239
|
-
} else if (parts[3] === "_git") {
|
|
240
|
-
owner = parts[1];
|
|
241
|
-
project = parts[2];
|
|
242
|
-
repo = parts[4];
|
|
243
|
-
} else if (parts[4] === "_git") {
|
|
244
|
-
owner = `${parts[1]}/${parts[2]}`;
|
|
245
|
-
project = parts[3];
|
|
246
|
-
repo = parts[5];
|
|
247
|
-
}
|
|
248
|
-
if (!owner || !project || !repo) {
|
|
249
|
-
throw new Error("Azure URL must point to a git repository");
|
|
250
|
-
}
|
|
251
|
-
const path = url.searchParams.get("path") ?? void 0;
|
|
252
|
-
let ref;
|
|
253
|
-
const version = url.searchParams.get("version");
|
|
254
|
-
if (version) {
|
|
255
|
-
const prefix = version.slice(0, 2);
|
|
256
|
-
if (prefix !== "GB") {
|
|
257
|
-
throw new Error("Azure URL version must point to a git branch");
|
|
258
|
-
}
|
|
259
|
-
ref = version.slice(2);
|
|
260
|
-
}
|
|
261
|
-
return new AzureUrl(url.origin, owner, project, repo, path, ref);
|
|
262
|
-
}
|
|
263
|
-
#origin;
|
|
264
|
-
#owner;
|
|
265
|
-
#project;
|
|
266
|
-
#repo;
|
|
267
|
-
#path;
|
|
268
|
-
#ref;
|
|
269
|
-
constructor(origin, owner, project, repo, path, ref) {
|
|
270
|
-
this.#origin = origin;
|
|
271
|
-
this.#owner = owner;
|
|
272
|
-
this.#project = project;
|
|
273
|
-
this.#repo = repo;
|
|
274
|
-
this.#path = path;
|
|
275
|
-
this.#ref = ref;
|
|
276
|
-
}
|
|
277
|
-
#baseUrl = (...parts) => {
|
|
278
|
-
const url = new URL(this.#origin);
|
|
279
|
-
url.pathname = parts.map((part) => encodeURIComponent(part)).join("/");
|
|
280
|
-
return url;
|
|
281
|
-
};
|
|
282
|
-
/**
|
|
283
|
-
* Returns a repo URL that can be used to navigate to the resource in azure.
|
|
284
|
-
*
|
|
285
|
-
* Throws an error if the URL is not a valid azure repo URL.
|
|
286
|
-
*/
|
|
287
|
-
toRepoUrl() {
|
|
288
|
-
let url;
|
|
289
|
-
if (this.#project === this.#repo) {
|
|
290
|
-
url = this.#baseUrl(this.#owner, "_git", this.#repo);
|
|
291
|
-
} else {
|
|
292
|
-
url = this.#baseUrl(this.#owner, this.#project, "_git", this.#repo);
|
|
293
|
-
}
|
|
294
|
-
if (this.#path) {
|
|
295
|
-
url.searchParams.set("path", this.#path);
|
|
296
|
-
}
|
|
297
|
-
if (this.#ref) {
|
|
298
|
-
url.searchParams.set("version", VERSION_PREFIX_GIT_BRANCH + this.#ref);
|
|
299
|
-
}
|
|
300
|
-
return url.toString();
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Returns the file download URL for this azure resource.
|
|
304
|
-
*
|
|
305
|
-
* Throws an error if the URL does not point to a file.
|
|
306
|
-
*/
|
|
307
|
-
toFileUrl() {
|
|
308
|
-
if (!this.#path) {
|
|
309
|
-
throw new Error(
|
|
310
|
-
"Azure URL must point to a specific path to be able to download a file"
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
const url = this.#baseUrl(
|
|
314
|
-
this.#owner,
|
|
315
|
-
this.#project,
|
|
316
|
-
"_apis",
|
|
317
|
-
"git",
|
|
318
|
-
"repositories",
|
|
319
|
-
this.#repo,
|
|
320
|
-
"items"
|
|
321
|
-
);
|
|
322
|
-
url.searchParams.set("api-version", "6.0");
|
|
323
|
-
url.searchParams.set("path", this.#path);
|
|
324
|
-
if (this.#ref) {
|
|
325
|
-
url.searchParams.set("version", this.#ref);
|
|
326
|
-
}
|
|
327
|
-
return url.toString();
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Returns the archive download URL for this azure resource.
|
|
331
|
-
*
|
|
332
|
-
* Throws an error if the URL does not point to a repo.
|
|
333
|
-
*/
|
|
334
|
-
toArchiveUrl() {
|
|
335
|
-
const url = this.#baseUrl(
|
|
336
|
-
this.#owner,
|
|
337
|
-
this.#project,
|
|
338
|
-
"_apis",
|
|
339
|
-
"git",
|
|
340
|
-
"repositories",
|
|
341
|
-
this.#repo,
|
|
342
|
-
"items"
|
|
343
|
-
);
|
|
344
|
-
url.searchParams.set("recursionLevel", "full");
|
|
345
|
-
url.searchParams.set("download", "true");
|
|
346
|
-
url.searchParams.set("api-version", "6.0");
|
|
347
|
-
if (this.#path) {
|
|
348
|
-
url.searchParams.set("scopePath", this.#path);
|
|
349
|
-
}
|
|
350
|
-
if (this.#ref) {
|
|
351
|
-
url.searchParams.set("version", this.#ref);
|
|
352
|
-
}
|
|
353
|
-
return url.toString();
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Returns the API url for fetching commits from a branch for this azure resource.
|
|
357
|
-
*
|
|
358
|
-
* Throws an error if the URL does not point to a commit.
|
|
359
|
-
*/
|
|
360
|
-
toCommitsUrl() {
|
|
361
|
-
const url = this.#baseUrl(
|
|
362
|
-
this.#owner,
|
|
363
|
-
this.#project,
|
|
364
|
-
"_apis",
|
|
365
|
-
"git",
|
|
366
|
-
"repositories",
|
|
367
|
-
this.#repo,
|
|
368
|
-
"commits"
|
|
369
|
-
);
|
|
370
|
-
url.searchParams.set("api-version", "6.0");
|
|
371
|
-
if (this.#ref) {
|
|
372
|
-
url.searchParams.set("searchCriteria.itemVersion.version", this.#ref);
|
|
373
|
-
}
|
|
374
|
-
return url.toString();
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Returns the name of the owner, a user or an organization.
|
|
378
|
-
*/
|
|
379
|
-
getOwner() {
|
|
380
|
-
return this.#owner;
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Returns the name of the project.
|
|
384
|
-
*/
|
|
385
|
-
getProject() {
|
|
386
|
-
return this.#project;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Returns the name of the repo.
|
|
390
|
-
*/
|
|
391
|
-
getRepo() {
|
|
392
|
-
return this.#repo;
|
|
393
|
-
}
|
|
394
|
-
/**
|
|
395
|
-
* Returns the file path within the repo if the URL contains one.
|
|
396
|
-
*/
|
|
397
|
-
getPath() {
|
|
398
|
-
return this.#path;
|
|
399
|
-
}
|
|
400
|
-
/**
|
|
401
|
-
* Returns the git ref in the repo if the URL contains one.
|
|
402
|
-
*/
|
|
403
|
-
getRef() {
|
|
404
|
-
return this.#ref;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
const AZURE_HOST = "dev.azure.com";
|
|
409
|
-
const AzureDevOpsCredentialFields = [
|
|
410
|
-
"clientId",
|
|
411
|
-
"clientSecret",
|
|
412
|
-
"tenantId",
|
|
413
|
-
"personalAccessToken"
|
|
414
|
-
];
|
|
415
|
-
const AzureDevopsCredentialFieldMap = /* @__PURE__ */ new Map([
|
|
416
|
-
["ClientSecret", ["clientId", "clientSecret", "tenantId"]],
|
|
417
|
-
["ManagedIdentity", ["clientId"]],
|
|
418
|
-
["PersonalAccessToken", ["personalAccessToken"]]
|
|
419
|
-
]);
|
|
420
|
-
function asAzureDevOpsCredential(credential) {
|
|
421
|
-
for (const entry of AzureDevopsCredentialFieldMap.entries()) {
|
|
422
|
-
const [kind, requiredFields] = entry;
|
|
423
|
-
const forbiddenFields = AzureDevOpsCredentialFields.filter(
|
|
424
|
-
(field) => !requiredFields.includes(field)
|
|
425
|
-
);
|
|
426
|
-
if (requiredFields.every((field) => credential[field] !== void 0) && forbiddenFields.every((field) => credential[field] === void 0)) {
|
|
427
|
-
return {
|
|
428
|
-
kind,
|
|
429
|
-
organizations: credential.organizations,
|
|
430
|
-
...requiredFields.reduce((acc, field) => {
|
|
431
|
-
acc[field] = credential[field];
|
|
432
|
-
return acc;
|
|
433
|
-
}, {})
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
throw new Error("is not a valid credential");
|
|
438
|
-
}
|
|
439
|
-
function readAzureIntegrationConfig(config) {
|
|
440
|
-
const host = config.getOptionalString("host") ?? AZURE_HOST;
|
|
441
|
-
let credentialConfigs = config.getOptionalConfigArray("credentials")?.map((credential) => {
|
|
442
|
-
const result = {
|
|
443
|
-
organizations: credential.getOptionalStringArray("organizations"),
|
|
444
|
-
personalAccessToken: credential.getOptionalString("personalAccessToken")?.trim(),
|
|
445
|
-
tenantId: credential.getOptionalString("tenantId"),
|
|
446
|
-
clientId: credential.getOptionalString("clientId"),
|
|
447
|
-
clientSecret: credential.getOptionalString("clientSecret")?.trim()
|
|
448
|
-
};
|
|
449
|
-
return result;
|
|
450
|
-
});
|
|
451
|
-
const token = config.getOptionalString("token")?.trim();
|
|
452
|
-
if (config.getOptional("credential") !== void 0 && config.getOptional("credentials") !== void 0) {
|
|
453
|
-
throw new Error(
|
|
454
|
-
`Invalid Azure integration config, 'credential' and 'credentials' cannot be used together. Use 'credentials' instead.`
|
|
455
|
-
);
|
|
456
|
-
}
|
|
457
|
-
if (config.getOptional("token") !== void 0 && config.getOptional("credentials") !== void 0) {
|
|
458
|
-
throw new Error(
|
|
459
|
-
`Invalid Azure integration config, 'token' and 'credentials' cannot be used together. Use 'credentials' instead.`
|
|
460
|
-
);
|
|
461
|
-
}
|
|
462
|
-
if (token !== void 0) {
|
|
463
|
-
const mapped = [{ personalAccessToken: token }];
|
|
464
|
-
credentialConfigs = credentialConfigs?.concat(mapped) ?? mapped;
|
|
465
|
-
}
|
|
466
|
-
if (config.getOptional("credential") !== void 0) {
|
|
467
|
-
const mapped = [
|
|
468
|
-
{
|
|
469
|
-
organizations: config.getOptionalStringArray(
|
|
470
|
-
"credential.organizations"
|
|
471
|
-
),
|
|
472
|
-
token: config.getOptionalString("credential.token")?.trim(),
|
|
473
|
-
tenantId: config.getOptionalString("credential.tenantId"),
|
|
474
|
-
clientId: config.getOptionalString("credential.clientId"),
|
|
475
|
-
clientSecret: config.getOptionalString("credential.clientSecret")?.trim()
|
|
476
|
-
}
|
|
477
|
-
];
|
|
478
|
-
credentialConfigs = credentialConfigs?.concat(mapped) ?? mapped;
|
|
479
|
-
}
|
|
480
|
-
if (!isValidHost(host)) {
|
|
481
|
-
throw new Error(
|
|
482
|
-
`Invalid Azure integration config, '${host}' is not a valid host`
|
|
483
|
-
);
|
|
484
|
-
}
|
|
485
|
-
let credentials = void 0;
|
|
486
|
-
if (credentialConfigs !== void 0) {
|
|
487
|
-
const errors = credentialConfigs?.reduce((acc, credentialConfig, index) => {
|
|
488
|
-
let error = void 0;
|
|
489
|
-
try {
|
|
490
|
-
asAzureDevOpsCredential(credentialConfig);
|
|
491
|
-
} catch (e) {
|
|
492
|
-
error = e.message;
|
|
493
|
-
}
|
|
494
|
-
if (error !== void 0) {
|
|
495
|
-
acc.push(`credential at position ${index + 1} ${error}`);
|
|
496
|
-
}
|
|
497
|
-
return acc;
|
|
498
|
-
}, Array.of()).concat(
|
|
499
|
-
Object.entries(
|
|
500
|
-
credentialConfigs.filter(
|
|
501
|
-
(credential) => credential.organizations !== void 0 && credential.organizations.length > 0
|
|
502
|
-
).reduce((acc, credential, index) => {
|
|
503
|
-
credential.organizations?.forEach((organization) => {
|
|
504
|
-
if (!acc[organization]) {
|
|
505
|
-
acc[organization] = [];
|
|
506
|
-
}
|
|
507
|
-
acc[organization].push(index + 1);
|
|
508
|
-
});
|
|
509
|
-
return acc;
|
|
510
|
-
}, {})
|
|
511
|
-
).filter(([_, indexes]) => indexes.length > 1).reduce((acc, [org, indexes]) => {
|
|
512
|
-
acc.push(
|
|
513
|
-
`organization ${org} is specified multiple times in credentials at positions ${indexes.slice(0, indexes.length - 1).join(", ")} and ${indexes[indexes.length - 1]}`
|
|
514
|
-
);
|
|
515
|
-
return acc;
|
|
516
|
-
}, Array.of())
|
|
517
|
-
);
|
|
518
|
-
if (errors?.length > 0) {
|
|
519
|
-
throw new Error(
|
|
520
|
-
`Invalid Azure integration config for ${host}: ${errors.join("; ")}`
|
|
521
|
-
);
|
|
522
|
-
}
|
|
523
|
-
credentials = credentialConfigs.map(
|
|
524
|
-
(credentialConfig) => asAzureDevOpsCredential(credentialConfig)
|
|
525
|
-
);
|
|
526
|
-
if (credentials.some(
|
|
527
|
-
(credential) => credential.kind !== "PersonalAccessToken"
|
|
528
|
-
) && host !== AZURE_HOST) {
|
|
529
|
-
throw new Error(
|
|
530
|
-
`Invalid Azure integration config for ${host}, only personal access tokens can be used with hosts other than ${AZURE_HOST}`
|
|
531
|
-
);
|
|
532
|
-
}
|
|
533
|
-
if (credentials.filter(
|
|
534
|
-
(credential) => credential.organizations === void 0 || credential.organizations.length === 0
|
|
535
|
-
).length > 1) {
|
|
536
|
-
throw new Error(
|
|
537
|
-
`Invalid Azure integration config for ${host}, you cannot specify multiple credentials without organizations`
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
return {
|
|
542
|
-
host,
|
|
543
|
-
credentials
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
function readAzureIntegrationConfigs(configs) {
|
|
547
|
-
const result = configs.map(readAzureIntegrationConfig);
|
|
548
|
-
if (!result.some((c) => c.host === AZURE_HOST)) {
|
|
549
|
-
result.push({ host: AZURE_HOST });
|
|
550
|
-
}
|
|
551
|
-
return result;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
class AzureIntegration {
|
|
555
|
-
constructor(integrationConfig) {
|
|
556
|
-
this.integrationConfig = integrationConfig;
|
|
557
|
-
}
|
|
558
|
-
static factory = ({ config }) => {
|
|
559
|
-
const configs = readAzureIntegrationConfigs(
|
|
560
|
-
config.getOptionalConfigArray("integrations.azure") ?? []
|
|
561
|
-
);
|
|
562
|
-
return basicIntegrations(
|
|
563
|
-
configs.map((c) => new AzureIntegration(c)),
|
|
564
|
-
(i) => i.config.host
|
|
565
|
-
);
|
|
566
|
-
};
|
|
567
|
-
get type() {
|
|
568
|
-
return "azure";
|
|
569
|
-
}
|
|
570
|
-
get title() {
|
|
571
|
-
return this.integrationConfig.host;
|
|
572
|
-
}
|
|
573
|
-
get config() {
|
|
574
|
-
return this.integrationConfig;
|
|
575
|
-
}
|
|
576
|
-
/*
|
|
577
|
-
* Azure repo URLs on the form with a `path` query param are treated specially.
|
|
578
|
-
*
|
|
579
|
-
* Example base URL: https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml
|
|
580
|
-
*/
|
|
581
|
-
resolveUrl(options) {
|
|
582
|
-
const { url, base } = options;
|
|
583
|
-
if (isValidUrl(url)) {
|
|
584
|
-
return url;
|
|
585
|
-
}
|
|
586
|
-
try {
|
|
587
|
-
const azureUrl = AzureUrl.fromRepoUrl(base);
|
|
588
|
-
const newUrl = new URL(base);
|
|
589
|
-
const mockBaseUrl = new URL(`https://a.com${azureUrl.getPath() ?? ""}`);
|
|
590
|
-
const updatedPath = new URL(url, mockBaseUrl).pathname;
|
|
591
|
-
newUrl.searchParams.set("path", updatedPath);
|
|
592
|
-
if (options.lineNumber) {
|
|
593
|
-
newUrl.searchParams.set("line", String(options.lineNumber));
|
|
594
|
-
newUrl.searchParams.set("lineEnd", String(options.lineNumber + 1));
|
|
595
|
-
newUrl.searchParams.set("lineStartColumn", "1");
|
|
596
|
-
newUrl.searchParams.set("lineEndColumn", "1");
|
|
597
|
-
}
|
|
598
|
-
return newUrl.toString();
|
|
599
|
-
} catch {
|
|
600
|
-
return new URL(url, base).toString();
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
resolveEditUrl(url) {
|
|
604
|
-
return url;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
function getAzureFileFetchUrl(url) {
|
|
609
|
-
return AzureUrl.fromRepoUrl(url).toFileUrl();
|
|
610
|
-
}
|
|
611
|
-
function getAzureDownloadUrl(url) {
|
|
612
|
-
return AzureUrl.fromRepoUrl(url).toArchiveUrl();
|
|
613
|
-
}
|
|
614
|
-
function getAzureCommitsUrl(url) {
|
|
615
|
-
return AzureUrl.fromRepoUrl(url).toCommitsUrl();
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
const tenMinutes = 1e3 * 60 * 10;
|
|
619
|
-
class CachedAzureDevOpsCredentialsProvider {
|
|
620
|
-
constructor(credential) {
|
|
621
|
-
this.credential = credential;
|
|
622
|
-
}
|
|
623
|
-
azureDevOpsScope = "499b84ac-1321-427f-aa17-267ca6975798/.default";
|
|
624
|
-
cached;
|
|
625
|
-
static fromAzureDevOpsCredential(credential) {
|
|
626
|
-
switch (credential.kind) {
|
|
627
|
-
case "PersonalAccessToken":
|
|
628
|
-
return CachedAzureDevOpsCredentialsProvider.fromPersonalAccessTokenCredential(
|
|
629
|
-
credential
|
|
630
|
-
);
|
|
631
|
-
case "ClientSecret":
|
|
632
|
-
return CachedAzureDevOpsCredentialsProvider.fromTokenCredential(
|
|
633
|
-
new identity.ClientSecretCredential(
|
|
634
|
-
credential.tenantId,
|
|
635
|
-
credential.clientId,
|
|
636
|
-
credential.clientSecret
|
|
637
|
-
)
|
|
638
|
-
);
|
|
639
|
-
case "ManagedIdentity":
|
|
640
|
-
return CachedAzureDevOpsCredentialsProvider.fromTokenCredential(
|
|
641
|
-
new identity.ManagedIdentityCredential(credential.clientId)
|
|
642
|
-
);
|
|
643
|
-
default:
|
|
644
|
-
throw new Error(
|
|
645
|
-
`Credential kind '${credential.kind}' not supported`
|
|
646
|
-
);
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
static fromTokenCredential(credential) {
|
|
650
|
-
return new CachedAzureDevOpsCredentialsProvider(credential);
|
|
651
|
-
}
|
|
652
|
-
static fromPersonalAccessTokenCredential(credential) {
|
|
653
|
-
return new CachedAzureDevOpsCredentialsProvider(
|
|
654
|
-
credential.personalAccessToken
|
|
655
|
-
);
|
|
656
|
-
}
|
|
657
|
-
async getCredentials() {
|
|
658
|
-
if (this.cached === void 0 || this.cached.expiresAt !== void 0 && Date.now() > this.cached.expiresAt) {
|
|
659
|
-
if (typeof this.credential === "string") {
|
|
660
|
-
this.cached = {
|
|
661
|
-
headers: {
|
|
662
|
-
Authorization: `Basic ${btoa(`:${this.credential}`)}`
|
|
663
|
-
},
|
|
664
|
-
type: "pat",
|
|
665
|
-
token: this.credential
|
|
666
|
-
};
|
|
667
|
-
} else {
|
|
668
|
-
const accessToken = await this.credential.getToken(
|
|
669
|
-
this.azureDevOpsScope
|
|
670
|
-
);
|
|
671
|
-
if (!accessToken) {
|
|
672
|
-
throw new Error("Failed to retrieve access token");
|
|
673
|
-
}
|
|
674
|
-
this.cached = {
|
|
675
|
-
expiresAt: accessToken.expiresOnTimestamp - tenMinutes,
|
|
676
|
-
headers: {
|
|
677
|
-
Authorization: `Bearer ${accessToken.token}`
|
|
678
|
-
},
|
|
679
|
-
type: "bearer",
|
|
680
|
-
token: accessToken.token
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
return this.cached;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
class DefaultAzureDevOpsCredentialsProvider {
|
|
689
|
-
constructor(providers) {
|
|
690
|
-
this.providers = providers;
|
|
691
|
-
}
|
|
692
|
-
static fromIntegrations(integrations) {
|
|
693
|
-
const providers = integrations.azure.list().reduce((acc, integration) => {
|
|
694
|
-
integration.config.credentials?.forEach((credential) => {
|
|
695
|
-
if (credential.organizations === void 0 || credential.organizations.length === 0) {
|
|
696
|
-
if (acc.get(integration.config.host) === void 0) {
|
|
697
|
-
acc.set(
|
|
698
|
-
integration.config.host,
|
|
699
|
-
CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential(
|
|
700
|
-
credential
|
|
701
|
-
)
|
|
702
|
-
);
|
|
703
|
-
}
|
|
704
|
-
} else {
|
|
705
|
-
const provider = CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential(
|
|
706
|
-
credential
|
|
707
|
-
);
|
|
708
|
-
credential.organizations?.forEach((organization) => {
|
|
709
|
-
acc.set(`${integration.config.host}/${organization}`, provider);
|
|
710
|
-
});
|
|
711
|
-
}
|
|
712
|
-
});
|
|
713
|
-
if (integration.config.host === "dev.azure.com" && acc.get(integration.config.host) === void 0) {
|
|
714
|
-
acc.set(
|
|
715
|
-
integration.config.host,
|
|
716
|
-
CachedAzureDevOpsCredentialsProvider.fromTokenCredential(
|
|
717
|
-
new identity.DefaultAzureCredential()
|
|
718
|
-
)
|
|
719
|
-
);
|
|
720
|
-
}
|
|
721
|
-
return acc;
|
|
722
|
-
}, /* @__PURE__ */ new Map());
|
|
723
|
-
return new DefaultAzureDevOpsCredentialsProvider(providers);
|
|
724
|
-
}
|
|
725
|
-
forAzureDevOpsServerOrganization(url) {
|
|
726
|
-
const parts = url.pathname.split("/").filter((part) => part !== "");
|
|
727
|
-
if (url.host !== "dev.azure.com" && parts.length > 0) {
|
|
728
|
-
if (parts[0] !== "tfs") {
|
|
729
|
-
return this.providers.get(`${url.host}/${parts[0]}`);
|
|
730
|
-
} else if (parts[0] === "tfs" && parts.length > 1) {
|
|
731
|
-
return this.providers.get(`${url.host}/${parts[1]}`);
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
return void 0;
|
|
735
|
-
}
|
|
736
|
-
forAzureDevOpsOrganization(url) {
|
|
737
|
-
const parts = url.pathname.split("/").filter((part) => part !== "");
|
|
738
|
-
if (url.host === "dev.azure.com" && parts.length > 0) {
|
|
739
|
-
return this.providers.get(`${url.host}/${parts[0]}`);
|
|
740
|
-
}
|
|
741
|
-
return void 0;
|
|
742
|
-
}
|
|
743
|
-
forHost(url) {
|
|
744
|
-
return this.providers.get(url.host);
|
|
745
|
-
}
|
|
746
|
-
async getCredentials(opts) {
|
|
747
|
-
const url = new URL(opts.url);
|
|
748
|
-
const provider = this.forAzureDevOpsOrganization(url) ?? this.forAzureDevOpsServerOrganization(url) ?? this.forHost(url);
|
|
749
|
-
if (provider === void 0) {
|
|
750
|
-
return void 0;
|
|
751
|
-
}
|
|
752
|
-
return provider.getCredentials(opts);
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
async function getAzureRequestOptions(config, additionalHeaders) {
|
|
757
|
-
const headers = additionalHeaders ? { ...additionalHeaders } : {};
|
|
758
|
-
const credentialConfig = config.credentials?.filter(
|
|
759
|
-
(credential) => credential.organizations === void 0 || credential.organizations.length === 0
|
|
760
|
-
)[0];
|
|
761
|
-
if (credentialConfig) {
|
|
762
|
-
const credentialsProvider = CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential(
|
|
763
|
-
credentialConfig
|
|
764
|
-
);
|
|
765
|
-
const credentials = await credentialsProvider.getCredentials();
|
|
766
|
-
return {
|
|
767
|
-
headers: {
|
|
768
|
-
...credentials?.headers,
|
|
769
|
-
...headers
|
|
770
|
-
}
|
|
771
|
-
};
|
|
772
|
-
}
|
|
773
|
-
return { headers };
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
const BITBUCKET_HOST = "bitbucket.org";
|
|
777
|
-
const BITBUCKET_API_BASE_URL = "https://api.bitbucket.org/2.0";
|
|
778
|
-
function readBitbucketIntegrationConfig(config) {
|
|
779
|
-
const host = config.getOptionalString("host") ?? BITBUCKET_HOST;
|
|
780
|
-
let apiBaseUrl = config.getOptionalString("apiBaseUrl");
|
|
781
|
-
const token = config.getOptionalString("token")?.trim();
|
|
782
|
-
const username = config.getOptionalString("username");
|
|
783
|
-
const appPassword = config.getOptionalString("appPassword")?.trim();
|
|
784
|
-
if (!isValidHost(host)) {
|
|
785
|
-
throw new Error(
|
|
786
|
-
`Invalid Bitbucket integration config, '${host}' is not a valid host`
|
|
787
|
-
);
|
|
788
|
-
}
|
|
789
|
-
if (apiBaseUrl) {
|
|
790
|
-
apiBaseUrl = lodash.trimEnd(apiBaseUrl, "/");
|
|
791
|
-
} else if (host === BITBUCKET_HOST) {
|
|
792
|
-
apiBaseUrl = BITBUCKET_API_BASE_URL;
|
|
793
|
-
} else {
|
|
794
|
-
apiBaseUrl = `https://${host}/rest/api/1.0`;
|
|
795
|
-
}
|
|
796
|
-
return {
|
|
797
|
-
host,
|
|
798
|
-
apiBaseUrl,
|
|
799
|
-
token,
|
|
800
|
-
username,
|
|
801
|
-
appPassword
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
function readBitbucketIntegrationConfigs(configs) {
|
|
805
|
-
const result = configs.map(readBitbucketIntegrationConfig);
|
|
806
|
-
if (!result.some((c) => c.host === BITBUCKET_HOST)) {
|
|
807
|
-
result.push({
|
|
808
|
-
host: BITBUCKET_HOST,
|
|
809
|
-
apiBaseUrl: BITBUCKET_API_BASE_URL
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
return result;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
class BitbucketIntegration {
|
|
816
|
-
constructor(integrationConfig) {
|
|
817
|
-
this.integrationConfig = integrationConfig;
|
|
818
|
-
}
|
|
819
|
-
static factory = ({
|
|
820
|
-
config
|
|
821
|
-
}) => {
|
|
822
|
-
const configs = readBitbucketIntegrationConfigs(
|
|
823
|
-
config.getOptionalConfigArray("integrations.bitbucket") ?? [
|
|
824
|
-
// if integrations.bitbucket was not used assume the use was migrated to the new configs
|
|
825
|
-
// and backport for the deprecated integration to be usable for other parts of the system
|
|
826
|
-
// until these got migrated
|
|
827
|
-
...config.getOptionalConfigArray("integrations.bitbucketCloud") ?? [],
|
|
828
|
-
...config.getOptionalConfigArray("integrations.bitbucketServer") ?? []
|
|
829
|
-
]
|
|
830
|
-
);
|
|
831
|
-
return basicIntegrations(
|
|
832
|
-
configs.map((c) => new BitbucketIntegration(c)),
|
|
833
|
-
(i) => i.config.host
|
|
834
|
-
);
|
|
835
|
-
};
|
|
836
|
-
get type() {
|
|
837
|
-
return "bitbucket";
|
|
838
|
-
}
|
|
839
|
-
get title() {
|
|
840
|
-
return this.integrationConfig.host;
|
|
841
|
-
}
|
|
842
|
-
get config() {
|
|
843
|
-
return this.integrationConfig;
|
|
844
|
-
}
|
|
845
|
-
resolveUrl(options) {
|
|
846
|
-
const resolved = defaultScmResolveUrl(options);
|
|
847
|
-
if (!options.lineNumber) {
|
|
848
|
-
return resolved;
|
|
849
|
-
}
|
|
850
|
-
const url = new URL(resolved);
|
|
851
|
-
if (this.integrationConfig.host === "bitbucket.org") {
|
|
852
|
-
url.hash = `lines-${options.lineNumber}`;
|
|
853
|
-
} else {
|
|
854
|
-
url.hash = `${options.lineNumber}`;
|
|
855
|
-
}
|
|
856
|
-
return url.toString();
|
|
857
|
-
}
|
|
858
|
-
resolveEditUrl(url) {
|
|
859
|
-
const urlData = parseGitUrl__default.default(url);
|
|
860
|
-
const editUrl = new URL(url);
|
|
861
|
-
editUrl.searchParams.set("mode", "edit");
|
|
862
|
-
editUrl.searchParams.set("spa", "0");
|
|
863
|
-
editUrl.searchParams.set("at", urlData.ref);
|
|
864
|
-
return editUrl.toString();
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
async function getBitbucketDefaultBranch(url, config) {
|
|
869
|
-
const { name: repoName, owner: project, resource } = parseGitUrl__default.default(url);
|
|
870
|
-
const isHosted = resource === "bitbucket.org";
|
|
871
|
-
let branchUrl = isHosted ? `${config.apiBaseUrl}/repositories/${project}/${repoName}` : `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/default-branch`;
|
|
872
|
-
let response = await fetch__default.default(branchUrl, getBitbucketRequestOptions(config));
|
|
873
|
-
if (response.status === 404 && !isHosted) {
|
|
874
|
-
branchUrl = `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/branches/default`;
|
|
875
|
-
response = await fetch__default.default(branchUrl, getBitbucketRequestOptions(config));
|
|
876
|
-
}
|
|
877
|
-
if (!response.ok) {
|
|
878
|
-
const message = `Failed to retrieve default branch from ${branchUrl}, ${response.status} ${response.statusText}`;
|
|
879
|
-
throw new Error(message);
|
|
880
|
-
}
|
|
881
|
-
let defaultBranch;
|
|
882
|
-
if (isHosted) {
|
|
883
|
-
const repoInfo = await response.json();
|
|
884
|
-
defaultBranch = repoInfo.mainbranch.name;
|
|
885
|
-
} else {
|
|
886
|
-
const { displayId } = await response.json();
|
|
887
|
-
defaultBranch = displayId;
|
|
888
|
-
}
|
|
889
|
-
if (!defaultBranch) {
|
|
890
|
-
throw new Error(
|
|
891
|
-
`Failed to read default branch from ${branchUrl}. Response ${response.status} ${response.json()}`
|
|
892
|
-
);
|
|
893
|
-
}
|
|
894
|
-
return defaultBranch;
|
|
895
|
-
}
|
|
896
|
-
async function getBitbucketDownloadUrl(url, config) {
|
|
897
|
-
const {
|
|
898
|
-
name: repoName,
|
|
899
|
-
owner: project,
|
|
900
|
-
ref,
|
|
901
|
-
protocol,
|
|
902
|
-
resource,
|
|
903
|
-
filepath
|
|
904
|
-
} = parseGitUrl__default.default(url);
|
|
905
|
-
const isHosted = resource === "bitbucket.org";
|
|
906
|
-
let branch = ref;
|
|
907
|
-
if (!branch) {
|
|
908
|
-
branch = await getBitbucketDefaultBranch(url, config);
|
|
909
|
-
}
|
|
910
|
-
const path = filepath ? `&path=${encodeURIComponent(decodeURIComponent(filepath))}` : "";
|
|
911
|
-
const archiveUrl = isHosted ? `${protocol}://${resource}/${project}/${repoName}/get/${branch}.tar.gz` : `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/archive?format=tgz&at=${branch}&prefix=${project}-${repoName}${path}`;
|
|
912
|
-
return archiveUrl;
|
|
913
|
-
}
|
|
914
|
-
function getBitbucketFileFetchUrl(url, config) {
|
|
915
|
-
try {
|
|
916
|
-
const { owner, name, ref, filepathtype, filepath } = parseGitUrl__default.default(url);
|
|
917
|
-
if (!owner || !name || filepathtype !== "browse" && filepathtype !== "raw" && filepathtype !== "src") {
|
|
918
|
-
throw new Error("Invalid Bitbucket URL or file path");
|
|
919
|
-
}
|
|
920
|
-
const pathWithoutSlash = filepath.replace(/^\//, "");
|
|
921
|
-
if (config.host === "bitbucket.org") {
|
|
922
|
-
if (!ref) {
|
|
923
|
-
throw new Error("Invalid Bitbucket URL or file path");
|
|
924
|
-
}
|
|
925
|
-
return `${config.apiBaseUrl}/repositories/${owner}/${name}/src/${ref}/${pathWithoutSlash}`;
|
|
926
|
-
}
|
|
927
|
-
return `${config.apiBaseUrl}/projects/${owner}/repos/${name}/raw/${pathWithoutSlash}?at=${ref}`;
|
|
928
|
-
} catch (e) {
|
|
929
|
-
throw new Error(`Incorrect URL: ${url}, ${e}`);
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
function getBitbucketRequestOptions(config) {
|
|
933
|
-
const headers = {};
|
|
934
|
-
if (config.token) {
|
|
935
|
-
headers.Authorization = `Bearer ${config.token}`;
|
|
936
|
-
} else if (config.username && config.appPassword) {
|
|
937
|
-
const buffer = Buffer.from(
|
|
938
|
-
`${config.username}:${config.appPassword}`,
|
|
939
|
-
"utf8"
|
|
940
|
-
);
|
|
941
|
-
headers.Authorization = `Basic ${buffer.toString("base64")}`;
|
|
942
|
-
}
|
|
943
|
-
return {
|
|
944
|
-
headers
|
|
945
|
-
};
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
const BITBUCKET_CLOUD_HOST = "bitbucket.org";
|
|
949
|
-
const BITBUCKET_CLOUD_API_BASE_URL = "https://api.bitbucket.org/2.0";
|
|
950
|
-
function readBitbucketCloudIntegrationConfig(config) {
|
|
951
|
-
const host = BITBUCKET_CLOUD_HOST;
|
|
952
|
-
const apiBaseUrl = BITBUCKET_CLOUD_API_BASE_URL;
|
|
953
|
-
const username = config.getString("username");
|
|
954
|
-
const appPassword = config.getString("appPassword")?.trim();
|
|
955
|
-
return {
|
|
956
|
-
host,
|
|
957
|
-
apiBaseUrl,
|
|
958
|
-
username,
|
|
959
|
-
appPassword
|
|
960
|
-
};
|
|
961
|
-
}
|
|
962
|
-
function readBitbucketCloudIntegrationConfigs(configs) {
|
|
963
|
-
const result = configs.map(readBitbucketCloudIntegrationConfig);
|
|
964
|
-
if (result.length === 0) {
|
|
965
|
-
result.push({
|
|
966
|
-
host: BITBUCKET_CLOUD_HOST,
|
|
967
|
-
apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL
|
|
968
|
-
});
|
|
969
|
-
}
|
|
970
|
-
return result;
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
class BitbucketCloudIntegration {
|
|
974
|
-
constructor(integrationConfig) {
|
|
975
|
-
this.integrationConfig = integrationConfig;
|
|
976
|
-
}
|
|
977
|
-
static factory = ({
|
|
978
|
-
config
|
|
979
|
-
}) => {
|
|
980
|
-
const configs = readBitbucketCloudIntegrationConfigs(
|
|
981
|
-
config.getOptionalConfigArray("integrations.bitbucketCloud") ?? []
|
|
982
|
-
);
|
|
983
|
-
return basicIntegrations(
|
|
984
|
-
configs.map((c) => new BitbucketCloudIntegration(c)),
|
|
985
|
-
(i) => i.config.host
|
|
986
|
-
);
|
|
987
|
-
};
|
|
988
|
-
get type() {
|
|
989
|
-
return "bitbucketCloud";
|
|
990
|
-
}
|
|
991
|
-
get title() {
|
|
992
|
-
return this.integrationConfig.host;
|
|
993
|
-
}
|
|
994
|
-
get config() {
|
|
995
|
-
return this.integrationConfig;
|
|
996
|
-
}
|
|
997
|
-
resolveUrl(options) {
|
|
998
|
-
const resolved = defaultScmResolveUrl(options);
|
|
999
|
-
if (options.lineNumber) {
|
|
1000
|
-
const url = new URL(resolved);
|
|
1001
|
-
url.hash = `lines-${options.lineNumber}`;
|
|
1002
|
-
return url.toString();
|
|
1003
|
-
}
|
|
1004
|
-
return resolved;
|
|
1005
|
-
}
|
|
1006
|
-
resolveEditUrl(url) {
|
|
1007
|
-
const urlData = parseGitUrl__default.default(url);
|
|
1008
|
-
const editUrl = new URL(url);
|
|
1009
|
-
editUrl.searchParams.set("mode", "edit");
|
|
1010
|
-
editUrl.searchParams.set("at", urlData.ref);
|
|
1011
|
-
return editUrl.toString();
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
async function getBitbucketCloudDefaultBranch(url, config) {
|
|
1016
|
-
const { name: repoName, owner: project } = parseGitUrl__default.default(url);
|
|
1017
|
-
const branchUrl = `${config.apiBaseUrl}/repositories/${project}/${repoName}`;
|
|
1018
|
-
const response = await fetch__default.default(
|
|
1019
|
-
branchUrl,
|
|
1020
|
-
getBitbucketCloudRequestOptions(config)
|
|
1021
|
-
);
|
|
1022
|
-
if (!response.ok) {
|
|
1023
|
-
const message = `Failed to retrieve default branch from ${branchUrl}, ${response.status} ${response.statusText}`;
|
|
1024
|
-
throw new Error(message);
|
|
1025
|
-
}
|
|
1026
|
-
const repoInfo = await response.json();
|
|
1027
|
-
const defaultBranch = repoInfo.mainbranch.name;
|
|
1028
|
-
if (!defaultBranch) {
|
|
1029
|
-
throw new Error(
|
|
1030
|
-
`Failed to read default branch from ${branchUrl}. Response ${response.status} ${response.json()}`
|
|
1031
|
-
);
|
|
1032
|
-
}
|
|
1033
|
-
return defaultBranch;
|
|
1034
|
-
}
|
|
1035
|
-
async function getBitbucketCloudDownloadUrl(url, config) {
|
|
1036
|
-
const {
|
|
1037
|
-
name: repoName,
|
|
1038
|
-
owner: project,
|
|
1039
|
-
ref,
|
|
1040
|
-
protocol,
|
|
1041
|
-
resource
|
|
1042
|
-
} = parseGitUrl__default.default(url);
|
|
1043
|
-
let branch = ref;
|
|
1044
|
-
if (!branch) {
|
|
1045
|
-
branch = await getBitbucketCloudDefaultBranch(url, config);
|
|
1046
|
-
}
|
|
1047
|
-
return `${protocol}://${resource}/${project}/${repoName}/get/${branch}.tar.gz`;
|
|
1048
|
-
}
|
|
1049
|
-
function getBitbucketCloudFileFetchUrl(url, config) {
|
|
1050
|
-
try {
|
|
1051
|
-
const { owner, name, ref, filepathtype, filepath } = parseGitUrl__default.default(url);
|
|
1052
|
-
if (!owner || !name || filepathtype !== "src" && filepathtype !== "raw") {
|
|
1053
|
-
throw new Error("Invalid Bitbucket Cloud URL or file path");
|
|
1054
|
-
}
|
|
1055
|
-
const pathWithoutSlash = filepath.replace(/^\//, "");
|
|
1056
|
-
if (!ref) {
|
|
1057
|
-
throw new Error("Invalid Bitbucket Cloud URL or file path");
|
|
1058
|
-
}
|
|
1059
|
-
return `${config.apiBaseUrl}/repositories/${owner}/${name}/src/${ref}/${pathWithoutSlash}`;
|
|
1060
|
-
} catch (e) {
|
|
1061
|
-
throw new Error(`Incorrect URL: ${url}, ${e}`);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
function getBitbucketCloudRequestOptions(config) {
|
|
1065
|
-
const headers = {};
|
|
1066
|
-
if (config.username && config.appPassword) {
|
|
1067
|
-
const buffer = Buffer.from(
|
|
1068
|
-
`${config.username}:${config.appPassword}`,
|
|
1069
|
-
"utf8"
|
|
1070
|
-
);
|
|
1071
|
-
headers.Authorization = `Basic ${buffer.toString("base64")}`;
|
|
1072
|
-
}
|
|
1073
|
-
return {
|
|
1074
|
-
headers
|
|
1075
|
-
};
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
function readBitbucketServerIntegrationConfig(config) {
|
|
1079
|
-
const host = config.getString("host");
|
|
1080
|
-
let apiBaseUrl = config.getOptionalString("apiBaseUrl");
|
|
1081
|
-
const token = config.getOptionalString("token")?.trim();
|
|
1082
|
-
const username = config.getOptionalString("username");
|
|
1083
|
-
const password = config.getOptionalString("password");
|
|
1084
|
-
if (!isValidHost(host)) {
|
|
1085
|
-
throw new Error(
|
|
1086
|
-
`Invalid Bitbucket Server integration config, '${host}' is not a valid host`
|
|
1087
|
-
);
|
|
1088
|
-
}
|
|
1089
|
-
if (apiBaseUrl) {
|
|
1090
|
-
apiBaseUrl = lodash.trimEnd(apiBaseUrl, "/");
|
|
1091
|
-
} else {
|
|
1092
|
-
apiBaseUrl = `https://${host}/rest/api/1.0`;
|
|
1093
|
-
}
|
|
1094
|
-
return {
|
|
1095
|
-
host,
|
|
1096
|
-
apiBaseUrl,
|
|
1097
|
-
token,
|
|
1098
|
-
username,
|
|
1099
|
-
password
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1102
|
-
function readBitbucketServerIntegrationConfigs(configs) {
|
|
1103
|
-
return configs.map(readBitbucketServerIntegrationConfig);
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
class BitbucketServerIntegration {
|
|
1107
|
-
constructor(integrationConfig) {
|
|
1108
|
-
this.integrationConfig = integrationConfig;
|
|
1109
|
-
}
|
|
1110
|
-
static factory = ({
|
|
1111
|
-
config
|
|
1112
|
-
}) => {
|
|
1113
|
-
const configs = readBitbucketServerIntegrationConfigs(
|
|
1114
|
-
config.getOptionalConfigArray("integrations.bitbucketServer") ?? []
|
|
1115
|
-
);
|
|
1116
|
-
return basicIntegrations(
|
|
1117
|
-
configs.map((c) => new BitbucketServerIntegration(c)),
|
|
1118
|
-
(i) => i.config.host
|
|
1119
|
-
);
|
|
1120
|
-
};
|
|
1121
|
-
get type() {
|
|
1122
|
-
return "bitbucketServer";
|
|
1123
|
-
}
|
|
1124
|
-
get title() {
|
|
1125
|
-
return this.integrationConfig.host;
|
|
1126
|
-
}
|
|
1127
|
-
get config() {
|
|
1128
|
-
return this.integrationConfig;
|
|
1129
|
-
}
|
|
1130
|
-
resolveUrl(options) {
|
|
1131
|
-
const resolved = defaultScmResolveUrl(options);
|
|
1132
|
-
if (options.lineNumber) {
|
|
1133
|
-
const url = new URL(resolved);
|
|
1134
|
-
url.hash = options.lineNumber.toString();
|
|
1135
|
-
return url.toString();
|
|
1136
|
-
}
|
|
1137
|
-
return resolved;
|
|
1138
|
-
}
|
|
1139
|
-
resolveEditUrl(url) {
|
|
1140
|
-
if (url.includes("?")) {
|
|
1141
|
-
return url.substring(0, url.indexOf("?"));
|
|
1142
|
-
}
|
|
1143
|
-
return url;
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
async function getBitbucketServerDefaultBranch(url, config) {
|
|
1148
|
-
const { name: repoName, owner: project } = parseGitUrl__default.default(url);
|
|
1149
|
-
let branchUrl = `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/default-branch`;
|
|
1150
|
-
let response = await fetch__default.default(
|
|
1151
|
-
branchUrl,
|
|
1152
|
-
getBitbucketServerRequestOptions(config)
|
|
1153
|
-
);
|
|
1154
|
-
if (response.status === 404) {
|
|
1155
|
-
branchUrl = `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/branches/default`;
|
|
1156
|
-
response = await fetch__default.default(branchUrl, getBitbucketServerRequestOptions(config));
|
|
1157
|
-
}
|
|
1158
|
-
if (!response.ok) {
|
|
1159
|
-
const message = `Failed to retrieve default branch from ${branchUrl}, ${response.status} ${response.statusText}`;
|
|
1160
|
-
throw new Error(message);
|
|
1161
|
-
}
|
|
1162
|
-
const { displayId } = await response.json();
|
|
1163
|
-
const defaultBranch = displayId;
|
|
1164
|
-
if (!defaultBranch) {
|
|
1165
|
-
throw new Error(
|
|
1166
|
-
`Failed to read default branch from ${branchUrl}. Response ${response.status} ${response.json()}`
|
|
1167
|
-
);
|
|
1168
|
-
}
|
|
1169
|
-
return defaultBranch;
|
|
1170
|
-
}
|
|
1171
|
-
async function getBitbucketServerDownloadUrl(url, config) {
|
|
1172
|
-
const { name: repoName, owner: project, ref, filepath } = parseGitUrl__default.default(url);
|
|
1173
|
-
let branch = ref;
|
|
1174
|
-
if (!branch) {
|
|
1175
|
-
branch = await getBitbucketServerDefaultBranch(url, config);
|
|
1176
|
-
}
|
|
1177
|
-
const path = filepath ? `&path=${encodeURIComponent(decodeURIComponent(filepath))}` : "";
|
|
1178
|
-
return `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/archive?format=tgz&at=${branch}&prefix=${project}-${repoName}${path}`;
|
|
1179
|
-
}
|
|
1180
|
-
function getBitbucketServerFileFetchUrl(url, config) {
|
|
1181
|
-
try {
|
|
1182
|
-
const { owner, name, ref, filepathtype, filepath } = parseGitUrl__default.default(url);
|
|
1183
|
-
if (!owner || !name || filepathtype !== "browse" && filepathtype !== "raw" && filepathtype !== "src") {
|
|
1184
|
-
throw new Error("Invalid Bitbucket Server URL or file path");
|
|
1185
|
-
}
|
|
1186
|
-
const pathWithoutSlash = filepath.replace(/^\//, "");
|
|
1187
|
-
return `${config.apiBaseUrl}/projects/${owner}/repos/${name}/raw/${pathWithoutSlash}?at=${ref}`;
|
|
1188
|
-
} catch (e) {
|
|
1189
|
-
throw new Error(`Incorrect URL: ${url}, ${e}`);
|
|
1190
|
-
}
|
|
1191
|
-
}
|
|
1192
|
-
function getBitbucketServerRequestOptions(config) {
|
|
1193
|
-
const headers = {};
|
|
1194
|
-
if (config.token) {
|
|
1195
|
-
headers.Authorization = `Bearer ${config.token}`;
|
|
1196
|
-
} else if (config.username && config.password) {
|
|
1197
|
-
const buffer = Buffer.from(`${config.username}:${config.password}`, "utf8");
|
|
1198
|
-
headers.Authorization = `Basic ${buffer.toString("base64")}`;
|
|
1199
|
-
}
|
|
1200
|
-
return {
|
|
1201
|
-
headers
|
|
1202
|
-
};
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
function readGerritIntegrationConfig(config) {
|
|
1206
|
-
const host = config.getString("host");
|
|
1207
|
-
let baseUrl = config.getOptionalString("baseUrl");
|
|
1208
|
-
let cloneUrl = config.getOptionalString("cloneUrl");
|
|
1209
|
-
let gitilesBaseUrl = config.getString("gitilesBaseUrl");
|
|
1210
|
-
const username = config.getOptionalString("username");
|
|
1211
|
-
const password = config.getOptionalString("password")?.trim();
|
|
1212
|
-
if (!isValidHost(host)) {
|
|
1213
|
-
throw new Error(
|
|
1214
|
-
`Invalid Gerrit integration config, '${host}' is not a valid host`
|
|
1215
|
-
);
|
|
1216
|
-
} else if (baseUrl && !isValidUrl(baseUrl)) {
|
|
1217
|
-
throw new Error(
|
|
1218
|
-
`Invalid Gerrit integration config, '${baseUrl}' is not a valid baseUrl`
|
|
1219
|
-
);
|
|
1220
|
-
} else if (cloneUrl && !isValidUrl(cloneUrl)) {
|
|
1221
|
-
throw new Error(
|
|
1222
|
-
`Invalid Gerrit integration config, '${cloneUrl}' is not a valid cloneUrl`
|
|
1223
|
-
);
|
|
1224
|
-
} else if (!isValidUrl(gitilesBaseUrl)) {
|
|
1225
|
-
throw new Error(
|
|
1226
|
-
`Invalid Gerrit integration config, '${gitilesBaseUrl}' is not a valid gitilesBaseUrl`
|
|
1227
|
-
);
|
|
1228
|
-
}
|
|
1229
|
-
if (baseUrl) {
|
|
1230
|
-
baseUrl = lodash.trimEnd(baseUrl, "/");
|
|
1231
|
-
} else {
|
|
1232
|
-
baseUrl = `https://${host}`;
|
|
1233
|
-
}
|
|
1234
|
-
if (gitilesBaseUrl) {
|
|
1235
|
-
gitilesBaseUrl = lodash.trimEnd(gitilesBaseUrl, "/");
|
|
1236
|
-
} else {
|
|
1237
|
-
gitilesBaseUrl = `https://${host}`;
|
|
1238
|
-
}
|
|
1239
|
-
if (cloneUrl) {
|
|
1240
|
-
cloneUrl = lodash.trimEnd(cloneUrl, "/");
|
|
1241
|
-
} else {
|
|
1242
|
-
cloneUrl = baseUrl;
|
|
1243
|
-
}
|
|
1244
|
-
return {
|
|
1245
|
-
host,
|
|
1246
|
-
baseUrl,
|
|
1247
|
-
cloneUrl,
|
|
1248
|
-
gitilesBaseUrl,
|
|
1249
|
-
username,
|
|
1250
|
-
password
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
function readGerritIntegrationConfigs(configs) {
|
|
1254
|
-
return configs.map(readGerritIntegrationConfig);
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
|
-
const GERRIT_BODY_PREFIX = ")]}'";
|
|
1258
|
-
function parseGerritGitilesUrl(config, url) {
|
|
1259
|
-
const baseUrlParse = new URL(config.gitilesBaseUrl);
|
|
1260
|
-
const urlParse = new URL(url);
|
|
1261
|
-
const urlPath = urlParse.pathname.substring(urlParse.pathname.startsWith("/a/") ? 2 : 0).replace(baseUrlParse.pathname, "");
|
|
1262
|
-
const parts = urlPath.split("/").filter((p) => !!p);
|
|
1263
|
-
const projectEndIndex = parts.indexOf("+");
|
|
1264
|
-
if (projectEndIndex <= 0) {
|
|
1265
|
-
throw new Error(`Unable to parse project from url: ${url}`);
|
|
1266
|
-
}
|
|
1267
|
-
const project = lodash.trimStart(parts.slice(0, projectEndIndex).join("/"), "/");
|
|
1268
|
-
const branchIndex = parts.indexOf("heads");
|
|
1269
|
-
if (branchIndex <= 0) {
|
|
1270
|
-
throw new Error(`Unable to parse branch from url: ${url}`);
|
|
1271
|
-
}
|
|
1272
|
-
const branch = parts[branchIndex + 1];
|
|
1273
|
-
const filePath = parts.slice(branchIndex + 2).join("/");
|
|
1274
|
-
return {
|
|
1275
|
-
branch,
|
|
1276
|
-
filePath: filePath === "" ? "/" : filePath,
|
|
1277
|
-
project
|
|
1278
|
-
};
|
|
1279
|
-
}
|
|
1280
|
-
function parseGitilesUrlRef(config, url) {
|
|
1281
|
-
const baseUrlParse = new URL(config.gitilesBaseUrl);
|
|
1282
|
-
const urlParse = new URL(url);
|
|
1283
|
-
const urlPath = lodash.trimStart(
|
|
1284
|
-
urlParse.pathname.substring(urlParse.pathname.startsWith("/a/") ? 2 : 0).replace(baseUrlParse.pathname, ""),
|
|
1285
|
-
"/"
|
|
1286
|
-
);
|
|
1287
|
-
const parts = urlPath.split("/").filter((p) => !!p);
|
|
1288
|
-
const projectParts = lodash.takeWhile(parts, (p) => p !== "+");
|
|
1289
|
-
if (projectParts.length === 0) {
|
|
1290
|
-
throw new Error(`Unable to parse gitiles url: ${url}`);
|
|
1291
|
-
}
|
|
1292
|
-
const rest = parts.slice(projectParts.length + 1);
|
|
1293
|
-
const project = lodash.join(projectParts, "/");
|
|
1294
|
-
if (rest.length > 0 && rest[0] === "HEAD") {
|
|
1295
|
-
const ref = rest.shift();
|
|
1296
|
-
const path = lodash.join(rest, "/");
|
|
1297
|
-
return {
|
|
1298
|
-
project,
|
|
1299
|
-
ref,
|
|
1300
|
-
refType: "head",
|
|
1301
|
-
path: path || "/",
|
|
1302
|
-
basePath: lodash.trimEnd(url.replace(path, ""), "/")
|
|
1303
|
-
};
|
|
1304
|
-
}
|
|
1305
|
-
if (rest.length > 0 && rest[0].length === 40) {
|
|
1306
|
-
const ref = rest.shift();
|
|
1307
|
-
const path = lodash.join(rest, "/");
|
|
1308
|
-
return {
|
|
1309
|
-
project,
|
|
1310
|
-
ref,
|
|
1311
|
-
refType: "sha",
|
|
1312
|
-
path: path || "/",
|
|
1313
|
-
basePath: lodash.trimEnd(url.replace(path, ""), "/")
|
|
1314
|
-
};
|
|
1315
|
-
}
|
|
1316
|
-
const remainingPath = lodash.join(rest, "/");
|
|
1317
|
-
const refsRegexp = /^refs\/(?<refsReference>heads|tags)\/(?<ref>.*?)(\/|$)/;
|
|
1318
|
-
const result = refsRegexp.exec(remainingPath);
|
|
1319
|
-
if (result) {
|
|
1320
|
-
const matchString = result[0];
|
|
1321
|
-
let refType;
|
|
1322
|
-
const { refsReference, ref } = result.groups || {};
|
|
1323
|
-
const path = remainingPath.replace(matchString, "");
|
|
1324
|
-
switch (refsReference) {
|
|
1325
|
-
case "heads":
|
|
1326
|
-
refType = "branch";
|
|
1327
|
-
break;
|
|
1328
|
-
case "tags":
|
|
1329
|
-
refType = "tag";
|
|
1330
|
-
break;
|
|
1331
|
-
default:
|
|
1332
|
-
throw new Error(`Unable to parse gitiles url: ${url}`);
|
|
1333
|
-
}
|
|
1334
|
-
return {
|
|
1335
|
-
project,
|
|
1336
|
-
ref,
|
|
1337
|
-
refType,
|
|
1338
|
-
path: path || "/",
|
|
1339
|
-
basePath: lodash.trimEnd(url.replace(path, ""), "/")
|
|
1340
|
-
};
|
|
1341
|
-
}
|
|
1342
|
-
throw new Error(`Unable to parse gitiles : ${url}`);
|
|
1343
|
-
}
|
|
1344
|
-
function buildGerritGitilesArchiveUrl(config, project, branch, filePath) {
|
|
1345
|
-
const archiveName = filePath === "/" || filePath === "" ? ".tar.gz" : `/${filePath}.tar.gz`;
|
|
1346
|
-
return `${getGitilesAuthenticationUrl(
|
|
1347
|
-
config
|
|
1348
|
-
)}/${project}/+archive/refs/heads/${branch}${archiveName}`;
|
|
1349
|
-
}
|
|
1350
|
-
function getAuthenticationPrefix(config) {
|
|
1351
|
-
return config.password ? "/a/" : "/";
|
|
1352
|
-
}
|
|
1353
|
-
function getGitilesAuthenticationUrl(config) {
|
|
1354
|
-
if (!config.baseUrl || !config.gitilesBaseUrl) {
|
|
1355
|
-
throw new Error(
|
|
1356
|
-
"Unexpected Gerrit config values. baseUrl or gitilesBaseUrl not set."
|
|
1357
|
-
);
|
|
1358
|
-
}
|
|
1359
|
-
if (config.gitilesBaseUrl.startsWith(config.baseUrl)) {
|
|
1360
|
-
return config.gitilesBaseUrl.replace(
|
|
1361
|
-
config.baseUrl.concat("/"),
|
|
1362
|
-
config.baseUrl.concat(getAuthenticationPrefix(config))
|
|
1363
|
-
);
|
|
1364
|
-
}
|
|
1365
|
-
if (config.password) {
|
|
1366
|
-
throw new Error(
|
|
1367
|
-
"Since the baseUrl (Gerrit) is not part of the gitilesBaseUrl, an authentication URL could not be constructed."
|
|
1368
|
-
);
|
|
1369
|
-
}
|
|
1370
|
-
return config.gitilesBaseUrl;
|
|
1371
|
-
}
|
|
1372
|
-
function getGerritBranchApiUrl(config, url) {
|
|
1373
|
-
const { branch, project } = parseGerritGitilesUrl(config, url);
|
|
1374
|
-
return `${config.baseUrl}${getAuthenticationPrefix(
|
|
1375
|
-
config
|
|
1376
|
-
)}projects/${encodeURIComponent(project)}/branches/${branch}`;
|
|
1377
|
-
}
|
|
1378
|
-
function getGerritCloneRepoUrl(config, url) {
|
|
1379
|
-
const { project } = parseGerritGitilesUrl(config, url);
|
|
1380
|
-
return `${config.cloneUrl}${getAuthenticationPrefix(config)}${project}`;
|
|
1381
|
-
}
|
|
1382
|
-
function getGerritFileContentsApiUrl(config, url) {
|
|
1383
|
-
const { branch, filePath, project } = parseGerritGitilesUrl(config, url);
|
|
1384
|
-
return `${config.baseUrl}${getAuthenticationPrefix(
|
|
1385
|
-
config
|
|
1386
|
-
)}projects/${encodeURIComponent(
|
|
1387
|
-
project
|
|
1388
|
-
)}/branches/${branch}/files/${encodeURIComponent(filePath)}/content`;
|
|
1389
|
-
}
|
|
1390
|
-
function getGerritProjectsApiUrl(config) {
|
|
1391
|
-
return `${config.baseUrl}${getAuthenticationPrefix(config)}projects/`;
|
|
1392
|
-
}
|
|
1393
|
-
function getGerritRequestOptions(config) {
|
|
1394
|
-
const headers = {};
|
|
1395
|
-
if (!config.password) {
|
|
1396
|
-
return headers;
|
|
1397
|
-
}
|
|
1398
|
-
const buffer = Buffer.from(`${config.username}:${config.password}`, "utf8");
|
|
1399
|
-
headers.Authorization = `Basic ${buffer.toString("base64")}`;
|
|
1400
|
-
return {
|
|
1401
|
-
headers
|
|
1402
|
-
};
|
|
1403
|
-
}
|
|
1404
|
-
async function parseGerritJsonResponse(response) {
|
|
1405
|
-
const responseBody = await response.text();
|
|
1406
|
-
if (responseBody.startsWith(GERRIT_BODY_PREFIX)) {
|
|
1407
|
-
try {
|
|
1408
|
-
return JSON.parse(responseBody.slice(GERRIT_BODY_PREFIX.length));
|
|
1409
|
-
} catch (ex) {
|
|
1410
|
-
throw new Error(
|
|
1411
|
-
`Invalid response from Gerrit: ${responseBody.slice(0, 10)} - ${ex}`
|
|
1412
|
-
);
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
throw new Error(
|
|
1416
|
-
`Gerrit JSON body prefix missing. Found: ${responseBody.slice(0, 10)}`
|
|
1417
|
-
);
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
class GerritIntegration {
|
|
1421
|
-
constructor(integrationConfig) {
|
|
1422
|
-
this.integrationConfig = integrationConfig;
|
|
1423
|
-
}
|
|
1424
|
-
static factory = ({ config }) => {
|
|
1425
|
-
const configs = readGerritIntegrationConfigs(
|
|
1426
|
-
config.getOptionalConfigArray("integrations.gerrit") ?? []
|
|
1427
|
-
);
|
|
1428
|
-
return basicIntegrations(
|
|
1429
|
-
configs.map((c) => new GerritIntegration(c)),
|
|
1430
|
-
(i) => i.config.host
|
|
1431
|
-
);
|
|
1432
|
-
};
|
|
1433
|
-
get type() {
|
|
1434
|
-
return "gerrit";
|
|
1435
|
-
}
|
|
1436
|
-
get title() {
|
|
1437
|
-
return this.integrationConfig.host;
|
|
1438
|
-
}
|
|
1439
|
-
get config() {
|
|
1440
|
-
return this.integrationConfig;
|
|
1441
|
-
}
|
|
1442
|
-
resolveUrl(options) {
|
|
1443
|
-
const { url, base, lineNumber } = options;
|
|
1444
|
-
let updated;
|
|
1445
|
-
if (url.startsWith("/")) {
|
|
1446
|
-
const { basePath } = parseGitilesUrlRef(this.config, base);
|
|
1447
|
-
return basePath + url;
|
|
1448
|
-
}
|
|
1449
|
-
if (url) {
|
|
1450
|
-
updated = new URL(url, base);
|
|
1451
|
-
} else {
|
|
1452
|
-
updated = new URL(base);
|
|
1453
|
-
}
|
|
1454
|
-
if (lineNumber) {
|
|
1455
|
-
updated.hash = lineNumber.toString();
|
|
1456
|
-
}
|
|
1457
|
-
return updated.toString();
|
|
1458
|
-
}
|
|
1459
|
-
resolveEditUrl(url) {
|
|
1460
|
-
return url;
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
function readGiteaConfig(config) {
|
|
1465
|
-
const host = config.getString("host");
|
|
1466
|
-
let baseUrl = config.getOptionalString("baseUrl");
|
|
1467
|
-
const username = config.getOptionalString("username");
|
|
1468
|
-
const password = config.getOptionalString("password")?.trim();
|
|
1469
|
-
if (!isValidHost(host)) {
|
|
1470
|
-
throw new Error(
|
|
1471
|
-
`Invalid Gitea integration config, '${host}' is not a valid host`
|
|
1472
|
-
);
|
|
1473
|
-
} else if (baseUrl && !isValidUrl(baseUrl)) {
|
|
1474
|
-
throw new Error(
|
|
1475
|
-
`Invalid Gitea integration config, '${baseUrl}' is not a valid baseUrl`
|
|
1476
|
-
);
|
|
1477
|
-
}
|
|
1478
|
-
if (baseUrl) {
|
|
1479
|
-
baseUrl = lodash.trimEnd(baseUrl, "/");
|
|
1480
|
-
} else {
|
|
1481
|
-
baseUrl = `https://${host}`;
|
|
1482
|
-
}
|
|
1483
|
-
return {
|
|
1484
|
-
host,
|
|
1485
|
-
baseUrl,
|
|
1486
|
-
username,
|
|
1487
|
-
password
|
|
1488
|
-
};
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
function getGiteaEditContentsUrl(config, url) {
|
|
1492
|
-
const giteaUrl = parseGiteaUrl(config, url);
|
|
1493
|
-
return `${giteaUrl.url}/${giteaUrl.owner}/${giteaUrl.name}/_edit/${giteaUrl.ref}/${giteaUrl.path}`;
|
|
1494
|
-
}
|
|
1495
|
-
function getGiteaFileContentsUrl(config, url) {
|
|
1496
|
-
const giteaUrl = parseGiteaUrl(config, url);
|
|
1497
|
-
return `${giteaUrl.url}/api/v1/repos/${giteaUrl.owner}/${giteaUrl.name}/contents/${giteaUrl.path}?ref=${giteaUrl.ref}`;
|
|
1498
|
-
}
|
|
1499
|
-
function getGiteaArchiveUrl(config, url) {
|
|
1500
|
-
const giteaUrl = parseGiteaUrl(config, url);
|
|
1501
|
-
return `${giteaUrl.url}/api/v1/repos/${giteaUrl.owner}/${giteaUrl.name}/archive/${giteaUrl.ref}.tar.gz`;
|
|
1502
|
-
}
|
|
1503
|
-
function getGiteaLatestCommitUrl(config, url) {
|
|
1504
|
-
const giteaUrl = parseGiteaUrl(config, url);
|
|
1505
|
-
return `${giteaUrl.url}/api/v1/repos/${giteaUrl.owner}/${giteaUrl.name}/git/commits/${giteaUrl.ref}`;
|
|
1506
|
-
}
|
|
1507
|
-
function getGiteaRequestOptions(config) {
|
|
1508
|
-
const headers = {};
|
|
1509
|
-
const { username, password } = config;
|
|
1510
|
-
if (!password) {
|
|
1511
|
-
return headers;
|
|
1512
|
-
}
|
|
1513
|
-
if (username) {
|
|
1514
|
-
headers.Authorization = `basic ${Buffer.from(
|
|
1515
|
-
`${username}:${password}`
|
|
1516
|
-
).toString("base64")}`;
|
|
1517
|
-
} else {
|
|
1518
|
-
headers.Authorization = `token ${password}`;
|
|
1519
|
-
}
|
|
1520
|
-
return {
|
|
1521
|
-
headers
|
|
1522
|
-
};
|
|
1523
|
-
}
|
|
1524
|
-
function parseGiteaUrl(config, url) {
|
|
1525
|
-
const baseUrl = config.baseUrl ?? `https://${config.host}`;
|
|
1526
|
-
try {
|
|
1527
|
-
const [_blank, owner, name, _src, _branch, ref, ...path] = url.replace(baseUrl, "").split("/");
|
|
1528
|
-
const pathWithoutSlash = path.join("/").replace(/^\//, "");
|
|
1529
|
-
return {
|
|
1530
|
-
url: baseUrl,
|
|
1531
|
-
owner,
|
|
1532
|
-
name,
|
|
1533
|
-
ref,
|
|
1534
|
-
path: pathWithoutSlash
|
|
1535
|
-
};
|
|
1536
|
-
} catch (e) {
|
|
1537
|
-
throw new Error(`Incorrect URL: ${url}, ${e}`);
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1541
|
-
class GiteaIntegration {
|
|
1542
|
-
constructor(config) {
|
|
1543
|
-
this.config = config;
|
|
1544
|
-
}
|
|
1545
|
-
static factory = ({ config }) => {
|
|
1546
|
-
const configs = config.getOptionalConfigArray("integrations.gitea") ?? [];
|
|
1547
|
-
const giteaConfigs = configs.map((c) => readGiteaConfig(c));
|
|
1548
|
-
return basicIntegrations(
|
|
1549
|
-
giteaConfigs.map((c) => new GiteaIntegration(c)),
|
|
1550
|
-
(gitea) => gitea.config.host
|
|
1551
|
-
);
|
|
1552
|
-
};
|
|
1553
|
-
get type() {
|
|
1554
|
-
return "gitea";
|
|
1555
|
-
}
|
|
1556
|
-
get title() {
|
|
1557
|
-
return this.config.host;
|
|
1558
|
-
}
|
|
1559
|
-
resolveUrl(options) {
|
|
1560
|
-
return defaultScmResolveUrl(options);
|
|
1561
|
-
}
|
|
1562
|
-
resolveEditUrl(url) {
|
|
1563
|
-
return getGiteaEditContentsUrl(this.config, url);
|
|
1564
|
-
}
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
const GITHUB_HOST = "github.com";
|
|
1568
|
-
const GITHUB_API_BASE_URL = "https://api.github.com";
|
|
1569
|
-
const GITHUB_RAW_BASE_URL = "https://raw.githubusercontent.com";
|
|
1570
|
-
function readGithubIntegrationConfig(config) {
|
|
1571
|
-
const host = config.getOptionalString("host") ?? GITHUB_HOST;
|
|
1572
|
-
let apiBaseUrl = config.getOptionalString("apiBaseUrl");
|
|
1573
|
-
let rawBaseUrl = config.getOptionalString("rawBaseUrl");
|
|
1574
|
-
const token = config.getOptionalString("token")?.trim();
|
|
1575
|
-
const apps = config.getOptionalConfigArray("apps")?.map((c) => ({
|
|
1576
|
-
appId: c.getNumber("appId"),
|
|
1577
|
-
clientId: c.getString("clientId"),
|
|
1578
|
-
clientSecret: c.getString("clientSecret"),
|
|
1579
|
-
webhookSecret: c.getString("webhookSecret"),
|
|
1580
|
-
privateKey: c.getString("privateKey"),
|
|
1581
|
-
allowedInstallationOwners: c.getOptionalStringArray(
|
|
1582
|
-
"allowedInstallationOwners"
|
|
1583
|
-
)
|
|
1584
|
-
}));
|
|
1585
|
-
if (!isValidHost(host)) {
|
|
1586
|
-
throw new Error(
|
|
1587
|
-
`Invalid GitHub integration config, '${host}' is not a valid host`
|
|
1588
|
-
);
|
|
1589
|
-
}
|
|
1590
|
-
if (apiBaseUrl) {
|
|
1591
|
-
apiBaseUrl = lodash.trimEnd(apiBaseUrl, "/");
|
|
1592
|
-
} else if (host === GITHUB_HOST) {
|
|
1593
|
-
apiBaseUrl = GITHUB_API_BASE_URL;
|
|
1594
|
-
}
|
|
1595
|
-
if (rawBaseUrl) {
|
|
1596
|
-
rawBaseUrl = lodash.trimEnd(rawBaseUrl, "/");
|
|
1597
|
-
} else if (host === GITHUB_HOST) {
|
|
1598
|
-
rawBaseUrl = GITHUB_RAW_BASE_URL;
|
|
1599
|
-
}
|
|
1600
|
-
return { host, apiBaseUrl, rawBaseUrl, token, apps };
|
|
1601
|
-
}
|
|
1602
|
-
function readGithubIntegrationConfigs(configs) {
|
|
1603
|
-
const result = configs.map(readGithubIntegrationConfig);
|
|
1604
|
-
if (!result.some((c) => c.host === GITHUB_HOST)) {
|
|
1605
|
-
result.push({
|
|
1606
|
-
host: GITHUB_HOST,
|
|
1607
|
-
apiBaseUrl: GITHUB_API_BASE_URL,
|
|
1608
|
-
rawBaseUrl: GITHUB_RAW_BASE_URL
|
|
1609
|
-
});
|
|
1610
|
-
}
|
|
1611
|
-
return result;
|
|
1612
|
-
}
|
|
1613
|
-
|
|
1614
|
-
function getGithubFileFetchUrl(url, config, credentials) {
|
|
1615
|
-
try {
|
|
1616
|
-
const { owner, name, ref, filepathtype, filepath } = parseGitUrl__default.default(url);
|
|
1617
|
-
if (!owner || !name || !ref || // GitHub is automatically redirecting tree urls to blob urls so it's
|
|
1618
|
-
// fine to pass a tree url.
|
|
1619
|
-
filepathtype !== "blob" && filepathtype !== "raw" && filepathtype !== "tree") {
|
|
1620
|
-
throw new Error("Invalid GitHub URL or file path");
|
|
1621
|
-
}
|
|
1622
|
-
const pathWithoutSlash = filepath.replace(/^\//, "");
|
|
1623
|
-
if (chooseEndpoint(config, credentials) === "api") {
|
|
1624
|
-
return `${config.apiBaseUrl}/repos/${owner}/${name}/contents/${pathWithoutSlash}?ref=${ref}`;
|
|
1625
|
-
}
|
|
1626
|
-
return `${config.rawBaseUrl}/${owner}/${name}/${ref}/${pathWithoutSlash}`;
|
|
1627
|
-
} catch (e) {
|
|
1628
|
-
throw new Error(`Incorrect URL: ${url}, ${e}`);
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
function getGitHubRequestOptions(config, credentials) {
|
|
1632
|
-
const headers = {};
|
|
1633
|
-
if (chooseEndpoint(config, credentials) === "api") {
|
|
1634
|
-
headers.Accept = "application/vnd.github.v3.raw";
|
|
1635
|
-
}
|
|
1636
|
-
if (credentials.token) {
|
|
1637
|
-
headers.Authorization = `token ${credentials.token}`;
|
|
1638
|
-
}
|
|
1639
|
-
return { headers };
|
|
1640
|
-
}
|
|
1641
|
-
function chooseEndpoint(config, credentials) {
|
|
1642
|
-
if (config.apiBaseUrl && (credentials.token || !config.rawBaseUrl)) {
|
|
1643
|
-
return "api";
|
|
1644
|
-
}
|
|
1645
|
-
return "raw";
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
class Cache {
|
|
1649
|
-
tokenCache = /* @__PURE__ */ new Map();
|
|
1650
|
-
async getOrCreateToken(owner, repo, supplier) {
|
|
1651
|
-
let existingInstallationData = this.tokenCache.get(owner);
|
|
1652
|
-
if (!existingInstallationData || this.isExpired(existingInstallationData.expiresAt)) {
|
|
1653
|
-
existingInstallationData = await supplier();
|
|
1654
|
-
existingInstallationData.expiresAt = existingInstallationData.expiresAt.minus({ minutes: 10 });
|
|
1655
|
-
this.tokenCache.set(owner, existingInstallationData);
|
|
1656
|
-
}
|
|
1657
|
-
if (!this.appliesToRepo(existingInstallationData, repo)) {
|
|
1658
|
-
throw new Error(
|
|
1659
|
-
`The Backstage GitHub application used in the ${owner} organization does not have access to a repository with the name ${repo}`
|
|
1660
|
-
);
|
|
1661
|
-
}
|
|
1662
|
-
return { accessToken: existingInstallationData.token };
|
|
1663
|
-
}
|
|
1664
|
-
isExpired = (date) => luxon.DateTime.local() > date;
|
|
1665
|
-
appliesToRepo(tokenData, repo) {
|
|
1666
|
-
if (repo === void 0) {
|
|
1667
|
-
return true;
|
|
1668
|
-
}
|
|
1669
|
-
if (tokenData.repositories !== void 0) {
|
|
1670
|
-
return tokenData.repositories.includes(repo);
|
|
1671
|
-
}
|
|
1672
|
-
return true;
|
|
1673
|
-
}
|
|
1674
|
-
}
|
|
1675
|
-
const HEADERS = {
|
|
1676
|
-
Accept: "application/vnd.github.machine-man-preview+json"
|
|
1677
|
-
};
|
|
1678
|
-
class GithubAppManager {
|
|
1679
|
-
appClient;
|
|
1680
|
-
baseUrl;
|
|
1681
|
-
baseAuthConfig;
|
|
1682
|
-
cache = new Cache();
|
|
1683
|
-
allowedInstallationOwners;
|
|
1684
|
-
// undefined allows all installations
|
|
1685
|
-
constructor(config, baseUrl) {
|
|
1686
|
-
this.allowedInstallationOwners = config.allowedInstallationOwners;
|
|
1687
|
-
this.baseUrl = baseUrl;
|
|
1688
|
-
this.baseAuthConfig = {
|
|
1689
|
-
appId: config.appId,
|
|
1690
|
-
privateKey: config.privateKey.replace(/\\n/gm, "\n")
|
|
1691
|
-
};
|
|
1692
|
-
this.appClient = new rest.Octokit({
|
|
1693
|
-
baseUrl,
|
|
1694
|
-
headers: HEADERS,
|
|
1695
|
-
authStrategy: authApp.createAppAuth,
|
|
1696
|
-
auth: this.baseAuthConfig
|
|
1697
|
-
});
|
|
1698
|
-
}
|
|
1699
|
-
async getInstallationCredentials(owner, repo) {
|
|
1700
|
-
if (this.allowedInstallationOwners) {
|
|
1701
|
-
if (!this.allowedInstallationOwners?.includes(owner)) {
|
|
1702
|
-
return { accessToken: void 0 };
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
return this.cache.getOrCreateToken(owner, repo, async () => {
|
|
1706
|
-
const { installationId, suspended } = await this.getInstallationData(
|
|
1707
|
-
owner
|
|
1708
|
-
);
|
|
1709
|
-
if (suspended) {
|
|
1710
|
-
throw new Error(`The GitHub application for ${owner} is suspended`);
|
|
1711
|
-
}
|
|
1712
|
-
const result = await this.appClient.apps.createInstallationAccessToken({
|
|
1713
|
-
installation_id: installationId,
|
|
1714
|
-
headers: HEADERS
|
|
1715
|
-
});
|
|
1716
|
-
let repositoryNames;
|
|
1717
|
-
if (result.data.repository_selection === "selected") {
|
|
1718
|
-
const installationClient = new rest.Octokit({
|
|
1719
|
-
baseUrl: this.baseUrl,
|
|
1720
|
-
auth: result.data.token
|
|
1721
|
-
});
|
|
1722
|
-
const repos = await installationClient.paginate(
|
|
1723
|
-
installationClient.apps.listReposAccessibleToInstallation
|
|
1724
|
-
);
|
|
1725
|
-
const repositories = repos.repositories ?? repos;
|
|
1726
|
-
repositoryNames = repositories.map((repository) => repository.name);
|
|
1727
|
-
}
|
|
1728
|
-
return {
|
|
1729
|
-
token: result.data.token,
|
|
1730
|
-
expiresAt: luxon.DateTime.fromISO(result.data.expires_at),
|
|
1731
|
-
repositories: repositoryNames
|
|
1732
|
-
};
|
|
1733
|
-
});
|
|
1734
|
-
}
|
|
1735
|
-
getInstallations() {
|
|
1736
|
-
return this.appClient.paginate(this.appClient.apps.listInstallations);
|
|
1737
|
-
}
|
|
1738
|
-
async getInstallationData(owner) {
|
|
1739
|
-
const allInstallations = await this.getInstallations();
|
|
1740
|
-
const installation = allInstallations.find(
|
|
1741
|
-
(inst) => inst.account && "login" in inst.account && inst.account.login?.toLocaleLowerCase("en-US") === owner.toLocaleLowerCase("en-US")
|
|
1742
|
-
);
|
|
1743
|
-
if (installation) {
|
|
1744
|
-
return {
|
|
1745
|
-
installationId: installation.id,
|
|
1746
|
-
suspended: Boolean(installation.suspended_by)
|
|
1747
|
-
};
|
|
1748
|
-
}
|
|
1749
|
-
const notFoundError = new Error(
|
|
1750
|
-
`No app installation found for ${owner} in ${this.baseAuthConfig.appId}`
|
|
1751
|
-
);
|
|
1752
|
-
notFoundError.name = "NotFoundError";
|
|
1753
|
-
throw notFoundError;
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
class GithubAppCredentialsMux {
|
|
1757
|
-
apps;
|
|
1758
|
-
constructor(config) {
|
|
1759
|
-
this.apps = config.apps?.map((ac) => new GithubAppManager(ac, config.apiBaseUrl)) ?? [];
|
|
1760
|
-
}
|
|
1761
|
-
async getAllInstallations() {
|
|
1762
|
-
if (!this.apps.length) {
|
|
1763
|
-
return [];
|
|
1764
|
-
}
|
|
1765
|
-
const installs = await Promise.all(
|
|
1766
|
-
this.apps.map((app) => app.getInstallations())
|
|
1767
|
-
);
|
|
1768
|
-
return installs.flat();
|
|
1769
|
-
}
|
|
1770
|
-
async getAppToken(owner, repo) {
|
|
1771
|
-
if (this.apps.length === 0) {
|
|
1772
|
-
return void 0;
|
|
1773
|
-
}
|
|
1774
|
-
const results = await Promise.all(
|
|
1775
|
-
this.apps.map(
|
|
1776
|
-
(app) => app.getInstallationCredentials(owner, repo).then(
|
|
1777
|
-
(credentials) => ({ credentials, error: void 0 }),
|
|
1778
|
-
(error) => ({ credentials: void 0, error })
|
|
1779
|
-
)
|
|
1780
|
-
)
|
|
1781
|
-
);
|
|
1782
|
-
const result = results.find(
|
|
1783
|
-
(resultItem) => resultItem.credentials?.accessToken
|
|
1784
|
-
);
|
|
1785
|
-
if (result) {
|
|
1786
|
-
return result.credentials.accessToken;
|
|
1787
|
-
}
|
|
1788
|
-
const errors = results.map((r) => r.error);
|
|
1789
|
-
const notNotFoundError = errors.find((err) => err?.name !== "NotFoundError");
|
|
1790
|
-
if (notNotFoundError) {
|
|
1791
|
-
throw notNotFoundError;
|
|
1792
|
-
}
|
|
1793
|
-
return void 0;
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
|
-
class SingleInstanceGithubCredentialsProvider {
|
|
1797
|
-
constructor(githubAppCredentialsMux, token) {
|
|
1798
|
-
this.githubAppCredentialsMux = githubAppCredentialsMux;
|
|
1799
|
-
this.token = token;
|
|
1800
|
-
}
|
|
1801
|
-
static create = (config) => {
|
|
1802
|
-
return new SingleInstanceGithubCredentialsProvider(
|
|
1803
|
-
new GithubAppCredentialsMux(config),
|
|
1804
|
-
config.token
|
|
1805
|
-
);
|
|
1806
|
-
};
|
|
1807
|
-
/**
|
|
1808
|
-
* Returns {@link GithubCredentials} for a given URL.
|
|
1809
|
-
*
|
|
1810
|
-
* @remarks
|
|
1811
|
-
*
|
|
1812
|
-
* Consecutive calls to this method with the same URL will return cached
|
|
1813
|
-
* credentials.
|
|
1814
|
-
*
|
|
1815
|
-
* The shortest lifetime for a token returned is 10 minutes.
|
|
1816
|
-
*
|
|
1817
|
-
* @example
|
|
1818
|
-
* ```ts
|
|
1819
|
-
* const { token, headers } = await getCredentials({
|
|
1820
|
-
* url: 'github.com/backstage/foobar'
|
|
1821
|
-
* })
|
|
1822
|
-
* ```
|
|
1823
|
-
*
|
|
1824
|
-
* @param opts - The organization or repository URL
|
|
1825
|
-
* @returns A promise of {@link GithubCredentials}.
|
|
1826
|
-
*/
|
|
1827
|
-
async getCredentials(opts) {
|
|
1828
|
-
const parsed = parseGitUrl__default.default(opts.url);
|
|
1829
|
-
const owner = parsed.owner || parsed.name;
|
|
1830
|
-
const repo = parsed.owner ? parsed.name : void 0;
|
|
1831
|
-
let type = "app";
|
|
1832
|
-
let token = await this.githubAppCredentialsMux.getAppToken(owner, repo);
|
|
1833
|
-
if (!token) {
|
|
1834
|
-
type = "token";
|
|
1835
|
-
token = this.token;
|
|
1836
|
-
}
|
|
1837
|
-
return {
|
|
1838
|
-
headers: token ? { Authorization: `Bearer ${token}` } : void 0,
|
|
1839
|
-
token,
|
|
1840
|
-
type
|
|
1841
|
-
};
|
|
1842
|
-
}
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
|
-
class DefaultGithubCredentialsProvider {
|
|
1846
|
-
constructor(providers) {
|
|
1847
|
-
this.providers = providers;
|
|
1848
|
-
}
|
|
1849
|
-
static fromIntegrations(integrations) {
|
|
1850
|
-
const credentialsProviders = /* @__PURE__ */ new Map();
|
|
1851
|
-
integrations.github.list().forEach((integration) => {
|
|
1852
|
-
const credentialsProvider = SingleInstanceGithubCredentialsProvider.create(integration.config);
|
|
1853
|
-
credentialsProviders.set(integration.config.host, credentialsProvider);
|
|
1854
|
-
});
|
|
1855
|
-
return new DefaultGithubCredentialsProvider(credentialsProviders);
|
|
1856
|
-
}
|
|
1857
|
-
/**
|
|
1858
|
-
* Returns {@link GithubCredentials} for a given URL.
|
|
1859
|
-
*
|
|
1860
|
-
* @remarks
|
|
1861
|
-
*
|
|
1862
|
-
* Consecutive calls to this method with the same URL will return cached
|
|
1863
|
-
* credentials.
|
|
1864
|
-
*
|
|
1865
|
-
* The shortest lifetime for a token returned is 10 minutes.
|
|
1866
|
-
*
|
|
1867
|
-
* @example
|
|
1868
|
-
* ```ts
|
|
1869
|
-
* const { token, headers } = await getCredentials({
|
|
1870
|
-
* url: 'https://github.com/backstage/foobar'
|
|
1871
|
-
* })
|
|
1872
|
-
*
|
|
1873
|
-
* const { token, headers } = await getCredentials({
|
|
1874
|
-
* url: 'https://github.com/backstage'
|
|
1875
|
-
* })
|
|
1876
|
-
* ```
|
|
1877
|
-
*
|
|
1878
|
-
* @param opts - The organization or repository URL
|
|
1879
|
-
* @returns A promise of {@link GithubCredentials}.
|
|
1880
|
-
*/
|
|
1881
|
-
async getCredentials(opts) {
|
|
1882
|
-
const parsed = new URL(opts.url);
|
|
1883
|
-
const provider = this.providers.get(parsed.host);
|
|
1884
|
-
if (!provider) {
|
|
1885
|
-
throw new Error(
|
|
1886
|
-
`There is no GitHub integration that matches ${opts.url}. Please add a configuration for an integration.`
|
|
1887
|
-
);
|
|
1888
|
-
}
|
|
1889
|
-
return provider.getCredentials(opts);
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
|
|
1893
|
-
class GithubIntegration {
|
|
1894
|
-
constructor(integrationConfig) {
|
|
1895
|
-
this.integrationConfig = integrationConfig;
|
|
1896
|
-
}
|
|
1897
|
-
static factory = ({ config }) => {
|
|
1898
|
-
const configs = readGithubIntegrationConfigs(
|
|
1899
|
-
config.getOptionalConfigArray("integrations.github") ?? []
|
|
1900
|
-
);
|
|
1901
|
-
return basicIntegrations(
|
|
1902
|
-
configs.map((c) => new GithubIntegration(c)),
|
|
1903
|
-
(i) => i.config.host
|
|
1904
|
-
);
|
|
1905
|
-
};
|
|
1906
|
-
get type() {
|
|
1907
|
-
return "github";
|
|
1908
|
-
}
|
|
1909
|
-
get title() {
|
|
1910
|
-
return this.integrationConfig.host;
|
|
1911
|
-
}
|
|
1912
|
-
get config() {
|
|
1913
|
-
return this.integrationConfig;
|
|
1914
|
-
}
|
|
1915
|
-
resolveUrl(options) {
|
|
1916
|
-
return replaceGithubUrlType(defaultScmResolveUrl(options), "tree");
|
|
1917
|
-
}
|
|
1918
|
-
resolveEditUrl(url) {
|
|
1919
|
-
return replaceGithubUrlType(url, "edit");
|
|
1920
|
-
}
|
|
1921
|
-
parseRateLimitInfo(response) {
|
|
1922
|
-
return {
|
|
1923
|
-
isRateLimited: response.status === 429 || response.status === 403 && response.headers.get("x-ratelimit-remaining") === "0"
|
|
1924
|
-
};
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
function replaceGithubUrlType(url, type) {
|
|
1928
|
-
return url.replace(
|
|
1929
|
-
/\/\/([^/]+)\/([^/]+)\/([^/]+)\/(blob|tree|edit)\//,
|
|
1930
|
-
(_, host, owner, repo) => {
|
|
1931
|
-
return `//${host}/${owner}/${repo}/${type}/`;
|
|
1932
|
-
}
|
|
1933
|
-
);
|
|
1934
|
-
}
|
|
1935
|
-
|
|
1936
|
-
const GITLAB_HOST = "gitlab.com";
|
|
1937
|
-
const GITLAB_API_BASE_URL = "https://gitlab.com/api/v4";
|
|
1938
|
-
function readGitLabIntegrationConfig(config) {
|
|
1939
|
-
const host = config.getString("host");
|
|
1940
|
-
let apiBaseUrl = config.getOptionalString("apiBaseUrl");
|
|
1941
|
-
const token = config.getOptionalString("token")?.trim();
|
|
1942
|
-
let baseUrl = config.getOptionalString("baseUrl");
|
|
1943
|
-
if (apiBaseUrl) {
|
|
1944
|
-
apiBaseUrl = lodash.trimEnd(apiBaseUrl, "/");
|
|
1945
|
-
} else if (host === GITLAB_HOST) {
|
|
1946
|
-
apiBaseUrl = GITLAB_API_BASE_URL;
|
|
1947
|
-
}
|
|
1948
|
-
if (baseUrl) {
|
|
1949
|
-
baseUrl = lodash.trimEnd(baseUrl, "/");
|
|
1950
|
-
} else {
|
|
1951
|
-
baseUrl = `https://${host}`;
|
|
1952
|
-
}
|
|
1953
|
-
if (!isValidHost(host)) {
|
|
1954
|
-
throw new Error(
|
|
1955
|
-
`Invalid GitLab integration config, '${host}' is not a valid host`
|
|
1956
|
-
);
|
|
1957
|
-
} else if (!apiBaseUrl || !isValidUrl(apiBaseUrl)) {
|
|
1958
|
-
throw new Error(
|
|
1959
|
-
`Invalid GitLab integration config, '${apiBaseUrl}' is not a valid apiBaseUrl`
|
|
1960
|
-
);
|
|
1961
|
-
} else if (!isValidUrl(baseUrl)) {
|
|
1962
|
-
throw new Error(
|
|
1963
|
-
`Invalid GitLab integration config, '${baseUrl}' is not a valid baseUrl`
|
|
1964
|
-
);
|
|
1965
|
-
}
|
|
1966
|
-
return { host, token, apiBaseUrl, baseUrl };
|
|
1967
|
-
}
|
|
1968
|
-
function readGitLabIntegrationConfigs(configs) {
|
|
1969
|
-
const result = configs.map(readGitLabIntegrationConfig);
|
|
1970
|
-
if (!result.some((c) => c.host === GITLAB_HOST)) {
|
|
1971
|
-
result.push({
|
|
1972
|
-
host: GITLAB_HOST,
|
|
1973
|
-
apiBaseUrl: GITLAB_API_BASE_URL,
|
|
1974
|
-
baseUrl: `https://${GITLAB_HOST}`
|
|
1975
|
-
});
|
|
1976
|
-
}
|
|
1977
|
-
return result;
|
|
1978
|
-
}
|
|
1979
|
-
function getGitLabIntegrationRelativePath(config) {
|
|
1980
|
-
let relativePath = "";
|
|
1981
|
-
if (config.host !== GITLAB_HOST) {
|
|
1982
|
-
relativePath = new URL(config.baseUrl).pathname;
|
|
1983
|
-
}
|
|
1984
|
-
return lodash.trimEnd(relativePath, "/");
|
|
1985
|
-
}
|
|
1986
|
-
|
|
1987
|
-
async function getGitLabFileFetchUrl(url, config) {
|
|
1988
|
-
const projectID = await getProjectId(url, config);
|
|
1989
|
-
return buildProjectUrl(url, projectID, config).toString();
|
|
1990
|
-
}
|
|
1991
|
-
function getGitLabRequestOptions(config, token) {
|
|
1992
|
-
if (token) {
|
|
1993
|
-
return {
|
|
1994
|
-
headers: token.startsWith("gl") ? { "PRIVATE-TOKEN": token } : { Authorization: `Bearer ${token}` }
|
|
1995
|
-
// Otherwise, it's a bearer token
|
|
1996
|
-
};
|
|
1997
|
-
}
|
|
1998
|
-
const { token: configToken = "" } = config;
|
|
1999
|
-
return {
|
|
2000
|
-
headers: { "PRIVATE-TOKEN": configToken }
|
|
2001
|
-
};
|
|
2002
|
-
}
|
|
2003
|
-
function buildProjectUrl(target, projectID, config) {
|
|
2004
|
-
try {
|
|
2005
|
-
const url = new URL(target);
|
|
2006
|
-
const branchAndFilePath = url.pathname.split("/blob/").slice(1).join("/blob/");
|
|
2007
|
-
const [branch, ...filePath] = branchAndFilePath.split("/");
|
|
2008
|
-
const relativePath = getGitLabIntegrationRelativePath(config);
|
|
2009
|
-
url.pathname = [
|
|
2010
|
-
...relativePath ? [relativePath] : [],
|
|
2011
|
-
"api/v4/projects",
|
|
2012
|
-
projectID,
|
|
2013
|
-
"repository/files",
|
|
2014
|
-
encodeURIComponent(decodeURIComponent(filePath.join("/"))),
|
|
2015
|
-
"raw"
|
|
2016
|
-
].join("/");
|
|
2017
|
-
url.search = `?ref=${branch}`;
|
|
2018
|
-
return url;
|
|
2019
|
-
} catch (e) {
|
|
2020
|
-
throw new Error(`Incorrect url: ${target}, ${e}`);
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
async function getProjectId(target, config) {
|
|
2024
|
-
const url = new URL(target);
|
|
2025
|
-
if (!url.pathname.includes("/blob/")) {
|
|
2026
|
-
throw new Error(
|
|
2027
|
-
`Failed converting ${url.pathname} to a project id. Url path must include /blob/.`
|
|
2028
|
-
);
|
|
2029
|
-
}
|
|
2030
|
-
try {
|
|
2031
|
-
let repo = url.pathname.split("/-/blob/")[0].split("/blob/")[0];
|
|
2032
|
-
const relativePath = getGitLabIntegrationRelativePath(config);
|
|
2033
|
-
if (relativePath) {
|
|
2034
|
-
repo = repo.replace(relativePath, "");
|
|
2035
|
-
}
|
|
2036
|
-
const repoIDLookup = new URL(
|
|
2037
|
-
`${url.origin}${relativePath}/api/v4/projects/${encodeURIComponent(
|
|
2038
|
-
repo.replace(/^\//, "")
|
|
2039
|
-
)}`
|
|
2040
|
-
);
|
|
2041
|
-
const response = await fetch__default.default(
|
|
2042
|
-
repoIDLookup.toString(),
|
|
2043
|
-
getGitLabRequestOptions(config)
|
|
2044
|
-
);
|
|
2045
|
-
const data = await response.json();
|
|
2046
|
-
if (!response.ok) {
|
|
2047
|
-
throw new Error(
|
|
2048
|
-
`GitLab Error '${data.error}', ${data.error_description}`
|
|
2049
|
-
);
|
|
2050
|
-
}
|
|
2051
|
-
return Number(data.id);
|
|
2052
|
-
} catch (e) {
|
|
2053
|
-
throw new Error(`Could not get GitLab project ID for: ${target}, ${e}`);
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
|
-
class GitLabIntegration {
|
|
2058
|
-
constructor(integrationConfig) {
|
|
2059
|
-
this.integrationConfig = integrationConfig;
|
|
2060
|
-
}
|
|
2061
|
-
static factory = ({ config }) => {
|
|
2062
|
-
const configs = readGitLabIntegrationConfigs(
|
|
2063
|
-
config.getOptionalConfigArray("integrations.gitlab") ?? []
|
|
2064
|
-
);
|
|
2065
|
-
return basicIntegrations(
|
|
2066
|
-
configs.map((c) => new GitLabIntegration(c)),
|
|
2067
|
-
(i) => i.config.host
|
|
2068
|
-
);
|
|
2069
|
-
};
|
|
2070
|
-
get type() {
|
|
2071
|
-
return "gitlab";
|
|
2072
|
-
}
|
|
2073
|
-
get title() {
|
|
2074
|
-
return this.integrationConfig.host;
|
|
2075
|
-
}
|
|
2076
|
-
get config() {
|
|
2077
|
-
return this.integrationConfig;
|
|
2078
|
-
}
|
|
2079
|
-
resolveUrl(options) {
|
|
2080
|
-
return defaultScmResolveUrl(options);
|
|
2081
|
-
}
|
|
2082
|
-
resolveEditUrl(url) {
|
|
2083
|
-
return replaceGitLabUrlType(url, "edit");
|
|
2084
|
-
}
|
|
2085
|
-
}
|
|
2086
|
-
function replaceGitLabUrlType(url, type) {
|
|
2087
|
-
return url.replace(/\/\-\/(blob|tree|edit)\//, `/-/${type}/`);
|
|
2088
|
-
}
|
|
2089
|
-
|
|
2090
|
-
class SingleInstanceGitlabCredentialsProvider {
|
|
2091
|
-
constructor(token) {
|
|
2092
|
-
this.token = token;
|
|
2093
|
-
}
|
|
2094
|
-
static create = (config) => {
|
|
2095
|
-
return new SingleInstanceGitlabCredentialsProvider(config.token);
|
|
2096
|
-
};
|
|
2097
|
-
async getCredentials(_opts) {
|
|
2098
|
-
if (!this.token) {
|
|
2099
|
-
return {};
|
|
2100
|
-
}
|
|
2101
|
-
return {
|
|
2102
|
-
headers: {
|
|
2103
|
-
Authorization: `Bearer ${this.token}`
|
|
2104
|
-
},
|
|
2105
|
-
token: this.token
|
|
2106
|
-
};
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
|
|
2110
|
-
class DefaultGitlabCredentialsProvider {
|
|
2111
|
-
constructor(providers) {
|
|
2112
|
-
this.providers = providers;
|
|
2113
|
-
}
|
|
2114
|
-
static fromIntegrations(integrations) {
|
|
2115
|
-
const credentialsProviders = /* @__PURE__ */ new Map();
|
|
2116
|
-
integrations.gitlab.list().forEach((integration) => {
|
|
2117
|
-
const credentialsProvider = SingleInstanceGitlabCredentialsProvider.create(integration.config);
|
|
2118
|
-
credentialsProviders.set(integration.config.host, credentialsProvider);
|
|
2119
|
-
});
|
|
2120
|
-
return new DefaultGitlabCredentialsProvider(credentialsProviders);
|
|
2121
|
-
}
|
|
2122
|
-
async getCredentials(opts) {
|
|
2123
|
-
const parsed = new URL(opts.url);
|
|
2124
|
-
const provider = this.providers.get(parsed.host);
|
|
2125
|
-
if (!provider) {
|
|
2126
|
-
throw new Error(
|
|
2127
|
-
`There is no GitLab integration that matches ${opts.url}. Please add a configuration for an integration.`
|
|
2128
|
-
);
|
|
2129
|
-
}
|
|
2130
|
-
return provider.getCredentials(opts);
|
|
2131
|
-
}
|
|
2132
|
-
}
|
|
2133
|
-
|
|
2134
|
-
function readGoogleGcsIntegrationConfig(config) {
|
|
2135
|
-
if (!config) {
|
|
2136
|
-
return {};
|
|
2137
|
-
}
|
|
2138
|
-
if (!config.has("clientEmail") && !config.has("privateKey")) {
|
|
2139
|
-
return {};
|
|
2140
|
-
}
|
|
2141
|
-
const privateKey = config.getString("privateKey").split("\\n").join("\n");
|
|
2142
|
-
const clientEmail = config.getString("clientEmail");
|
|
2143
|
-
return { clientEmail, privateKey };
|
|
2144
|
-
}
|
|
2145
|
-
|
|
2146
|
-
function readHarnessConfig(config) {
|
|
2147
|
-
const host = config.getString("host");
|
|
2148
|
-
const token = config.getOptionalString("token");
|
|
2149
|
-
const apiKey = config.getOptionalString("apiKey");
|
|
2150
|
-
if (!isValidHost(host)) {
|
|
2151
|
-
throw new Error(
|
|
2152
|
-
`Invalid Harness Code integration config, '${host}' is not a valid host`
|
|
2153
|
-
);
|
|
2154
|
-
}
|
|
2155
|
-
return {
|
|
2156
|
-
host,
|
|
2157
|
-
apiKey,
|
|
2158
|
-
token
|
|
2159
|
-
};
|
|
2160
|
-
}
|
|
2161
|
-
|
|
2162
|
-
function getHarnessEditContentsUrl(config, url) {
|
|
2163
|
-
const parsedUrl = parseHarnessUrl(config, url);
|
|
2164
|
-
return `${parsedUrl.baseUrl}/ng/account/${parsedUrl.accountId}/module/code${parsedUrl.orgName !== "" ? `/orgs/${parsedUrl.orgName}` : ""}${parsedUrl.projectName !== "" ? `/projects/${parsedUrl.projectName}` : ""}/repos/${parsedUrl.repoName}/files/${parsedUrl.branch}/~/${parsedUrl.path}`;
|
|
2165
|
-
}
|
|
2166
|
-
function getHarnessFileContentsUrl(config, url) {
|
|
2167
|
-
const parsedUrl = parseHarnessUrl(config, url);
|
|
2168
|
-
let constructedUrl = `${parsedUrl.baseUrl}/gateway/code/api/v1/repos/${parsedUrl.accountId}`;
|
|
2169
|
-
if (parsedUrl.orgName) {
|
|
2170
|
-
constructedUrl += `/${parsedUrl.orgName}`;
|
|
2171
|
-
}
|
|
2172
|
-
if (parsedUrl.projectName) {
|
|
2173
|
-
constructedUrl += `/${parsedUrl.projectName}`;
|
|
2174
|
-
}
|
|
2175
|
-
constructedUrl += `/${parsedUrl.repoName}/+/raw/${parsedUrl.path}?routingId=${parsedUrl.accountId}&git_ref=refs/heads/${parsedUrl.refString}`;
|
|
2176
|
-
return constructedUrl;
|
|
2177
|
-
}
|
|
2178
|
-
function getHarnessArchiveUrl(config, url) {
|
|
2179
|
-
const parsedUrl = parseHarnessUrl(config, url);
|
|
2180
|
-
let constructedUrl = `${parsedUrl.baseUrl}/gateway/code/api/v1/repos/${parsedUrl.accountId}`;
|
|
2181
|
-
if (parsedUrl.orgName) {
|
|
2182
|
-
constructedUrl += `/${parsedUrl.orgName}`;
|
|
2183
|
-
}
|
|
2184
|
-
if (parsedUrl.projectName) {
|
|
2185
|
-
constructedUrl += `/${parsedUrl.projectName}`;
|
|
2186
|
-
}
|
|
2187
|
-
constructedUrl += `/${parsedUrl.repoName}/+/archive/${parsedUrl.branch}.zip?routingId=${parsedUrl.accountId}`;
|
|
2188
|
-
return constructedUrl;
|
|
2189
|
-
}
|
|
2190
|
-
function getHarnessLatestCommitUrl(config, url) {
|
|
2191
|
-
const parsedUrl = parseHarnessUrl(config, url);
|
|
2192
|
-
let constructedUrl = `${parsedUrl.baseUrl}/gateway/code/api/v1/repos/${parsedUrl.accountId}`;
|
|
2193
|
-
if (parsedUrl.orgName) {
|
|
2194
|
-
constructedUrl += `/${parsedUrl.orgName}`;
|
|
2195
|
-
}
|
|
2196
|
-
if (parsedUrl.projectName) {
|
|
2197
|
-
constructedUrl += `/${parsedUrl.projectName}`;
|
|
2198
|
-
}
|
|
2199
|
-
constructedUrl += `/${parsedUrl.repoName}/+/content?routingId=${parsedUrl.accountId}&include_commit=true&git_ref=refs/heads/${parsedUrl.branch}`;
|
|
2200
|
-
return constructedUrl;
|
|
2201
|
-
}
|
|
2202
|
-
function getHarnessRequestOptions(config) {
|
|
2203
|
-
const headers = {};
|
|
2204
|
-
const { token, apiKey } = config;
|
|
2205
|
-
if (apiKey) {
|
|
2206
|
-
headers["x-api-key"] = apiKey;
|
|
2207
|
-
} else if (token) {
|
|
2208
|
-
headers.Authorization = `Bearer ${token}`;
|
|
2209
|
-
}
|
|
2210
|
-
return {
|
|
2211
|
-
headers
|
|
2212
|
-
};
|
|
2213
|
-
}
|
|
2214
|
-
function parseHarnessUrl(config, url) {
|
|
2215
|
-
const baseUrl = `https://${config.host}`;
|
|
2216
|
-
try {
|
|
2217
|
-
const pathUrl = new URL(url);
|
|
2218
|
-
const pathSegments = pathUrl.pathname.split("/").filter((segment) => segment !== "");
|
|
2219
|
-
const urlParts = pathUrl.pathname.split("/");
|
|
2220
|
-
const accountIdIndex = pathSegments.findIndex((segment) => segment === "account") + 1;
|
|
2221
|
-
const accountId = pathSegments[accountIdIndex];
|
|
2222
|
-
const orgNameIndex = pathSegments.findIndex((segment) => segment === "orgs");
|
|
2223
|
-
const orgName = orgNameIndex !== -1 ? pathSegments[orgNameIndex + 1] : "";
|
|
2224
|
-
const projectNameIndex = pathSegments.findIndex(
|
|
2225
|
-
(segment) => segment === "projects"
|
|
2226
|
-
);
|
|
2227
|
-
const projectName = projectNameIndex !== -1 ? pathSegments[projectNameIndex + 1] : "";
|
|
2228
|
-
const repoNameIndex = pathSegments.findIndex(
|
|
2229
|
-
(segment, index) => segment === "repos" && index > Math.max(accountIdIndex, orgNameIndex, projectNameIndex)
|
|
2230
|
-
) + 1;
|
|
2231
|
-
const repoName = pathSegments[repoNameIndex];
|
|
2232
|
-
const refAndPath = urlParts.slice(
|
|
2233
|
-
urlParts.findIndex((i) => i === "files" || i === "edit") + 1
|
|
2234
|
-
);
|
|
2235
|
-
const refIndex = refAndPath.findIndex((item) => item === "~");
|
|
2236
|
-
const refString = refAndPath.slice(0, refIndex).join("/");
|
|
2237
|
-
const pathWithoutSlash = refIndex !== -1 ? refAndPath.slice(refIndex + 1).join("/").replace(/^\//, "") : "";
|
|
2238
|
-
return {
|
|
2239
|
-
baseUrl,
|
|
2240
|
-
accountId,
|
|
2241
|
-
orgName,
|
|
2242
|
-
projectName,
|
|
2243
|
-
refString,
|
|
2244
|
-
path: pathWithoutSlash,
|
|
2245
|
-
repoName,
|
|
2246
|
-
refDashStr: refAndPath.slice(0, refIndex).join("-"),
|
|
2247
|
-
branch: refIndex !== -1 ? refAndPath.slice(0, refIndex).join("/") : refAndPath.join("/")
|
|
2248
|
-
};
|
|
2249
|
-
} catch (e) {
|
|
2250
|
-
throw new Error(`Incorrect URL: ${url}, ${e}`);
|
|
2251
|
-
}
|
|
2252
|
-
}
|
|
2253
|
-
|
|
2254
|
-
class HarnessIntegration {
|
|
2255
|
-
constructor(config) {
|
|
2256
|
-
this.config = config;
|
|
2257
|
-
}
|
|
2258
|
-
static factory = ({ config }) => {
|
|
2259
|
-
const configs = config.getOptionalConfigArray("integrations.harness") ?? [];
|
|
2260
|
-
const harnessConfigs = configs.map((c) => readHarnessConfig(c));
|
|
2261
|
-
return basicIntegrations(
|
|
2262
|
-
harnessConfigs.map((c) => new HarnessIntegration(c)),
|
|
2263
|
-
(harness) => harness.config.host
|
|
2264
|
-
);
|
|
2265
|
-
};
|
|
2266
|
-
get type() {
|
|
2267
|
-
return "harness";
|
|
2268
|
-
}
|
|
2269
|
-
get title() {
|
|
2270
|
-
return this.config.host;
|
|
2271
|
-
}
|
|
2272
|
-
resolveUrl(options) {
|
|
2273
|
-
return defaultScmResolveUrl(options);
|
|
2274
|
-
}
|
|
2275
|
-
resolveEditUrl(url) {
|
|
2276
|
-
return getHarnessEditContentsUrl(this.config, url);
|
|
2277
|
-
}
|
|
2278
|
-
}
|
|
2279
|
-
|
|
2280
|
-
class ScmIntegrations {
|
|
2281
|
-
byType;
|
|
2282
|
-
static fromConfig(config) {
|
|
2283
|
-
return new ScmIntegrations({
|
|
2284
|
-
awsS3: AwsS3Integration.factory({ config }),
|
|
2285
|
-
awsCodeCommit: AwsCodeCommitIntegration.factory({ config }),
|
|
2286
|
-
azure: AzureIntegration.factory({ config }),
|
|
2287
|
-
bitbucket: BitbucketIntegration.factory({ config }),
|
|
2288
|
-
bitbucketCloud: BitbucketCloudIntegration.factory({ config }),
|
|
2289
|
-
bitbucketServer: BitbucketServerIntegration.factory({ config }),
|
|
2290
|
-
gerrit: GerritIntegration.factory({ config }),
|
|
2291
|
-
github: GithubIntegration.factory({ config }),
|
|
2292
|
-
gitlab: GitLabIntegration.factory({ config }),
|
|
2293
|
-
gitea: GiteaIntegration.factory({ config }),
|
|
2294
|
-
harness: HarnessIntegration.factory({ config })
|
|
2295
|
-
});
|
|
2296
|
-
}
|
|
2297
|
-
constructor(integrationsByType) {
|
|
2298
|
-
this.byType = integrationsByType;
|
|
2299
|
-
}
|
|
2300
|
-
get awsS3() {
|
|
2301
|
-
return this.byType.awsS3;
|
|
2302
|
-
}
|
|
2303
|
-
get awsCodeCommit() {
|
|
2304
|
-
return this.byType.awsCodeCommit;
|
|
2305
|
-
}
|
|
2306
|
-
get azure() {
|
|
2307
|
-
return this.byType.azure;
|
|
2308
|
-
}
|
|
2309
|
-
/**
|
|
2310
|
-
* @deprecated in favor of `bitbucketCloud()` and `bitbucketServer()`
|
|
2311
|
-
*/
|
|
2312
|
-
get bitbucket() {
|
|
2313
|
-
return this.byType.bitbucket;
|
|
2314
|
-
}
|
|
2315
|
-
get bitbucketCloud() {
|
|
2316
|
-
return this.byType.bitbucketCloud;
|
|
2317
|
-
}
|
|
2318
|
-
get bitbucketServer() {
|
|
2319
|
-
return this.byType.bitbucketServer;
|
|
2320
|
-
}
|
|
2321
|
-
get gerrit() {
|
|
2322
|
-
return this.byType.gerrit;
|
|
2323
|
-
}
|
|
2324
|
-
get github() {
|
|
2325
|
-
return this.byType.github;
|
|
2326
|
-
}
|
|
2327
|
-
get gitlab() {
|
|
2328
|
-
return this.byType.gitlab;
|
|
2329
|
-
}
|
|
2330
|
-
get gitea() {
|
|
2331
|
-
return this.byType.gitea;
|
|
2332
|
-
}
|
|
2333
|
-
get harness() {
|
|
2334
|
-
return this.byType.harness;
|
|
2335
|
-
}
|
|
2336
|
-
list() {
|
|
2337
|
-
return Object.values(this.byType).flatMap(
|
|
2338
|
-
(i) => i.list()
|
|
2339
|
-
);
|
|
2340
|
-
}
|
|
2341
|
-
byUrl(url) {
|
|
2342
|
-
let candidates = Object.values(this.byType).map((i) => i.byUrl(url)).filter(Boolean);
|
|
2343
|
-
if (candidates.length > 1) {
|
|
2344
|
-
const filteredCandidates = candidates.filter(
|
|
2345
|
-
(x) => !(x instanceof BitbucketIntegration)
|
|
2346
|
-
);
|
|
2347
|
-
if (filteredCandidates.length !== 0) {
|
|
2348
|
-
candidates = filteredCandidates;
|
|
2349
|
-
}
|
|
2350
|
-
}
|
|
2351
|
-
return candidates[0];
|
|
2352
|
-
}
|
|
2353
|
-
byHost(host) {
|
|
2354
|
-
return Object.values(this.byType).map((i) => i.byHost(host)).find(Boolean);
|
|
2355
|
-
}
|
|
2356
|
-
resolveUrl(options) {
|
|
2357
|
-
const integration = this.byUrl(options.base);
|
|
2358
|
-
if (!integration) {
|
|
2359
|
-
return defaultScmResolveUrl(options);
|
|
2360
|
-
}
|
|
2361
|
-
return integration.resolveUrl(options);
|
|
2362
|
-
}
|
|
2363
|
-
resolveEditUrl(url) {
|
|
2364
|
-
const integration = this.byUrl(url);
|
|
2365
|
-
if (!integration) {
|
|
2366
|
-
return url;
|
|
2367
|
-
}
|
|
2368
|
-
return integration.resolveEditUrl(url);
|
|
2369
|
-
}
|
|
2370
|
-
}
|
|
2371
|
-
|
|
2372
|
-
exports.AwsCodeCommitIntegration = AwsCodeCommitIntegration;
|
|
2373
|
-
exports.AwsS3Integration = AwsS3Integration;
|
|
2374
|
-
exports.AzureIntegration = AzureIntegration;
|
|
2375
|
-
exports.BitbucketCloudIntegration = BitbucketCloudIntegration;
|
|
2376
|
-
exports.BitbucketIntegration = BitbucketIntegration;
|
|
2377
|
-
exports.BitbucketServerIntegration = BitbucketServerIntegration;
|
|
2378
|
-
exports.DefaultAzureDevOpsCredentialsProvider = DefaultAzureDevOpsCredentialsProvider;
|
|
2379
|
-
exports.DefaultGithubCredentialsProvider = DefaultGithubCredentialsProvider;
|
|
2380
|
-
exports.DefaultGitlabCredentialsProvider = DefaultGitlabCredentialsProvider;
|
|
2381
|
-
exports.GerritIntegration = GerritIntegration;
|
|
2382
|
-
exports.GitLabIntegration = GitLabIntegration;
|
|
2383
|
-
exports.GiteaIntegration = GiteaIntegration;
|
|
2384
|
-
exports.GithubAppCredentialsMux = GithubAppCredentialsMux;
|
|
2385
|
-
exports.GithubIntegration = GithubIntegration;
|
|
2386
|
-
exports.HarnessIntegration = HarnessIntegration;
|
|
2387
|
-
exports.ScmIntegrations = ScmIntegrations;
|
|
2388
|
-
exports.SingleInstanceGithubCredentialsProvider = SingleInstanceGithubCredentialsProvider;
|
|
2389
|
-
exports.buildGerritGitilesArchiveUrl = buildGerritGitilesArchiveUrl;
|
|
2390
|
-
exports.defaultScmResolveUrl = defaultScmResolveUrl;
|
|
2391
|
-
exports.getAzureCommitsUrl = getAzureCommitsUrl;
|
|
2392
|
-
exports.getAzureDownloadUrl = getAzureDownloadUrl;
|
|
2393
|
-
exports.getAzureFileFetchUrl = getAzureFileFetchUrl;
|
|
2394
|
-
exports.getAzureRequestOptions = getAzureRequestOptions;
|
|
2395
|
-
exports.getBitbucketCloudDefaultBranch = getBitbucketCloudDefaultBranch;
|
|
2396
|
-
exports.getBitbucketCloudDownloadUrl = getBitbucketCloudDownloadUrl;
|
|
2397
|
-
exports.getBitbucketCloudFileFetchUrl = getBitbucketCloudFileFetchUrl;
|
|
2398
|
-
exports.getBitbucketCloudRequestOptions = getBitbucketCloudRequestOptions;
|
|
2399
|
-
exports.getBitbucketDefaultBranch = getBitbucketDefaultBranch;
|
|
2400
|
-
exports.getBitbucketDownloadUrl = getBitbucketDownloadUrl;
|
|
2401
|
-
exports.getBitbucketFileFetchUrl = getBitbucketFileFetchUrl;
|
|
2402
|
-
exports.getBitbucketRequestOptions = getBitbucketRequestOptions;
|
|
2403
|
-
exports.getBitbucketServerDefaultBranch = getBitbucketServerDefaultBranch;
|
|
2404
|
-
exports.getBitbucketServerDownloadUrl = getBitbucketServerDownloadUrl;
|
|
2405
|
-
exports.getBitbucketServerFileFetchUrl = getBitbucketServerFileFetchUrl;
|
|
2406
|
-
exports.getBitbucketServerRequestOptions = getBitbucketServerRequestOptions;
|
|
2407
|
-
exports.getGerritBranchApiUrl = getGerritBranchApiUrl;
|
|
2408
|
-
exports.getGerritCloneRepoUrl = getGerritCloneRepoUrl;
|
|
2409
|
-
exports.getGerritFileContentsApiUrl = getGerritFileContentsApiUrl;
|
|
2410
|
-
exports.getGerritProjectsApiUrl = getGerritProjectsApiUrl;
|
|
2411
|
-
exports.getGerritRequestOptions = getGerritRequestOptions;
|
|
2412
|
-
exports.getGitHubRequestOptions = getGitHubRequestOptions;
|
|
2413
|
-
exports.getGitLabFileFetchUrl = getGitLabFileFetchUrl;
|
|
2414
|
-
exports.getGitLabIntegrationRelativePath = getGitLabIntegrationRelativePath;
|
|
2415
|
-
exports.getGitLabRequestOptions = getGitLabRequestOptions;
|
|
2416
|
-
exports.getGiteaArchiveUrl = getGiteaArchiveUrl;
|
|
2417
|
-
exports.getGiteaEditContentsUrl = getGiteaEditContentsUrl;
|
|
2418
|
-
exports.getGiteaFileContentsUrl = getGiteaFileContentsUrl;
|
|
2419
|
-
exports.getGiteaLatestCommitUrl = getGiteaLatestCommitUrl;
|
|
2420
|
-
exports.getGiteaRequestOptions = getGiteaRequestOptions;
|
|
2421
|
-
exports.getGithubFileFetchUrl = getGithubFileFetchUrl;
|
|
2422
|
-
exports.getHarnessArchiveUrl = getHarnessArchiveUrl;
|
|
2423
|
-
exports.getHarnessFileContentsUrl = getHarnessFileContentsUrl;
|
|
2424
|
-
exports.getHarnessLatestCommitUrl = getHarnessLatestCommitUrl;
|
|
2425
|
-
exports.getHarnessRequestOptions = getHarnessRequestOptions;
|
|
2426
|
-
exports.parseGerritGitilesUrl = parseGerritGitilesUrl;
|
|
2427
|
-
exports.parseGerritJsonResponse = parseGerritJsonResponse;
|
|
2428
|
-
exports.parseGiteaUrl = parseGiteaUrl;
|
|
2429
|
-
exports.parseGitilesUrlRef = parseGitilesUrlRef;
|
|
2430
|
-
exports.parseHarnessUrl = parseHarnessUrl;
|
|
2431
|
-
exports.readAwsCodeCommitIntegrationConfig = readAwsCodeCommitIntegrationConfig;
|
|
2432
|
-
exports.readAwsCodeCommitIntegrationConfigs = readAwsCodeCommitIntegrationConfigs;
|
|
2433
|
-
exports.readAwsS3IntegrationConfig = readAwsS3IntegrationConfig;
|
|
2434
|
-
exports.readAwsS3IntegrationConfigs = readAwsS3IntegrationConfigs;
|
|
2435
|
-
exports.readAzureIntegrationConfig = readAzureIntegrationConfig;
|
|
2436
|
-
exports.readAzureIntegrationConfigs = readAzureIntegrationConfigs;
|
|
2437
|
-
exports.readBitbucketCloudIntegrationConfig = readBitbucketCloudIntegrationConfig;
|
|
2438
|
-
exports.readBitbucketCloudIntegrationConfigs = readBitbucketCloudIntegrationConfigs;
|
|
2439
|
-
exports.readBitbucketIntegrationConfig = readBitbucketIntegrationConfig;
|
|
2440
|
-
exports.readBitbucketIntegrationConfigs = readBitbucketIntegrationConfigs;
|
|
2441
|
-
exports.readBitbucketServerIntegrationConfig = readBitbucketServerIntegrationConfig;
|
|
2442
|
-
exports.readBitbucketServerIntegrationConfigs = readBitbucketServerIntegrationConfigs;
|
|
2443
|
-
exports.readGerritIntegrationConfig = readGerritIntegrationConfig;
|
|
2444
|
-
exports.readGerritIntegrationConfigs = readGerritIntegrationConfigs;
|
|
2445
|
-
exports.readGitLabIntegrationConfig = readGitLabIntegrationConfig;
|
|
2446
|
-
exports.readGitLabIntegrationConfigs = readGitLabIntegrationConfigs;
|
|
2447
|
-
exports.readGiteaConfig = readGiteaConfig;
|
|
2448
|
-
exports.readGithubIntegrationConfig = readGithubIntegrationConfig;
|
|
2449
|
-
exports.readGithubIntegrationConfigs = readGithubIntegrationConfigs;
|
|
2450
|
-
exports.readGoogleGcsIntegrationConfig = readGoogleGcsIntegrationConfig;
|
|
2451
|
-
exports.readHarnessConfig = readHarnessConfig;
|
|
2452
|
-
exports.replaceGitLabUrlType = replaceGitLabUrlType;
|
|
2453
|
-
exports.replaceGithubUrlType = replaceGithubUrlType;
|
|
3
|
+
var AwsS3Integration = require('./awsS3/AwsS3Integration.cjs.js');
|
|
4
|
+
var config = require('./awsS3/config.cjs.js');
|
|
5
|
+
var AwsCodeCommitIntegration = require('./awsCodeCommit/AwsCodeCommitIntegration.cjs.js');
|
|
6
|
+
var config$1 = require('./awsCodeCommit/config.cjs.js');
|
|
7
|
+
var AzureIntegration = require('./azure/AzureIntegration.cjs.js');
|
|
8
|
+
var config$2 = require('./azure/config.cjs.js');
|
|
9
|
+
var core = require('./azure/core.cjs.js');
|
|
10
|
+
var DefaultAzureDevOpsCredentialsProvider = require('./azure/DefaultAzureDevOpsCredentialsProvider.cjs.js');
|
|
11
|
+
var deprecated = require('./azure/deprecated.cjs.js');
|
|
12
|
+
var BitbucketIntegration = require('./bitbucket/BitbucketIntegration.cjs.js');
|
|
13
|
+
var config$3 = require('./bitbucket/config.cjs.js');
|
|
14
|
+
var core$1 = require('./bitbucket/core.cjs.js');
|
|
15
|
+
var BitbucketCloudIntegration = require('./bitbucketCloud/BitbucketCloudIntegration.cjs.js');
|
|
16
|
+
var config$4 = require('./bitbucketCloud/config.cjs.js');
|
|
17
|
+
var core$2 = require('./bitbucketCloud/core.cjs.js');
|
|
18
|
+
var BitbucketServerIntegration = require('./bitbucketServer/BitbucketServerIntegration.cjs.js');
|
|
19
|
+
var config$5 = require('./bitbucketServer/config.cjs.js');
|
|
20
|
+
var core$3 = require('./bitbucketServer/core.cjs.js');
|
|
21
|
+
var GerritIntegration = require('./gerrit/GerritIntegration.cjs.js');
|
|
22
|
+
var config$6 = require('./gerrit/config.cjs.js');
|
|
23
|
+
var core$4 = require('./gerrit/core.cjs.js');
|
|
24
|
+
var GiteaIntegration = require('./gitea/GiteaIntegration.cjs.js');
|
|
25
|
+
var core$5 = require('./gitea/core.cjs.js');
|
|
26
|
+
var config$7 = require('./gitea/config.cjs.js');
|
|
27
|
+
var config$8 = require('./github/config.cjs.js');
|
|
28
|
+
var core$6 = require('./github/core.cjs.js');
|
|
29
|
+
var DefaultGithubCredentialsProvider = require('./github/DefaultGithubCredentialsProvider.cjs.js');
|
|
30
|
+
var SingleInstanceGithubCredentialsProvider = require('./github/SingleInstanceGithubCredentialsProvider.cjs.js');
|
|
31
|
+
var GithubIntegration = require('./github/GithubIntegration.cjs.js');
|
|
32
|
+
var config$9 = require('./gitlab/config.cjs.js');
|
|
33
|
+
var core$7 = require('./gitlab/core.cjs.js');
|
|
34
|
+
var GitLabIntegration = require('./gitlab/GitLabIntegration.cjs.js');
|
|
35
|
+
var DefaultGitlabCredentialsProvider = require('./gitlab/DefaultGitlabCredentialsProvider.cjs.js');
|
|
36
|
+
var config$a = require('./googleGcs/config.cjs.js');
|
|
37
|
+
var HarnessIntegration = require('./harness/HarnessIntegration.cjs.js');
|
|
38
|
+
var core$8 = require('./harness/core.cjs.js');
|
|
39
|
+
var config$b = require('./harness/config.cjs.js');
|
|
40
|
+
var helpers = require('./helpers.cjs.js');
|
|
41
|
+
var ScmIntegrations = require('./ScmIntegrations.cjs.js');
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
exports.AwsS3Integration = AwsS3Integration.AwsS3Integration;
|
|
46
|
+
exports.readAwsS3IntegrationConfig = config.readAwsS3IntegrationConfig;
|
|
47
|
+
exports.readAwsS3IntegrationConfigs = config.readAwsS3IntegrationConfigs;
|
|
48
|
+
exports.AwsCodeCommitIntegration = AwsCodeCommitIntegration.AwsCodeCommitIntegration;
|
|
49
|
+
exports.readAwsCodeCommitIntegrationConfig = config$1.readAwsCodeCommitIntegrationConfig;
|
|
50
|
+
exports.readAwsCodeCommitIntegrationConfigs = config$1.readAwsCodeCommitIntegrationConfigs;
|
|
51
|
+
exports.AzureIntegration = AzureIntegration.AzureIntegration;
|
|
52
|
+
exports.readAzureIntegrationConfig = config$2.readAzureIntegrationConfig;
|
|
53
|
+
exports.readAzureIntegrationConfigs = config$2.readAzureIntegrationConfigs;
|
|
54
|
+
exports.getAzureCommitsUrl = core.getAzureCommitsUrl;
|
|
55
|
+
exports.getAzureDownloadUrl = core.getAzureDownloadUrl;
|
|
56
|
+
exports.getAzureFileFetchUrl = core.getAzureFileFetchUrl;
|
|
57
|
+
exports.DefaultAzureDevOpsCredentialsProvider = DefaultAzureDevOpsCredentialsProvider.DefaultAzureDevOpsCredentialsProvider;
|
|
58
|
+
exports.getAzureRequestOptions = deprecated.getAzureRequestOptions;
|
|
59
|
+
exports.BitbucketIntegration = BitbucketIntegration.BitbucketIntegration;
|
|
60
|
+
exports.readBitbucketIntegrationConfig = config$3.readBitbucketIntegrationConfig;
|
|
61
|
+
exports.readBitbucketIntegrationConfigs = config$3.readBitbucketIntegrationConfigs;
|
|
62
|
+
exports.getBitbucketDefaultBranch = core$1.getBitbucketDefaultBranch;
|
|
63
|
+
exports.getBitbucketDownloadUrl = core$1.getBitbucketDownloadUrl;
|
|
64
|
+
exports.getBitbucketFileFetchUrl = core$1.getBitbucketFileFetchUrl;
|
|
65
|
+
exports.getBitbucketRequestOptions = core$1.getBitbucketRequestOptions;
|
|
66
|
+
exports.BitbucketCloudIntegration = BitbucketCloudIntegration.BitbucketCloudIntegration;
|
|
67
|
+
exports.readBitbucketCloudIntegrationConfig = config$4.readBitbucketCloudIntegrationConfig;
|
|
68
|
+
exports.readBitbucketCloudIntegrationConfigs = config$4.readBitbucketCloudIntegrationConfigs;
|
|
69
|
+
exports.getBitbucketCloudDefaultBranch = core$2.getBitbucketCloudDefaultBranch;
|
|
70
|
+
exports.getBitbucketCloudDownloadUrl = core$2.getBitbucketCloudDownloadUrl;
|
|
71
|
+
exports.getBitbucketCloudFileFetchUrl = core$2.getBitbucketCloudFileFetchUrl;
|
|
72
|
+
exports.getBitbucketCloudRequestOptions = core$2.getBitbucketCloudRequestOptions;
|
|
73
|
+
exports.BitbucketServerIntegration = BitbucketServerIntegration.BitbucketServerIntegration;
|
|
74
|
+
exports.readBitbucketServerIntegrationConfig = config$5.readBitbucketServerIntegrationConfig;
|
|
75
|
+
exports.readBitbucketServerIntegrationConfigs = config$5.readBitbucketServerIntegrationConfigs;
|
|
76
|
+
exports.getBitbucketServerDefaultBranch = core$3.getBitbucketServerDefaultBranch;
|
|
77
|
+
exports.getBitbucketServerDownloadUrl = core$3.getBitbucketServerDownloadUrl;
|
|
78
|
+
exports.getBitbucketServerFileFetchUrl = core$3.getBitbucketServerFileFetchUrl;
|
|
79
|
+
exports.getBitbucketServerRequestOptions = core$3.getBitbucketServerRequestOptions;
|
|
80
|
+
exports.GerritIntegration = GerritIntegration.GerritIntegration;
|
|
81
|
+
exports.readGerritIntegrationConfig = config$6.readGerritIntegrationConfig;
|
|
82
|
+
exports.readGerritIntegrationConfigs = config$6.readGerritIntegrationConfigs;
|
|
83
|
+
exports.buildGerritGitilesArchiveUrl = core$4.buildGerritGitilesArchiveUrl;
|
|
84
|
+
exports.getGerritBranchApiUrl = core$4.getGerritBranchApiUrl;
|
|
85
|
+
exports.getGerritCloneRepoUrl = core$4.getGerritCloneRepoUrl;
|
|
86
|
+
exports.getGerritFileContentsApiUrl = core$4.getGerritFileContentsApiUrl;
|
|
87
|
+
exports.getGerritProjectsApiUrl = core$4.getGerritProjectsApiUrl;
|
|
88
|
+
exports.getGerritRequestOptions = core$4.getGerritRequestOptions;
|
|
89
|
+
exports.parseGerritGitilesUrl = core$4.parseGerritGitilesUrl;
|
|
90
|
+
exports.parseGerritJsonResponse = core$4.parseGerritJsonResponse;
|
|
91
|
+
exports.parseGitilesUrlRef = core$4.parseGitilesUrlRef;
|
|
92
|
+
exports.GiteaIntegration = GiteaIntegration.GiteaIntegration;
|
|
93
|
+
exports.getGiteaArchiveUrl = core$5.getGiteaArchiveUrl;
|
|
94
|
+
exports.getGiteaEditContentsUrl = core$5.getGiteaEditContentsUrl;
|
|
95
|
+
exports.getGiteaFileContentsUrl = core$5.getGiteaFileContentsUrl;
|
|
96
|
+
exports.getGiteaLatestCommitUrl = core$5.getGiteaLatestCommitUrl;
|
|
97
|
+
exports.getGiteaRequestOptions = core$5.getGiteaRequestOptions;
|
|
98
|
+
exports.parseGiteaUrl = core$5.parseGiteaUrl;
|
|
99
|
+
exports.readGiteaConfig = config$7.readGiteaConfig;
|
|
100
|
+
exports.readGithubIntegrationConfig = config$8.readGithubIntegrationConfig;
|
|
101
|
+
exports.readGithubIntegrationConfigs = config$8.readGithubIntegrationConfigs;
|
|
102
|
+
exports.getGitHubRequestOptions = core$6.getGitHubRequestOptions;
|
|
103
|
+
exports.getGithubFileFetchUrl = core$6.getGithubFileFetchUrl;
|
|
104
|
+
exports.DefaultGithubCredentialsProvider = DefaultGithubCredentialsProvider.DefaultGithubCredentialsProvider;
|
|
105
|
+
exports.GithubAppCredentialsMux = SingleInstanceGithubCredentialsProvider.GithubAppCredentialsMux;
|
|
106
|
+
exports.SingleInstanceGithubCredentialsProvider = SingleInstanceGithubCredentialsProvider.SingleInstanceGithubCredentialsProvider;
|
|
107
|
+
exports.GithubIntegration = GithubIntegration.GithubIntegration;
|
|
108
|
+
exports.replaceGithubUrlType = GithubIntegration.replaceGithubUrlType;
|
|
109
|
+
exports.getGitLabIntegrationRelativePath = config$9.getGitLabIntegrationRelativePath;
|
|
110
|
+
exports.readGitLabIntegrationConfig = config$9.readGitLabIntegrationConfig;
|
|
111
|
+
exports.readGitLabIntegrationConfigs = config$9.readGitLabIntegrationConfigs;
|
|
112
|
+
exports.getGitLabFileFetchUrl = core$7.getGitLabFileFetchUrl;
|
|
113
|
+
exports.getGitLabRequestOptions = core$7.getGitLabRequestOptions;
|
|
114
|
+
exports.GitLabIntegration = GitLabIntegration.GitLabIntegration;
|
|
115
|
+
exports.replaceGitLabUrlType = GitLabIntegration.replaceGitLabUrlType;
|
|
116
|
+
exports.DefaultGitlabCredentialsProvider = DefaultGitlabCredentialsProvider.DefaultGitlabCredentialsProvider;
|
|
117
|
+
exports.readGoogleGcsIntegrationConfig = config$a.readGoogleGcsIntegrationConfig;
|
|
118
|
+
exports.HarnessIntegration = HarnessIntegration.HarnessIntegration;
|
|
119
|
+
exports.getHarnessArchiveUrl = core$8.getHarnessArchiveUrl;
|
|
120
|
+
exports.getHarnessFileContentsUrl = core$8.getHarnessFileContentsUrl;
|
|
121
|
+
exports.getHarnessLatestCommitUrl = core$8.getHarnessLatestCommitUrl;
|
|
122
|
+
exports.getHarnessRequestOptions = core$8.getHarnessRequestOptions;
|
|
123
|
+
exports.parseHarnessUrl = core$8.parseHarnessUrl;
|
|
124
|
+
exports.readHarnessConfig = config$b.readHarnessConfig;
|
|
125
|
+
exports.defaultScmResolveUrl = helpers.defaultScmResolveUrl;
|
|
126
|
+
exports.ScmIntegrations = ScmIntegrations.ScmIntegrations;
|
|
2454
127
|
//# sourceMappingURL=index.cjs.js.map
|