@red-hat-developer-hub/backstage-plugin-bulk-import-backend 5.0.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 (56) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +161 -0
  3. package/app-config.yaml +0 -0
  4. package/config.d.ts +17 -0
  5. package/dist/catalog/catalogHttpClient.cjs.js +284 -0
  6. package/dist/catalog/catalogHttpClient.cjs.js.map +1 -0
  7. package/dist/catalog/catalogInfoGenerator.cjs.js +60 -0
  8. package/dist/catalog/catalogInfoGenerator.cjs.js.map +1 -0
  9. package/dist/catalog/catalogUtils.cjs.js +34 -0
  10. package/dist/catalog/catalogUtils.cjs.js.map +1 -0
  11. package/dist/generated/openapidocument.cjs.js +1168 -0
  12. package/dist/generated/openapidocument.cjs.js.map +1 -0
  13. package/dist/github/GithubAppManager.cjs.js +395 -0
  14. package/dist/github/GithubAppManager.cjs.js.map +1 -0
  15. package/dist/github/githubApiService.cjs.js +659 -0
  16. package/dist/github/githubApiService.cjs.js.map +1 -0
  17. package/dist/github/types.cjs.js +8 -0
  18. package/dist/github/types.cjs.js.map +1 -0
  19. package/dist/github/utils/ghUtils.cjs.js +103 -0
  20. package/dist/github/utils/ghUtils.cjs.js.map +1 -0
  21. package/dist/github/utils/orgUtils.cjs.js +151 -0
  22. package/dist/github/utils/orgUtils.cjs.js.map +1 -0
  23. package/dist/github/utils/prUtils.cjs.js +85 -0
  24. package/dist/github/utils/prUtils.cjs.js.map +1 -0
  25. package/dist/github/utils/repoUtils.cjs.js +307 -0
  26. package/dist/github/utils/repoUtils.cjs.js.map +1 -0
  27. package/dist/github/utils/utils.cjs.js +206 -0
  28. package/dist/github/utils/utils.cjs.js.map +1 -0
  29. package/dist/helpers/auditLogUtils.cjs.js +112 -0
  30. package/dist/helpers/auditLogUtils.cjs.js.map +1 -0
  31. package/dist/helpers/auth.cjs.js +36 -0
  32. package/dist/helpers/auth.cjs.js.map +1 -0
  33. package/dist/helpers/loggingUtils.cjs.js +19 -0
  34. package/dist/helpers/loggingUtils.cjs.js.map +1 -0
  35. package/dist/helpers/pagination.cjs.js +19 -0
  36. package/dist/helpers/pagination.cjs.js.map +1 -0
  37. package/dist/index.cjs.js +12 -0
  38. package/dist/index.cjs.js.map +1 -0
  39. package/dist/index.d.ts +25 -0
  40. package/dist/plugin.cjs.js +54 -0
  41. package/dist/plugin.cjs.js.map +1 -0
  42. package/dist/service/handlers/handlers.cjs.js +8 -0
  43. package/dist/service/handlers/handlers.cjs.js.map +1 -0
  44. package/dist/service/handlers/import/bulkImports.cjs.js +551 -0
  45. package/dist/service/handlers/import/bulkImports.cjs.js.map +1 -0
  46. package/dist/service/handlers/import/importStatus.cjs.js +49 -0
  47. package/dist/service/handlers/import/importStatus.cjs.js.map +1 -0
  48. package/dist/service/handlers/organization/organizations.cjs.js +77 -0
  49. package/dist/service/handlers/organization/organizations.cjs.js.map +1 -0
  50. package/dist/service/handlers/ping/ping.cjs.js +12 -0
  51. package/dist/service/handlers/ping/ping.cjs.js.map +1 -0
  52. package/dist/service/handlers/repository/repositories.cjs.js +99 -0
  53. package/dist/service/handlers/repository/repositories.cjs.js.map +1 -0
  54. package/dist/service/router.cjs.js +324 -0
  55. package/dist/service/router.cjs.js.map +1 -0
  56. package/package.json +110 -0
