@red-hat-developer-hub/backstage-plugin-bulk-import-backend 6.3.0 → 6.4.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 (46) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +28 -0
  3. package/config.d.ts +9 -1
  4. package/dist/catalog/catalogHttpClient.cjs.js +2 -0
  5. package/dist/catalog/catalogHttpClient.cjs.js.map +1 -1
  6. package/dist/catalog/catalogInfoGenerator.cjs.js +1 -0
  7. package/dist/catalog/catalogInfoGenerator.cjs.js.map +1 -1
  8. package/dist/database/migration.cjs.js +20 -0
  9. package/dist/database/migration.cjs.js.map +1 -0
  10. package/dist/database/repositoryDao.cjs.js +117 -0
  11. package/dist/database/repositoryDao.cjs.js.map +1 -0
  12. package/dist/generated/openapidocument.cjs.js +321 -72
  13. package/dist/generated/openapidocument.cjs.js.map +1 -1
  14. package/dist/github/githubApiService.cjs.js +217 -91
  15. package/dist/github/githubApiService.cjs.js.map +1 -1
  16. package/dist/github/utils/orgUtils.cjs.js +1 -0
  17. package/dist/github/utils/orgUtils.cjs.js.map +1 -1
  18. package/dist/github/utils/prUtils.cjs.js +2 -0
  19. package/dist/github/utils/prUtils.cjs.js.map +1 -1
  20. package/dist/github/utils/repoUtils.cjs.js +1 -38
  21. package/dist/github/utils/repoUtils.cjs.js.map +1 -1
  22. package/dist/github/utils/utils.cjs.js +39 -1
  23. package/dist/github/utils/utils.cjs.js.map +1 -1
  24. package/dist/gitlab/gitlabApiService.cjs.js +102 -0
  25. package/dist/gitlab/gitlabApiService.cjs.js.map +1 -1
  26. package/dist/gitlab/utils/prUtils.cjs.js +1 -0
  27. package/dist/gitlab/utils/prUtils.cjs.js.map +1 -1
  28. package/dist/gitlab/utils/utils.cjs.js +1 -0
  29. package/dist/gitlab/utils/utils.cjs.js.map +1 -1
  30. package/dist/helpers/utils.cjs.js +21 -0
  31. package/dist/helpers/utils.cjs.js.map +1 -1
  32. package/dist/index.d.ts +2 -1
  33. package/dist/plugin.cjs.js +6 -3
  34. package/dist/plugin.cjs.js.map +1 -1
  35. package/dist/service/handlers/import/bulkImports.cjs.js +155 -2
  36. package/dist/service/handlers/import/bulkImports.cjs.js.map +1 -1
  37. package/dist/service/handlers/import/execute-template.cjs.js +264 -0
  38. package/dist/service/handlers/import/execute-template.cjs.js.map +1 -0
  39. package/dist/service/handlers/import/importStatus.cjs.js +1 -1
  40. package/dist/service/handlers/import/importStatus.cjs.js.map +1 -1
  41. package/dist/service/handlers/repository/repositories.cjs.js +1 -0
  42. package/dist/service/handlers/repository/repositories.cjs.js.map +1 -1
  43. package/dist/service/router.cjs.js +179 -24
  44. package/dist/service/router.cjs.js.map +1 -1
  45. package/migrations/20250808122501_migrations.js +53 -0
  46. package/package.json +8 -3
