# # Copyright Red Hat, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # openapi: '3.1.0' info: version: '1.0' title: 'Bulk Import Backend' description: The Bulk Import Backend APIs allow users to bulk import repositories into the Backstage catalog from remote sources such as Git. servers: - url: '{protocol}://{host}:{port}/{basePath}' variables: protocol: enum: [http, https] default: http host: default: localhost port: default: '7007' basePath: default: 'api/bulk-import' paths: /ping: get: operationId: ping summary: Check the health of the Bulk Import backend router tags: [Management] responses: 200: description: The backend router for the Bulk Import backend is up and running content: application/json: schema: type: object properties: status: enum: ['ok'] example: status: 'ok' /organizations: get: operationId: findAllOrganizations summary: Fetch Organizations accessible by Backstage Github Integrations security: - BearerAuth: [] tags: [Organization] parameters: - $ref: '#/components/parameters/pagePerIntegrationQueryParam' - $ref: '#/components/parameters/sizePerIntegrationQueryParam' - $ref: '#/components/parameters/searchQueryParam' - $ref: '#/components/parameters/approvalToolParam' responses: 200: description: Organization list was fetched successfully with no errors content: application/json: schema: $ref: '#/components/schemas/OrganizationList' examples: multipleRepos: $ref: '#/components/examples/multipleOrgs' 500: description: Generic error when there are errors and no Organization is returned content: application/json: schema: $ref: '#/components/schemas/OrganizationList' examples: repositoryListErrors: $ref: '#/components/examples/orgListErrors' /organizations/{organizationName}/repositories: get: operationId: findRepositoriesByOrganization summary: Fetch Repositories in the specified GitHub organization, provided it is accessible by any of the configured GitHub Integrations. security: - BearerAuth: [] tags: [Organization] parameters: - in: path name: organizationName description: Organization name required: true schema: type: string - in: query name: checkImportStatus description: whether to return import status. Note that this might incur a performance penalty because the import status is computed for each repository. schema: type: boolean default: 'false' - $ref: '#/components/parameters/pagePerIntegrationQueryParam' - $ref: '#/components/parameters/sizePerIntegrationQueryParam' - $ref: '#/components/parameters/searchQueryParam' - $ref: '#/components/parameters/approvalToolParam' responses: 200: description: Org Repository list was fetched successfully with no errors content: application/json: schema: $ref: '#/components/schemas/RepositoryList' examples: multipleRepos: $ref: '#/components/examples/multipleRepos' 500: description: Generic error when there are errors and no Org Repository is returned content: application/json: schema: $ref: '#/components/schemas/RepositoryList' examples: repositoryListErrors: $ref: '#/components/examples/repositoryListErrors' /repositories: get: operationId: findAllRepositories summary: Fetch Organization Repositories accessible by Backstage Github Integrations security: - BearerAuth: [] tags: [Repository] parameters: - in: query name: checkImportStatus description: whether to return import status. Note that this might incur a performance penalty because the import status is computed for each repository. schema: type: boolean default: 'false' - $ref: '#/components/parameters/pagePerIntegrationQueryParam' - $ref: '#/components/parameters/sizePerIntegrationQueryParam' - $ref: '#/components/parameters/searchQueryParam' - $ref: '#/components/parameters/approvalToolParam' responses: 200: description: Repository list was fetched successfully with no errors content: application/json: schema: $ref: '#/components/schemas/RepositoryList' examples: multipleRepos: $ref: '#/components/examples/multipleRepos' 500: description: Generic error when there are errors and no repository is returned content: application/json: schema: $ref: '#/components/schemas/RepositoryList' examples: repositoryListErrors: $ref: '#/components/examples/repositoryListErrors' /imports: get: operationId: findAllImports summary: Fetch Import Jobs security: - BearerAuth: [] tags: [Import] parameters: - $ref: '#/components/parameters/apiVersionHeaderParam' # The '*PerIntegration' query params are being kept for backward compatibility, # but the behavior depends on the API Version specified in the request headers. - $ref: '#/components/parameters/pagePerIntegrationQueryParamDeprecated' - $ref: '#/components/parameters/sizePerIntegrationQueryParamDeprecated' - $ref: '#/components/parameters/pageQueryParam' - $ref: '#/components/parameters/sizeQueryParam' - $ref: '#/components/parameters/sortOrderQueryParam' - $ref: '#/components/parameters/sortColumnQueryParam' - $ref: '#/components/parameters/searchQueryParam' - $ref: '#/components/parameters/approvalToolParam' responses: 200: description: Import Job list was fetched successfully with no errors content: application/json: schema: oneOf: - type: array items: $ref: '#/components/schemas/SourceImport' - $ref: '#/components/schemas/ImportJobListV2' examples: twoImports: $ref: '#/components/examples/twoImports' multipleImportJobsV2: $ref: '#/components/examples/multipleImportJobsV2' 500: description: Generic error when there are errors and no Import Job is returned content: application/json: schema: oneOf: - type: string description: Generic error - $ref: '#/components/schemas/ImportJobListV2' examples: repositoryListErrors: $ref: '#/components/examples/importJobListErrors' post: operationId: createImportJobs summary: Submit Import Jobs security: - BearerAuth: [] tags: [Import] parameters: - in: query name: dryRun description: whether to perform a dry-run to check if entity name collisions would occur in the catalog schema: type: boolean default: 'false' requestBody: description: List of Import jobs to create required: true content: application/json: schema: type: array items: $ref: '#/components/schemas/ImportRequest' examples: multipleImportRequests: $ref: '#/components/examples/multipleImportRequests' responses: 202: description: Import Jobs request was submitted successfully to the API. Check the status in each item of the response body list to see their individual status. content: application/json: schema: type: array items: $ref: '#/components/schemas/Import' examples: twoImports: $ref: '#/components/examples/twoImportJobs' /task-imports: get: operationId: findAllTaskImports summary: Fetch Import Jobs security: - BearerAuth: [] tags: [Import] parameters: - $ref: '#/components/parameters/apiVersionHeaderParam' # The '*PerIntegration' query params are being kept for backward compatibility, # but the behavior depends on the API Version specified in the request headers. - $ref: '#/components/parameters/pagePerIntegrationQueryParamDeprecated' - $ref: '#/components/parameters/sizePerIntegrationQueryParamDeprecated' - $ref: '#/components/parameters/pageQueryParam' - $ref: '#/components/parameters/sizeQueryParam' - $ref: '#/components/parameters/sortOrderQueryParam' - $ref: '#/components/parameters/sortColumnQueryParam' - $ref: '#/components/parameters/searchQueryParam' responses: 200: description: Import Job list was fetched successfully with no errors content: application/json: schema: oneOf: - type: array items: $ref: '#/components/schemas/SourceImport' - $ref: '#/components/schemas/ImportJobListV2' examples: twoImports: $ref: '#/components/examples/twoImports' multipleImportJobsV2: $ref: '#/components/examples/multipleImportJobsV2' 500: description: Generic error when there are errors and no Import Job is returned content: application/json: schema: oneOf: - type: string description: Generic error - $ref: '#/components/schemas/ImportJobListV2' examples: repositoryListErrors: $ref: '#/components/examples/importJobListErrors' post: operationId: createTaskImportJobs summary: Execute a scaffolder template for a list of repositories security: - BearerAuth: [] tags: - Import requestBody: description: The template to execute and the repositories to run it against. required: true content: application/json: schema: type: array items: $ref: '#/components/schemas/ImportRequest' responses: 202: description: Import Jobs request was submitted successfully to the API. Check the status in each item of the response body list to see their individual status. content: application/json: schema: type: array items: $ref: '#/components/schemas/Import' /orchestrator-workflows: get: operationId: findAllOrchestratorWorkflowImports summary: Fetch Import Jobs security: - BearerAuth: [] tags: [Import] parameters: - $ref: '#/components/parameters/apiVersionHeaderParam' # The '*PerIntegration' query params are being kept for backward compatibility, # but the behavior depends on the API Version specified in the request headers. - $ref: '#/components/parameters/pagePerIntegrationQueryParamDeprecated' - $ref: '#/components/parameters/sizePerIntegrationQueryParamDeprecated' - $ref: '#/components/parameters/pageQueryParam' - $ref: '#/components/parameters/sizeQueryParam' - $ref: '#/components/parameters/sortOrderQueryParam' - $ref: '#/components/parameters/sortColumnQueryParam' - $ref: '#/components/parameters/searchQueryParam' responses: 200: description: Import Job list was fetched successfully with no errors content: application/json: schema: oneOf: - type: array items: $ref: '#/components/schemas/SourceImport' - $ref: '#/components/schemas/ImportJobListV2' examples: twoImports: $ref: '#/components/examples/twoImports' multipleImportJobsV2: $ref: '#/components/examples/multipleImportJobsV2' 500: description: Generic error when there are errors and no Import Job is returned content: application/json: schema: oneOf: - type: string description: Generic error - $ref: '#/components/schemas/ImportJobListV2' examples: repositoryListErrors: $ref: '#/components/examples/importJobListErrors' post: operationId: createOrchestratorWorkflowJobs summary: Execute an orchestrator workflow security: - BearerAuth: [] tags: - Import requestBody: description: List of Import jobs to create required: true content: application/json: schema: type: array items: $ref: '#/components/schemas/ImportRequest' examples: multipleImportRequests: $ref: '#/components/examples/multipleImportRequests' responses: '200': description: The orchestrator workflow was triggered successfully. /task-import/by-repo: get: operationId: findTaskImportStatusByRepo summary: Get Import Status by repository security: - BearerAuth: [] tags: [Import] parameters: - in: query name: repo description: the full URL to the repo schema: type: string - in: query name: defaultBranch description: the name of the default branch schema: type: string default: 'main' - $ref: '#/components/parameters/approvalToolParam' responses: 200: description: Import Job status was determined successfully with no errors content: application/json: schema: $ref: '#/components/schemas/Import' examples: singleImportStatusForRepo: $ref: '#/components/examples/singleImportStatusForRepo' 500: description: Generic error delete: operationId: deleteTaskImportByRepo summary: Delete stored scaffolder task records for a specific repository security: - BearerAuth: [] tags: [Import] parameters: - in: query name: repo description: the full URL to the repo schema: type: string - $ref: '#/components/parameters/approvalToolParam' responses: 204: description: Repository was deleted successfully with no errors 500: description: Generic error /orchestrator-import/by-repo: get: operationId: findOrchestratorImportStatusByRepo summary: Get Import Status by repository security: - BearerAuth: [] tags: [Import] parameters: - in: query name: repo description: the full URL to the repo schema: type: string - $ref: '#/components/parameters/approvalToolParam' responses: 200: description: Import Job status was determined successfully with no errors content: application/json: schema: $ref: '#/components/schemas/Import' examples: singleImportStatusForRepo: $ref: '#/components/examples/singleImportStatusForRepo' 500: description: Generic error delete: operationId: deleteOrchestratorImportByRepo summary: Delete stored orchestrator workflow records for a specific repository security: - BearerAuth: [] tags: [Import] parameters: - in: query name: repo description: the full URL to the repo schema: type: string - $ref: '#/components/parameters/approvalToolParam' responses: 204: description: Repository was deleted successfully with no errors 500: description: Generic error /import/by-repo: get: operationId: findImportStatusByRepo summary: Get Import Status by repository security: - BearerAuth: [] tags: [Import] parameters: - in: query name: repo description: the full URL to the repo schema: type: string - in: query name: defaultBranch description: the name of the default branch schema: type: string default: 'main' - $ref: '#/components/parameters/approvalToolParam' responses: 200: description: Import Job status was determined successfully with no errors content: application/json: schema: $ref: '#/components/schemas/Import' examples: singleImportStatusForRepo: $ref: '#/components/examples/singleImportStatusForRepo' 500: description: Generic error delete: operationId: deleteImportByRepo summary: Delete Import by repository security: - BearerAuth: [] tags: [Import] parameters: - in: query name: repo description: the full URL to the repo schema: type: string - in: query name: defaultBranch description: the name of the default branch schema: type: string default: 'main' - $ref: '#/components/parameters/approvalToolParam' responses: 204: description: Import Job was successfully delete with no errors 500: description: Generic error # todo: rework examples to use newer API. components: parameters: apiVersionHeaderParam: in: header name: api-version description: | API version. ## Changelog ### v1 (default) Initial version #### Deprecations * GET /imports * Deprecation of 'pagePerIntegration' and 'sizePerIntegration' query parameters and introduction of new 'page' and 'size' parameters * 'page' takes precedence over 'pagePerIntegration' if both are passed * 'size' takes precedence over 'sizePerIntegration' if both are passed ### v2 #### Breaking changes * GET /imports * Query parameters: * 'pagePerIntegration' is ignored in favor of 'page' * 'sizePerIntegration' is ignored in favor of 'size' * Response structure changed to include pagination info: instead of returning a simple list of Imports, the response is now an object containing the following fields: * 'imports': the list of Imports * 'page': the page requested * 'size': the requested number of Imports requested per page * 'totalCount': the total count of Imports schema: type: string enum: ['v1', 'v2'] default: 'v1' pagePerIntegrationQueryParam: in: query name: pagePerIntegration description: the page number for each Integration schema: type: integer default: 1 sizePerIntegrationQueryParam: in: query name: sizePerIntegration description: the number of items per Integration to return per page schema: type: integer default: 20 pagePerIntegrationQueryParamDeprecated: in: query name: pagePerIntegration description: the page number for each Integration. **Deprecated**. Use the 'page' query parameter instead. deprecated: true schema: type: integer default: 1 sortColumnQueryParam: in: query name: sortColumn description: | The allowed values for sorting columns: - repository.name: Sort by repository name. - repository.organization: Sort by organization URL. - repository.url: Sort by repository URL. - lastUpdate: Sort by the last time the catalog-info.yaml was updated. - status: Sort by the status of the catalog-info.yaml. required: false schema: enum: - repository.name - repository.organization - repository.url - lastUpdate - status default: repository.name sortOrderQueryParam: in: query name: sortOrder description: The order of sorting asc for ascending or desc for descending required: false schema: type: string enum: - asc - desc default: asc sizePerIntegrationQueryParamDeprecated: in: query name: sizePerIntegration description: the number of items per Integration to return per page. **Deprecated**. Use the 'size' query parameter instead. deprecated: true schema: type: integer default: 20 searchQueryParam: in: query name: search description: returns only the items that match the search string schema: type: string pageQueryParam: # used for endpoints where pagination does not depend on the Integrations configured in: query name: page description: the requested page number schema: type: integer default: 1 sizeQueryParam: # used for endpoints where pagination does not depend on the Integrations configured in: query name: size description: the number of items to return per page schema: type: integer default: 20 approvalToolParam: in: query name: approvalTool description: the approvalTool to use schema: type: string default: GIT schemas: OrganizationList: title: Organization List type: object properties: organizations: type: array items: $ref: '#/components/schemas/Organization' errors: type: array items: type: string totalCount: type: integer pagePerIntegration: type: integer sizePerIntegration: type: integer Organization: title: Organization type: object properties: id: type: string description: unique identifier name: type: string description: organization name description: type: string description: organization description url: type: string description: organization URL totalRepoCount: type: number description: total number of repositories in this Organization errors: type: array items: type: string RepositoryList: title: Repository List type: object properties: repositories: type: array items: $ref: '#/components/schemas/Repository' errors: type: array items: type: string totalCount: type: integer pagePerIntegration: type: integer sizePerIntegration: type: integer Repository: title: Repository type: object properties: id: type: string description: unique identifier name: type: string description: repository name url: type: string description: repository URL organization: type: string description: organization which the repository is part of importStatus: oneOf: - $ref: '#/components/schemas/ImportStatus' - $ref: '#/components/schemas/TaskImportStatus' - $ref: '#/components/schemas/WorkflowImportStatus' defaultBranch: type: string description: default branch lastUpdate: type: string format: date-time errors: type: array items: type: string ApprovalTool: type: string enum: - GIT - SERVICENOW - GITLAB TaskImportStatus: type: string description: Import Job status enum: - 'TASK_CANCELLED' - 'TASK_COMPLETED' - 'TASK_FAILED' - 'TASK_OPEN' - 'TASK_PROCESSING' - 'TASK_SKIPPED' - TASK_FETCH_FAILED ImportStatus: type: string nullable: true description: Import Job status enum: #- WAIT_APPROVAL - ADDED #- WAIT_PR_START - WAIT_PR_APPROVAL #- PR_REJECTED #- WAIT_SERVICENOW_START #- WAIT_SERVICENOW_RESOLUTION - PR_ERROR #- SERVICENOW_ERROR #- SERVICENOW_TICKET_REJECTED - null ImportJobListV2: title: Import Job List type: object properties: imports: type: array items: $ref: '#/components/schemas/SourceImport' errors: type: array items: type: string totalCount: type: integer page: type: integer size: type: integer Import: title: Import Job type: object properties: id: type: string status: oneOf: - $ref: '#/components/schemas/ImportStatus' - $ref: '#/components/schemas/TaskImportStatus' - $ref: '#/components/schemas/WorkflowImportStatus' task: type: object properties: taskId: type: string workflow: type: object properties: workflowId: type: string tasks: type: array items: type: object properties: taskId: type: string workflows: type: array items: type: object properties: workflowId: type: string catalogEntityName: type: string description: Specified entity name in the catalog. Filled only in response for dry-run import requests. lastUpdate: type: string format: date-time errors: type: array items: type: string approvalTool: $ref: '#/components/schemas/ApprovalTool' repository: $ref: '#/components/schemas/Repository' gitlab: type: object description: GitLab details. Applicable if approvalTool is gitlab. properties: pullRequest: $ref: '#/components/schemas/PullRequest' github: type: object description: GitHub details. Applicable if approvalTool is git. properties: pullRequest: $ref: '#/components/schemas/PullRequest' PullRequest: type: object properties: url: type: string description: URL of the Pull Request number: type: number description: Pull Request number title: type: string description: title of the Pull Request body: type: string description: body of the Pull Request catalogInfoContent: type: string description: content of the catalog-info.yaml as fetched from the Pull Request. status: type: string enum: - WAIT_PR_APPROVAL - PR_MERGED - PR_ERROR SourceImport: title: Import Job with source it originates from allOf: - $ref: '#/components/schemas/Import' - type: object properties: source: $ref: '#/components/schemas/Source' Source: type: string nullable: true description: > Import Source: * 'config' - Import from static catalog location configuration in 'app-config' * 'location' - Import of user registered entities using locations endpoint * 'integration' - Import using a GitHub integration * null - Import source is unknown enum: - config - location - integration - null ImportRequest: title: Import Job request type: object required: - repository properties: approvalTool: $ref: '#/components/schemas/ApprovalTool' catalogEntityName: type: string description: Expected Entity name in the catalog. Relevant only if the 'dryRun' query parameter is set to 'true'. codeOwnersFileAsEntityOwner: type: boolean description: Whether the CODEOWNERS file will be used as entity owner. Only relevant for dry-run requests. If set to 'false', the corresponding dry-run check will be skipped. repository: type: object required: - url properties: name: type: string description: repository name url: type: string description: repository URL organization: type: string description: organization which the repository is part of defaultBranch: type: string description: default branch catalogInfoContent: type: string description: content of the catalog-info.yaml to include in the import Pull Request. gitlab: type: object description: GitLab details. Applicable if approvalTool is gitlab. properties: pullRequest: $ref: '#/components/schemas/PullRequest' github: type: object description: GitHub details. Applicable if approvalTool is git. properties: pullRequest: $ref: '#/components/schemas/PullRequest' ScaffolderTask: title: Scaffolder Task type: object properties: taskId: type: string repositoryId: type: number locations: type: array items: type: string WorkflowImportStatus: type: string description: Import Job status enum: - 'WORKFLOW_ACTIVE' - 'WORKFLOW_COMPLETED' - 'WORKFLOW_ABORTED' - 'WORKFLOW_SUSPENDED' - 'WORKFLOW_ERROR' - 'WORKFLOW_PENDING' - WORKFLOW_FETCH_FAILED securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: Backstage Permissions Framework JWT examples: multipleOrgs: summary: Multiple organizations value: errors: [] organizations: - id: 'unique-org-id-1' name: 'pet-org' url: 'https://github.com/pet-org' description: 'A great Pet Org' totalRepoCount: 10 - id: 'unique-org-id-2' name: 'org-zero' url: 'https://ghe.example.com/org-zero' totalRepoCount: 0 - id: 'unique-id-2' name: 'org-one' url: 'https://ghe.example.com/org-one' description: 'Org One description' totalRepoCount: 1234 orgListErrors: summary: Errors when listing organizations value: errors: - 'Github App with ID 2 failed spectacularly' organizations: [] multipleRepos: summary: Multiple repositories value: errors: [] repositories: - id: 'unique-id-1' name: 'pet-app' url: 'https://github.com/my-org/pet-app' organization: 'my-org' importStatus: 'WAIT_PR_APPROVAL' defaultBranch: 'main' - id: 'unique-id-2' name: 'project-zero' url: 'https://ghe.example.com/my-other-org/project-zero' organization: 'my-other-org' importStatus: 'PR_REJECTED' defaultBranch: 'dev' - id: 'unique-id-2' name: 'project-one' defaultBranch: 'trunk' url: 'https://ghe.example.com/my-other-org-2/project-one' organization: 'my-other-org-2' repositoryListErrors: summary: Errors when listing repositories value: errors: - 'Github App with ID 2 failed spectacularly' repositories: [] twoImports: summary: Two import job requests (V1) value: - id: 'bulk-import-id-1' status: 'WAIT_PR_APPROVAL' errors: [] approvalTool: GIT repository: name: 'pet-app' url: 'https://github.com/my-org/pet-app' organization: 'my-org' github: pullRequest: url: 'https://github.com/my-org/pet-app/pull/1' number: 1 - id: 'bulk-import-id-2' status: 'PR_REJECTED' errors: [] approvalTool: GIT repository: name: 'pet-app-test' url: 'https://github.com/my-org/pet-app-test' organization: 'my-org' github: pullRequest: url: 'https://github.com/my-org/pet-app-test/pull/10' number: 10 multipleImportJobsV2: summary: Two import job requests (V2) value: errors: [] page: 1 size: 2 totalCount: 10 imports: - id: 'bulk-import-id-1' status: 'WAIT_PR_APPROVAL' errors: [] approvalTool: GIT repository: name: 'pet-app' url: 'https://github.com/my-org/pet-app' organization: 'my-org' github: pullRequest: url: 'https://github.com/my-org/pet-app/pull/1' number: 1 - id: 'bulk-import-id-2' status: 'PR_REJECTED' errors: [] approvalTool: GIT repository: name: 'pet-app-test' url: 'https://github.com/my-org/pet-app-test' organization: 'my-org' github: pullRequest: url: 'https://github.com/my-org/pet-app-test/pull/10' number: 10 importJobListErrors: summary: Errors when listing import jobs value: errors: - 'Github App with ID xyz-123 failed spectacularly' imports: [] twoImportJobs: summary: Two import jobs value: - id: 'bulk-import-id-1' status: 'WAIT_PR_APPROVAL' errors: [] approvalTool: GIT repository: name: 'pet-app' url: 'https://github.com/my-org/pet-app' organization: 'my-org' github: pullRequest: url: 'https://github.com/my-org/pet-app/pull/1' number: 1 - id: 'bulk-import-id-2' status: 'PR_REJECTED' errors: [] approvalTool: GIT repository: name: 'pet-app-test' url: 'https://github.com/my-org/pet-app-test' organization: 'my-org' github: pullRequest: url: 'https://github.com/my-org/pet-app-test/pull/10' number: 10 singleImportStatusForRepo: summary: Single import job status for given repo value: id: 'bulk-import-id-1' status: 'WAIT_PR_APPROVAL' errors: [] approvalTool: GIT repository: name: 'pet-app' url: 'https://github.com/my-org/pet-app' organization: 'my-org' github: pullRequest: url: 'https://github.com/my-org/pet-app/pull/1' number: 1 multipleImportRequests: summary: Multiple import requests value: - approvalTool: GIT repository: name: 'pet-app' url: 'https://github.com/my-org/pet-app' organization: 'my-org' defaultBranch: main github: pullRequest: title: 'Add default catalog-info.yaml to import to Red Hat Developer Hub' - approvalTool: GIT repository: name: 'project-zero' url: 'https://ghe.example.com/my-other-org/project-zero' organization: 'my-other-org' defaultBranch: dev github: pullRequest: title: 'Add custom catalog-info.yaml to import to Red Hat Developer Hub' body: |- This pull request adds a **Backstage entity metadata file** to this repository so that the component can be added to the Red Hat Developer Hub software catalog. After this pull request is merged, the component will become available. For more information, read an [overview of the Backstage software catalog](https://backstage.io/docs/features/software-catalog/). catalogInfoContent: |- apiVersion: backstage.io/v1alpha1 kind: Component metadata: name: project-zero annotations: github.com/project-slug: my-other-org/project-zero acme.com/custom-annotation: my-value spec: type: other lifecycle: unknown owner: my-other-org