@@ -0,0 +1,551 @@
1
+ 'use strict';
2
+
3
+ var gitUrlParse = require('git-url-parse');
4
+ var catalogUtils = require('../../../catalog/catalogUtils.cjs.js');
5
+ require('@backstage/errors');
6
+ require('@backstage/plugin-permission-common');
7
+ require('@red-hat-developer-hub/backstage-plugin-bulk-import-common');
8
+ var loggingUtils = require('../../../helpers/loggingUtils.cjs.js');
9
+ var pagination = require('../../../helpers/pagination.cjs.js');
10
+ var handlers = require('../handlers.cjs.js');
11
+
12
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
13
+
14
+ var gitUrlParse__default = /*#__PURE__*/_interopDefaultCompat(gitUrlParse);
15
+
16
+ function sortImports(imports) {
17
+ imports.sort((a, b) => {
18
+ if (a.repository?.name === void 0 && b.repository?.name === void 0) {
19
+ return 0;
20
+ }
21
+ if (a.repository?.name === void 0) {
22
+ return -1;
23
+ }
24
+ if (b.repository?.name === void 0) {
25
+ return 1;
26
+ }
27
+ return a.repository.name.localeCompare(b.repository.name);
28
+ });
29
+ }
30
+ async function findAllImports(deps, requestHeaders, queryParams) {
31
+ const apiVersion = requestHeaders?.apiVersion ?? "v1";
32
+ const search = queryParams?.search;
33
+ const pageNumber = queryParams?.pageNumber ?? handlers.DefaultPageNumber;
34
+ const pageSize = queryParams?.pageSize ?? handlers.DefaultPageSize;
35
+ deps.logger.debug(
36
+ `Getting all bulk import jobs (apiVersion=${apiVersion}, search=${search}, page=${pageNumber}, size=${pageSize})..`
37
+ );
38
+ const catalogFilename = catalogUtils.getCatalogFilename(deps.config);
39
+ const allLocations = (await deps.catalogHttpClient.listCatalogUrlLocations(
40
+ search,
41
+ pageNumber,
42
+ pageSize
43
+ )).targetUrls;
44
+ const defaultBranchByRepoUrl = await resolveReposDefaultBranches(
45
+ deps.logger,
46
+ deps.githubApiService,
47
+ allLocations,
48
+ catalogFilename
49
+ );
50
+ const importCandidates = findImportCandidates(
51
+ allLocations,
52
+ defaultBranchByRepoUrl,
53
+ catalogFilename
54
+ );
55
+ const importsReachableFromGHIntegrations = await deps.githubApiService.filterLocationsAccessibleFromIntegrations(
56
+ importCandidates
57
+ );
58
+ const importStatusPromises = [];
59
+ for (const loc of importsReachableFromGHIntegrations) {
60
+ const repoUrl = repoUrlFromLocation(loc);
61
+ if (!repoUrl) {
62
+ continue;
63
+ }
64
+ importStatusPromises.push(
65
+ findImportStatusByRepo(
66
+ deps,
67
+ repoUrl,
68
+ defaultBranchByRepoUrl.get(repoUrl),
69
+ false
70
+ )
71
+ );
72
+ }
73
+ const result = await Promise.all(importStatusPromises);
74
+ const imports = result.filter((res) => res.responseBody).map((res) => res.responseBody);
75
+ sortImports(imports);
76
+ const paginated = pagination.paginateArray(imports, pageNumber, pageSize);
77
+ if (apiVersion === "v1") {
78
+ return {
79
+ statusCode: 200,
80
+ responseBody: paginated.result
81
+ };
82
+ }
83
+ return {
84
+ statusCode: 200,
85
+ responseBody: {
86
+ imports: paginated.result,
87
+ totalCount: paginated.totalCount,
88
+ page: pageNumber,
89
+ size: pageSize
90
+ }
91
+ };
92
+ }
93
+ async function resolveReposDefaultBranches(logger, githubApiService, allLocations, catalogFilename) {
94
+ const defaultBranchByRepoUrlPromises = [];
95
+ for (const loc of allLocations) {
96
+ if (!loc.endsWith(catalogFilename)) {
97
+ logger.debug(
98
+ `Ignored location ${loc} because it does not point to a file named ${catalogFilename}`
99
+ );
100
+ continue;
101
+ }
102
+ const repoUrl = repoUrlFromLocation(loc);
103
+ if (!repoUrl) {
104
+ continue;
105
+ }
106
+ defaultBranchByRepoUrlPromises.push(
107
+ githubApiService.getRepositoryFromIntegrations(repoUrl).then((resp) => {
108
+ return { repoUrl, defaultBranch: resp?.repository?.default_branch };
109
+ }).catch((err) => {
110
+ loggingUtils.logErrorIfNeeded(
111
+ logger,
112
+ `Ignored repo ${repoUrl} due to an error while fetching details from GitHub`,
113
+ err
114
+ );
115
+ return {
116
+ repoUrl,
117
+ defaultBranch: void 0
118
+ };
119
+ })
120
+ );
121
+ }
122
+ const defaultBranchesResponses = await Promise.all(
123
+ defaultBranchByRepoUrlPromises
124
+ );
125
+ return new Map(
126
+ defaultBranchesResponses.flat().filter((r) => r.defaultBranch).map((r) => [r.repoUrl, r.defaultBranch])
127
+ );
128
+ }
129
+ function repoUrlFromLocation(loc) {
130
+ const split = loc.split("/blob/");
131
+ if (split.length < 2) {
132
+ return void 0;
133
+ }
134
+ return split[0];
135
+ }
136
+ function findImportCandidates(allLocations, defaultBranchByRepoUrl, catalogFilename) {
137
+ const filteredLocations = [];
138
+ for (const loc of allLocations) {
139
+ const repoUrl = repoUrlFromLocation(loc);
140
+ if (!repoUrl) {
141
+ continue;
142
+ }
143
+ const defaultBranch = defaultBranchByRepoUrl.get(repoUrl);
144
+ if (!defaultBranch) {
145
+ continue;
146
+ }
147
+ if (loc !== `${repoUrl}/blob/${defaultBranch}/${catalogFilename}`) {
148
+ continue;
149
+ }
150
+ filteredLocations.push(loc);
151
+ }
152
+ return filteredLocations;
153
+ }
154
+ async function createPR(githubApiService, logger, req, gitUrl, catalogInfoGenerator, config) {
155
+ const appTitle = config.getOptionalString("app.title") ?? "Red Hat Developer Hub";
156
+ const appBaseUrl = config.getString("app.baseUrl");
157
+ const catalogFileName = catalogUtils.getCatalogFilename(config);
158
+ return await githubApiService.submitPrToRepo(logger, {
159
+ repoUrl: req.repository.url,
160
+ gitUrl,
161
+ defaultBranch: req.repository.defaultBranch,
162
+ catalogInfoContent: req.catalogInfoContent ?? await catalogInfoGenerator.generateDefaultCatalogInfoContent(
163
+ req.repository.url
164
+ ),
165
+ prTitle: req.github?.pullRequest?.title ?? `Add ${catalogFileName}`,
166
+ prBody: req.github?.pullRequest?.body ?? `
167
+ This pull request adds a **Backstage entity metadata file** to this repository so that the component can be added to a Backstage application.
168
+
169
+ After this pull request is merged, the component will become available in the [${appTitle} software catalog](${appBaseUrl}).
170
+
171
+ For more information, read an [overview of the Backstage software catalog](https://backstage.io/docs/features/software-catalog/).
172
+ `
173
+ });
174
+ }
175
+ async function handleAddedReposFromCreateImportJobs(deps, importRequests) {
176
+ const result = [];
177
+ for (const req of importRequests) {
178
+ const repoCatalogUrl = catalogUtils.getCatalogUrl(
179
+ deps.config,
180
+ req.repository.url,
181
+ req.repository.defaultBranch
182
+ );
183
+ const hasLocation = await deps.catalogHttpClient.verifyLocationExistence(
184
+ repoCatalogUrl
185
+ );
186
+ if (!hasLocation) {
187
+ continue;
188
+ }
189
+ const hasCatalogInfoFileInRepo = await deps.githubApiService.hasFileInRepo({
190
+ repoUrl: req.repository.url,
191
+ defaultBranch: req.repository.defaultBranch,
192
+ fileName: catalogUtils.getCatalogFilename(deps.config)
193
+ });
194
+ if (!hasCatalogInfoFileInRepo) {
195
+ continue;
196
+ }
197
+ const ghRepo = await deps.githubApiService.getRepositoryFromIntegrations(
198
+ req.repository.url
199
+ );
200
+ await deps.catalogHttpClient.refreshLocationByRepoUrl(
201
+ req.repository.url,
202
+ req.repository.defaultBranch
203
+ );
204
+ const gitUrl = gitUrlParse__default.default(req.repository.url);
205
+ result.push({
206
+ status: "ADDED",
207
+ lastUpdate: ghRepo?.repository?.updated_at ?? void 0,
208
+ repository: {
209
+ url: req.repository.url,
210
+ name: gitUrl.name,
211
+ organization: gitUrl.organization
212
+ }
213
+ });
214
+ }
215
+ return result;
216
+ }
217
+ async function handlePrCreationRequest(deps, req, gitUrl) {
218
+ const repoCatalogUrl = catalogUtils.getCatalogUrl(
219
+ deps.config,
220
+ req.repository.url,
221
+ req.repository.defaultBranch
222
+ );
223
+ const prToRepo = await createPR(
224
+ deps.githubApiService,
225
+ deps.logger,
226
+ req,
227
+ gitUrl,
228
+ deps.catalogInfoGenerator,
229
+ deps.config
230
+ );
231
+ if (prToRepo.errors && prToRepo.errors.length > 0) {
232
+ return {
233
+ errors: prToRepo.errors,
234
+ status: "PR_ERROR",
235
+ repository: req.repository
236
+ };
237
+ }
238
+ if (prToRepo.prUrl) {
239
+ deps.logger.debug(`Created new PR from request: ${prToRepo.prUrl}`);
240
+ }
241
+ await deps.catalogHttpClient.possiblyCreateLocation(repoCatalogUrl);
242
+ if (prToRepo.hasChanges === false) {
243
+ deps.logger.debug(
244
+ `No bulk import PR created on ${req.repository.url} since its default branch (${req.repository.defaultBranch}) already contains a catalog-info file`
245
+ );
246
+ await deps.catalogHttpClient.refreshLocationByRepoUrl(
247
+ req.repository.url,
248
+ req.repository.defaultBranch
249
+ );
250
+ return {
251
+ status: "ADDED",
252
+ lastUpdate: prToRepo.lastUpdate,
253
+ repository: {
254
+ url: req.repository.url,
255
+ name: gitUrl.name,
256
+ organization: gitUrl.organization
257
+ }
258
+ };
259
+ }
260
+ return {
261
+ errors: prToRepo.errors,
262
+ status: "WAIT_PR_APPROVAL",
263
+ lastUpdate: prToRepo.lastUpdate,
264
+ repository: {
265
+ url: req.repository.url,
266
+ name: gitUrl.name,
267
+ organization: gitUrl.organization
268
+ },
269
+ github: {
270
+ pullRequest: {
271
+ url: prToRepo.prUrl,
272
+ number: prToRepo.prNumber
273
+ }
274
+ }
275
+ };
276
+ }
277
+ async function createImportJobs(deps, reqParams) {
278
+ const dryRun = reqParams.dryRun ?? false;
279
+ const importRequests = reqParams.importRequests;
280
+ deps.logger.debug(
281
+ `Handling request to import ${importRequests?.length} repo(s) (dryRun=${dryRun})..`
282
+ );
283
+ if (importRequests.length === 0) {
284
+ deps.logger.debug("Missing import requests from request body");
285
+ return {
286
+ statusCode: 400,
287
+ responseBody: []
288
+ };
289
+ }
290
+ if (dryRun) {
291
+ return {
292
+ statusCode: 202,
293
+ responseBody: await dryRunCreateImportJobs(deps, importRequests)
294
+ };
295
+ }
296
+ const result = [];
297
+ const addedRepos = await handleAddedReposFromCreateImportJobs(
298
+ deps,
299
+ importRequests
300
+ );
301
+ result.push(...addedRepos);
302
+ const addedReposMap = new Map(
303
+ addedRepos.map((res) => [res.repository?.url, res])
304
+ );
305
+ const remainingRequests = importRequests.filter(
306
+ (req) => !addedReposMap.has(req.repository.url)
307
+ );
308
+ for (const req of remainingRequests) {
309
+ const gitUrl = gitUrlParse__default.default(req.repository.url);
310
+ try {
311
+ result.push(await handlePrCreationRequest(deps, req, gitUrl));
312
+ } catch (error) {
313
+ result.push({
314
+ errors: [error.message],
315
+ status: "PR_ERROR",
316
+ repository: {
317
+ url: req.repository.url,
318
+ name: gitUrl.name,
319
+ organization: gitUrl.organization
320
+ }
321
+ });
322
+ }
323
+ }
324
+ sortImports(result);
325
+ return {
326
+ statusCode: 202,
327
+ responseBody: result
328
+ };
329
+ }
330
+ async function dryRunCreateImportJobs(deps, importRequests) {
331
+ const result = [];
332
+ for (const req of importRequests) {
333
+ const gitUrl = gitUrlParse__default.default(req.repository.url);
334
+ const dryRunChecks = await performDryRunChecks(deps, req);
335
+ if (dryRunChecks.errors?.length > 0) {
336
+ deps.logger.warn(
337
+ `Errors while performing dry-run checks: ${dryRunChecks.errors}`
338
+ );
339
+ }
340
+ result.push({
341
+ errors: dryRunChecks.dryRunStatuses,
342
+ catalogEntityName: req.catalogEntityName,
343
+ repository: {
344
+ url: req.repository.url,
345
+ name: gitUrl.name,
346
+ organization: gitUrl.organization
347
+ }
348
+ });
349
+ }
350
+ return result;
351
+ }
352
+ async function performDryRunChecks(deps, req) {
353
+ const checkCatalog = async (catalogEntityName) => {
354
+ const hasEntity = await deps.catalogHttpClient.hasEntityInCatalog(
355
+ catalogEntityName
356
+ );
357
+ if (hasEntity) {
358
+ return { dryRunStatuses: ["CATALOG_ENTITY_CONFLICT"] };
359
+ }
360
+ return {};
361
+ };
362
+ const checkEmptyRepo = async () => {
363
+ const empty = await deps.githubApiService.isRepoEmpty({
364
+ repoUrl: req.repository.url
365
+ });
366
+ if (empty) {
367
+ return {
368
+ dryRunStatuses: ["REPO_EMPTY"]
369
+ };
370
+ }
371
+ return {};
372
+ };
373
+ const checkCatalogInfoPresenceInRepo = async () => {
374
+ const exists = await deps.githubApiService.hasFileInRepo({
375
+ repoUrl: req.repository.url,
376
+ defaultBranch: req.repository.defaultBranch,
377
+ fileName: catalogUtils.getCatalogFilename(deps.config)
378
+ });
379
+ if (exists) {
380
+ return {
381
+ dryRunStatuses: ["CATALOG_INFO_FILE_EXISTS_IN_REPO"]
382
+ };
383
+ }
384
+ return {};
385
+ };
386
+ const checkCodeOwnersFileInRepo = async () => {
387
+ const exists = await deps.githubApiService.hasFileInRepo({
388
+ repoUrl: req.repository.url,
389
+ defaultBranch: req.repository.defaultBranch,
390
+ fileName: ".github/CODEOWNERS"
391
+ });
392
+ if (!exists) {
393
+ return {
394
+ dryRunStatuses: ["CODEOWNERS_FILE_NOT_FOUND_IN_REPO"]
395
+ };
396
+ }
397
+ return {};
398
+ };
399
+ const dryRunStatuses = [];
400
+ const errors = [];
401
+ const allChecksFn = [checkEmptyRepo(), checkCatalogInfoPresenceInRepo()];
402
+ if (req.catalogEntityName?.trim()) {
403
+ allChecksFn.push(checkCatalog(req.catalogEntityName));
404
+ }
405
+ if (req.codeOwnersFileAsEntityOwner) {
406
+ allChecksFn.push(checkCodeOwnersFileInRepo());
407
+ }
408
+ const allChecks = await Promise.all(allChecksFn);
409
+ allChecks.flat().forEach((res) => {
410
+ if (res.dryRunStatuses) {
411
+ dryRunStatuses.push(...res.dryRunStatuses);
412
+ }
413
+ if (res.errors) {
414
+ errors.push(...res.errors);
415
+ }
416
+ });
417
+ dryRunStatuses.sort((a, b) => a.localeCompare(b));
418
+ return {
419
+ dryRunStatuses,
420
+ errors
421
+ };
422
+ }
423
+ async function findImportStatusByRepo(deps, repoUrl, defaultBranch, includeCatalogInfoContent) {
424
+ deps.logger.debug(`Getting bulk import job status for ${repoUrl}..`);
425
+ const gitUrl = gitUrlParse__default.default(repoUrl);
426
+ const errors = [];
427
+ const result = {
428
+ id: repoUrl,
429
+ repository: {
430
+ url: repoUrl,
431
+ name: gitUrl.name,
432
+ organization: gitUrl.organization,
433
+ id: `${gitUrl.organization}/${gitUrl.name}`,
434
+ defaultBranch
435
+ },
436
+ approvalTool: "GIT",
437
+ status: null
438
+ };
439
+ try {
440
+ const openImportPr = await deps.githubApiService.findImportOpenPr(
441
+ deps.logger,
442
+ {
443
+ repoUrl,
444
+ includeCatalogInfoContent
445
+ }
446
+ );
447
+ if (!openImportPr.prUrl) {
448
+ const catalogLocations = (await deps.catalogHttpClient.listCatalogUrlLocations()).targetUrls;
449
+ const catalogUrl = catalogUtils.getCatalogUrl(deps.config, repoUrl, defaultBranch);
450
+ let exists = false;
451
+ for (const loc of catalogLocations) {
452
+ if (loc === catalogUrl) {
453
+ exists = true;
454
+ break;
455
+ }
456
+ }
457
+ if (exists && await deps.githubApiService.hasFileInRepo({
458
+ repoUrl,
459
+ defaultBranch,
460
+ fileName: catalogUtils.getCatalogFilename(deps.config)
461
+ })) {
462
+ result.status = "ADDED";
463
+ await deps.catalogHttpClient.refreshLocationByRepoUrl(
464
+ repoUrl,
465
+ defaultBranch
466
+ );
467
+ }
468
+ const ghRepo = await deps.githubApiService.getRepositoryFromIntegrations(
469
+ repoUrl
470
+ );
471
+ result.lastUpdate = ghRepo.repository?.updated_at ?? void 0;
472
+ return {
473
+ statusCode: 200,
474
+ responseBody: result
475
+ };
476
+ }
477
+ result.status = "WAIT_PR_APPROVAL";
478
+ result.github = {
479
+ pullRequest: {
480
+ number: openImportPr.prNum,
481
+ url: openImportPr.prUrl,
482
+ title: openImportPr.prTitle,
483
+ body: openImportPr.prBody,
484
+ catalogInfoContent: openImportPr.prCatalogInfoContent
485
+ }
486
+ };
487
+ result.lastUpdate = openImportPr.lastUpdate;
488
+ } catch (error) {
489
+ errors.push(error.message);
490
+ result.errors = errors;
491
+ if (error.message?.includes("Not Found")) {
492
+ return {
493
+ statusCode: 404,
494
+ responseBody: result
495
+ };
496
+ }
497
+ result.status = "PR_ERROR";
498
+ }
499
+ return {
500
+ statusCode: 200,
501
+ responseBody: result
502
+ };
503
+ }
504
+ async function deleteImportByRepo(deps, repoUrl, defaultBranch) {
505
+ deps.logger.debug(`Deleting bulk import job status for ${repoUrl}..`);
506
+ const openImportPr = await deps.githubApiService.findImportOpenPr(
507
+ deps.logger,
508
+ {
509
+ repoUrl
510
+ }
511
+ );
512
+ const gitUrl = gitUrlParse__default.default(repoUrl);
513
+ if (openImportPr.prUrl) {
514
+ const appTitle = deps.config.getOptionalString("app.title") ?? "Red Hat Developer Hub";
515
+ const appBaseUrl = deps.config.getString("app.baseUrl");
516
+ await deps.githubApiService.closeImportPR(deps.logger, {
517
+ repoUrl,
518
+ gitUrl,
519
+ comment: `Closing PR upon request for bulk import deletion. This request was created from [${appTitle}](${appBaseUrl}).`
520
+ });
521
+ }
522
+ await deps.githubApiService.deleteImportBranch({
523
+ repoUrl,
524
+ gitUrl
525
+ });
526
+ const catalogUrl = catalogUtils.getCatalogUrl(deps.config, repoUrl, defaultBranch);
527
+ const findLocationFrom = (list) => {
528
+ for (const loc of list) {
529
+ if (loc.target === catalogUrl) {
530
+ return loc.id;
531
+ }
532
+ }
533
+ return void 0;
534
+ };
535
+ const locationId = findLocationFrom(
536
+ (await deps.catalogHttpClient.listCatalogUrlLocationsByIdFromLocationsEndpoint()).locations
537
+ );
538
+ if (locationId) {
539
+ await deps.catalogHttpClient.deleteCatalogLocationById(locationId);
540
+ }
541
+ return {
542
+ statusCode: 204,
543
+ responseBody: void 0
544
+ };
545
+ }
546
+
547
+ exports.createImportJobs = createImportJobs;
548
+ exports.deleteImportByRepo = deleteImportByRepo;
549
+ exports.findAllImports = findAllImports;
550
+ exports.findImportStatusByRepo = findImportStatusByRepo;
551
+ //# sourceMappingURL=bulkImports.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulkImports.cjs.js","sources":["../../../../src/service/handlers/import/bulkImports.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { AuthService, LoggerService } from '@backstage/backend-plugin-api';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport type { Config } from '@backstage/config';\n\nimport gitUrlParse from 'git-url-parse';\n\nimport { CatalogHttpClient } from '../../../catalog/catalogHttpClient';\nimport type { CatalogInfoGenerator } from '../../../catalog/catalogInfoGenerator';\nimport {\n getCatalogFilename,\n getCatalogUrl,\n} from '../../../catalog/catalogUtils';\nimport type { Components, Paths } from '../../../generated/openapi';\nimport type { GithubApiService } from '../../../github';\nimport { logErrorIfNeeded, paginateArray } from '../../../helpers';\nimport {\n DefaultPageNumber,\n DefaultPageSize,\n type HandlerResponse,\n} from '../handlers';\n\ntype CreateImportDryRunStatus =\n | 'CATALOG_ENTITY_CONFLICT'\n | 'CATALOG_INFO_FILE_EXISTS_IN_REPO'\n | 'CODEOWNERS_FILE_NOT_FOUND_IN_REPO'\n | 'REPO_EMPTY';\n\ntype FindAllImportsResponse =\n | Components.Schemas.Import[]\n | Components.Schemas.ImportJobListV2;\n\nfunction sortImports(imports: Components.Schemas.Import[]) {\n imports.sort((a, b) => {\n if (a.repository?.name === undefined && b.repository?.name === undefined) {\n return 0;\n }\n if (a.repository?.name === undefined) {\n return -1;\n }\n if (b.repository?.name === undefined) {\n return 1;\n }\n return a.repository.name.localeCompare(b.repository.name);\n });\n}\n\nexport async function findAllImports(\n deps: {\n logger: LoggerService;\n config: Config;\n githubApiService: GithubApiService;\n catalogHttpClient: CatalogHttpClient;\n },\n requestHeaders?: {\n apiVersion?: Paths.FindAllImports.Parameters.ApiVersion;\n },\n queryParams?: {\n search?: string;\n pageNumber?: number;\n pageSize?: number;\n },\n): Promise<HandlerResponse<FindAllImportsResponse>> {\n const apiVersion = requestHeaders?.apiVersion ?? 'v1';\n const search = queryParams?.search;\n const pageNumber = queryParams?.pageNumber ?? DefaultPageNumber;\n const pageSize = queryParams?.pageSize ?? DefaultPageSize;\n\n deps.logger.debug(\n `Getting all bulk import jobs (apiVersion=${apiVersion}, search=${search}, page=${pageNumber}, size=${pageSize})..`,\n );\n\n const catalogFilename = getCatalogFilename(deps.config);\n\n const allLocations = (\n await deps.catalogHttpClient.listCatalogUrlLocations(\n search,\n pageNumber,\n pageSize,\n )\n ).targetUrls;\n\n // resolve default branches for each unique repo URL from GH,\n // because we cannot easily determine that from the location target URL.\n // It can be 'main' or something more convoluted like 'our/awesome/main'.\n const defaultBranchByRepoUrl = await resolveReposDefaultBranches(\n deps.logger,\n deps.githubApiService,\n allLocations,\n catalogFilename,\n );\n\n // filter out locations that do not match what we are expecting, i.e.:\n // an URL to a catalog-info YAML file at the root of the repo\n const importCandidates = findImportCandidates(\n allLocations,\n defaultBranchByRepoUrl,\n catalogFilename,\n );\n\n // Keep only repos that are accessible from the configured GH integrations\n const importsReachableFromGHIntegrations =\n await deps.githubApiService.filterLocationsAccessibleFromIntegrations(\n importCandidates,\n );\n\n // now fetch the import statuses in different promises\n const importStatusPromises: Promise<\n HandlerResponse<Components.Schemas.Import>\n >[] = [];\n for (const loc of importsReachableFromGHIntegrations) {\n const repoUrl = repoUrlFromLocation(loc);\n if (!repoUrl) {\n continue;\n }\n\n importStatusPromises.push(\n findImportStatusByRepo(\n deps,\n repoUrl,\n defaultBranchByRepoUrl.get(repoUrl),\n false,\n ),\n );\n }\n\n const result = await Promise.all(importStatusPromises);\n const imports = result\n .filter(res => res.responseBody)\n .map(res => res.responseBody!);\n\n // sorting the output to make it deterministic and easy to navigate in the UI\n sortImports(imports);\n\n const paginated = paginateArray(imports, pageNumber, pageSize);\n if (apiVersion === 'v1') {\n return {\n statusCode: 200,\n responseBody: paginated.result,\n };\n }\n return {\n statusCode: 200,\n responseBody: {\n imports: paginated.result,\n totalCount: paginated.totalCount,\n page: pageNumber,\n size: pageSize,\n },\n };\n}\n\nasync function resolveReposDefaultBranches(\n logger: LoggerService,\n githubApiService: GithubApiService,\n allLocations: string[],\n catalogFilename: string,\n) {\n const defaultBranchByRepoUrlPromises: Promise<{\n repoUrl: string;\n defaultBranch?: string;\n }>[] = [];\n for (const loc of allLocations) {\n // loc has the following format: https://github.com/<org>/<repo>/blob/<default-branch>/catalog-info.yaml\n // but it can have a more convoluted format like 'https://github.com/janus-idp/backstage-plugins/blob/main/plugins/scaffolder-annotator-action/examples/templates/01-scaffolder-template.yaml'\n // if registered manually from the 'Register existing component' feature in Backstage.\n if (!loc.endsWith(catalogFilename)) {\n logger.debug(\n `Ignored location ${loc} because it does not point to a file named ${catalogFilename}`,\n );\n continue;\n }\n const repoUrl = repoUrlFromLocation(loc);\n if (!repoUrl) {\n continue;\n }\n defaultBranchByRepoUrlPromises.push(\n githubApiService\n .getRepositoryFromIntegrations(repoUrl)\n .then(resp => {\n return { repoUrl, defaultBranch: resp?.repository?.default_branch };\n })\n .catch((err: any) => {\n logErrorIfNeeded(\n logger,\n `Ignored repo ${repoUrl} due to an error while fetching details from GitHub`,\n err,\n );\n return {\n repoUrl,\n defaultBranch: undefined,\n };\n }),\n );\n }\n const defaultBranchesResponses = await Promise.all(\n defaultBranchByRepoUrlPromises,\n );\n return new Map(\n defaultBranchesResponses\n .flat()\n .filter(r => r.defaultBranch)\n .map(r => [r.repoUrl, r.defaultBranch!]),\n );\n}\n\nfunction repoUrlFromLocation(loc: string) {\n const split = loc.split('/blob/');\n if (split.length < 2) {\n return undefined;\n }\n return split[0];\n}\n\nfunction findImportCandidates(\n allLocations: string[],\n defaultBranchByRepoUrl: Map<string, string>,\n catalogFilename: string,\n) {\n const filteredLocations: string[] = [];\n for (const loc of allLocations) {\n const repoUrl = repoUrlFromLocation(loc);\n if (!repoUrl) {\n continue;\n }\n\n const defaultBranch = defaultBranchByRepoUrl.get(repoUrl);\n if (!defaultBranch) {\n continue;\n }\n if (loc !== `${repoUrl}/blob/${defaultBranch}/${catalogFilename}`) {\n // Because users can use the \"Register existing component\" workflow to register a Location\n // using any file path in the repo, we consider a repository as an Import Location only\n // if it is at the root of the repository, because that is what the import PR ultimately does.\n continue;\n }\n filteredLocations.push(loc);\n }\n return filteredLocations;\n}\n\nasync function createPR(\n githubApiService: GithubApiService,\n logger: LoggerService,\n req: Components.Schemas.ImportRequest,\n gitUrl: gitUrlParse.GitUrl,\n catalogInfoGenerator: CatalogInfoGenerator,\n config: Config,\n) {\n const appTitle =\n config.getOptionalString('app.title') ?? 'Red Hat Developer Hub';\n const appBaseUrl = config.getString('app.baseUrl');\n const catalogFileName = getCatalogFilename(config);\n return await githubApiService.submitPrToRepo(logger, {\n repoUrl: req.repository.url,\n gitUrl: gitUrl,\n defaultBranch: req.repository.defaultBranch,\n catalogInfoContent:\n req.catalogInfoContent ??\n (await catalogInfoGenerator.generateDefaultCatalogInfoContent(\n req.repository.url,\n )),\n prTitle: req.github?.pullRequest?.title ?? `Add ${catalogFileName}`,\n prBody:\n req.github?.pullRequest?.body ??\n `\nThis pull request adds a **Backstage entity metadata file** to this repository so that the component can be added to a Backstage application.\n\nAfter this pull request is merged, the component will become available in the [${appTitle} software catalog](${appBaseUrl}).\n\nFor more information, read an [overview of the Backstage software catalog](https://backstage.io/docs/features/software-catalog/).\n`,\n });\n}\n\nasync function handleAddedReposFromCreateImportJobs(\n deps: {\n logger: LoggerService;\n config: Config;\n auth: AuthService;\n catalogApi: CatalogApi;\n githubApiService: GithubApiService;\n catalogInfoGenerator: CatalogInfoGenerator;\n catalogHttpClient: CatalogHttpClient;\n },\n importRequests: Components.Schemas.ImportRequest[],\n) {\n const result: Components.Schemas.Import[] = [];\n\n for (const req of importRequests) {\n // Check if repo is already imported\n const repoCatalogUrl = getCatalogUrl(\n deps.config,\n req.repository.url,\n req.repository.defaultBranch,\n );\n const hasLocation = await deps.catalogHttpClient.verifyLocationExistence(\n repoCatalogUrl,\n );\n if (!hasLocation) {\n continue;\n }\n const hasCatalogInfoFileInRepo = await deps.githubApiService.hasFileInRepo({\n repoUrl: req.repository.url,\n defaultBranch: req.repository.defaultBranch,\n fileName: getCatalogFilename(deps.config),\n });\n if (!hasCatalogInfoFileInRepo) {\n continue;\n }\n\n const ghRepo = await deps.githubApiService.getRepositoryFromIntegrations(\n req.repository.url,\n );\n\n // Force a refresh of the Location, so that the entities from the catalog-info.yaml can show up quickly (not guaranteed however).\n await deps.catalogHttpClient.refreshLocationByRepoUrl(\n req.repository.url,\n req.repository.defaultBranch,\n );\n\n const gitUrl = gitUrlParse(req.repository.url);\n result.push({\n status: 'ADDED',\n lastUpdate: ghRepo?.repository?.updated_at ?? undefined,\n repository: {\n url: req.repository.url,\n name: gitUrl.name,\n organization: gitUrl.organization,\n },\n });\n }\n return result;\n}\n\nasync function handlePrCreationRequest(\n deps: {\n logger: LoggerService;\n config: Config;\n auth: AuthService;\n catalogApi: CatalogApi;\n githubApiService: GithubApiService;\n catalogInfoGenerator: CatalogInfoGenerator;\n catalogHttpClient: CatalogHttpClient;\n },\n req: Components.Schemas.ImportRequest,\n gitUrl: gitUrlParse.GitUrl,\n): Promise<Components.Schemas.Import> {\n const repoCatalogUrl = getCatalogUrl(\n deps.config,\n req.repository.url,\n req.repository.defaultBranch,\n );\n const prToRepo = await createPR(\n deps.githubApiService,\n deps.logger,\n req,\n gitUrl,\n deps.catalogInfoGenerator,\n deps.config,\n );\n if (prToRepo.errors && prToRepo.errors.length > 0) {\n return {\n errors: prToRepo.errors,\n status: 'PR_ERROR',\n repository: req.repository,\n };\n }\n if (prToRepo.prUrl) {\n deps.logger.debug(`Created new PR from request: ${prToRepo.prUrl}`);\n }\n\n // Create Location\n await deps.catalogHttpClient.possiblyCreateLocation(repoCatalogUrl);\n\n if (prToRepo.hasChanges === false) {\n deps.logger.debug(\n `No bulk import PR created on ${req.repository.url} since its default branch (${req.repository.defaultBranch}) already contains a catalog-info file`,\n );\n\n // Force a refresh of the Location, so that the entities from the catalog-info.yaml can show up quickly (not guaranteed however).\n await deps.catalogHttpClient.refreshLocationByRepoUrl(\n req.repository.url,\n req.repository.defaultBranch,\n );\n return {\n status: 'ADDED',\n lastUpdate: prToRepo.lastUpdate,\n repository: {\n url: req.repository.url,\n name: gitUrl.name,\n organization: gitUrl.organization,\n },\n };\n }\n\n return {\n errors: prToRepo.errors,\n status: 'WAIT_PR_APPROVAL',\n lastUpdate: prToRepo.lastUpdate,\n repository: {\n url: req.repository.url,\n name: gitUrl.name,\n organization: gitUrl.organization,\n },\n github: {\n pullRequest: {\n url: prToRepo.prUrl,\n number: prToRepo.prNumber,\n },\n },\n };\n}\n\nexport async function createImportJobs(\n deps: {\n logger: LoggerService;\n config: Config;\n auth: AuthService;\n catalogApi: CatalogApi;\n githubApiService: GithubApiService;\n catalogInfoGenerator: CatalogInfoGenerator;\n catalogHttpClient: CatalogHttpClient;\n },\n reqParams: {\n importRequests: Paths.CreateImportJobs.RequestBody;\n dryRun?: boolean;\n },\n): Promise<\n HandlerResponse<Components.Schemas.Import[] | { errors: string[] }>\n> {\n const dryRun = reqParams.dryRun ?? false;\n const importRequests = reqParams.importRequests;\n deps.logger.debug(\n `Handling request to import ${importRequests?.length} repo(s) (dryRun=${dryRun})..`,\n );\n\n if (importRequests.length === 0) {\n deps.logger.debug('Missing import requests from request body');\n return {\n statusCode: 400,\n responseBody: [],\n };\n }\n\n if (dryRun) {\n return {\n statusCode: 202,\n responseBody: await dryRunCreateImportJobs(deps, importRequests),\n };\n }\n\n const result: Components.Schemas.Import[] = [];\n\n const addedRepos = await handleAddedReposFromCreateImportJobs(\n deps,\n importRequests,\n );\n result.push(...addedRepos);\n const addedReposMap = new Map(\n addedRepos.map(res => [res.repository?.url, res]),\n );\n const remainingRequests = importRequests.filter(\n req => !addedReposMap.has(req.repository.url),\n );\n\n for (const req of remainingRequests) {\n const gitUrl = gitUrlParse(req.repository.url);\n\n // Create PR\n try {\n result.push(await handlePrCreationRequest(deps, req, gitUrl));\n } catch (error: any) {\n result.push({\n errors: [error.message],\n status: 'PR_ERROR',\n repository: {\n url: req.repository.url,\n name: gitUrl.name,\n organization: gitUrl.organization,\n },\n } as Components.Schemas.Import);\n }\n }\n\n sortImports(result);\n\n return {\n statusCode: 202,\n responseBody: result,\n };\n}\n\nasync function dryRunCreateImportJobs(\n deps: {\n logger: LoggerService;\n config: Config;\n auth: AuthService;\n catalogApi: CatalogApi;\n githubApiService: GithubApiService;\n catalogInfoGenerator: CatalogInfoGenerator;\n catalogHttpClient: CatalogHttpClient;\n },\n importRequests: Paths.CreateImportJobs.RequestBody,\n) {\n const result: Components.Schemas.Import[] = [];\n for (const req of importRequests) {\n const gitUrl = gitUrlParse(req.repository.url);\n\n const dryRunChecks = await performDryRunChecks(deps, req);\n if (dryRunChecks.errors?.length > 0) {\n deps.logger.warn(\n `Errors while performing dry-run checks: ${dryRunChecks.errors}`,\n );\n }\n result.push({\n errors: dryRunChecks.dryRunStatuses,\n catalogEntityName: req.catalogEntityName,\n repository: {\n url: req.repository.url,\n name: gitUrl.name,\n organization: gitUrl.organization,\n },\n });\n }\n return result;\n}\n\nasync function performDryRunChecks(\n deps: {\n logger: LoggerService;\n auth: AuthService;\n catalogApi: CatalogApi;\n config: Config;\n githubApiService: GithubApiService;\n catalogHttpClient: CatalogHttpClient;\n },\n req: Components.Schemas.ImportRequest,\n): Promise<{ dryRunStatuses: CreateImportDryRunStatus[]; errors: string[] }> {\n const checkCatalog = async (\n catalogEntityName: string,\n ): Promise<{\n dryRunStatuses?: CreateImportDryRunStatus[];\n errors?: string[];\n }> => {\n const hasEntity = await deps.catalogHttpClient.hasEntityInCatalog(\n catalogEntityName,\n );\n if (hasEntity) {\n return { dryRunStatuses: ['CATALOG_ENTITY_CONFLICT'] };\n }\n return {};\n };\n\n const checkEmptyRepo = async (): Promise<{\n dryRunStatuses?: CreateImportDryRunStatus[];\n errors?: string[];\n }> => {\n const empty = await deps.githubApiService.isRepoEmpty({\n repoUrl: req.repository.url,\n });\n if (empty) {\n return {\n dryRunStatuses: ['REPO_EMPTY'],\n };\n }\n return {};\n };\n\n const checkCatalogInfoPresenceInRepo = async (): Promise<{\n dryRunStatuses?: CreateImportDryRunStatus[];\n errors?: string[];\n }> => {\n const exists = await deps.githubApiService.hasFileInRepo({\n repoUrl: req.repository.url,\n defaultBranch: req.repository.defaultBranch,\n fileName: getCatalogFilename(deps.config),\n });\n if (exists) {\n return {\n dryRunStatuses: ['CATALOG_INFO_FILE_EXISTS_IN_REPO'],\n };\n }\n return {};\n };\n\n const checkCodeOwnersFileInRepo = async (): Promise<{\n dryRunStatuses?: CreateImportDryRunStatus[];\n errors?: string[];\n }> => {\n const exists = await deps.githubApiService.hasFileInRepo({\n repoUrl: req.repository.url,\n defaultBranch: req.repository.defaultBranch,\n fileName: '.github/CODEOWNERS',\n });\n if (!exists) {\n return {\n dryRunStatuses: ['CODEOWNERS_FILE_NOT_FOUND_IN_REPO'],\n };\n }\n return {};\n };\n\n const dryRunStatuses: CreateImportDryRunStatus[] = [];\n const errors: string[] = [];\n const allChecksFn = [checkEmptyRepo(), checkCatalogInfoPresenceInRepo()];\n if (req.catalogEntityName?.trim()) {\n allChecksFn.push(checkCatalog(req.catalogEntityName));\n }\n if (req.codeOwnersFileAsEntityOwner) {\n allChecksFn.push(checkCodeOwnersFileInRepo());\n }\n const allChecks = await Promise.all(allChecksFn);\n allChecks.flat().forEach(res => {\n if (res.dryRunStatuses) {\n dryRunStatuses.push(...res.dryRunStatuses);\n }\n if (res.errors) {\n errors.push(...res.errors);\n }\n });\n\n dryRunStatuses.sort((a, b) => a.localeCompare(b));\n\n return {\n dryRunStatuses,\n errors,\n };\n}\n\nexport async function findImportStatusByRepo(\n deps: {\n logger: LoggerService;\n config: Config;\n githubApiService: GithubApiService;\n catalogHttpClient: CatalogHttpClient;\n },\n repoUrl: string,\n defaultBranch?: string,\n includeCatalogInfoContent?: boolean,\n): Promise<HandlerResponse<Components.Schemas.Import>> {\n deps.logger.debug(`Getting bulk import job status for ${repoUrl}..`);\n\n const gitUrl = gitUrlParse(repoUrl);\n\n const errors: string[] = [];\n const result = {\n id: repoUrl,\n repository: {\n url: repoUrl,\n name: gitUrl.name,\n organization: gitUrl.organization,\n id: `${gitUrl.organization}/${gitUrl.name}`,\n defaultBranch,\n },\n approvalTool: 'GIT',\n status: null,\n } as Components.Schemas.Import;\n try {\n // Check to see if there are any PR\n const openImportPr = await deps.githubApiService.findImportOpenPr(\n deps.logger,\n {\n repoUrl: repoUrl,\n includeCatalogInfoContent,\n },\n );\n if (!openImportPr.prUrl) {\n const catalogLocations = (\n await deps.catalogHttpClient.listCatalogUrlLocations()\n ).targetUrls;\n const catalogUrl = getCatalogUrl(deps.config, repoUrl, defaultBranch);\n let exists = false;\n for (const loc of catalogLocations) {\n if (loc === catalogUrl) {\n exists = true;\n break;\n }\n }\n if (\n exists &&\n (await deps.githubApiService.hasFileInRepo({\n repoUrl,\n defaultBranch,\n fileName: getCatalogFilename(deps.config),\n }))\n ) {\n result.status = 'ADDED';\n // Force a refresh of the Location, so that the entities from the catalog-info.yaml can show up quickly (not guaranteed however).\n await deps.catalogHttpClient.refreshLocationByRepoUrl(\n repoUrl,\n defaultBranch,\n );\n }\n // No import PR => let's determine last update from the repository\n const ghRepo = await deps.githubApiService.getRepositoryFromIntegrations(\n repoUrl,\n );\n result.lastUpdate = ghRepo.repository?.updated_at ?? undefined;\n return {\n statusCode: 200,\n responseBody: result,\n };\n }\n result.status = 'WAIT_PR_APPROVAL';\n result.github = {\n pullRequest: {\n number: openImportPr.prNum,\n url: openImportPr.prUrl,\n title: openImportPr.prTitle,\n body: openImportPr.prBody,\n catalogInfoContent: openImportPr.prCatalogInfoContent,\n },\n };\n result.lastUpdate = openImportPr.lastUpdate;\n } catch (error: any) {\n errors.push(error.message);\n result.errors = errors;\n if (error.message?.includes('Not Found')) {\n return {\n statusCode: 404,\n responseBody: result,\n };\n }\n result.status = 'PR_ERROR';\n }\n\n return {\n statusCode: 200,\n responseBody: result,\n };\n}\n\nexport async function deleteImportByRepo(\n deps: {\n logger: LoggerService;\n config: Config;\n githubApiService: GithubApiService;\n catalogHttpClient: CatalogHttpClient;\n },\n repoUrl: string,\n defaultBranch?: string,\n): Promise<HandlerResponse<void>> {\n deps.logger.debug(`Deleting bulk import job status for ${repoUrl}..`);\n\n // Check to see if there are any PR\n const openImportPr = await deps.githubApiService.findImportOpenPr(\n deps.logger,\n {\n repoUrl: repoUrl,\n },\n );\n const gitUrl = gitUrlParse(repoUrl);\n if (openImportPr.prUrl) {\n // Close PR\n const appTitle =\n deps.config.getOptionalString('app.title') ?? 'Red Hat Developer Hub';\n const appBaseUrl = deps.config.getString('app.baseUrl');\n await deps.githubApiService.closeImportPR(deps.logger, {\n repoUrl,\n gitUrl,\n comment: `Closing PR upon request for bulk import deletion. This request was created from [${appTitle}](${appBaseUrl}).`,\n });\n }\n // Also delete the import branch, so that it is not outdated if we try later to import the repo again\n await deps.githubApiService.deleteImportBranch({\n repoUrl,\n gitUrl,\n });\n // Remove Location from catalog\n const catalogUrl = getCatalogUrl(deps.config, repoUrl, defaultBranch);\n const findLocationFrom = (list: { id?: string; target: string }[]) => {\n for (const loc of list) {\n if (loc.target === catalogUrl) {\n return loc.id;\n }\n }\n return undefined;\n };\n\n const locationId = findLocationFrom(\n (\n await deps.catalogHttpClient.listCatalogUrlLocationsByIdFromLocationsEndpoint()\n ).locations,\n );\n if (locationId) {\n await deps.catalogHttpClient.deleteCatalogLocationById(locationId);\n }\n\n return {\n statusCode: 204,\n responseBody: undefined,\n };\n}\n"],"names":["DefaultPageNumber","DefaultPageSize","getCatalogFilename","paginateArray","logErrorIfNeeded","getCatalogUrl","gitUrlParse"],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+
3
+ var catalogUtils = require('../../../catalog/catalogUtils.cjs.js');
4
+
5
+ async function getImportStatusFromLocations(deps, repoUrl, catalogUrlLocations, defaultBranch) {
6
+ return getImportStatusWithCheckerFn(
7
+ deps,
8
+ repoUrl,
9
+ async (catalogUrl) => {
10
+ for (const loc of catalogUrlLocations) {
11
+ if (catalogUrl === loc) {
12
+ return true;
13
+ }
14
+ }
15
+ return false;
16
+ },
17
+ defaultBranch
18
+ );
19
+ }
20
+ async function getImportStatusWithCheckerFn(deps, repoUrl, catalogExistenceCheckFn, defaultBranch) {
21
+ const openImportPr = await deps.githubApiService.findImportOpenPr(
22
+ deps.logger,
23
+ {
24
+ repoUrl
25
+ }
26
+ );
27
+ if (!openImportPr.prUrl) {
28
+ const existsInCatalog = await catalogExistenceCheckFn(
29
+ catalogUtils.getCatalogUrl(deps.config, repoUrl, defaultBranch)
30
+ );
31
+ const existsInRepo = await deps.githubApiService.hasFileInRepo({
32
+ repoUrl,
33
+ defaultBranch,
34
+ fileName: catalogUtils.getCatalogFilename(deps.config)
35
+ });
36
+ if (existsInCatalog && existsInRepo) {
37
+ await deps.catalogHttpClient.refreshLocationByRepoUrl(
38
+ repoUrl,
39
+ defaultBranch
40
+ );
41
+ return { status: "ADDED" };
42
+ }
43
+ return null;
44
+ }
45
+ return { status: "WAIT_PR_APPROVAL", lastUpdate: openImportPr.lastUpdate };
46
+ }
47
+
48
+ exports.getImportStatusFromLocations = getImportStatusFromLocations;
49
+ //# sourceMappingURL=importStatus.cjs.js.map