@@ -1 +1 @@
1
- {"version":3,"file":"gitlabApiService.cjs.js","sources":["../../src/gitlab/gitlabApiService.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 {\n CacheService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport {\n GitLabIntegrationConfig,\n ScmIntegrations,\n} from '@backstage/integration';\n\nimport { Gitlab } from '@gitbeaker/rest';\nimport gitUrlParse from 'git-url-parse';\n\nimport { getBranchName, getCatalogFilename } from '../catalog/catalogUtils';\nimport {\n computeTotalCount,\n extractLocationOwnerMap,\n logErrorIfNeeded,\n} from '../helpers';\nimport {\n DefaultPageNumber,\n DefaultPageSize,\n} from '../service/handlers/handlers';\nimport { CustomGitlabCredentialsProvider } from './GitlabAppManager';\nimport {\n ExtendedGitlabCredentials,\n GitlabFetchError,\n GitlabOrganization,\n GitlabOrganizationResponse,\n GitlabRepository,\n GitlabRepositoryResponse,\n} from './types';\nimport { buildGitlab } from './utils/glUtils';\nimport { addGitlabTokenGroups } from './utils/orgUtils';\nimport { closePRWithComment, findOpenPRForBranch } from './utils/prUtils';\nimport {\n addGitlabTokenOrgRepositories,\n addGitlabTokenRepositories,\n createOrUpdateFileInBranch,\n fileExistsInDefaultBranch,\n ValidatedRepo,\n} from './utils/repoUtils';\nimport {\n executeFunctionOnFirstSuccessfulIntegration,\n fetchFromAllIntegrations,\n getCredentialsForConfig,\n} from './utils/utils';\n\nexport class GitlabApiService {\n private readonly logger: LoggerService;\n private readonly integrations: ScmIntegrations;\n private readonly gitlabCredentialsProvider: CustomGitlabCredentialsProvider;\n private readonly config: Config;\n // Cache for storing ETags (used for efficient caching of unchanged data returned by GitHub)\n private readonly cache: CacheService;\n constructor(\n logger: LoggerService,\n config: Config,\n cacheService: CacheService,\n ) {\n this.logger = logger;\n this.config = config;\n this.integrations = ScmIntegrations.fromConfig(config);\n this.gitlabCredentialsProvider =\n CustomGitlabCredentialsProvider.fromIntegrations(this.integrations);\n this.cache = cacheService;\n }\n\n async getRepositoryFromIntegrations(repoUrl: string): Promise<{\n repository?: GitlabRepository;\n errors?: GitlabFetchError[];\n }> {\n const gitUrl = gitUrlParse(repoUrl);\n\n const glConfig = this.integrations.gitlab.byUrl(repoUrl)?.config;\n if (!glConfig) {\n throw new Error(\n `No Gitlab integration config found for repo ${repoUrl}. Please add a configuration entry under 'integrations.gitlab`,\n );\n }\n\n const credentials = await getCredentialsForConfig(\n this.gitlabCredentialsProvider,\n glConfig,\n );\n let repository: GitlabRepository | undefined = undefined;\n for (const credential of credentials) {\n const glKit = buildGitlab(\n {\n logger: this.logger,\n cache: this.cache,\n },\n { credential, owner: gitUrl.owner },\n glConfig.baseUrl,\n );\n const repo = await glKit.Projects.show(`${gitUrl.owner}/${gitUrl.name}`);\n if (!repo) {\n continue;\n }\n repository = {\n name: repo.name,\n full_name: repo.path_with_namespace,\n url: repo._links.self,\n html_url: repo.web_url,\n default_branch: repo.default_branch,\n updated_at: repo.updated_at,\n };\n break;\n }\n\n return {\n repository,\n errors: [],\n };\n }\n\n async getOrganizationsFromIntegrations(\n search?: string,\n pageNumber: number = DefaultPageNumber,\n pageSize: number = DefaultPageSize,\n ): Promise<GitlabOrganizationResponse> {\n const groups = new Map<string, GitlabOrganization>();\n const result = await fetchFromAllIntegrations(\n {\n logger: this.logger,\n cache: this.cache,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n dataFetcher: async (\n glApi: InstanceType<typeof Gitlab<false>>,\n credential: ExtendedGitlabCredentials,\n glConfig: GitLabIntegrationConfig,\n ) => {\n const dataFetchErrors = new Map<number, GitlabFetchError>();\n const resp = await addGitlabTokenGroups(\n {\n logger: this.logger,\n },\n glApi,\n credential,\n {\n search,\n groups,\n pageNumber,\n pageSize,\n errors: dataFetchErrors,\n },\n );\n this.logger.debug(\n `Got ${resp.totalCount} groups(s) for ${glConfig.host}`,\n );\n return {\n result: resp.totalCount ?? 0,\n errors: Array.from(dataFetchErrors.values()),\n };\n },\n },\n );\n\n const groupList = Array.from(groups.values());\n const totalCount = computeTotalCount(groupList, result.data, pageSize);\n return {\n organizations: groupList,\n errors: Array.from(result.errors?.values() ?? []),\n totalCount,\n };\n }\n\n async getOrgRepositoriesFromIntegrations(\n orgName: string,\n search?: string,\n pageNumber: number = DefaultPageNumber,\n pageSize: number = DefaultPageSize,\n ): Promise<GitlabRepositoryResponse> {\n const orgRepositories = new Map<string, GitlabRepository>();\n const result = await fetchFromAllIntegrations(\n {\n logger: this.logger,\n cache: this.cache,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n dataFetcher: async (\n glApi: InstanceType<typeof Gitlab<false>>,\n credential: ExtendedGitlabCredentials,\n glConfig: GitLabIntegrationConfig,\n ) => {\n const dataFetchErrors = new Map<number, GitlabFetchError>();\n const resp = await addGitlabTokenOrgRepositories(\n {\n logger: this.logger,\n },\n glApi,\n credential,\n orgName,\n orgRepositories,\n dataFetchErrors,\n {\n search,\n pageNumber,\n pageSize,\n },\n );\n this.logger.debug(\n `Got ${resp.totalCount} org repo(s) for ${glConfig.host}`,\n );\n return {\n stopFetchingData: true,\n result: resp.totalCount ?? 0,\n errors: Array.from(dataFetchErrors.values()),\n };\n },\n },\n );\n\n const repoList = Array.from(orgRepositories.values());\n const totalCount = computeTotalCount(repoList, result.data, pageSize);\n return {\n repositories: repoList,\n errors: Array.from(result.errors?.values() ?? []),\n totalCount,\n };\n }\n\n /**\n * Returns GitlabRepositoryResponse containing:\n * - a list of unique repositories the gitlab integrations have access to\n * - a list of errors encountered by each token (if any exist)\n */\n async getRepositoriesFromIntegrations(\n search?: string,\n pageNumber: number = DefaultPageNumber,\n pageSize: number = DefaultPageSize,\n ): Promise<GitlabRepositoryResponse> {\n const repositories = new Map<string, GitlabRepository>();\n const result = await fetchFromAllIntegrations(\n {\n logger: this.logger,\n cache: this.cache,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n dataFetcher: async (\n glApi: InstanceType<typeof Gitlab<false>>,\n credential: ExtendedGitlabCredentials,\n glConfig: GitLabIntegrationConfig,\n ) => {\n const dataFetchErrors = new Map<number, GitlabFetchError>();\n const resp = await addGitlabTokenRepositories(\n {\n logger: this.logger,\n },\n glApi,\n credential,\n repositories,\n dataFetchErrors,\n {\n search,\n pageNumber,\n pageSize,\n },\n );\n this.logger.debug(\n `Got ${resp.totalCount} repo(s) for ${glConfig.host}`,\n );\n return {\n result: resp.totalCount ?? 0,\n errors: Array.from(dataFetchErrors.values()),\n };\n },\n },\n );\n\n const repoList = Array.from(repositories.values());\n const totalCount = computeTotalCount(repoList, result.data, pageSize);\n return {\n repositories: repoList,\n errors: Array.from(result.errors?.values() ?? []),\n totalCount,\n };\n }\n\n async filterLocationsAccessibleFromIntegrations(\n locationUrls: string[],\n ): Promise<string[]> {\n const locationGitOwnerMap = extractLocationOwnerMap(locationUrls);\n\n const allAccessibleTokenOrgs = new Set<string>();\n const allAccessibleUsernames = new Set<string>();\n await fetchFromAllIntegrations(\n {\n logger: this.logger,\n cache: this.cache,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n dataFetcher: async (gitlab: InstanceType<typeof Gitlab<false>>) => {\n // find authenticated gitlab owner...\n const username = (await gitlab.Users.showCurrentUser()).username;\n if (username) {\n allAccessibleUsernames.add(username);\n }\n // ... along with orgs accessible from the token auth\n\n const allGroups = await gitlab.Groups.all<false, 'offset'>({\n allAvailable: false,\n });\n allGroups\n .map(org => org.path)\n ?.forEach((orgName: string) => allAccessibleTokenOrgs.add(orgName));\n return {};\n },\n },\n );\n\n return locationUrls.filter(loc => {\n if (!locationGitOwnerMap.has(loc)) {\n return false;\n }\n const owner = locationGitOwnerMap.get(loc)!;\n return (\n allAccessibleTokenOrgs.has(owner) || allAccessibleUsernames.has(owner)\n );\n });\n }\n\n async findImportOpenPr(\n logger: LoggerService,\n input: {\n repoUrl: string;\n includeCatalogInfoContent?: boolean;\n },\n ): Promise<{\n prNum?: number;\n prUrl?: string;\n prTitle?: string;\n prBody?: string;\n prCatalogInfoContent?: string;\n lastUpdate?: string;\n }> {\n const glConfig = this.integrations.gitlab.byUrl(input.repoUrl)?.config;\n if (!glConfig) {\n throw new Error(`Could not find GL integration from ${input.repoUrl}`);\n }\n\n const gitUrl = gitUrlParse(input.repoUrl);\n const owner = gitUrl.organization;\n const repo = gitUrl.name;\n\n const credentials = await this.gitlabCredentialsProvider.getAllCredentials({\n host: glConfig.host,\n });\n if (credentials.length === 0) {\n throw new Error(`No credentials for GL integration`);\n }\n\n const branchName = getBranchName(this.config);\n for (const credential of credentials) {\n const glKit = buildGitlab(\n {\n logger: this.logger,\n cache: this.cache,\n },\n { credential, owner },\n glConfig.baseUrl,\n );\n try {\n return await findOpenPRForBranch(\n logger,\n this.config,\n glKit,\n owner,\n repo,\n branchName,\n input.includeCatalogInfoContent,\n );\n } catch (error: any) {\n logErrorIfNeeded(this.logger, 'Error fetching pull requests', error);\n }\n }\n return {};\n }\n\n async submitPrToRepo(\n logger: LoggerService,\n input: {\n repoUrl: string;\n gitUrl: gitUrlParse.GitUrl;\n defaultBranch?: string;\n prTitle: string;\n prBody: string;\n catalogInfoContent: string;\n },\n ): Promise<{\n prUrl?: string;\n prNumber?: number;\n hasChanges?: boolean;\n lastUpdate?: string;\n errors?: string[];\n }> {\n const fileName = getCatalogFilename(this.config);\n const errors: any[] = [];\n\n const result = await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ): Promise<{\n successful: boolean;\n result?: {\n prUrl?: string;\n prNumber?: number;\n hasChanges?: boolean;\n lastUpdate?: string;\n };\n }> => {\n const { owner, repo, branchName } = validatedRepo;\n try {\n // Check if there is already a catalogInfo in the default branch\n const catalogInfoFileExists = await fileExistsInDefaultBranch(\n logger,\n gitlab,\n owner,\n repo,\n fileName,\n input.defaultBranch,\n );\n if (catalogInfoFileExists) {\n // No need to create a PR => component will be imported as is\n return {\n successful: true,\n result: {\n hasChanges: false,\n },\n };\n }\n\n const existingPrForBranch = await findOpenPRForBranch(\n logger,\n this.config,\n gitlab,\n owner,\n repo,\n branchName,\n );\n\n const repoData = await gitlab.Projects.show(`${owner}/${repo}`);\n\n const parentRef = await gitlab.Branches.show(\n `${owner}/${repo}`,\n repoData.default_branch,\n ); // This might not be neccesarry\n\n if (existingPrForBranch.prNum) {\n await createOrUpdateFileInBranch(\n gitlab,\n owner,\n repo,\n branchName,\n fileName,\n input.catalogInfoContent,\n );\n const pullRequestResponse = await gitlab.MergeRequests.edit(\n `${owner}/${repo}`,\n existingPrForBranch.prNum,\n {\n description: input.prBody,\n title: input.prTitle,\n targetBranch: repoData.default_branch,\n },\n );\n return {\n successful: true,\n result: {\n prNumber: existingPrForBranch.prNum,\n prUrl: pullRequestResponse.web_url,\n lastUpdate: pullRequestResponse.updated_at,\n },\n };\n }\n\n try {\n await gitlab.Branches.show(`${owner}/${repo}`, branchName);\n } catch (error: any) {\n if (error.cause.response.status === 404) {\n await gitlab.Branches.create(\n `${owner}/${repo}`,\n branchName,\n parentRef.name,\n );\n } else {\n throw error;\n }\n }\n\n // Might not be able to do this in the gitlab api\n // This is if the branch exists, but there wasn't a PR yet\n // if (branchExists) {\n // // update it in case it is outdated compared to the base branch\n // try {\n // await octo.repos.merge({\n // owner: owner,\n // repo: repo,\n // base: branchName,\n // head: repoData.data.default_branch,\n // });\n // } catch (error: any) {\n // logErrorIfNeeded(\n // this.logger,\n // `Could not merge default branch ${repoData.data.default_branch} into import branch ${branchName}`,\n // error,\n // );\n // }\n // }\n\n await createOrUpdateFileInBranch(\n gitlab,\n owner,\n repo,\n branchName,\n fileName,\n input.catalogInfoContent,\n );\n\n const pullRequestResponse = await gitlab.MergeRequests.create(\n `${owner}/${repo}`,\n branchName,\n repoData.default_branch,\n input.prTitle,\n {\n description: input.prBody,\n },\n );\n return {\n successful: true,\n result: {\n prNumber: pullRequestResponse.iid,\n prUrl: pullRequestResponse.web_url,\n lastUpdate: pullRequestResponse.updated_at,\n hasChanges: true,\n },\n };\n } catch (e: any) {\n logErrorIfNeeded(\n this.logger,\n `Couldn't create PR in ${input.repoUrl}`,\n e,\n );\n errors.push(e.message);\n return { successful: false };\n }\n },\n },\n );\n\n if (result) {\n return result;\n }\n\n logger.warn(\n `Tried all possible Gitlab credentials, but could not create PR in ${input.repoUrl}. Please try again later...`,\n );\n\n return {\n errors: errors,\n };\n }\n\n async hasFileInRepo(input: {\n repoUrl: string;\n defaultBranch?: string;\n fileName: string;\n }) {\n const fileExists = await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => {\n const { owner, repo } = validatedRepo;\n const exists = await fileExistsInDefaultBranch(\n this.logger,\n gitlab,\n owner,\n repo,\n input.fileName,\n input.defaultBranch,\n );\n if (exists === undefined) {\n return { successful: false };\n }\n return { successful: true, result: exists };\n },\n },\n );\n\n if (fileExists === undefined) {\n throw new Error(\n `Could not determine if repo at ${input.repoUrl} already has a file named ${input.fileName} in its default branch (${input.defaultBranch})`,\n );\n }\n\n return fileExists;\n }\n\n async closeImportPR(\n logger: LoggerService,\n input: {\n repoUrl: string;\n gitUrl: gitUrlParse.GitUrl;\n comment: string;\n },\n ) {\n await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => {\n const { owner, repo, branchName } = validatedRepo;\n try {\n const existingPrForBranch = await findOpenPRForBranch(\n logger,\n this.config,\n gitlab,\n owner,\n repo,\n branchName,\n );\n if (existingPrForBranch.prNum) {\n await closePRWithComment(\n gitlab,\n owner,\n repo,\n existingPrForBranch.prNum,\n input.comment,\n );\n }\n return { successful: true };\n } catch (e: any) {\n logErrorIfNeeded(\n this.logger,\n `Couldn't close PR in ${input.repoUrl}`,\n e,\n );\n return { successful: false };\n }\n },\n },\n );\n }\n\n async deleteImportBranch(input: {\n repoUrl: string;\n gitUrl: gitUrlParse.GitUrl;\n }) {\n await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => {\n const { owner, repo, branchName } = validatedRepo;\n try {\n await gitlab.Branches.remove(`${owner}/${repo}`, branchName);\n return { successful: true };\n } catch (e: any) {\n logErrorIfNeeded(\n this.logger,\n `Couldn't close import PR and/or delete import branch in ${input.repoUrl}`,\n e,\n );\n return { successful: false };\n }\n },\n },\n );\n }\n\n async isRepoEmpty(input: { repoUrl: string }) {\n return await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => {\n const { owner, repo } = validatedRepo;\n const resp = await gitlab.Repositories.allContributors(\n `${owner}/${repo}`,\n {\n showExpanded: true,\n },\n );\n return { successful: true, result: resp?.data?.length < 1 };\n },\n },\n );\n }\n}\n"],"names":["ScmIntegrations","CustomGitlabCredentialsProvider","gitUrlParse","getCredentialsForConfig","buildGitlab","DefaultPageNumber","DefaultPageSize","fetchFromAllIntegrations","addGitlabTokenGroups","computeTotalCount","addGitlabTokenOrgRepositories","addGitlabTokenRepositories","extractLocationOwnerMap","getBranchName","findOpenPRForBranch","logErrorIfNeeded","getCatalogFilename","executeFunctionOnFirstSuccessfulIntegration","fileExistsInDefaultBranch","createOrUpdateFileInBranch","pullRequestResponse","closePRWithComment"],"mappings":"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"}
1
+ {"version":3,"file":"gitlabApiService.cjs.js","sources":["../../src/gitlab/gitlabApiService.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 {\n CacheService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport {\n GitLabIntegrationConfig,\n ScmIntegrations,\n} from '@backstage/integration';\n\nimport { Gitlab } from '@gitbeaker/rest';\nimport gitUrlParse from 'git-url-parse';\n\nimport { getBranchName, getCatalogFilename } from '../catalog/catalogUtils';\nimport {\n computeTotalCount,\n extractLocationOwnerMap,\n logErrorIfNeeded,\n} from '../helpers';\nimport {\n DefaultPageNumber,\n DefaultPageSize,\n} from '../service/handlers/handlers';\nimport { CustomGitlabCredentialsProvider } from './GitlabAppManager';\nimport {\n ExtendedGitlabCredentials,\n GitlabFetchError,\n GitlabOrganization,\n GitlabOrganizationResponse,\n GitlabRepository,\n GitlabRepositoryResponse,\n} from './types';\nimport { buildGitlab } from './utils/glUtils';\nimport { addGitlabTokenGroups } from './utils/orgUtils';\nimport { closePRWithComment, findOpenPRForBranch } from './utils/prUtils';\nimport {\n addGitlabTokenOrgRepositories,\n addGitlabTokenRepositories,\n createOrUpdateFileInBranch,\n fileExistsInDefaultBranch,\n ValidatedRepo,\n} from './utils/repoUtils';\nimport {\n executeFunctionOnFirstSuccessfulIntegration,\n fetchFromAllIntegrations,\n getCredentialsForConfig,\n} from './utils/utils';\n\nexport class GitlabApiService {\n private readonly logger: LoggerService;\n private readonly integrations: ScmIntegrations;\n private readonly gitlabCredentialsProvider: CustomGitlabCredentialsProvider;\n private readonly config: Config;\n // Cache for storing ETags (used for efficient caching of unchanged data returned by GitHub)\n private readonly cache: CacheService;\n constructor(\n logger: LoggerService,\n config: Config,\n cacheService: CacheService,\n ) {\n this.logger = logger;\n this.config = config;\n this.integrations = ScmIntegrations.fromConfig(config);\n this.gitlabCredentialsProvider =\n CustomGitlabCredentialsProvider.fromIntegrations(this.integrations);\n this.cache = cacheService;\n }\n\n async getRepositoryFromIntegrations(repoUrl: string): Promise<{\n repository?: GitlabRepository;\n errors?: GitlabFetchError[];\n }> {\n const gitUrl = gitUrlParse(repoUrl);\n\n const glConfig = this.integrations.gitlab.byUrl(repoUrl)?.config;\n if (!glConfig) {\n throw new Error(\n `No Gitlab integration config found for repo ${repoUrl}. Please add a configuration entry under 'integrations.gitlab`,\n );\n }\n\n const credentials = await getCredentialsForConfig(\n this.gitlabCredentialsProvider,\n glConfig,\n );\n let repository: GitlabRepository | undefined = undefined;\n for (const credential of credentials) {\n const glKit = buildGitlab(\n {\n logger: this.logger,\n cache: this.cache,\n },\n { credential, owner: gitUrl.owner },\n glConfig.baseUrl,\n );\n const repo = await glKit.Projects.show(`${gitUrl.owner}/${gitUrl.name}`);\n if (!repo) {\n continue;\n }\n repository = {\n name: repo.name,\n full_name: repo.path_with_namespace,\n url: repo._links.self,\n html_url: repo.web_url,\n default_branch: repo.default_branch,\n updated_at: repo.updated_at,\n };\n break;\n }\n\n return {\n repository,\n errors: [],\n };\n }\n\n async getOrganizationsFromIntegrations(\n search?: string,\n pageNumber: number = DefaultPageNumber,\n pageSize: number = DefaultPageSize,\n ): Promise<GitlabOrganizationResponse> {\n const groups = new Map<string, GitlabOrganization>();\n const result = await fetchFromAllIntegrations(\n {\n logger: this.logger,\n cache: this.cache,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n dataFetcher: async (\n glApi: InstanceType<typeof Gitlab<false>>,\n credential: ExtendedGitlabCredentials,\n glConfig: GitLabIntegrationConfig,\n ) => {\n const dataFetchErrors = new Map<number, GitlabFetchError>();\n const resp = await addGitlabTokenGroups(\n {\n logger: this.logger,\n },\n glApi,\n credential,\n {\n search,\n groups,\n pageNumber,\n pageSize,\n errors: dataFetchErrors,\n },\n );\n this.logger.debug(\n `Got ${resp.totalCount} groups(s) for ${glConfig.host}`,\n );\n return {\n result: resp.totalCount ?? 0,\n errors: Array.from(dataFetchErrors.values()),\n };\n },\n },\n );\n\n const groupList = Array.from(groups.values());\n const totalCount = computeTotalCount(groupList, result.data, pageSize);\n return {\n organizations: groupList,\n errors: Array.from(result.errors?.values() ?? []),\n totalCount,\n };\n }\n\n async getOrgRepositoriesFromIntegrations(\n orgName: string,\n search?: string,\n pageNumber: number = DefaultPageNumber,\n pageSize: number = DefaultPageSize,\n ): Promise<GitlabRepositoryResponse> {\n const orgRepositories = new Map<string, GitlabRepository>();\n const result = await fetchFromAllIntegrations(\n {\n logger: this.logger,\n cache: this.cache,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n dataFetcher: async (\n glApi: InstanceType<typeof Gitlab<false>>,\n credential: ExtendedGitlabCredentials,\n glConfig: GitLabIntegrationConfig,\n ) => {\n const dataFetchErrors = new Map<number, GitlabFetchError>();\n const resp = await addGitlabTokenOrgRepositories(\n {\n logger: this.logger,\n },\n glApi,\n credential,\n orgName,\n orgRepositories,\n dataFetchErrors,\n {\n search,\n pageNumber,\n pageSize,\n },\n );\n this.logger.debug(\n `Got ${resp.totalCount} org repo(s) for ${glConfig.host}`,\n );\n return {\n stopFetchingData: true,\n result: resp.totalCount ?? 0,\n errors: Array.from(dataFetchErrors.values()),\n };\n },\n },\n );\n\n const repoList = Array.from(orgRepositories.values());\n const totalCount = computeTotalCount(repoList, result.data, pageSize);\n return {\n repositories: repoList,\n errors: Array.from(result.errors?.values() ?? []),\n totalCount,\n };\n }\n\n /**\n * Returns GitlabRepositoryResponse containing:\n * - a list of unique repositories the gitlab integrations have access to\n * - a list of errors encountered by each token (if any exist)\n */\n async getRepositoriesFromIntegrations(\n search?: string,\n pageNumber: number = DefaultPageNumber,\n pageSize: number = DefaultPageSize,\n ): Promise<GitlabRepositoryResponse> {\n const repositories = new Map<string, GitlabRepository>();\n const result = await fetchFromAllIntegrations(\n {\n logger: this.logger,\n cache: this.cache,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n dataFetcher: async (\n glApi: InstanceType<typeof Gitlab<false>>,\n credential: ExtendedGitlabCredentials,\n glConfig: GitLabIntegrationConfig,\n ) => {\n const dataFetchErrors = new Map<number, GitlabFetchError>();\n const resp = await addGitlabTokenRepositories(\n {\n logger: this.logger,\n },\n glApi,\n credential,\n repositories,\n dataFetchErrors,\n {\n search,\n pageNumber,\n pageSize,\n },\n );\n this.logger.debug(\n `Got ${resp.totalCount} repo(s) for ${glConfig.host}`,\n );\n return {\n result: resp.totalCount ?? 0,\n errors: Array.from(dataFetchErrors.values()),\n };\n },\n },\n );\n\n const repoList = Array.from(repositories.values());\n const totalCount = computeTotalCount(repoList, result.data, pageSize);\n return {\n repositories: repoList,\n errors: Array.from(result.errors?.values() ?? []),\n totalCount,\n };\n }\n\n async filterLocationsAccessibleFromIntegrations(\n locationUrls: string[],\n ): Promise<string[]> {\n const locationGitOwnerMap = extractLocationOwnerMap(locationUrls);\n\n const allAccessibleTokenOrgs = new Set<string>();\n const allAccessibleUsernames = new Set<string>();\n await fetchFromAllIntegrations(\n {\n logger: this.logger,\n cache: this.cache,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n dataFetcher: async (gitlab: InstanceType<typeof Gitlab<false>>) => {\n // find authenticated gitlab owner...\n const username = (await gitlab.Users.showCurrentUser()).username;\n if (username) {\n allAccessibleUsernames.add(username);\n }\n // ... along with orgs accessible from the token auth\n\n const allGroups = await gitlab.Groups.all<false, 'offset'>({\n allAvailable: false,\n });\n allGroups\n .map(org => org.path)\n ?.forEach((orgName: string) => allAccessibleTokenOrgs.add(orgName));\n return {};\n },\n },\n );\n\n return locationUrls.filter(loc => {\n if (!locationGitOwnerMap.has(loc)) {\n return false;\n }\n const owner = locationGitOwnerMap.get(loc)!;\n return (\n allAccessibleTokenOrgs.has(owner) || allAccessibleUsernames.has(owner)\n );\n });\n }\n\n async findImportOpenPr(\n logger: LoggerService,\n input: {\n repoUrl: string;\n includeCatalogInfoContent?: boolean;\n },\n ): Promise<{\n prNum?: number;\n prUrl?: string;\n prTitle?: string;\n prBody?: string;\n prCatalogInfoContent?: string;\n lastUpdate?: string;\n }> {\n const glConfig = this.integrations.gitlab.byUrl(input.repoUrl)?.config;\n if (!glConfig) {\n throw new Error(`Could not find GL integration from ${input.repoUrl}`);\n }\n\n const gitUrl = gitUrlParse(input.repoUrl);\n const owner = gitUrl.organization;\n const repo = gitUrl.name;\n\n const credentials = await this.gitlabCredentialsProvider.getAllCredentials({\n host: glConfig.host,\n });\n if (credentials.length === 0) {\n throw new Error(`No credentials for GL integration`);\n }\n\n const branchName = getBranchName(this.config);\n for (const credential of credentials) {\n const glKit = buildGitlab(\n {\n logger: this.logger,\n cache: this.cache,\n },\n { credential, owner },\n glConfig.baseUrl,\n );\n try {\n return await findOpenPRForBranch(\n logger,\n this.config,\n glKit,\n owner,\n repo,\n branchName,\n input.includeCatalogInfoContent,\n );\n } catch (error: any) {\n logErrorIfNeeded(this.logger, 'Error fetching pull requests', error);\n }\n }\n return {};\n }\n\n async submitPrToRepo(\n logger: LoggerService,\n input: {\n repoUrl: string;\n gitUrl: gitUrlParse.GitUrl;\n defaultBranch?: string;\n prTitle: string;\n prBody: string;\n catalogInfoContent: string;\n },\n ): Promise<{\n prUrl?: string;\n prNumber?: number;\n hasChanges?: boolean;\n lastUpdate?: string;\n errors?: string[];\n }> {\n const fileName = getCatalogFilename(this.config);\n const errors: any[] = [];\n\n const result = await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ): Promise<{\n successful: boolean;\n result?: {\n prUrl?: string;\n prNumber?: number;\n hasChanges?: boolean;\n lastUpdate?: string;\n };\n }> => {\n const { owner, repo, branchName } = validatedRepo;\n try {\n // Check if there is already a catalogInfo in the default branch\n const catalogInfoFileExists = await fileExistsInDefaultBranch(\n logger,\n gitlab,\n owner,\n repo,\n fileName,\n input.defaultBranch,\n );\n if (catalogInfoFileExists) {\n // No need to create a PR => component will be imported as is\n return {\n successful: true,\n result: {\n hasChanges: false,\n },\n };\n }\n\n const existingPrForBranch = await findOpenPRForBranch(\n logger,\n this.config,\n gitlab,\n owner,\n repo,\n branchName,\n );\n\n const repoData = await gitlab.Projects.show(`${owner}/${repo}`);\n\n const parentRef = await gitlab.Branches.show(\n `${owner}/${repo}`,\n repoData.default_branch,\n ); // This might not be neccesarry\n\n if (existingPrForBranch.prNum) {\n await createOrUpdateFileInBranch(\n gitlab,\n owner,\n repo,\n branchName,\n fileName,\n input.catalogInfoContent,\n );\n const pullRequestResponse = await gitlab.MergeRequests.edit(\n `${owner}/${repo}`,\n existingPrForBranch.prNum,\n {\n description: input.prBody,\n title: input.prTitle,\n targetBranch: repoData.default_branch,\n },\n );\n return {\n successful: true,\n result: {\n prNumber: existingPrForBranch.prNum,\n prUrl: pullRequestResponse.web_url,\n lastUpdate: pullRequestResponse.updated_at,\n },\n };\n }\n\n try {\n await gitlab.Branches.show(`${owner}/${repo}`, branchName);\n } catch (error: any) {\n if (error.cause.response.status === 404) {\n await gitlab.Branches.create(\n `${owner}/${repo}`,\n branchName,\n parentRef.name,\n );\n } else {\n throw error;\n }\n }\n\n // Might not be able to do this in the gitlab api\n // This is if the branch exists, but there wasn't a PR yet\n // if (branchExists) {\n // // update it in case it is outdated compared to the base branch\n // try {\n // await octo.repos.merge({\n // owner: owner,\n // repo: repo,\n // base: branchName,\n // head: repoData.data.default_branch,\n // });\n // } catch (error: any) {\n // logErrorIfNeeded(\n // this.logger,\n // `Could not merge default branch ${repoData.data.default_branch} into import branch ${branchName}`,\n // error,\n // );\n // }\n // }\n\n await createOrUpdateFileInBranch(\n gitlab,\n owner,\n repo,\n branchName,\n fileName,\n input.catalogInfoContent,\n );\n\n const pullRequestResponse = await gitlab.MergeRequests.create(\n `${owner}/${repo}`,\n branchName,\n repoData.default_branch,\n input.prTitle,\n {\n description: input.prBody,\n },\n );\n return {\n successful: true,\n result: {\n prNumber: pullRequestResponse.iid,\n prUrl: pullRequestResponse.web_url,\n lastUpdate: pullRequestResponse.updated_at,\n hasChanges: true,\n },\n };\n } catch (e: any) {\n logErrorIfNeeded(\n this.logger,\n `Couldn't create PR in ${input.repoUrl}`,\n e,\n );\n errors.push(e.message);\n return { successful: false };\n }\n },\n },\n );\n\n if (result) {\n return result;\n }\n\n logger.warn(\n `Tried all possible Gitlab credentials, but could not create PR in ${input.repoUrl}. Please try again later...`,\n );\n\n return {\n errors: errors,\n };\n }\n\n async hasFileInRepo(input: {\n repoUrl: string;\n defaultBranch?: string;\n fileName: string;\n }) {\n const fileExists = await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => {\n const { owner, repo } = validatedRepo;\n const exists = await fileExistsInDefaultBranch(\n this.logger,\n gitlab,\n owner,\n repo,\n input.fileName,\n input.defaultBranch,\n );\n if (exists === undefined) {\n return { successful: false };\n }\n return { successful: true, result: exists };\n },\n },\n );\n\n if (fileExists === undefined) {\n throw new Error(\n `Could not determine if repo at ${input.repoUrl} already has a file named ${input.fileName} in its default branch (${input.defaultBranch})`,\n );\n }\n\n return fileExists;\n }\n\n async closeImportPR(\n logger: LoggerService,\n input: {\n repoUrl: string;\n gitUrl: gitUrlParse.GitUrl;\n comment: string;\n },\n ) {\n await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => {\n const { owner, repo, branchName } = validatedRepo;\n try {\n const existingPrForBranch = await findOpenPRForBranch(\n logger,\n this.config,\n gitlab,\n owner,\n repo,\n branchName,\n );\n if (existingPrForBranch.prNum) {\n await closePRWithComment(\n gitlab,\n owner,\n repo,\n existingPrForBranch.prNum,\n input.comment,\n );\n }\n return { successful: true };\n } catch (e: any) {\n logErrorIfNeeded(\n this.logger,\n `Couldn't close PR in ${input.repoUrl}`,\n e,\n );\n return { successful: false };\n }\n },\n },\n );\n }\n\n async deleteImportBranch(input: {\n repoUrl: string;\n gitUrl: gitUrlParse.GitUrl;\n }) {\n await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => {\n const { owner, repo, branchName } = validatedRepo;\n try {\n await gitlab.Branches.remove(`${owner}/${repo}`, branchName);\n return { successful: true };\n } catch (e: any) {\n logErrorIfNeeded(\n this.logger,\n `Couldn't close import PR and/or delete import branch in ${input.repoUrl}`,\n e,\n );\n return { successful: false };\n }\n },\n },\n );\n }\n\n async isRepoEmpty(input: { repoUrl: string }) {\n return await executeFunctionOnFirstSuccessfulIntegration(\n {\n logger: this.logger,\n cache: this.cache,\n config: this.config,\n gitlabCredentialsProvider: this.gitlabCredentialsProvider,\n },\n this.integrations,\n {\n repoUrl: input.repoUrl,\n fn: async (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => {\n const { owner, repo } = validatedRepo;\n const resp = await gitlab.Repositories.allContributors(\n `${owner}/${repo}`,\n {\n showExpanded: true,\n },\n );\n return { successful: true, result: resp?.data?.length < 1 };\n },\n },\n );\n }\n\n async getPullRequest(\n repoUrl: string,\n pullRequestNumber: number,\n ): Promise<{\n title?: string;\n body?: string;\n merged?: boolean;\n lastUpdated?: string;\n prSha?: string;\n prBranch?: string;\n }> {\n const glConfig = this.integrations.gitlab.byUrl(repoUrl)?.config;\n if (!glConfig) {\n this.logger.error(\n `No Gitlab integration config found for repo ${repoUrl}`,\n );\n return {};\n }\n\n const gitUrl = gitUrlParse(repoUrl);\n const owner = gitUrl.owner;\n const repo = gitUrl.name;\n\n const credentials = await this.gitlabCredentialsProvider.getAllCredentials({\n host: glConfig.host,\n });\n\n if (credentials.length === 0) {\n this.logger.error(`No credentials for GL integration`);\n return {};\n }\n\n for (const credential of credentials) {\n const glKit = buildGitlab(\n {\n logger: this.logger,\n cache: this.cache,\n },\n { credential, owner },\n glConfig.baseUrl,\n );\n\n try {\n const pr = await glKit.MergeRequests.show(\n `${owner}/${repo}`,\n pullRequestNumber,\n );\n\n return {\n title: pr.title,\n body: pr.description || undefined,\n merged: pr.state === 'merged',\n lastUpdated: pr.updated_at,\n prSha: pr.sha,\n prBranch: pr.source_branch,\n };\n } catch (error: any) {\n this.logger.error(\n `Error fetching pull request ${pullRequestNumber} from ${repoUrl}`,\n error,\n );\n }\n }\n\n return {};\n }\n\n async getCatalogInfoFile(\n logger: LoggerService,\n input: {\n repoUrl: string;\n prNumber: number;\n prHeadSha: string;\n },\n ): Promise<string | undefined> {\n const glConfig = this.integrations.gitlab.byUrl(input.repoUrl)?.config;\n if (!glConfig) {\n logger.error(\n `No Gitlab integration config found for repo ${input.repoUrl}`,\n );\n return undefined;\n }\n\n const gitUrl = gitUrlParse(input.repoUrl);\n const owner = gitUrl.owner;\n const repo = gitUrl.name;\n\n const credentials = await this.gitlabCredentialsProvider.getAllCredentials({\n host: glConfig.host,\n });\n\n if (credentials.length === 0) {\n logger.error(`No credentials for GL integration`);\n return undefined;\n }\n\n for (const credential of credentials) {\n const glKit = buildGitlab(\n {\n logger: this.logger,\n cache: this.cache,\n },\n { credential, owner },\n glConfig.baseUrl,\n );\n\n try {\n const file = await glKit.RepositoryFiles.show(\n `${owner}/${repo}`,\n getCatalogFilename(this.config),\n input.prHeadSha,\n );\n\n if (file) {\n const content = Buffer.from(file.content, 'base64').toString('utf-8');\n return content;\n }\n } catch (error: any) {\n if (error.cause?.response?.status === 404) {\n logger.warn(\n `catalog-info.yaml not found in PR ${input.prNumber} of ${input.repoUrl}`,\n );\n return undefined;\n }\n logger.error(\n `Error fetching catalog-info.yaml from PR ${input.prNumber} of ${input.repoUrl}`,\n error,\n );\n return undefined;\n }\n }\n\n return undefined;\n }\n}\n"],"names":["ScmIntegrations","CustomGitlabCredentialsProvider","gitUrlParse","getCredentialsForConfig","buildGitlab","DefaultPageNumber","DefaultPageSize","fetchFromAllIntegrations","addGitlabTokenGroups","computeTotalCount","addGitlabTokenOrgRepositories","addGitlabTokenRepositories","extractLocationOwnerMap","getBranchName","findOpenPRForBranch","logErrorIfNeeded","getCatalogFilename","executeFunctionOnFirstSuccessfulIntegration","fileExistsInDefaultBranch","createOrUpdateFileInBranch","pullRequestResponse","closePRWithComment"],"mappings":"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"}
@@ -6,6 +6,7 @@ require('@backstage/plugin-permission-common');
6
6
  require('@red-hat-developer-hub/backstage-plugin-bulk-import-common');
