@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.
Files changed (88) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/ScmIntegrations.cjs.js +110 -0
  3. package/dist/ScmIntegrations.cjs.js.map +1 -0
  4. package/dist/awsCodeCommit/AwsCodeCommitIntegration.cjs.js +58 -0
  5. package/dist/awsCodeCommit/AwsCodeCommitIntegration.cjs.js.map +1 -0
  6. package/dist/awsCodeCommit/config.cjs.js +26 -0
  7. package/dist/awsCodeCommit/config.cjs.js.map +1 -0
  8. package/dist/awsS3/AwsS3Integration.cjs.js +38 -0
  9. package/dist/awsS3/AwsS3Integration.cjs.js.map +1 -0
  10. package/dist/awsS3/config.cjs.js +53 -0
  11. package/dist/awsS3/config.cjs.js.map +1 -0
  12. package/dist/azure/AzureIntegration.cjs.js +62 -0
  13. package/dist/azure/AzureIntegration.cjs.js.map +1 -0
  14. package/dist/azure/AzureUrl.cjs.js +189 -0
  15. package/dist/azure/AzureUrl.cjs.js.map +1 -0
  16. package/dist/azure/CachedAzureDevOpsCredentialsProvider.cjs.js +76 -0
  17. package/dist/azure/CachedAzureDevOpsCredentialsProvider.cjs.js.map +1 -0
  18. package/dist/azure/DefaultAzureDevOpsCredentialsProvider.cjs.js +75 -0
  19. package/dist/azure/DefaultAzureDevOpsCredentialsProvider.cjs.js.map +1 -0
  20. package/dist/azure/config.cjs.js +153 -0
  21. package/dist/azure/config.cjs.js.map +1 -0
  22. package/dist/azure/core.cjs.js +18 -0
  23. package/dist/azure/core.cjs.js.map +1 -0
  24. package/dist/azure/deprecated.cjs.js +26 -0
  25. package/dist/azure/deprecated.cjs.js.map +1 -0
  26. package/dist/bitbucket/BitbucketIntegration.cjs.js +65 -0
  27. package/dist/bitbucket/BitbucketIntegration.cjs.js.map +1 -0
  28. package/dist/bitbucket/config.cjs.js +47 -0
  29. package/dist/bitbucket/config.cjs.js.map +1 -0
  30. package/dist/bitbucket/core.cjs.js +95 -0
  31. package/dist/bitbucket/core.cjs.js.map +1 -0
  32. package/dist/bitbucketCloud/BitbucketCloudIntegration.cjs.js +54 -0
  33. package/dist/bitbucketCloud/BitbucketCloudIntegration.cjs.js.map +1 -0
  34. package/dist/bitbucketCloud/config.cjs.js +30 -0
  35. package/dist/bitbucketCloud/config.cjs.js.map +1 -0
  36. package/dist/bitbucketCloud/core.cjs.js +78 -0
  37. package/dist/bitbucketCloud/core.cjs.js.map +1 -0
  38. package/dist/bitbucketServer/BitbucketServerIntegration.cjs.js +48 -0
  39. package/dist/bitbucketServer/BitbucketServerIntegration.cjs.js.map +1 -0
  40. package/dist/bitbucketServer/config.cjs.js +36 -0
  41. package/dist/bitbucketServer/config.cjs.js.map +1 -0
  42. package/dist/bitbucketServer/core.cjs.js +73 -0
  43. package/dist/bitbucketServer/core.cjs.js.map +1 -0
  44. package/dist/gerrit/GerritIntegration.cjs.js +52 -0
  45. package/dist/gerrit/GerritIntegration.cjs.js.map +1 -0
  46. package/dist/gerrit/config.cjs.js +60 -0
  47. package/dist/gerrit/config.cjs.js.map +1 -0
  48. package/dist/gerrit/core.cjs.js +179 -0
  49. package/dist/gerrit/core.cjs.js.map +1 -0
  50. package/dist/gitea/GiteaIntegration.cjs.js +34 -0
  51. package/dist/gitea/GiteaIntegration.cjs.js.map +1 -0
  52. package/dist/gitea/config.cjs.js +34 -0
  53. package/dist/gitea/config.cjs.js.map +1 -0
  54. package/dist/gitea/core.cjs.js +59 -0
  55. package/dist/gitea/core.cjs.js.map +1 -0
  56. package/dist/github/DefaultGithubCredentialsProvider.cjs.js +54 -0
  57. package/dist/github/DefaultGithubCredentialsProvider.cjs.js.map +1 -0
  58. package/dist/github/GithubIntegration.cjs.js +51 -0
  59. package/dist/github/GithubIntegration.cjs.js.map +1 -0
  60. package/dist/github/SingleInstanceGithubCredentialsProvider.cjs.js +211 -0
  61. package/dist/github/SingleInstanceGithubCredentialsProvider.cjs.js.map +1 -0
  62. package/dist/github/config.cjs.js +55 -0
  63. package/dist/github/config.cjs.js.map +1 -0
  64. package/dist/github/core.cjs.js +46 -0
  65. package/dist/github/core.cjs.js.map +1 -0
  66. package/dist/gitlab/DefaultGitlabCredentialsProvider.cjs.js +30 -0
  67. package/dist/gitlab/DefaultGitlabCredentialsProvider.cjs.js.map +1 -0
  68. package/dist/gitlab/GitLabIntegration.cjs.js +41 -0
  69. package/dist/gitlab/GitLabIntegration.cjs.js.map +1 -0
  70. package/dist/gitlab/SingleInstanceGitlabCredentialsProvider.cjs.js +24 -0
  71. package/dist/gitlab/SingleInstanceGitlabCredentialsProvider.cjs.js.map +1 -0
  72. package/dist/gitlab/config.cjs.js +60 -0
  73. package/dist/gitlab/config.cjs.js.map +1 -0
  74. package/dist/gitlab/core.cjs.js +84 -0
  75. package/dist/gitlab/core.cjs.js.map +1 -0
  76. package/dist/googleGcs/config.cjs.js +16 -0
  77. package/dist/googleGcs/config.cjs.js.map +1 -0
  78. package/dist/harness/HarnessIntegration.cjs.js +34 -0
  79. package/dist/harness/HarnessIntegration.cjs.js.map +1 -0
  80. package/dist/harness/config.cjs.js +22 -0
  81. package/dist/harness/config.cjs.js.map +1 -0
  82. package/dist/harness/core.cjs.js +101 -0
  83. package/dist/harness/core.cjs.js.map +1 -0
  84. package/dist/helpers.cjs.js +71 -0
  85. package/dist/helpers.cjs.js.map +1 -0
  86. package/dist/index.cjs.js +124 -2451
  87. package/dist/index.cjs.js.map +1 -1
  88. package/package.json +6 -6
