@backstage/integration 1.2.2-next.3 → 1.3.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -8,7 +8,6 @@ var fetch = require('cross-fetch');
8
8
  var authApp = require('@octokit/auth-app');
9
9
  var rest = require('@octokit/rest');
10
10
  var luxon = require('luxon');
11
- var errors = require('@backstage/errors');
12
11
 
13
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
14
13
 
@@ -57,7 +56,10 @@ function defaultScmResolveUrl(options) {
57
56
  if (url.startsWith("/")) {
58
57
  const { filepath } = parseGitUrl__default["default"](base);
59
58
  updated = new URL(base);
60
- const repoRootPath = lodash.trimEnd(updated.pathname.substring(0, updated.pathname.length - filepath.length), "/");
59
+ const repoRootPath = lodash.trimEnd(
60
+ updated.pathname.substring(0, updated.pathname.length - filepath.length),
61
+ "/"
62
+ );
61
63
  updated.pathname = `${repoRootPath}${url}`;
62
64
  } else {
63
65
  updated = new URL(url, base);
@@ -82,10 +84,14 @@ function readAwsS3IntegrationConfig(config) {
82
84
  host = url.host;
83
85
  pathname = url.pathname;
84
86
  } catch {
85
- throw new Error(`invalid awsS3 integration config, endpoint '${endpoint}' is not a valid URL`);
87
+ throw new Error(
88
+ `invalid awsS3 integration config, endpoint '${endpoint}' is not a valid URL`
89
+ );
86
90
  }
87
91
  if (pathname !== "/") {
88
- throw new Error(`invalid awsS3 integration config, endpoints cannot contain path, got '${endpoint}'`);
92
+ throw new Error(
93
+ `invalid awsS3 integration config, endpoints cannot contain path, got '${endpoint}'`
94
+ );
89
95
  }
90
96
  } else {
91
97
  host = AMAZON_AWS_HOST;
@@ -138,8 +144,13 @@ const _AwsS3Integration = class {
138
144
  let AwsS3Integration = _AwsS3Integration;
139
145
  AwsS3Integration.factory = ({ config }) => {
140
146
  var _a;
141
- const configs = readAwsS3IntegrationConfigs((_a = config.getOptionalConfigArray("integrations.awsS3")) != null ? _a : []);
142
- return basicIntegrations(configs.map((c) => new _AwsS3Integration(c)), (i) => i.config.host);
147
+ const configs = readAwsS3IntegrationConfigs(
148
+ (_a = config.getOptionalConfigArray("integrations.awsS3")) != null ? _a : []
149
+ );
150
+ return basicIntegrations(
151
+ configs.map((c) => new _AwsS3Integration(c)),
152
+ (i) => i.config.host
153
+ );
143
154
  };
144
155
 
145
156
  var __accessCheck = (obj, member, msg) => {
@@ -233,7 +244,9 @@ const _AzureUrl = class {
233
244
  }
234
245
  toFileUrl() {
235
246
  if (!__privateGet(this, _path)) {
236
- throw new Error("Azure URL must point to a specific path to be able to download a file");
247
+ throw new Error(
248
+ "Azure URL must point to a specific path to be able to download a file"
249
+ );
237
250
  }
238
251
  const url = __privateGet(this, _baseUrl).call(this, __privateGet(this, _owner), __privateGet(this, _project), "_apis", "git", "repositories", __privateGet(this, _repo), "items");
239
252
  url.searchParams.set("api-version", "6.0");
@@ -295,7 +308,9 @@ function readAzureIntegrationConfig(config) {
295
308
  const host = (_a = config.getOptionalString("host")) != null ? _a : AZURE_HOST;
296
309
  const token = config.getOptionalString("token");
297
310
  if (!isValidHost(host)) {
298
- throw new Error(`Invalid Azure integration config, '${host}' is not a valid host`);
311
+ throw new Error(
312
+ `Invalid Azure integration config, '${host}' is not a valid host`
313
+ );
299
314
  }
300
315
  return { host, token };
301
316
  }
@@ -350,8 +365,13 @@ const _AzureIntegration = class {
350
365
  let AzureIntegration = _AzureIntegration;
351
366
  AzureIntegration.factory = ({ config }) => {
352
367
  var _a;
353
- const configs = readAzureIntegrationConfigs((_a = config.getOptionalConfigArray("integrations.azure")) != null ? _a : []);
354
- return basicIntegrations(configs.map((c) => new _AzureIntegration(c)), (i) => i.config.host);
368
+ const configs = readAzureIntegrationConfigs(
369
+ (_a = config.getOptionalConfigArray("integrations.azure")) != null ? _a : []
370
+ );
371
+ return basicIntegrations(
372
+ configs.map((c) => new _AzureIntegration(c)),
373
+ (i) => i.config.host
374
+ );
355
375
  };
356
376
 
357
377
  function getAzureFileFetchUrl(url) {
@@ -382,7 +402,9 @@ function readBitbucketIntegrationConfig(config) {
382
402
  const username = config.getOptionalString("username");
383
403
  const appPassword = config.getOptionalString("appPassword");
384
404
  if (!isValidHost(host)) {
385
- throw new Error(`Invalid Bitbucket integration config, '${host}' is not a valid host`);
405
+ throw new Error(
406
+ `Invalid Bitbucket integration config, '${host}' is not a valid host`
407
+ );
386
408
  }
387
409
  if (apiBaseUrl) {
388
410
  apiBaseUrl = lodash.trimEnd(apiBaseUrl, "/");
@@ -450,11 +472,16 @@ BitbucketIntegration.factory = ({
450
472
  config
451
473
  }) => {
452
474
  var _a, _b, _c;
453
- const configs = readBitbucketIntegrationConfigs((_c = config.getOptionalConfigArray("integrations.bitbucket")) != null ? _c : [
454
- ...(_a = config.getOptionalConfigArray("integrations.bitbucketCloud")) != null ? _a : [],
455
- ...(_b = config.getOptionalConfigArray("integrations.bitbucketServer")) != null ? _b : []
456
- ]);
457
- return basicIntegrations(configs.map((c) => new _BitbucketIntegration(c)), (i) => i.config.host);
475
+ const configs = readBitbucketIntegrationConfigs(
476
+ (_c = config.getOptionalConfigArray("integrations.bitbucket")) != null ? _c : [
477
+ ...(_a = config.getOptionalConfigArray("integrations.bitbucketCloud")) != null ? _a : [],
478
+ ...(_b = config.getOptionalConfigArray("integrations.bitbucketServer")) != null ? _b : []
479
+ ]
480
+ );
481
+ return basicIntegrations(
482
+ configs.map((c) => new _BitbucketIntegration(c)),
483
+ (i) => i.config.host
484
+ );
458
485
  };
459
486
 
460
487
  async function getBitbucketDefaultBranch(url, config) {
@@ -479,7 +506,9 @@ async function getBitbucketDefaultBranch(url, config) {
479
506
  defaultBranch = displayId;
480
507
  }
481
508
  if (!defaultBranch) {
482
- throw new Error(`Failed to read default branch from ${branchUrl}. Response ${response.status} ${response.json()}`);
509
+ throw new Error(
510
+ `Failed to read default branch from ${branchUrl}. Response ${response.status} ${response.json()}`
511
+ );
483
512
  }
484
513
  return defaultBranch;
485
514
  }
@@ -497,7 +526,7 @@ async function getBitbucketDownloadUrl(url, config) {
497
526
  if (!branch) {
498
527
  branch = await getBitbucketDefaultBranch(url, config);
499
528
  }
500
- const path = filepath ? `&path=${encodeURIComponent(filepath)}` : "";
529
+ const path = filepath ? `&path=${encodeURIComponent(decodeURIComponent(filepath))}` : "";
501
530
  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}`;
502
531
  return archiveUrl;
503
532
  }
@@ -524,7 +553,10 @@ function getBitbucketRequestOptions(config) {
524
553
  if (config.token) {
525
554
  headers.Authorization = `Bearer ${config.token}`;
526
555
  } else if (config.username && config.appPassword) {
527
- const buffer = Buffer.from(`${config.username}:${config.appPassword}`, "utf8");
556
+ const buffer = Buffer.from(
557
+ `${config.username}:${config.appPassword}`,
558
+ "utf8"
559
+ );
528
560
  headers.Authorization = `Basic ${buffer.toString("base64")}`;
529
561
  }
530
562
  return {
@@ -592,14 +624,22 @@ BitbucketCloudIntegration.factory = ({
592
624
  config
593
625
  }) => {
594
626
  var _a;
595
- const configs = readBitbucketCloudIntegrationConfigs((_a = config.getOptionalConfigArray("integrations.bitbucketCloud")) != null ? _a : []);
596
- return basicIntegrations(configs.map((c) => new _BitbucketCloudIntegration(c)), (i) => i.config.host);
627
+ const configs = readBitbucketCloudIntegrationConfigs(
628
+ (_a = config.getOptionalConfigArray("integrations.bitbucketCloud")) != null ? _a : []
629
+ );
630
+ return basicIntegrations(
631
+ configs.map((c) => new _BitbucketCloudIntegration(c)),
632
+ (i) => i.config.host
633
+ );
597
634
  };
598
635
 
599
636
  async function getBitbucketCloudDefaultBranch(url, config) {
600
637
  const { name: repoName, owner: project } = parseGitUrl__default["default"](url);
601
638
  const branchUrl = `${config.apiBaseUrl}/repositories/${project}/${repoName}`;
602
- const response = await fetch__default["default"](branchUrl, getBitbucketCloudRequestOptions(config));
639
+ const response = await fetch__default["default"](
640
+ branchUrl,
641
+ getBitbucketCloudRequestOptions(config)
642
+ );
603
643
  if (!response.ok) {
604
644
  const message = `Failed to retrieve default branch from ${branchUrl}, ${response.status} ${response.statusText}`;
605
645
  throw new Error(message);
@@ -607,7 +647,9 @@ async function getBitbucketCloudDefaultBranch(url, config) {
607
647
  const repoInfo = await response.json();
608
648
  const defaultBranch = repoInfo.mainbranch.name;
609
649
  if (!defaultBranch) {
610
- throw new Error(`Failed to read default branch from ${branchUrl}. Response ${response.status} ${response.json()}`);
650
+ throw new Error(
651
+ `Failed to read default branch from ${branchUrl}. Response ${response.status} ${response.json()}`
652
+ );
611
653
  }
612
654
  return defaultBranch;
613
655
  }
@@ -643,7 +685,10 @@ function getBitbucketCloudFileFetchUrl(url, config) {
643
685
  function getBitbucketCloudRequestOptions(config) {
644
686
  const headers = {};
645
687
  if (config.username && config.appPassword) {
646
- const buffer = Buffer.from(`${config.username}:${config.appPassword}`, "utf8");
688
+ const buffer = Buffer.from(
689
+ `${config.username}:${config.appPassword}`,
690
+ "utf8"
691
+ );
647
692
  headers.Authorization = `Basic ${buffer.toString("base64")}`;
648
693
  }
649
694
  return {
@@ -655,8 +700,12 @@ function readBitbucketServerIntegrationConfig(config) {
655
700
  const host = config.getString("host");
656
701
  let apiBaseUrl = config.getOptionalString("apiBaseUrl");
657
702
  const token = config.getOptionalString("token");
703
+ const username = config.getOptionalString("username");
704
+ const password = config.getOptionalString("password");
658
705
  if (!isValidHost(host)) {
659
- throw new Error(`Invalid Bitbucket Server integration config, '${host}' is not a valid host`);
706
+ throw new Error(
707
+ `Invalid Bitbucket Server integration config, '${host}' is not a valid host`
708
+ );
660
709
  }
661
710
  if (apiBaseUrl) {
662
711
  apiBaseUrl = lodash.trimEnd(apiBaseUrl, "/");
@@ -666,7 +715,9 @@ function readBitbucketServerIntegrationConfig(config) {
666
715
  return {
667
716
  host,
668
717
  apiBaseUrl,
669
- token
718
+ token,
719
+ username,
720
+ password
670
721
  };
671
722
  }
672
723
  function readBitbucketServerIntegrationConfigs(configs) {
@@ -690,19 +741,16 @@ const _BitbucketServerIntegration = class {
690
741
  const resolved = defaultScmResolveUrl(options);
691
742
  if (options.lineNumber) {
692
743
  const url = new URL(resolved);
693
- const filename = url.pathname.split("/").slice(-1)[0];
694
- url.hash = `${filename}-${options.lineNumber}`;
744
+ url.hash = options.lineNumber.toString();
695
745
  return url.toString();
696
746
  }
697
747
  return resolved;
698
748
  }
699
749
  resolveEditUrl(url) {
700
- const urlData = parseGitUrl__default["default"](url);
701
- const editUrl = new URL(url);
702
- editUrl.searchParams.set("mode", "edit");
703
- editUrl.searchParams.set("spa", "0");
704
- editUrl.searchParams.set("at", urlData.ref);
705
- return editUrl.toString();
750
+ if (url.includes("?")) {
751
+ return url.substring(0, url.indexOf("?"));
752
+ }
753
+ return url;
706
754
  }
707
755
  };
708
756
  let BitbucketServerIntegration = _BitbucketServerIntegration;
@@ -710,14 +758,22 @@ BitbucketServerIntegration.factory = ({
710
758
  config
711
759
  }) => {
712
760
  var _a;
713
- const configs = readBitbucketServerIntegrationConfigs((_a = config.getOptionalConfigArray("integrations.bitbucketServer")) != null ? _a : []);
714
- return basicIntegrations(configs.map((c) => new _BitbucketServerIntegration(c)), (i) => i.config.host);
761
+ const configs = readBitbucketServerIntegrationConfigs(
762
+ (_a = config.getOptionalConfigArray("integrations.bitbucketServer")) != null ? _a : []
763
+ );
764
+ return basicIntegrations(
765
+ configs.map((c) => new _BitbucketServerIntegration(c)),
766
+ (i) => i.config.host
767
+ );
715
768
  };
716
769
 
717
770
  async function getBitbucketServerDefaultBranch(url, config) {
718
771
  const { name: repoName, owner: project } = parseGitUrl__default["default"](url);
719
772
  let branchUrl = `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/default-branch`;
720
- let response = await fetch__default["default"](branchUrl, getBitbucketServerRequestOptions(config));
773
+ let response = await fetch__default["default"](
774
+ branchUrl,
775
+ getBitbucketServerRequestOptions(config)
776
+ );
721
777
  if (response.status === 404) {
722
778
  branchUrl = `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/branches/default`;
723
779
  response = await fetch__default["default"](branchUrl, getBitbucketServerRequestOptions(config));
@@ -729,7 +785,9 @@ async function getBitbucketServerDefaultBranch(url, config) {
729
785
  const { displayId } = await response.json();
730
786
  const defaultBranch = displayId;
731
787
  if (!defaultBranch) {
732
- throw new Error(`Failed to read default branch from ${branchUrl}. Response ${response.status} ${response.json()}`);
788
+ throw new Error(
789
+ `Failed to read default branch from ${branchUrl}. Response ${response.status} ${response.json()}`
790
+ );
733
791
  }
734
792
  return defaultBranch;
735
793
  }
@@ -759,6 +817,10 @@ function getBitbucketServerRequestOptions(config) {
759
817
  if (config.token) {
760
818
  headers.Authorization = `Bearer ${config.token}`;
761
819
  }
820
+ if (config.username && config.password) {
821
+ const buffer = Buffer.from(`${config.username}:${config.password}`, "utf8");
822
+ headers.Authorization = `Basic ${buffer.toString("base64")}`;
823
+ }
762
824
  return {
763
825
  headers
764
826
  };
@@ -772,13 +834,21 @@ function readGerritIntegrationConfig(config) {
772
834
  const username = config.getOptionalString("username");
773
835
  const password = config.getOptionalString("password");
774
836
  if (!isValidHost(host)) {
775
- throw new Error(`Invalid Gerrit integration config, '${host}' is not a valid host`);
837
+ throw new Error(
838
+ `Invalid Gerrit integration config, '${host}' is not a valid host`
839
+ );
776
840
  } else if (baseUrl && !isValidUrl(baseUrl)) {
777
- throw new Error(`Invalid Gerrit integration config, '${baseUrl}' is not a valid baseUrl`);
841
+ throw new Error(
842
+ `Invalid Gerrit integration config, '${baseUrl}' is not a valid baseUrl`
843
+ );
778
844
  } else if (cloneUrl && !isValidUrl(cloneUrl)) {
779
- throw new Error(`Invalid Gerrit integration config, '${cloneUrl}' is not a valid cloneUrl`);
845
+ throw new Error(
846
+ `Invalid Gerrit integration config, '${cloneUrl}' is not a valid cloneUrl`
847
+ );
780
848
  } else if (gitilesBaseUrl && !isValidUrl(gitilesBaseUrl)) {
781
- throw new Error(`Invalid Gerrit integration config, '${gitilesBaseUrl}' is not a valid gitilesBaseUrl`);
849
+ throw new Error(
850
+ `Invalid Gerrit integration config, '${gitilesBaseUrl}' is not a valid gitilesBaseUrl`
851
+ );
782
852
  }
783
853
  if (baseUrl) {
784
854
  baseUrl = lodash.trimEnd(baseUrl, "/");
@@ -837,7 +907,9 @@ function getAuthenticationPrefix(config) {
837
907
  }
838
908
  function getGerritBranchApiUrl(config, url) {
839
909
  const { branch, project } = parseGerritGitilesUrl(config, url);
840
- return `${config.baseUrl}${getAuthenticationPrefix(config)}projects/${encodeURIComponent(project)}/branches/${branch}`;
910
+ return `${config.baseUrl}${getAuthenticationPrefix(
911
+ config
912
+ )}projects/${encodeURIComponent(project)}/branches/${branch}`;
841
913
  }
842
914
  function getGerritCloneRepoUrl(config, url) {
843
915
  const { project } = parseGerritGitilesUrl(config, url);
@@ -845,7 +917,11 @@ function getGerritCloneRepoUrl(config, url) {
845
917
  }
846
918
  function getGerritFileContentsApiUrl(config, url) {
847
919
  const { branch, filePath, project } = parseGerritGitilesUrl(config, url);
848
- return `${config.baseUrl}${getAuthenticationPrefix(config)}projects/${encodeURIComponent(project)}/branches/${branch}/files/${encodeURIComponent(filePath)}/content`;
920
+ return `${config.baseUrl}${getAuthenticationPrefix(
921
+ config
922
+ )}projects/${encodeURIComponent(
923
+ project
924
+ )}/branches/${branch}/files/${encodeURIComponent(filePath)}/content`;
849
925
  }
850
926
  function getGerritProjectsApiUrl(config) {
851
927
  return `${config.baseUrl}${getAuthenticationPrefix(config)}projects/`;
@@ -867,10 +943,14 @@ async function parseGerritJsonResponse(response) {
867
943
  try {
868
944
  return JSON.parse(responseBody.slice(GERRIT_BODY_PREFIX.length));
869
945
  } catch (ex) {
870
- throw new Error(`Invalid response from Gerrit: ${responseBody.slice(0, 10)} - ${ex}`);
946
+ throw new Error(
947
+ `Invalid response from Gerrit: ${responseBody.slice(0, 10)} - ${ex}`
948
+ );
871
949
  }
872
950
  }
873
- throw new Error(`Gerrit JSON body prefix missing. Found: ${responseBody.slice(0, 10)}`);
951
+ throw new Error(
952
+ `Gerrit JSON body prefix missing. Found: ${responseBody.slice(0, 10)}`
953
+ );
874
954
  }
875
955
 
876
956
  const _GerritIntegration = class {
@@ -910,8 +990,13 @@ const _GerritIntegration = class {
910
990
  let GerritIntegration = _GerritIntegration;
911
991
  GerritIntegration.factory = ({ config }) => {
912
992
  var _a;
913
- const configs = readGerritIntegrationConfigs((_a = config.getOptionalConfigArray("integrations.gerrit")) != null ? _a : []);
914
- return basicIntegrations(configs.map((c) => new _GerritIntegration(c)), (i) => i.config.host);
993
+ const configs = readGerritIntegrationConfigs(
994
+ (_a = config.getOptionalConfigArray("integrations.gerrit")) != null ? _a : []
995
+ );
996
+ return basicIntegrations(
997
+ configs.map((c) => new _GerritIntegration(c)),
998
+ (i) => i.config.host
999
+ );
915
1000
  };
916
1001
 
917
1002
  const GITHUB_HOST = "github.com";
@@ -929,10 +1014,14 @@ function readGitHubIntegrationConfig(config) {
929
1014
  clientSecret: c.getString("clientSecret"),
930
1015
  webhookSecret: c.getString("webhookSecret"),
931
1016
  privateKey: c.getString("privateKey"),
932
- allowedInstallationOwners: c.getOptionalStringArray("allowedInstallationOwners")
1017
+ allowedInstallationOwners: c.getOptionalStringArray(
1018
+ "allowedInstallationOwners"
1019
+ )
933
1020
  }));
934
1021
  if (!isValidHost(host)) {
935
- throw new Error(`Invalid GitHub integration config, '${host}' is not a valid host`);
1022
+ throw new Error(
1023
+ `Invalid GitHub integration config, '${host}' is not a valid host`
1024
+ );
936
1025
  }
937
1026
  if (apiBaseUrl) {
938
1027
  apiBaseUrl = lodash.trimEnd(apiBaseUrl, "/");
@@ -1037,6 +1126,7 @@ class GithubAppManager {
1037
1126
  }
1038
1127
  const cacheKey = repo ? `${owner}/${repo}` : owner;
1039
1128
  return this.cache.getOrCreateToken(cacheKey, async () => {
1129
+ var _a2;
1040
1130
  const result = await this.appClient.apps.createInstallationAccessToken({
1041
1131
  installation_id: installationId,
1042
1132
  headers: HEADERS
@@ -1046,12 +1136,17 @@ class GithubAppManager {
1046
1136
  baseUrl: this.baseUrl,
1047
1137
  auth: result.data.token
1048
1138
  });
1049
- const repos = await installationClient.paginate(installationClient.apps.listReposAccessibleToInstallation);
1050
- const hasRepo = repos.some((repository) => {
1139
+ const repos = await installationClient.paginate(
1140
+ installationClient.apps.listReposAccessibleToInstallation
1141
+ );
1142
+ const repositories = (_a2 = repos.repositories) != null ? _a2 : repos;
1143
+ const hasRepo = repositories.some((repository) => {
1051
1144
  return repository.name === repo;
1052
1145
  });
1053
1146
  if (!hasRepo) {
1054
- throw new Error(`The Backstage GitHub application used in the ${owner} organization does not have access to a repository with the name ${repo}`);
1147
+ throw new Error(
1148
+ `The Backstage GitHub application used in the ${owner} organization does not have access to a repository with the name ${repo}`
1149
+ );
1055
1150
  }
1056
1151
  }
1057
1152
  return {
@@ -1065,17 +1160,21 @@ class GithubAppManager {
1065
1160
  }
1066
1161
  async getInstallationData(owner) {
1067
1162
  const allInstallations = await this.getInstallations();
1068
- const installation = allInstallations.find((inst) => {
1069
- var _a, _b;
1070
- return ((_b = (_a = inst.account) == null ? void 0 : _a.login) == null ? void 0 : _b.toLocaleLowerCase("en-US")) === owner.toLocaleLowerCase("en-US");
1071
- });
1163
+ const installation = allInstallations.find(
1164
+ (inst) => {
1165
+ var _a, _b;
1166
+ return ((_b = (_a = inst.account) == null ? void 0 : _a.login) == null ? void 0 : _b.toLocaleLowerCase("en-US")) === owner.toLocaleLowerCase("en-US");
1167
+ }
1168
+ );
1072
1169
  if (installation) {
1073
1170
  return {
1074
1171
  installationId: installation.id,
1075
1172
  suspended: Boolean(installation.suspended_by)
1076
1173
  };
1077
1174
  }
1078
- const notFoundError = new Error(`No app installation found for ${owner} in ${this.baseAuthConfig.appId}`);
1175
+ const notFoundError = new Error(
1176
+ `No app installation found for ${owner} in ${this.baseAuthConfig.appId}`
1177
+ );
1079
1178
  notFoundError.name = "NotFoundError";
1080
1179
  throw notFoundError;
1081
1180
  }
@@ -1089,14 +1188,23 @@ class GithubAppCredentialsMux {
1089
1188
  if (!this.apps.length) {
1090
1189
  return [];
1091
1190
  }
1092
- const installs = await Promise.all(this.apps.map((app) => app.getInstallations()));
1191
+ const installs = await Promise.all(
1192
+ this.apps.map((app) => app.getInstallations())
1193
+ );
1093
1194
  return installs.flat();
1094
1195
  }
1095
1196
  async getAppToken(owner, repo) {
1096
1197
  if (this.apps.length === 0) {
1097
1198
  return void 0;
1098
1199
  }
1099
- const results = await Promise.all(this.apps.map((app) => app.getInstallationCredentials(owner, repo).then((credentials) => ({ credentials, error: void 0 }), (error) => ({ credentials: void 0, error }))));
1200
+ const results = await Promise.all(
1201
+ this.apps.map(
1202
+ (app) => app.getInstallationCredentials(owner, repo).then(
1203
+ (credentials) => ({ credentials, error: void 0 }),
1204
+ (error) => ({ credentials: void 0, error })
1205
+ )
1206
+ )
1207
+ );
1100
1208
  const result = results.find((resultItem) => resultItem.credentials);
1101
1209
  if (result) {
1102
1210
  return result.credentials.accessToken;
@@ -1133,7 +1241,10 @@ const _SingleInstanceGithubCredentialsProvider = class {
1133
1241
  };
1134
1242
  let SingleInstanceGithubCredentialsProvider = _SingleInstanceGithubCredentialsProvider;
1135
1243
  SingleInstanceGithubCredentialsProvider.create = (config) => {
1136
- return new _SingleInstanceGithubCredentialsProvider(new GithubAppCredentialsMux(config), config.token);
1244
+ return new _SingleInstanceGithubCredentialsProvider(
1245
+ new GithubAppCredentialsMux(config),
1246
+ config.token
1247
+ );
1137
1248
  };
1138
1249
 
1139
1250
  class DefaultGithubCredentialsProvider {
@@ -1152,7 +1263,9 @@ class DefaultGithubCredentialsProvider {
1152
1263
  const parsed = new URL(opts.url);
1153
1264
  const provider = this.providers.get(parsed.host);
1154
1265
  if (!provider) {
1155
- throw new Error(`There is no GitHub integration that matches ${opts.url}. Please add a configuration for an integration.`);
1266
+ throw new Error(
1267
+ `There is no GitHub integration that matches ${opts.url}. Please add a configuration for an integration.`
1268
+ );
1156
1269
  }
1157
1270
  return provider.getCredentials(opts);
1158
1271
  }
@@ -1181,13 +1294,21 @@ const _GitHubIntegration = class {
1181
1294
  let GitHubIntegration = _GitHubIntegration;
1182
1295
  GitHubIntegration.factory = ({ config }) => {
1183
1296
  var _a;
1184
- const configs = readGitHubIntegrationConfigs((_a = config.getOptionalConfigArray("integrations.github")) != null ? _a : []);
1185
- return basicIntegrations(configs.map((c) => new _GitHubIntegration(c)), (i) => i.config.host);
1297
+ const configs = readGitHubIntegrationConfigs(
1298
+ (_a = config.getOptionalConfigArray("integrations.github")) != null ? _a : []
1299
+ );
1300
+ return basicIntegrations(
1301
+ configs.map((c) => new _GitHubIntegration(c)),
1302
+ (i) => i.config.host
1303
+ );
1186
1304
  };
1187
1305
  function replaceGitHubUrlType(url, type) {
1188
- return url.replace(/\/\/([^/]+)\/([^/]+)\/([^/]+)\/(blob|tree|edit)\//, (_, host, owner, repo) => {
1189
- return `//${host}/${owner}/${repo}/${type}/`;
1190
- });
1306
+ return url.replace(
1307
+ /\/\/([^/]+)\/([^/]+)\/([^/]+)\/(blob|tree|edit)\//,
1308
+ (_, host, owner, repo) => {
1309
+ return `//${host}/${owner}/${repo}/${type}/`;
1310
+ }
1311
+ );
1191
1312
  }
1192
1313
 
1193
1314
  const GITLAB_HOST = "gitlab.com";
@@ -1208,11 +1329,17 @@ function readGitLabIntegrationConfig(config) {
1208
1329
  baseUrl = `https://${host}`;
1209
1330
  }
1210
1331
  if (!isValidHost(host)) {
1211
- throw new Error(`Invalid GitLab integration config, '${host}' is not a valid host`);
1332
+ throw new Error(
1333
+ `Invalid GitLab integration config, '${host}' is not a valid host`
1334
+ );
1212
1335
  } else if (!apiBaseUrl || !isValidUrl(apiBaseUrl)) {
1213
- throw new Error(`Invalid GitLab integration config, '${apiBaseUrl}' is not a valid apiBaseUrl`);
1336
+ throw new Error(
1337
+ `Invalid GitLab integration config, '${apiBaseUrl}' is not a valid apiBaseUrl`
1338
+ );
1214
1339
  } else if (!isValidUrl(baseUrl)) {
1215
- throw new Error(`Invalid GitLab integration config, '${baseUrl}' is not a valid baseUrl`);
1340
+ throw new Error(
1341
+ `Invalid GitLab integration config, '${baseUrl}' is not a valid baseUrl`
1342
+ );
1216
1343
  }
1217
1344
  return { host, token, apiBaseUrl, baseUrl };
1218
1345
  }
@@ -1227,13 +1354,17 @@ function readGitLabIntegrationConfigs(configs) {
1227
1354
  }
1228
1355
  return result;
1229
1356
  }
1357
+ function getGitLabIntegrationRelativePath(config) {
1358
+ let relativePath = "";
1359
+ if (config.host !== GITLAB_HOST) {
1360
+ relativePath = new URL(config.baseUrl).pathname;
1361
+ }
1362
+ return lodash.trimEnd(relativePath, "/");
1363
+ }
1230
1364
 
1231
1365
  async function getGitLabFileFetchUrl(url, config) {
1232
- if (url.includes("/-/blob/")) {
1233
- const projectID = await getProjectId(url, config);
1234
- return buildProjectUrl(url, projectID).toString();
1235
- }
1236
- return buildRawUrl(url).toString();
1366
+ const projectID = await getProjectId(url, config);
1367
+ return buildProjectUrl(url, projectID, config).toString();
1237
1368
  }
1238
1369
  function getGitLabRequestOptions(config) {
1239
1370
  const { token = "" } = config;
@@ -1243,32 +1374,15 @@ function getGitLabRequestOptions(config) {
1243
1374
  }
1244
1375
  };
1245
1376
  }
1246
- function buildRawUrl(target) {
1377
+ function buildProjectUrl(target, projectID, config) {
1247
1378
  try {
1248
1379
  const url = new URL(target);
1249
- const splitPath = url.pathname.split("/").filter(Boolean);
1250
- const blobIndex = splitPath.indexOf("blob", 2);
1251
- if (blobIndex < 2 || blobIndex === splitPath.length - 1) {
1252
- throw new errors.InputError("Wrong GitLab URL");
1253
- }
1254
- const repoPath = splitPath.slice(0, blobIndex);
1255
- const restOfPath = splitPath.slice(blobIndex + 1);
1256
- if (!restOfPath.join("/").match(/\.(yaml|yml)$/)) {
1257
- throw new errors.InputError("Wrong GitLab URL");
1258
- }
1259
- url.pathname = [...repoPath, "raw", ...restOfPath].join("/");
1260
- return url;
1261
- } catch (e) {
1262
- throw new errors.InputError(`Incorrect url: ${target}, ${e}`);
1263
- }
1264
- }
1265
- function buildProjectUrl(target, projectID) {
1266
- try {
1267
- const url = new URL(target);
1268
- const branchAndFilePath = url.pathname.split("/-/blob/")[1];
1380
+ const branchAndFilePath = url.pathname.split("/blob/").slice(1).join("/blob/");
1269
1381
  const [branch, ...filePath] = branchAndFilePath.split("/");
1382
+ const relativePath = getGitLabIntegrationRelativePath(config);
1270
1383
  url.pathname = [
1271
- "/api/v4/projects",
1384
+ ...relativePath ? [relativePath] : [],
1385
+ "api/v4/projects",
1272
1386
  projectID,
1273
1387
  "repository/files",
1274
1388
  encodeURIComponent(decodeURIComponent(filePath.join("/"))),
@@ -1282,16 +1396,29 @@ function buildProjectUrl(target, projectID) {
1282
1396
  }
1283
1397
  async function getProjectId(target, config) {
1284
1398
  const url = new URL(target);
1285
- if (!url.pathname.includes("/-/blob/")) {
1399
+ if (!url.pathname.includes("/blob/")) {
1286
1400
  throw new Error("Please provide full path to yaml file from GitLab");
1287
1401
  }
1288
1402
  try {
1289
- const repo = url.pathname.split("/-/blob/")[0];
1290
- const repoIDLookup = new URL(`${url.origin}/api/v4/projects/${encodeURIComponent(repo.replace(/^\//, ""))}`);
1291
- const response = await fetch__default["default"](repoIDLookup.toString(), getGitLabRequestOptions(config));
1403
+ let repo = url.pathname.split("/-/blob/")[0].split("/blob/")[0];
1404
+ const relativePath = getGitLabIntegrationRelativePath(config);
1405
+ if (relativePath) {
1406
+ repo = repo.replace(relativePath, "");
1407
+ }
1408
+ const repoIDLookup = new URL(
1409
+ `${url.origin}${relativePath}/api/v4/projects/${encodeURIComponent(
1410
+ repo.replace(/^\//, "")
1411
+ )}`
1412
+ );
1413
+ const response = await fetch__default["default"](
1414
+ repoIDLookup.toString(),
1415
+ getGitLabRequestOptions(config)
1416
+ );
1292
1417
  const data = await response.json();
1293
1418
  if (!response.ok) {
1294
- throw new Error(`GitLab Error '${data.error}', ${data.error_description}`);
1419
+ throw new Error(
1420
+ `GitLab Error '${data.error}', ${data.error_description}`
1421
+ );
1295
1422
  }
1296
1423
  return Number(data.id);
1297
1424
  } catch (e) {
@@ -1322,8 +1449,13 @@ const _GitLabIntegration = class {
1322
1449
  let GitLabIntegration = _GitLabIntegration;
1323
1450
  GitLabIntegration.factory = ({ config }) => {
1324
1451
  var _a;
1325
- const configs = readGitLabIntegrationConfigs((_a = config.getOptionalConfigArray("integrations.gitlab")) != null ? _a : []);
1326
- return basicIntegrations(configs.map((c) => new _GitLabIntegration(c)), (i) => i.config.host);
1452
+ const configs = readGitLabIntegrationConfigs(
1453
+ (_a = config.getOptionalConfigArray("integrations.gitlab")) != null ? _a : []
1454
+ );
1455
+ return basicIntegrations(
1456
+ configs.map((c) => new _GitLabIntegration(c)),
1457
+ (i) => i.config.host
1458
+ );
1327
1459
  };
1328
1460
  function replaceGitLabUrlType(url, type) {
1329
1461
  return url.replace(/\/\-\/(blob|tree|edit)\//, `/-/${type}/`);
@@ -1382,10 +1514,21 @@ class ScmIntegrations {
1382
1514
  return this.byType.gitlab;
1383
1515
  }
1384
1516
  list() {
1385
- return Object.values(this.byType).flatMap((i) => i.list());
1517
+ return Object.values(this.byType).flatMap(
1518
+ (i) => i.list()
1519
+ );
1386
1520
  }
1387
1521
  byUrl(url) {
1388
- return Object.values(this.byType).map((i) => i.byUrl(url)).find(Boolean);
1522
+ let candidates = Object.values(this.byType).map((i) => i.byUrl(url)).filter(Boolean);
1523
+ if (candidates.length > 1) {
1524
+ const filteredCandidates = candidates.filter(
1525
+ (x) => !(x instanceof BitbucketIntegration)
1526
+ );
1527
+ if (filteredCandidates.length !== 0) {
1528
+ candidates = filteredCandidates;
1529
+ }
1530
+ }
1531
+ return candidates[0];
1389
1532
  }
1390
1533
  byHost(host) {
1391
1534
  return Object.values(this.byType).map((i) => i.byHost(host)).find(Boolean);
@@ -1443,6 +1586,7 @@ exports.getGerritRequestOptions = getGerritRequestOptions;
1443
1586
  exports.getGitHubFileFetchUrl = getGitHubFileFetchUrl;
1444
1587
  exports.getGitHubRequestOptions = getGitHubRequestOptions;
1445
1588
  exports.getGitLabFileFetchUrl = getGitLabFileFetchUrl;
1589
+ exports.getGitLabIntegrationRelativePath = getGitLabIntegrationRelativePath;
1446
1590
  exports.getGitLabRequestOptions = getGitLabRequestOptions;
1447
1591
  exports.parseGerritGitilesUrl = parseGerritGitilesUrl;
1448
1592
  exports.parseGerritJsonResponse = parseGerritJsonResponse;