@backstage/integration 1.3.1-next.0 → 1.3.1-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @backstage/integration
2
2
 
3
+ ## 1.3.1-next.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 7d47def9c4: Removed dependency on `@types/jest`.
8
+ - f76f22c649: Improved caching around github app tokens.
9
+ Tokens are now cached for 50 minutes, not 10.
10
+ Calls to get app installations are also included in this cache.
11
+ If you have more than one github app configured, consider adding `allowedInstallationOwners` to your apps configuration to gain the most benefit from these performance changes.
12
+ - Updated dependencies
13
+ - @backstage/config@1.0.2-next.0
14
+ - @backstage/errors@1.1.1-next.0
15
+
16
+ ## 1.3.1-next.1
17
+
18
+ ### Patch Changes
19
+
20
+ - eadf56bbbf: Bump `git-url-parse` version to `^13.0.0`
21
+ - 667d917488: Updated dependency `msw` to `^0.47.0`.
22
+ - 87ec2ba4d6: Updated dependency `msw` to `^0.46.0`.
23
+ - 42918e085c: Fixed bug in the `bitbucketServer` integration where token did not take precedence over supplied username and password which is described in the documentation.
24
+
3
25
  ## 1.3.1-next.0
4
26
 
5
27
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -816,8 +816,7 @@ function getBitbucketServerRequestOptions(config) {
816
816
  const headers = {};
817
817
  if (config.token) {
818
818
  headers.Authorization = `Bearer ${config.token}`;
819
- }
820
- if (config.username && config.password) {
819
+ } else if (config.username && config.password) {
821
820
  const buffer = Buffer.from(`${config.username}:${config.password}`, "utf8");
822
821
  headers.Authorization = `Basic ${buffer.toString("base64")}`;
823
822
  }
@@ -1082,16 +1081,30 @@ function chooseEndpoint(config, credentials) {
1082
1081
  class Cache {
1083
1082
  constructor() {
1084
1083
  this.tokenCache = /* @__PURE__ */ new Map();
1085
- this.isNotExpired = (date) => date.diff(luxon.DateTime.local(), "minutes").minutes > 50;
1084
+ this.isExpired = (date) => luxon.DateTime.local() > date;
1085
+ }
1086
+ async getOrCreateToken(owner, repo, supplier) {
1087
+ let existingInstallationData = this.tokenCache.get(owner);
1088
+ if (!existingInstallationData || this.isExpired(existingInstallationData.expiresAt)) {
1089
+ existingInstallationData = await supplier();
1090
+ existingInstallationData.expiresAt = existingInstallationData.expiresAt.minus({ minutes: 10 });
1091
+ this.tokenCache.set(owner, existingInstallationData);
1092
+ }
1093
+ if (!this.appliesToRepo(existingInstallationData, repo)) {
1094
+ throw new Error(
1095
+ `The Backstage GitHub application used in the ${owner} organization does not have access to a repository with the name ${repo}`
1096
+ );
1097
+ }
1098
+ return { accessToken: existingInstallationData.token };
1086
1099
  }
1087
- async getOrCreateToken(key, supplier) {
1088
- const item = this.tokenCache.get(key);
1089
- if (item && this.isNotExpired(item.expiresAt)) {
1090
- return { accessToken: item.token };
1100
+ appliesToRepo(tokenData, repo) {
1101
+ if (repo === void 0) {
1102
+ return true;
1103
+ }
1104
+ if (tokenData.repositories !== void 0) {
1105
+ return tokenData.repositories.includes(repo);
1091
1106
  }
1092
- const result = await supplier();
1093
- this.tokenCache.set(key, result);
1094
- return { accessToken: result.token };
1107
+ return true;
1095
1108
  }
1096
1109
  }
1097
1110
  const HEADERS = {
@@ -1115,23 +1128,25 @@ class GithubAppManager {
1115
1128
  }
1116
1129
  async getInstallationCredentials(owner, repo) {
1117
1130
  var _a;
1118
- const { installationId, suspended } = await this.getInstallationData(owner);
1119
1131
  if (this.allowedInstallationOwners) {
1120
1132
  if (!((_a = this.allowedInstallationOwners) == null ? void 0 : _a.includes(owner))) {
1121
1133
  return { accessToken: void 0 };
1122
1134
  }
1123
1135
  }
1124
- if (suspended) {
1125
- throw new Error(`The GitHub application for ${owner} is suspended`);
1126
- }
1127
- const cacheKey = repo ? `${owner}/${repo}` : owner;
1128
- return this.cache.getOrCreateToken(cacheKey, async () => {
1136
+ return this.cache.getOrCreateToken(owner, repo, async () => {
1129
1137
  var _a2;
1138
+ const { installationId, suspended } = await this.getInstallationData(
1139
+ owner
1140
+ );
1141
+ if (suspended) {
1142
+ throw new Error(`The GitHub application for ${owner} is suspended`);
1143
+ }
1130
1144
  const result = await this.appClient.apps.createInstallationAccessToken({
1131
1145
  installation_id: installationId,
1132
1146
  headers: HEADERS
1133
1147
  });
1134
- if (repo && result.data.repository_selection === "selected") {
1148
+ let repositoryNames;
1149
+ if (result.data.repository_selection === "selected") {
1135
1150
  const installationClient = new rest.Octokit({
1136
1151
  baseUrl: this.baseUrl,
1137
1152
  auth: result.data.token
@@ -1140,18 +1155,12 @@ class GithubAppManager {
1140
1155
  installationClient.apps.listReposAccessibleToInstallation
1141
1156
  );
1142
1157
  const repositories = (_a2 = repos.repositories) != null ? _a2 : repos;
1143
- const hasRepo = repositories.some((repository) => {
1144
- return repository.name === repo;
1145
- });
1146
- if (!hasRepo) {
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
- );
1150
- }
1158
+ repositoryNames = repositories.map((repository) => repository.name);
1151
1159
  }
1152
1160
  return {
1153
1161
  token: result.data.token,
1154
- expiresAt: luxon.DateTime.fromISO(result.data.expires_at)
1162
+ expiresAt: luxon.DateTime.fromISO(result.data.expires_at),
1163
+ repositories: repositoryNames
1155
1164
  };
1156
1165
  });
1157
1166
  }