package/dist/index.cjs.js CHANGED
@@ -1,2454 +1,127 @@
1
1
  'use strict';
2
2
 
3
- var parseGitUrl = require('git-url-parse');
4
- var lodash = require('lodash');
5
- var identity = require('@azure/identity');
6
- var fetch = require('cross-fetch');
7
- var authApp = require('@octokit/auth-app');
8
- var rest = require('@octokit/rest');
9
- var luxon = require('luxon');
10
-
11
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
12
-
13
- var parseGitUrl__default = /*#__PURE__*/_interopDefaultCompat(parseGitUrl);
14
- var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch);
15
-
16
- function isValidHost(host) {
17
- const check = new URL("http://example.com");
18
- check.host = host;
19
- return check.host === host;
20
- }
21
- function isValidUrl(url) {
22
- try {
23
- new URL(url);
24
- return true;
25
- } catch {
26
- return false;
27
- }
28
- }
29
- function basicIntegrations(integrations, getHost) {
30
- return {
31
- list() {
32
- return integrations;
33
- },
34
- byUrl(url) {
35
- try {
36
- const parsed = typeof url === "string" ? new URL(url) : url;
37
- return integrations.find((i) => getHost(i) === parsed.host);
38
- } catch {
39
- return void 0;
40
- }
41
- },
42
- byHost(host) {
43
- return integrations.find((i) => getHost(i) === host);
44
- }
45
- };
46
- }
47
- function defaultScmResolveUrl(options) {
48
- const { url, base, lineNumber } = options;
49
- try {
50
- new URL(url);
51
- return url;
52
- } catch {
53
- }
54
- let updated;
55
- if (url.startsWith("/")) {
56
- const { href, filepath } = parseGitUrl__default.default(base);
57
- updated = new URL(href);
58
- const repoRootPath = lodash.trimEnd(
59
- updated.pathname.substring(0, updated.pathname.length - filepath.length),
60
- "/"
61
- );
62
- updated.pathname = `${repoRootPath}${url}`;
63
- } else {
64
- updated = new URL(url, base);
65
- }
66
- updated.search = new URL(base).search;
67
- if (lineNumber) {
68
- updated.hash = `L${lineNumber}`;
69
- }
70
- return updated.toString();
71
- }
72
-
73
- const AMAZON_AWS_HOST = "amazonaws.com";
74
- function readAwsS3IntegrationConfig(config) {
75
- const endpoint = config.getOptionalString("endpoint");
76
- const s3ForcePathStyle = config.getOptionalBoolean("s3ForcePathStyle") ?? false;
77
- let host;
78
- let pathname;
79
- if (endpoint) {
80
- try {
81
- const url = new URL(endpoint);
82
- host = url.host;
83
- pathname = url.pathname;
84
- } catch {
85
- throw new Error(
86
- `invalid awsS3 integration config, endpoint '${endpoint}' is not a valid URL`
87
- );
88
- }
89
- if (pathname !== "/") {
90
- throw new Error(
91
- `invalid awsS3 integration config, endpoints cannot contain path, got '${endpoint}'`
92
- );
93
- }
94
- } else {
95
- host = AMAZON_AWS_HOST;
96
- }
97
- const accessKeyId = config.getOptionalString("accessKeyId");
98
- const secretAccessKey = config.getOptionalString("secretAccessKey")?.trim();
99
- const roleArn = config.getOptionalString("roleArn");
100
- const externalId = config.getOptionalString("externalId");
101
- return {
102
- host,
103
- endpoint,
104
- s3ForcePathStyle,
105
- accessKeyId,
106
- secretAccessKey,
107
- roleArn,
108
- externalId
109
- };
110
- }
111
- function readAwsS3IntegrationConfigs(configs) {
112
- const result = configs.map(readAwsS3IntegrationConfig);
113
- if (!result.some((c) => c.host === AMAZON_AWS_HOST)) {
114
- result.push({
115
- host: AMAZON_AWS_HOST
116
- });
117
- }
118
- return result;
119
- }
120
-
121
- class AwsS3Integration {
122
- constructor(integrationConfig) {
123
- this.integrationConfig = integrationConfig;
124
- }
125
- static factory = ({ config }) => {
126
- const configs = readAwsS3IntegrationConfigs(
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