7
7
  require('just-kebab-case');
8
8
  var loggingUtils = require('../../helpers/loggingUtils.cjs.js');
9
+ require('@backstage/catalog-model');
9
10
  require('git-url-parse');
10
11
 
11
12
  async function findOpenPRForBranch(logger, config, gitlab, owner, repo, branchName, withCatalogInfoContent = false) {
@@ -1 +1 @@
1
- {"version":3,"file":"prUtils.cjs.js","sources":["../../../src/gitlab/utils/prUtils.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\n\nimport { getCatalogFilename } from '../../catalog/catalogUtils';\nimport { logErrorIfNeeded } from '../../helpers';\n\nexport async function findOpenPRForBranch(\n logger: LoggerService,\n config: Config,\n gitlab: any,\n owner: string,\n repo: string,\n branchName: string,\n withCatalogInfoContent: boolean = false,\n): Promise<{\n prNum?: number;\n prUrl?: string;\n prTitle?: string;\n prBody?: string;\n prCatalogInfoContent?: string;\n lastUpdate?: string;\n}> {\n try {\n const response = await gitlab.MergeRequests.all({\n projectId: `${owner}/${repo}`,\n state: 'opened',\n });\n\n for (const pull of response) {\n if (pull.source_branch === branchName) {\n return {\n prNum: pull.iid,\n prUrl: pull.web_url,\n prTitle: pull.title,\n prBody: pull.description ?? undefined,\n prCatalogInfoContent: withCatalogInfoContent\n ? await getCatalogInfoContentFromPR(\n logger,\n config,\n gitlab,\n owner,\n repo,\n pull.iid,\n pull.sha,\n )\n : undefined,\n lastUpdate: pull.updated_at,\n };\n }\n }\n } catch (error) {\n logErrorIfNeeded(logger, 'Error fetching pull requests', error);\n }\n return {};\n}\n\nasync function getCatalogInfoContentFromPR(\n logger: LoggerService,\n config: Config,\n gitlab: any,\n owner: string,\n repo: string,\n prNumber: number,\n prHeadSha: string,\n): Promise<string | undefined> {\n try {\n const filePath = getCatalogFilename(config);\n const fileContentResponse = await gitlab.RepositoryFiles.show(\n `${owner}/${repo}`,\n filePath,\n prHeadSha,\n );\n if (!('content' in fileContentResponse)) {\n return undefined;\n }\n return Buffer.from(fileContentResponse.content, 'base64').toString('utf-8');\n } catch (error: any) {\n logErrorIfNeeded(\n logger,\n `Error fetching catalog-info content from PR ${prNumber}`,\n error,\n );\n return undefined;\n }\n}\n\nexport async function closePRWithComment(\n gitlab: any,\n owner: string,\n repo: string,\n prNum: number,\n comment: string,\n) {\n await gitlab.MergeRequestNotes.create(`${owner}/${repo}`, prNum, comment);\n await gitlab.MergeRequests.edit(`${owner}/${repo}`, prNum, {\n stateEvent: 'close',\n });\n}\n"],"names":["logErrorIfNeeded","getCatalogFilename"],"mappings":";;;;;;;;;;AAsBsB,eAAA,mBAAA,CACpB,QACA,MACA,EAAA,MAAA,EACA,OACA,IACA,EAAA,UAAA,EACA,yBAAkC,KAQjC,EAAA;AACD,EAAI,IAAA;AACF,IAAA,MAAM,QAAW,GAAA,MAAM,MAAO,CAAA,aAAA,CAAc,GAAI,CAAA;AAAA,MAC9C,SAAW,EAAA,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA,MAC3B,KAAO,EAAA;AAAA,KACR,CAAA;AAED,IAAA,KAAA,MAAW,QAAQ,QAAU,EAAA;AAC3B,MAAI,IAAA,IAAA,CAAK,kBAAkB,UAAY,EAAA;AACrC,QAAO,OAAA;AAAA,UACL,OAAO,IAAK,CAAA,GAAA;AAAA,UACZ,OAAO,IAAK,CAAA,OAAA;AAAA,UACZ,SAAS,IAAK,CAAA,KAAA;AAAA,UACd,MAAA,EAAQ,KAAK,WAAe,IAAA,KAAA,CAAA;AAAA,UAC5B,oBAAA,EAAsB,yBAClB,MAAM,2BAAA;AAAA,YACJ,MAAA;AAAA,YACA,MAAA;AAAA,YACA,MAAA;AAAA,YACA,KAAA;AAAA,YACA,IAAA;AAAA,YACA,IAAK,CAAA,GAAA;AAAA,YACL,IAAK,CAAA;AAAA,WAEP,GAAA,KAAA,CAAA;AAAA,UACJ,YAAY,IAAK,CAAA;AAAA,SACnB;AAAA;AACF;AACF,WACO,KAAO,EAAA;AACd,IAAiBA,6BAAA,CAAA,MAAA,EAAQ,gCAAgC,KAAK,CAAA;AAAA;AAEhE,EAAA,OAAO,EAAC;AACV;AAEA,eAAe,4BACb,MACA,EAAA,MAAA,EACA,QACA,KACA,EAAA,IAAA,EACA,UACA,SAC6B,EAAA;AAC7B,EAAI,IAAA;AACF,IAAM,MAAA,QAAA,GAAWC,gCAAmB,MAAM,CAAA;AAC1C,IAAM,MAAA,mBAAA,GAAsB,MAAM,MAAA,CAAO,eAAgB,CAAA,IAAA;AAAA,MACvD,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA,MAChB,QAAA;AAAA,MACA;AAAA,KACF;AACA,IAAI,IAAA,EAAE,aAAa,mBAAsB,CAAA,EAAA;AACvC,MAAO,OAAA,KAAA,CAAA;AAAA;AAET,IAAA,OAAO,OAAO,IAAK,CAAA,mBAAA,CAAoB,SAAS,QAAQ,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,WACnE,KAAY,EAAA;AACnB,IAAAD,6BAAA;AAAA,MACE,MAAA;AAAA,MACA,+CAA+C,QAAQ,CAAA,CAAA;AAAA,MACvD;AAAA,KACF;AACA,IAAO,OAAA,SAAA;AAAA;AAEX;AAEA,eAAsB,kBACpB,CAAA,MAAA,EACA,KACA,EAAA,IAAA,EACA,OACA,OACA,EAAA;AACA,EAAM,MAAA,MAAA,CAAO,kBAAkB,MAAO,CAAA,CAAA,EAAG,KAAK,CAAI,CAAA,EAAA,IAAI,CAAI,CAAA,EAAA,KAAA,EAAO,OAAO,CAAA;AACxE,EAAM,MAAA,MAAA,CAAO,cAAc,IAAK,CAAA,CAAA,EAAG,KAAK,CAAI,CAAA,EAAA,IAAI,IAAI,KAAO,EAAA;AAAA,IACzD,UAAY,EAAA;AAAA,GACb,CAAA;AACH;;;;;"}
1
+ {"version":3,"file":"prUtils.cjs.js","sources":["../../../src/gitlab/utils/prUtils.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\n\nimport { getCatalogFilename } from '../../catalog/catalogUtils';\nimport { logErrorIfNeeded } from '../../helpers';\n\nexport async function findOpenPRForBranch(\n logger: LoggerService,\n config: Config,\n gitlab: any,\n owner: string,\n repo: string,\n branchName: string,\n withCatalogInfoContent: boolean = false,\n): Promise<{\n prNum?: number;\n prUrl?: string;\n prTitle?: string;\n prBody?: string;\n prCatalogInfoContent?: string;\n lastUpdate?: string;\n}> {\n try {\n const response = await gitlab.MergeRequests.all({\n projectId: `${owner}/${repo}`,\n state: 'opened',\n });\n\n for (const pull of response) {\n if (pull.source_branch === branchName) {\n return {\n prNum: pull.iid,\n prUrl: pull.web_url,\n prTitle: pull.title,\n prBody: pull.description ?? undefined,\n prCatalogInfoContent: withCatalogInfoContent\n ? await getCatalogInfoContentFromPR(\n logger,\n config,\n gitlab,\n owner,\n repo,\n pull.iid,\n pull.sha,\n )\n : undefined,\n lastUpdate: pull.updated_at,\n };\n }\n }\n } catch (error) {\n logErrorIfNeeded(logger, 'Error fetching pull requests', error);\n }\n return {};\n}\n\nasync function getCatalogInfoContentFromPR(\n logger: LoggerService,\n config: Config,\n gitlab: any,\n owner: string,\n repo: string,\n prNumber: number,\n prHeadSha: string,\n): Promise<string | undefined> {\n try {\n const filePath = getCatalogFilename(config);\n const fileContentResponse = await gitlab.RepositoryFiles.show(\n `${owner}/${repo}`,\n filePath,\n prHeadSha,\n );\n if (!('content' in fileContentResponse)) {\n return undefined;\n }\n return Buffer.from(fileContentResponse.content, 'base64').toString('utf-8');\n } catch (error: any) {\n logErrorIfNeeded(\n logger,\n `Error fetching catalog-info content from PR ${prNumber}`,\n error,\n );\n return undefined;\n }\n}\n\nexport async function closePRWithComment(\n gitlab: any,\n owner: string,\n repo: string,\n prNum: number,\n comment: string,\n) {\n await gitlab.MergeRequestNotes.create(`${owner}/${repo}`, prNum, comment);\n await gitlab.MergeRequests.edit(`${owner}/${repo}`, prNum, {\n stateEvent: 'close',\n });\n}\n"],"names":["logErrorIfNeeded","getCatalogFilename"],"mappings":";;;;;;;;;;;AAsBsB,eAAA,mBAAA,CACpB,QACA,MACA,EAAA,MAAA,EACA,OACA,IACA,EAAA,UAAA,EACA,yBAAkC,KAQjC,EAAA;AACD,EAAI,IAAA;AACF,IAAA,MAAM,QAAW,GAAA,MAAM,MAAO,CAAA,aAAA,CAAc,GAAI,CAAA;AAAA,MAC9C,SAAW,EAAA,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA,MAC3B,KAAO,EAAA;AAAA,KACR,CAAA;AAED,IAAA,KAAA,MAAW,QAAQ,QAAU,EAAA;AAC3B,MAAI,IAAA,IAAA,CAAK,kBAAkB,UAAY,EAAA;AACrC,QAAO,OAAA;AAAA,UACL,OAAO,IAAK,CAAA,GAAA;AAAA,UACZ,OAAO,IAAK,CAAA,OAAA;AAAA,UACZ,SAAS,IAAK,CAAA,KAAA;AAAA,UACd,MAAA,EAAQ,KAAK,WAAe,IAAA,KAAA,CAAA;AAAA,UAC5B,oBAAA,EAAsB,yBAClB,MAAM,2BAAA;AAAA,YACJ,MAAA;AAAA,YACA,MAAA;AAAA,YACA,MAAA;AAAA,YACA,KAAA;AAAA,YACA,IAAA;AAAA,YACA,IAAK,CAAA,GAAA;AAAA,YACL,IAAK,CAAA;AAAA,WAEP,GAAA,KAAA,CAAA;AAAA,UACJ,YAAY,IAAK,CAAA;AAAA,SACnB;AAAA;AACF;AACF,WACO,KAAO,EAAA;AACd,IAAiBA,6BAAA,CAAA,MAAA,EAAQ,gCAAgC,KAAK,CAAA;AAAA;AAEhE,EAAA,OAAO,EAAC;AACV;AAEA,eAAe,4BACb,MACA,EAAA,MAAA,EACA,QACA,KACA,EAAA,IAAA,EACA,UACA,SAC6B,EAAA;AAC7B,EAAI,IAAA;AACF,IAAM,MAAA,QAAA,GAAWC,gCAAmB,MAAM,CAAA;AAC1C,IAAM,MAAA,mBAAA,GAAsB,MAAM,MAAA,CAAO,eAAgB,CAAA,IAAA;AAAA,MACvD,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA,MAChB,QAAA;AAAA,MACA;AAAA,KACF;AACA,IAAI,IAAA,EAAE,aAAa,mBAAsB,CAAA,EAAA;AACvC,MAAO,OAAA,KAAA,CAAA;AAAA;AAET,IAAA,OAAO,OAAO,IAAK,CAAA,mBAAA,CAAoB,SAAS,QAAQ,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,WACnE,KAAY,EAAA;AACnB,IAAAD,6BAAA;AAAA,MACE,MAAA;AAAA,MACA,+CAA+C,QAAQ,CAAA,CAAA;AAAA,MACvD;AAAA,KACF;AACA,IAAO,OAAA,SAAA;AAAA;AAEX;AAEA,eAAsB,kBACpB,CAAA,MAAA,EACA,KACA,EAAA,IAAA,EACA,OACA,OACA,EAAA;AACA,EAAM,MAAA,MAAA,CAAO,kBAAkB,MAAO,CAAA,CAAA,EAAG,KAAK,CAAI,CAAA,EAAA,IAAI,CAAI,CAAA,EAAA,KAAA,EAAO,OAAO,CAAA;AACxE,EAAM,MAAA,MAAA,CAAO,cAAc,IAAK,CAAA,CAAA,EAAG,KAAK,CAAI,CAAA,EAAA,IAAI,IAAI,KAAO,EAAA;AAAA,IACzD,UAAY,EAAA;AAAA,GACb,CAAA;AACH;;;;;"}
@@ -5,6 +5,7 @@ require('@backstage/plugin-permission-common');
5
5
  require('@red-hat-developer-hub/backstage-plugin-bulk-import-common');
6
6
  require('just-kebab-case');
7
7
  var loggingUtils = require('../../helpers/loggingUtils.cjs.js');
8
+ require('@backstage/catalog-model');
8
9
  require('git-url-parse');
9
10
  var glUtils = require('./glUtils.cjs.js');
10
11
  var repoUtils = require('./repoUtils.cjs.js');
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs.js","sources":["../../../src/gitlab/utils/utils.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 {\n CacheService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport {\n ScmIntegrations,\n type GitLabIntegrationConfig,\n} from '@backstage/integration';\n\nimport { Gitlab, OffsetPagination } from '@gitbeaker/rest';\n\nimport { logErrorIfNeeded } from '../../helpers';\nimport type { CustomGitlabCredentialsProvider } from '../GitlabAppManager';\nimport {\n type ExtendedGitlabCredentials,\n type GitlabFetchError,\n} from '../types';\nimport { buildGitlab } from './glUtils';\nimport { validateAndBuildRepoData, ValidatedRepo } from './repoUtils';\n\n// /**\n// * Creates the GitlabFetchError to be stored in the returned errors array of the returned GitlabRepositoryResponse object\n// */\nexport function createCredentialError(\n err?: Error,\n): GitlabFetchError | undefined {\n if (err) {\n return {\n type: 'token',\n error: {\n name: err.name,\n message: err.message,\n },\n };\n }\n return undefined;\n}\n\nexport function verifyAndGetIntegrations(\n deps: {\n logger: LoggerService;\n },\n\n integrations: ScmIntegrations,\n) {\n const glConfigs = integrations.gitlab.list().map(glInit => glInit.config);\n\n if (glConfigs.length === 0) {\n deps.logger.debug(\n 'No GitLab Integration in config => returning an empty list of repositories.',\n );\n throw new Error(\n \"Looks like there is no GitLab Integration in config. Please add a configuration entry under 'integrations.gitlab\",\n );\n }\n return glConfigs;\n}\n\nexport async function getCredentialsFromIntegrations(\n gitlabCredentialsProvider: CustomGitlabCredentialsProvider,\n glConfigs: GitLabIntegrationConfig[],\n) {\n const credentialsByConfig = new Map<\n GitLabIntegrationConfig,\n ExtendedGitlabCredentials[]\n >();\n for (const glConfig of glConfigs) {\n const creds = await getCredentialsForConfig(\n gitlabCredentialsProvider,\n glConfig,\n );\n credentialsByConfig.set(glConfig, creds);\n }\n return credentialsByConfig;\n}\n\nexport async function getCredentialsForConfig(\n gitlabCredentialsProvider: CustomGitlabCredentialsProvider,\n glConfig: GitLabIntegrationConfig,\n) {\n return await gitlabCredentialsProvider.getAllCredentials({\n host: glConfig.host,\n });\n}\n\nexport function handleError(\n deps: {\n logger: LoggerService;\n },\n desc: string,\n _credential: ExtendedGitlabCredentials,\n errors: Map<number, GitlabFetchError>,\n err: any,\n) {\n logErrorIfNeeded(deps.logger, `${desc} failed`, err);\n const credentialError = createCredentialError(err as Error);\n if (credentialError) {\n errors.set(-1, credentialError);\n }\n}\n\nexport async function computeTotalCountFromPaginationInfo(\n deps: {\n logger: LoggerService;\n },\n paginationInfo: OffsetPagination,\n pageSize?: number,\n): Promise<number | undefined> {\n /*\n paginationInfo: {\n total: , This is the total amount of repos, but will be NaN if the value is above 10k, see: https://github.com/jdalrymple/gitbeaker/issues/839#issuecomment-636482319\n next: ,\n current: ,\n previous: ,\n perPage: ,\n totalPages:\n }\n */\n\n if (isNaN(paginationInfo.total)) {\n deps.logger.debug(\n `Too many result, total count is NaN, returning current page size`,\n );\n return pageSize;\n }\n return paginationInfo.total;\n}\n\nexport async function executeFunctionOnFirstSuccessfulIntegration<T>(\n deps: {\n logger: LoggerService;\n cache: CacheService;\n config: Config;\n gitlabCredentialsProvider: CustomGitlabCredentialsProvider;\n },\n integrations: ScmIntegrations,\n params: {\n repoUrl: string;\n fn: (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => Promise<{ successful: boolean; result?: T }>;\n },\n) {\n const validatedRepo = await validateAndBuildRepoData(\n deps.gitlabCredentialsProvider,\n integrations,\n deps.config,\n params,\n );\n for (const credential of validatedRepo.credentials) {\n const glKit = buildGitlab(\n deps,\n { credential, owner: validatedRepo.owner },\n validatedRepo.glConfig.baseUrl,\n );\n const res = await params.fn(validatedRepo, glKit);\n if (!res.successful) {\n continue;\n }\n return res.result;\n }\n return undefined;\n}\n\nexport async function fetchFromAllIntegrations<T>(\n deps: {\n logger: LoggerService;\n cache: CacheService;\n gitlabCredentialsProvider: CustomGitlabCredentialsProvider;\n },\n integrations: ScmIntegrations,\n params: {\n dataFetcher: (\n gitlab: InstanceType<typeof Gitlab<false>>,\n credential: ExtendedGitlabCredentials,\n glConfig: GitLabIntegrationConfig,\n ) => Promise<{\n stopFetchingData?: boolean;\n result?: T;\n errors?: GitlabFetchError[];\n }>;\n },\n) {\n const glConfigs = verifyAndGetIntegrations(deps, integrations);\n\n const credentialsByConfig = await getCredentialsFromIntegrations(\n deps.gitlabCredentialsProvider,\n glConfigs,\n );\n const errors = new Map<number, GitlabFetchError>();\n const data: T[] = [];\n const dataErrs: GitlabFetchError[] = [];\n let stopFetchingData: boolean | undefined = false;\n for (const [glConfig, credentials] of credentialsByConfig) {\n if (stopFetchingData) {\n break;\n }\n deps.logger.debug(\n `Got ${credentials.length} credential(s) for ${glConfig.host}`,\n );\n for (const credential of credentials) {\n const glKit = buildGitlab(deps, { credential, errors }, glConfig.baseUrl);\n const res = await params.dataFetcher(glKit, credential, glConfig);\n res.errors?.forEach(err => dataErrs.push(err));\n\n if (res.result) {\n data.push(res.result);\n }\n\n stopFetchingData = res.stopFetchingData;\n }\n }\n\n const aggregatedErrors = new Map<number, GitlabFetchError>();\n errors.forEach((err, num) => aggregatedErrors.set(num, err));\n dataErrs.forEach((err, idx) => aggregatedErrors.set(idx, err));\n\n return { data, errors: aggregatedErrors };\n}\n"],"names":["logErrorIfNeeded","validateAndBuildRepoData","buildGitlab"],"mappings":"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"}
1
+ {"version":3,"file":"utils.cjs.js","sources":["../../../src/gitlab/utils/utils.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 {\n CacheService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport {\n ScmIntegrations,\n type GitLabIntegrationConfig,\n} from '@backstage/integration';\n\nimport { Gitlab, OffsetPagination } from '@gitbeaker/rest';\n\nimport { logErrorIfNeeded } from '../../helpers';\nimport type { CustomGitlabCredentialsProvider } from '../GitlabAppManager';\nimport {\n type ExtendedGitlabCredentials,\n type GitlabFetchError,\n} from '../types';\nimport { buildGitlab } from './glUtils';\nimport { validateAndBuildRepoData, ValidatedRepo } from './repoUtils';\n\n// /**\n// * Creates the GitlabFetchError to be stored in the returned errors array of the returned GitlabRepositoryResponse object\n// */\nexport function createCredentialError(\n err?: Error,\n): GitlabFetchError | undefined {\n if (err) {\n return {\n type: 'token',\n error: {\n name: err.name,\n message: err.message,\n },\n };\n }\n return undefined;\n}\n\nexport function verifyAndGetIntegrations(\n deps: {\n logger: LoggerService;\n },\n\n integrations: ScmIntegrations,\n) {\n const glConfigs = integrations.gitlab.list().map(glInit => glInit.config);\n\n if (glConfigs.length === 0) {\n deps.logger.debug(\n 'No GitLab Integration in config => returning an empty list of repositories.',\n );\n throw new Error(\n \"Looks like there is no GitLab Integration in config. Please add a configuration entry under 'integrations.gitlab\",\n );\n }\n return glConfigs;\n}\n\nexport async function getCredentialsFromIntegrations(\n gitlabCredentialsProvider: CustomGitlabCredentialsProvider,\n glConfigs: GitLabIntegrationConfig[],\n) {\n const credentialsByConfig = new Map<\n GitLabIntegrationConfig,\n ExtendedGitlabCredentials[]\n >();\n for (const glConfig of glConfigs) {\n const creds = await getCredentialsForConfig(\n gitlabCredentialsProvider,\n glConfig,\n );\n credentialsByConfig.set(glConfig, creds);\n }\n return credentialsByConfig;\n}\n\nexport async function getCredentialsForConfig(\n gitlabCredentialsProvider: CustomGitlabCredentialsProvider,\n glConfig: GitLabIntegrationConfig,\n) {\n return await gitlabCredentialsProvider.getAllCredentials({\n host: glConfig.host,\n });\n}\n\nexport function handleError(\n deps: {\n logger: LoggerService;\n },\n desc: string,\n _credential: ExtendedGitlabCredentials,\n errors: Map<number, GitlabFetchError>,\n err: any,\n) {\n logErrorIfNeeded(deps.logger, `${desc} failed`, err);\n const credentialError = createCredentialError(err as Error);\n if (credentialError) {\n errors.set(-1, credentialError);\n }\n}\n\nexport async function computeTotalCountFromPaginationInfo(\n deps: {\n logger: LoggerService;\n },\n paginationInfo: OffsetPagination,\n pageSize?: number,\n): Promise<number | undefined> {\n /*\n paginationInfo: {\n total: , This is the total amount of repos, but will be NaN if the value is above 10k, see: https://github.com/jdalrymple/gitbeaker/issues/839#issuecomment-636482319\n next: ,\n current: ,\n previous: ,\n perPage: ,\n totalPages:\n }\n */\n\n if (isNaN(paginationInfo.total)) {\n deps.logger.debug(\n `Too many result, total count is NaN, returning current page size`,\n );\n return pageSize;\n }\n return paginationInfo.total;\n}\n\nexport async function executeFunctionOnFirstSuccessfulIntegration<T>(\n deps: {\n logger: LoggerService;\n cache: CacheService;\n config: Config;\n gitlabCredentialsProvider: CustomGitlabCredentialsProvider;\n },\n integrations: ScmIntegrations,\n params: {\n repoUrl: string;\n fn: (\n validatedRepo: ValidatedRepo,\n gitlab: InstanceType<typeof Gitlab<false>>,\n ) => Promise<{ successful: boolean; result?: T }>;\n },\n) {\n const validatedRepo = await validateAndBuildRepoData(\n deps.gitlabCredentialsProvider,\n integrations,\n deps.config,\n params,\n );\n for (const credential of validatedRepo.credentials) {\n const glKit = buildGitlab(\n deps,\n { credential, owner: validatedRepo.owner },\n validatedRepo.glConfig.baseUrl,\n );\n const res = await params.fn(validatedRepo, glKit);\n if (!res.successful) {\n continue;\n }\n return res.result;\n }\n return undefined;\n}\n\nexport async function fetchFromAllIntegrations<T>(\n deps: {\n logger: LoggerService;\n cache: CacheService;\n gitlabCredentialsProvider: CustomGitlabCredentialsProvider;\n },\n integrations: ScmIntegrations,\n params: {\n dataFetcher: (\n gitlab: InstanceType<typeof Gitlab<false>>,\n credential: ExtendedGitlabCredentials,\n glConfig: GitLabIntegrationConfig,\n ) => Promise<{\n stopFetchingData?: boolean;\n result?: T;\n errors?: GitlabFetchError[];\n }>;\n },\n) {\n const glConfigs = verifyAndGetIntegrations(deps, integrations);\n\n const credentialsByConfig = await getCredentialsFromIntegrations(\n deps.gitlabCredentialsProvider,\n glConfigs,\n );\n const errors = new Map<number, GitlabFetchError>();\n const data: T[] = [];\n const dataErrs: GitlabFetchError[] = [];\n let stopFetchingData: boolean | undefined = false;\n for (const [glConfig, credentials] of credentialsByConfig) {\n if (stopFetchingData) {\n break;\n }\n deps.logger.debug(\n `Got ${credentials.length} credential(s) for ${glConfig.host}`,\n );\n for (const credential of credentials) {\n const glKit = buildGitlab(deps, { credential, errors }, glConfig.baseUrl);\n const res = await params.dataFetcher(glKit, credential, glConfig);\n res.errors?.forEach(err => dataErrs.push(err));\n\n if (res.result) {\n data.push(res.result);\n }\n\n stopFetchingData = res.stopFetchingData;\n }\n }\n\n const aggregatedErrors = new Map<number, GitlabFetchError>();\n errors.forEach((err, num) => aggregatedErrors.set(num, err));\n dataErrs.forEach((err, idx) => aggregatedErrors.set(idx, err));\n\n return { data, errors: aggregatedErrors };\n}\n"],"names":["logErrorIfNeeded","validateAndBuildRepoData","buildGitlab"],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var catalogModel = require('@backstage/catalog-model');
4
+ var errors = require('@backstage/errors');
3
5
  var gitUrlParse = require('git-url-parse');
4
6
 
5
7
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
@@ -40,9 +42,28 @@ function parseGitURLForApprovalTool(repoUrl) {
40
42
  }
41
43
  return "GIT";
42
44
  }
45
+ function getImportTemplateRef(templateRef) {
46
+ try {
47
+ const { name, namespace, kind } = catalogModel.parseEntityRef(templateRef, {
48
+ defaultKind: "template",
49
+ defaultNamespace: "default"
50
+ });
51
+ if (kind !== "template") {
52
+ throw new errors.InputError(
53
+ `Invalid 'kind' in bulkImport.importTemplate: expected 'template' but got '${kind}'.`
54
+ );
55
+ }
56
+ return catalogModel.stringifyEntityRef({ kind, namespace, name });
57
+ } catch (err) {
58
+ throw new errors.InputError(
59
+ `Invalid scaffolder template entity reference in the configuration 'bulkImport.importTemplate': '${templateRef}'. Error: ${err.message}`
60
+ );
61
+ }
62
+ }
43
63
 
44
64
  exports.computeTotalCount = computeTotalCount;
45
65
  exports.extractLocationOwnerMap = extractLocationOwnerMap;
66
+ exports.getImportTemplateRef = getImportTemplateRef;
46
67
  exports.getNestedValue = getNestedValue;
47
68
  exports.parseGitURLForApprovalTool = parseGitURLForApprovalTool;
48
69
  //# sourceMappingURL=utils.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs.js","sources":["../../src/helpers/utils.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 gitUrlParse from 'git-url-parse';\n\nexport function getNestedValue<T>(obj: T, path: string): any {\n return path\n .split('.')\n .reduce(\n (acc, key) =>\n acc && (acc as Record<string, any>)[key]\n ? (acc as Record<string, any>)[key]\n : undefined,\n obj,\n );\n}\n\nexport function extractLocationOwnerMap(locationUrls: string[]) {\n const locationGitOwnerMap = new Map<string, string>();\n for (const locationUrl of locationUrls) {\n const split = locationUrl.split('/blob/');\n if (split.length < 2) {\n continue;\n }\n locationGitOwnerMap.set(locationUrl, gitUrlParse(split[0]).owner);\n }\n return locationGitOwnerMap;\n}\n\nexport function computeTotalCount<T>(\n data: T[],\n countList: number[],\n pageSize: number,\n) {\n let totalCount = countList.reduce(\n (accumulator, currentValue) => accumulator + currentValue,\n 0,\n );\n if (totalCount < pageSize) {\n totalCount = data.length;\n }\n return totalCount;\n}\n\nexport function parseGitURLForApprovalTool(repoUrl: string) {\n const parsedRepoUrl = new URL(repoUrl);\n if (parsedRepoUrl.hostname.includes('gitlab')) {\n return 'GITLAB';\n }\n\n return 'GIT';\n}\n"],"names":["gitUrlParse"],"mappings":";;;;;;;;AAkBgB,SAAA,cAAA,CAAkB,KAAQ,IAAmB,EAAA;AAC3D,EAAO,OAAA,IAAA,CACJ,KAAM,CAAA,GAAG,CACT,CAAA,MAAA;AAAA,IACC,CAAC,KAAK,GACJ,KAAA,GAAA,IAAQ,IAA4B,GAAG,CAAA,GAClC,GAA4B,CAAA,GAAG,CAChC,GAAA,SAAA;AAAA,IACN;AAAA,GACF;AACJ;AAEO,SAAS,wBAAwB,YAAwB,EAAA;AAC9D,EAAM,MAAA,mBAAA,uBAA0B,GAAoB,EAAA;AACpD,EAAA,KAAA,MAAW,eAAe,YAAc,EAAA;AACtC,IAAM,MAAA,KAAA,GAAQ,WAAY,CAAA,KAAA,CAAM,QAAQ,CAAA;AACxC,IAAI,IAAA,KAAA,CAAM,SAAS,CAAG,EAAA;AACpB,MAAA;AAAA;AAEF,IAAA,mBAAA,CAAoB,IAAI,WAAa,EAAAA,4BAAA,CAAY,MAAM,CAAC,CAAC,EAAE,KAAK,CAAA;AAAA;AAElE,EAAO,OAAA,mBAAA;AACT;AAEgB,SAAA,iBAAA,CACd,IACA,EAAA,SAAA,EACA,QACA,EAAA;AACA,EAAA,IAAI,aAAa,SAAU,CAAA,MAAA;AAAA,IACzB,CAAC,WAAa,EAAA,YAAA,KAAiB,WAAc,GAAA,YAAA;AAAA,IAC7C;AAAA,GACF;AACA,EAAA,IAAI,aAAa,QAAU,EAAA;AACzB,IAAA,UAAA,GAAa,IAAK,CAAA,MAAA;AAAA;AAEpB,EAAO,OAAA,UAAA;AACT;AAEO,SAAS,2BAA2B,OAAiB,EAAA;AAC1D,EAAM,MAAA,aAAA,GAAgB,IAAI,GAAA,CAAI,OAAO,CAAA;AACrC,EAAA,IAAI,aAAc,CAAA,QAAA,CAAS,QAAS,CAAA,QAAQ,CAAG,EAAA;AAC7C,IAAO,OAAA,QAAA;AAAA;AAGT,EAAO,OAAA,KAAA;AACT;;;;;;;"}
1
+ {"version":3,"file":"utils.cjs.js","sources":["../../src/helpers/utils.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport { InputError } from '@backstage/errors';\n\nimport gitUrlParse from 'git-url-parse';\n\nexport function getNestedValue<T>(obj: T, path: string): any {\n return path\n .split('.')\n .reduce(\n (acc, key) =>\n acc && (acc as Record<string, any>)[key]\n ? (acc as Record<string, any>)[key]\n : undefined,\n obj,\n );\n}\n\nexport function extractLocationOwnerMap(locationUrls: string[]) {\n const locationGitOwnerMap = new Map<string, string>();\n for (const locationUrl of locationUrls) {\n const split = locationUrl.split('/blob/');\n if (split.length < 2) {\n continue;\n }\n locationGitOwnerMap.set(locationUrl, gitUrlParse(split[0]).owner);\n }\n return locationGitOwnerMap;\n}\n\nexport function computeTotalCount<T>(\n data: T[],\n countList: number[],\n pageSize: number,\n) {\n let totalCount = countList.reduce(\n (accumulator, currentValue) => accumulator + currentValue,\n 0,\n );\n if (totalCount < pageSize) {\n totalCount = data.length;\n }\n return totalCount;\n}\n\nexport function parseGitURLForApprovalTool(repoUrl: string) {\n const parsedRepoUrl = new URL(repoUrl);\n if (parsedRepoUrl.hostname.includes('gitlab')) {\n return 'GITLAB';\n }\n\n return 'GIT';\n}\n\nexport function getImportTemplateRef(templateRef: string): string {\n try {\n const { name, namespace, kind } = parseEntityRef(templateRef, {\n defaultKind: 'template',\n defaultNamespace: 'default',\n });\n\n if (kind !== 'template') {\n throw new InputError(\n `Invalid 'kind' in bulkImport.importTemplate: expected 'template' but got '${kind}'.`,\n );\n }\n\n return stringifyEntityRef({ kind, namespace, name });\n } catch (err) {\n throw new InputError(\n `Invalid scaffolder template entity reference in the configuration 'bulkImport.importTemplate': '${templateRef}'. ` +\n `Error: ${(err as Error).message}`,\n );\n }\n}\n"],"names":["gitUrlParse","parseEntityRef","InputError","stringifyEntityRef"],"mappings":";;;;;;;;;;AAqBgB,SAAA,cAAA,CAAkB,KAAQ,IAAmB,EAAA;AAC3D,EAAO,OAAA,IAAA,CACJ,KAAM,CAAA,GAAG,CACT,CAAA,MAAA;AAAA,IACC,CAAC,KAAK,GACJ,KAAA,GAAA,IAAQ,IAA4B,GAAG,CAAA,GAClC,GAA4B,CAAA,GAAG,CAChC,GAAA,SAAA;AAAA,IACN;AAAA,GACF;AACJ;AAEO,SAAS,wBAAwB,YAAwB,EAAA;AAC9D,EAAM,MAAA,mBAAA,uBAA0B,GAAoB,EAAA;AACpD,EAAA,KAAA,MAAW,eAAe,YAAc,EAAA;AACtC,IAAM,MAAA,KAAA,GAAQ,WAAY,CAAA,KAAA,CAAM,QAAQ,CAAA;AACxC,IAAI,IAAA,KAAA,CAAM,SAAS,CAAG,EAAA;AACpB,MAAA;AAAA;AAEF,IAAA,mBAAA,CAAoB,IAAI,WAAa,EAAAA,4BAAA,CAAY,MAAM,CAAC,CAAC,EAAE,KAAK,CAAA;AAAA;AAElE,EAAO,OAAA,mBAAA;AACT;AAEgB,SAAA,iBAAA,CACd,IACA,EAAA,SAAA,EACA,QACA,EAAA;AACA,EAAA,IAAI,aAAa,SAAU,CAAA,MAAA;AAAA,IACzB,CAAC,WAAa,EAAA,YAAA,KAAiB,WAAc,GAAA,YAAA;AAAA,IAC7C;AAAA,GACF;AACA,EAAA,IAAI,aAAa,QAAU,EAAA;AACzB,IAAA,UAAA,GAAa,IAAK,CAAA,MAAA;AAAA;AAEpB,EAAO,OAAA,UAAA;AACT;AAEO,SAAS,2BAA2B,OAAiB,EAAA;AAC1D,EAAM,MAAA,aAAA,GAAgB,IAAI,GAAA,CAAI,OAAO,CAAA;AACrC,EAAA,IAAI,aAAc,CAAA,QAAA,CAAS,QAAS,CAAA,QAAQ,CAAG,EAAA;AAC7C,IAAO,OAAA,QAAA;AAAA;AAGT,EAAO,OAAA,KAAA;AACT;AAEO,SAAS,qBAAqB,WAA6B,EAAA;AAChE,EAAI,IAAA;AACF,IAAA,MAAM,EAAE,IAAM,EAAA,SAAA,EAAW,IAAK,EAAA,GAAIC,4BAAe,WAAa,EAAA;AAAA,MAC5D,WAAa,EAAA,UAAA;AAAA,MACb,gBAAkB,EAAA;AAAA,KACnB,CAAA;AAED,IAAA,IAAI,SAAS,UAAY,EAAA;AACvB,MAAA,MAAM,IAAIC,iBAAA;AAAA,QACR,6EAA6E,IAAI,CAAA,EAAA;AAAA,OACnF;AAAA;AAGF,IAAA,OAAOC,+BAAmB,CAAA,EAAE,IAAM,EAAA,SAAA,EAAW,MAAM,CAAA;AAAA,WAC5C,GAAK,EAAA;AACZ,IAAA,MAAM,IAAID,iBAAA;AAAA,MACR,CAAmG,gGAAA,EAAA,WAAW,CACjG,UAAA,EAAA,GAAA,CAAc,OAAO,CAAA;AAAA,KACpC;AAAA;AAEJ;;;;;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
2
- import { LoggerService, CacheService, DiscoveryService, HttpAuthService, AuthService, AuditorService } from '@backstage/backend-plugin-api';
2
+ import { LoggerService, CacheService, DiscoveryService, HttpAuthService, AuthService, AuditorService, DatabaseService } from '@backstage/backend-plugin-api';
3
3
  import { CatalogApi } from '@backstage/catalog-client';
4
4
  import { Config } from '@backstage/config';
5
5
  import { PermissionEvaluator } from '@backstage/plugin-permission-common';
@@ -25,6 +25,7 @@ interface RouterOptions {
25
25
  auth: AuthService;
26
26
  catalogApi: CatalogApi;
27
27
  auditor: AuditorService;
28
+ database: DatabaseService;
28
29
  }
29
30
  /**
30
31
  * Router
@@ -18,7 +18,8 @@ const bulkImportPlugin = backendPluginApi.createBackendPlugin({
18
18
  httpAuth: backendPluginApi.coreServices.httpAuth,
19
19
  auth: backendPluginApi.coreServices.auth,
20
20
  catalogApi: alpha.catalogServiceRef,
21
- auditor: backendPluginApi.coreServices.auditor
21
+ auditor: backendPluginApi.coreServices.auditor,
22
+ database: backendPluginApi.coreServices.database
22
23
  },
23
24
  async init({
24
25
  config,
@@ -30,7 +31,8 @@ const bulkImportPlugin = backendPluginApi.createBackendPlugin({
30
31
  httpAuth,
31
32
  auth,
32
33
  catalogApi,
33
- auditor
34
+ auditor,
35
+ database
34
36
  }) {
35
37
  const router$1 = await router.createRouter({
36
38
  config,
@@ -41,7 +43,8 @@ const bulkImportPlugin = backendPluginApi.createBackendPlugin({
41
43
  httpAuth,
42
44
  auth,
43
45
  catalogApi,
44
- auditor
46
+ auditor,
47
+ database
45
48
  });
46
49
  http.use(router$1);
47
50
  http.addAuthPolicy({
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\n\nimport { createRouter } from './service/router';\n\n/**\n * The bulk-import backend plugin.\n * @public\n */\nexport const bulkImportPlugin = createBackendPlugin({\n pluginId: 'bulk-import',\n register(env) {\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n http: coreServices.httpRouter,\n cache: coreServices.cache,\n discovery: coreServices.discovery,\n permissions: coreServices.permissions,\n httpAuth: coreServices.httpAuth,\n auth: coreServices.auth,\n catalogApi: catalogServiceRef,\n auditor: coreServices.auditor,\n },\n async init({\n config,\n logger,\n http,\n cache,\n discovery,\n permissions,\n httpAuth,\n auth,\n catalogApi,\n auditor,\n }) {\n const router = await createRouter({\n config,\n cache,\n discovery,\n permissions,\n logger,\n httpAuth,\n auth,\n catalogApi,\n auditor,\n });\n http.use(router);\n http.addAuthPolicy({\n path: '/ping',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["createBackendPlugin","coreServices","catalogServiceRef","router","createRouter"],"mappings":";;;;;;AA4BO,MAAM,mBAAmBA,oCAAoB,CAAA;AAAA,EAClD,QAAU,EAAA,aAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,QAAQC,6BAAa,CAAA,MAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,UAAA;AAAA,QACrB,MAAMA,6BAAa,CAAA,UAAA;AAAA,QACnB,OAAOA,6BAAa,CAAA,KAAA;AAAA,QACpB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,aAAaA,6BAAa,CAAA,WAAA;AAAA,QAC1B,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,MAAMA,6BAAa,CAAA,IAAA;AAAA,QACnB,UAAY,EAAAC,uBAAA;AAAA,QACZ,SAASD,6BAAa,CAAA;AAAA,OACxB;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,MAAA;AAAA,QACA,MAAA;AAAA,QACA,IAAA;AAAA,QACA,KAAA;AAAA,QACA,SAAA;AAAA,QACA,WAAA;AAAA,QACA,QAAA;AAAA,QACA,IAAA;AAAA,QACA,UAAA;AAAA,QACA;AAAA,OACC,EAAA;AACD,QAAM,MAAAE,QAAA,GAAS,MAAMC,mBAAa,CAAA;AAAA,UAChC,MAAA;AAAA,UACA,KAAA;AAAA,UACA,SAAA;AAAA,UACA,WAAA;AAAA,UACA,MAAA;AAAA,UACA,QAAA;AAAA,UACA,IAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACD,CAAA;AACD,QAAA,IAAA,CAAK,IAAID,QAAM,CAAA;AACf,QAAA,IAAA,CAAK,aAAc,CAAA;AAAA,UACjB,IAAM,EAAA,OAAA;AAAA,UACN,KAAO,EAAA;AAAA,SACR,CAAA;AAAA;AACH,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\n\nimport { createRouter } from './service/router';\n\n/**\n * The bulk-import backend plugin.\n * @public\n */\nexport const bulkImportPlugin = createBackendPlugin({\n pluginId: 'bulk-import',\n register(env) {\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n http: coreServices.httpRouter,\n cache: coreServices.cache,\n discovery: coreServices.discovery,\n permissions: coreServices.permissions,\n httpAuth: coreServices.httpAuth,\n auth: coreServices.auth,\n catalogApi: catalogServiceRef,\n auditor: coreServices.auditor,\n database: coreServices.database,\n },\n async init({\n config,\n logger,\n http,\n cache,\n discovery,\n permissions,\n httpAuth,\n auth,\n catalogApi,\n auditor,\n database,\n }) {\n const router = await createRouter({\n config,\n cache,\n discovery,\n permissions,\n logger,\n httpAuth,\n auth,\n catalogApi,\n auditor,\n database,\n });\n http.use(router);\n http.addAuthPolicy({\n path: '/ping',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["createBackendPlugin","coreServices","catalogServiceRef","router","createRouter"],"mappings":";;;;;;AA4BO,MAAM,mBAAmBA,oCAAoB,CAAA;AAAA,EAClD,QAAU,EAAA,aAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,QAAQC,6BAAa,CAAA,MAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,UAAA;AAAA,QACrB,MAAMA,6BAAa,CAAA,UAAA;AAAA,QACnB,OAAOA,6BAAa,CAAA,KAAA;AAAA,QACpB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,aAAaA,6BAAa,CAAA,WAAA;AAAA,QAC1B,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,MAAMA,6BAAa,CAAA,IAAA;AAAA,QACnB,UAAY,EAAAC,uBAAA;AAAA,QACZ,SAASD,6BAAa,CAAA,OAAA;AAAA,QACtB,UAAUA,6BAAa,CAAA;AAAA,OACzB;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,MAAA;AAAA,QACA,MAAA;AAAA,QACA,IAAA;AAAA,QACA,KAAA;AAAA,QACA,SAAA;AAAA,QACA,WAAA;AAAA,QACA,QAAA;AAAA,QACA,IAAA;AAAA,QACA,UAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA,OACC,EAAA;AACD,QAAM,MAAAE,QAAA,GAAS,MAAMC,mBAAa,CAAA;AAAA,UAChC,MAAA;AAAA,UACA,KAAA;AAAA,UACA,SAAA;AAAA,UACA,WAAA;AAAA,UACA,MAAA;AAAA,UACA,QAAA;AAAA,UACA,IAAA;AAAA,UACA,UAAA;AAAA,UACA,OAAA;AAAA,UACA;AAAA,SACD,CAAA;AACD,QAAA,IAAA,CAAK,IAAID,QAAM,CAAA;AACf,QAAA,IAAA,CAAK,aAAc,CAAA;AAAA,UACjB,IAAM,EAAA,OAAA;AAAA,UACN,KAAO,EAAA;AAAA,SACR,CAAA;AAAA;AACH,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
@@ -483,7 +483,7 @@ async function findImportStatusByRepo(deps, repoUrl, defaultBranch, includeCatal
483
483
  includeCatalogInfoContent
484
484
  }
485
485
  );
486
- if (!openImportPr.prUrl) {
486
+ if (!openImportPr?.prUrl) {
487
487
  const catalogLocations = (await deps.catalogHttpClient.listCatalogUrlLocations()).uniqueCatalogUrlLocations.keys();
488
488
  const catalogUrl = catalogUtils.getCatalogUrl(deps.config, repoUrl, defaultBranch);
489
489
  let exists = false;
@@ -538,13 +538,145 @@ async function findImportStatusByRepo(deps, repoUrl, defaultBranch, includeCatal
538
538
  responseBody: result
539
539
  };
540
540
  }
541
+ async function findTaskImportStatusByRepo(deps, repoUrl, skipTasks) {
542
+ deps.logger.debug(`Getting bulk import job status for ${repoUrl}..`);
543
+ const gitUrl = gitUrlParse__default.default(repoUrl);
544
+ const errors = [];
545
+ const result = {
546
+ id: repoUrl,
547
+ repository: {
548
+ url: repoUrl,
549
+ name: gitUrl.name,
550
+ organization: gitUrl.organization,
551
+ id: `${gitUrl.organization}/${gitUrl.name}`
552
+ },
553
+ approvalTool: "GIT"
554
+ };
555
+ try {
556
+ const repository = await deps.repositoryDao.findRepositoryByUrl(repoUrl);
557
+ if (repository?.id) {
558
+ const task = await deps.taskDao.lastExecutedTaskByRepoId(repository?.id);
559
+ if (!task) {
560
+ throw new Error(
561
+ `Unable to find scaffolder task for repository: ${repository?.id}`
562
+ );
563
+ }
564
+ const scaffolderUrl = await deps.discovery.getBaseUrl("scaffolder");
565
+ const { token } = await deps.auth.getPluginRequestToken({
566
+ onBehalfOf: await deps.auth.getOwnServiceCredentials(),
567
+ targetPluginId: "scaffolder"
568
+ });
569
+ const response = await fetch(`${scaffolderUrl}/v2/tasks/${task.taskId}`, {
570
+ headers: {
571
+ Authorization: `Bearer ${token}`
572
+ }
573
+ });
574
+ if (!skipTasks) {
575
+ const tasks = await deps.taskDao.findTasksByRepositoryId(repository.id);
576
+ const tasksWithLocations = await Promise.all(
577
+ tasks.map(async (taskItem) => {
578
+ const locations = await deps.taskLocationsDao.findLocationsByTaskId(
579
+ taskItem.taskId
580
+ );
581
+ const taskLocations = locations.map((location) => location.location);
582
+ return {
583
+ ...taskItem,
584
+ locations: taskLocations
585
+ };
586
+ })
587
+ );
588
+ result.tasks = tasksWithLocations;
589
+ }
590
+ result.task = { taskId: task.taskId };
591
+ let data;
592
+ if (response.ok) {
593
+ data = await response.json();
594
+ result.lastUpdate = data.lastHeartbeatAt;
595
+ const approvalTool = repository.approvalTool;
596
+ const pullRequest = await parsePullOrMergeRequestInfo(
597
+ data.state?.checkpoints,
598
+ deps.gitlabApiService,
599
+ deps.githubApiService,
600
+ approvalTool,
601
+ deps.logger,
602
+ repoUrl
603
+ );
604
+ if (pullRequest && approvalTool === "GITLAB") {
605
+ result.gitlab = { pullRequest };
606
+ }
607
+ if (pullRequest && approvalTool === "GIT") {
608
+ result.github = { pullRequest };
609
+ }
610
+ result.status = `TASK_${data.status?.toLocaleUpperCase()}`;
611
+ } else {
612
+ const errMsg = await response.text() ?? `Failed to fetch task ${task.taskId}. Response status: ${response.status}`;
613
+ throw new Error(errMsg);
614
+ }
615
+ }
616
+ } catch (error) {
617
+ errors.push(error.message);
618
+ result.errors = errors;
619
+ result.status = "TASK_FETCH_FAILED";
620
+ if (error.message?.includes("Not Found")) {
621
+ return {
622
+ statusCode: 404,
623
+ responseBody: result
624
+ };
625
+ }
626
+ }
627
+ return {
628
+ statusCode: 200,
629
+ responseBody: result
630
+ };
631
+ }
632
+ async function parsePullOrMergeRequestInfo(checkpoints, githubApiService, gitlabApiService, approvalTool, logger, repoUrl) {
633
+ if (approvalTool !== "GITLAB" && approvalTool !== "GIT") {
634
+ return undefined;
635
+ }
636
+ const gitApiService = approvalTool === "GITLAB" ? gitlabApiService : githubApiService;
637
+ for (const key in checkpoints) {
638
+ if (!checkpoints.hasOwnProperty(key)) {
639
+ continue;
640
+ }
641
+ try {
642
+ if (key.startsWith("v1.task.checkpoint.publish.create.pr") || key.startsWith("v1.task.checkpoint.publish.create.mr")) {
643
+ const url = checkpoints[key]?.value?.html_url ?? checkpoints[key]?.value?.mrWebUrl;
644
+ if (!url) {
645
+ continue;
646
+ }
647
+ const prNumber = Number.parseInt(url.split("/").pop(), 10);
648
+ const prDetails = await gitApiService.getPullRequest(repoUrl, prNumber);
649
+ let catalogInfoContent;
650
+ if (prDetails.prSha) {
651
+ catalogInfoContent = await gitApiService.getCatalogInfoFile(logger, {
652
+ repoUrl,
653
+ prHeadSha: prDetails.prSha,
654
+ prNumber
655
+ });
656
+ }
657
+ return {
658
+ url,
659
+ number: prNumber,
660
+ title: prDetails.title,
661
+ body: prDetails.body,
662
+ status: prDetails.merged ? "PR_MERGED" : "WAIT_PR_APPROVAL",
663
+ catalogInfoContent
664
+ };
665
+ }
666
+ } catch (err) {
667
+ logger.warn(`Error while processing checkpoint ${key}: ${err}`);
668
+ continue;
669
+ }
670
+ }
671
+ return undefined;
672
+ }
541
673
  async function deleteImportByRepo(deps, repoUrl, defaultBranch) {
542
674
  deps.logger.debug(`Deleting bulk import job status for ${repoUrl}..`);
543
675
  const openImportPr = await deps.gitApiService.findImportOpenPr(deps.logger, {
544
676
  repoUrl
545
677
  });
546
678
  const gitUrl = gitUrlParse__default.default(repoUrl);
547
- if (openImportPr.prUrl) {
679
+ if (openImportPr?.prUrl) {
548
680
  const appTitle = deps.config.getOptionalString("app.title") ?? "Red Hat Developer Hub";
549
681
  const appBaseUrl = deps.config.getString("app.baseUrl");
550
682
  await deps.gitApiService.closeImportPR(deps.logger, {
@@ -577,9 +709,30 @@ async function deleteImportByRepo(deps, repoUrl, defaultBranch) {
577
709
  responseBody: undefined
578
710
  };
579
711
  }
712
+ async function deleteTaskImportByRepo(deps, repoUrl) {
713
+ deps.logger.debug(`Deleting repository from database by name ${repoUrl}...`);
714
+ try {
715
+ await deps.dao.deleteRepository(repoUrl);
716
+ return {
717
+ statusCode: 204,
718
+ responseBody: void 0
719
+ };
720
+ } catch (error) {
721
+ deps.logger.error(
722
+ `Failed to delete repository from database by url ${repoUrl}`,
723
+ error
724
+ );
725
+ return {
726
+ statusCode: 500
727
+ };
728
+ }
729
+ }
580
730
 
581
731
  exports.createImportJobs = createImportJobs;
582
732
  exports.deleteImportByRepo = deleteImportByRepo;
733
+ exports.deleteTaskImportByRepo = deleteTaskImportByRepo;
583
734
  exports.findAllImports = findAllImports;
584
735
  exports.findImportStatusByRepo = findImportStatusByRepo;
736
+ exports.findTaskImportStatusByRepo = findTaskImportStatusByRepo;
737
+ exports.sortImports = sortImports;
585
738
  //# sourceMappingURL=bulkImports.cjs.js.map