diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 5910d4674c..49d5f09fcf 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -35,7 +35,7 @@ import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; import { Router as LighthouseRouter } from '@backstage/plugin-lighthouse'; import { Router as RegisterComponentRouter } from '@backstage/plugin-register-component'; import { Router as SettingsRouter } from '@backstage/plugin-user-settings'; -import { Router as ImportComponentRouter } from '@backstage/plugin-catalog-import'; +import { CatalogImportPage } from '@backstage/plugin-catalog-import'; import { Route, Navigate } from 'react-router'; import { EntityPage } from './components/catalog/EntityPage'; @@ -69,7 +69,7 @@ const catalogRouteRef = createRouteRef({ const routes = ( - } /> + } /> } diff --git a/plugins/catalog-import/README.md b/plugins/catalog-import/README.md index c9583eb874..3befeb7918 100644 --- a/plugins/catalog-import/README.md +++ b/plugins/catalog-import/README.md @@ -7,7 +7,7 @@ It also assists by creating pull requests in repositories where no `catalog-info Current features: -- Import `catalog-info.yaml` files from a URL in a repository of one of the supported Git integrations (example `https://github.com/backstage/backstage/catalog.info`). +- Import `catalog-info.yaml` files from a URL in a repository of one of the supported Git integrations (example `https://github.com/backstage/backstage/catalog-info.yaml`). - _[GitHub only]_ Search for all `catalog-info.yaml` files in a Git repository (example: `https://github.com/backstage/backstage`). - _[GitHub only]_ Analyze a repository, generate a Component entity, and create a Pull Request to onboard the repository. @@ -28,40 +28,38 @@ yarn add @backstage/plugin-catalog-import ```ts // packages/app/src/plugins.ts -export { plugin as CatalogImportPlugin } from '@backstage/plugin-catalog-import'; +export { catalogImportPlugin } from '@backstage/plugin-catalog-import'; ``` -3. Register the `ImportComponentRouter` at the `/catalog-import` path: +3. Register the `CatalogImportPage` at the `/catalog-import` path: ```tsx // packages/app/src/App.tsx -import { Router as ImportComponentRouter } from '@backstage/plugin-catalog-import'; +import { CatalogImportPage } from '@backstage/plugin-catalog-import'; -} />; +} />; ``` ## Customizations ### Disable the creation of Pull Requests -The pull request feature can be disabled by options that are passed to the `ImportComponentRouter`: +The pull request feature can be disabled by options that are passed to the `CatalogImportPage`: ```tsx // packages/app/src/App.tsx - } + element={} /> ``` ### Customize the title and body of the Pull Request The pull request form is filled with a default title and body. -This can be configured by options that are passed to the `ImportComponentRouter`: +This can be configured by options that are passed to the `CatalogImportPage`: ```tsx // packages/app/src/App.tsx @@ -69,7 +67,7 @@ This can be configured by options that are passed to the `ImportComponentRouter` ({ diff --git a/plugins/catalog-import/dev/index.tsx b/plugins/catalog-import/dev/index.tsx index fc0a4c6c1b..e794628e6c 100644 --- a/plugins/catalog-import/dev/index.tsx +++ b/plugins/catalog-import/dev/index.tsx @@ -16,15 +16,18 @@ import { CatalogApi } from '@backstage/catalog-client'; import { Entity, EntityName } from '@backstage/catalog-model'; -import { Content, Header, Page } from '@backstage/core'; +import { Content, Header, InfoCard, Page } from '@backstage/core'; import { createDevApp } from '@backstage/dev-utils'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { Grid } from '@material-ui/core'; +import { Grid, ListItem, ListItemIcon, ListItemText } from '@material-ui/core'; +import AlarmIcon from '@material-ui/icons/Alarm'; +import LocationOnIcon from '@material-ui/icons/LocationOn'; import React from 'react'; import { AnalyzeResult, CatalogImportApi, catalogImportApiRef, + EntityListComponent, ImportStepper, } from '../src'; import { ImportComponentPage } from '../src/components/ImportComponentPage'; @@ -61,6 +64,59 @@ const getEntities = (url: string): Entity[] => [ }, ]; +const locations = [ + { + target: 'https://my-location-1', + entities: [ + { + kind: 'Domain', + namespace: 'default', + name: 'my-domain', + }, + { + kind: 'Group', + namespace: 'groups', + name: 'my-group', + }, + { + kind: 'Location', + namespace: 'default', + name: 'my-location', + }, + { + kind: 'System', + namespace: 'default', + name: 'my-system', + }, + { + kind: 'User', + namespace: 'users', + name: 'my-api', + }, + ], + }, + { + target: 'https://my-location-2', + entities: [ + { + kind: 'API', + namespace: 'default', + name: 'my-api', + }, + { + kind: 'Component', + namespace: 'default', + name: 'my-component', + }, + { + kind: 'Location', + namespace: 'default', + name: 'my-location', + }, + ], + }, +]; + createDevApp() .registerApi({ api: catalogApiRef, @@ -225,4 +281,71 @@ createDevApp() ), }) + .addPage({ + title: 'Components', + element: ( + +
+ + + + + } + /> + + + + + + + + + + + } + locations={locations} + locationListItemIcon={() => } + onItemClick={() => {}} + /> + + + + + } + /> + + + + + } + withLinks + /> + + + + + + ), + }) .render(); diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index c35b2b7bde..ab02da8798 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -41,7 +41,6 @@ "@material-ui/lab": "4.0.0-alpha.45", "@octokit/rest": "^18.0.12", "@types/react": "^16.9", - "cross-fetch": "^3.0.6", "git-url-parse": "^11.4.4", "react": "^16.13.1", "react-dom": "^16.13.1", diff --git a/plugins/catalog-import/src/api/CatalogImportApi.ts b/plugins/catalog-import/src/api/CatalogImportApi.ts index 7a72bcddfe..5237e0339f 100644 --- a/plugins/catalog-import/src/api/CatalogImportApi.ts +++ b/plugins/catalog-import/src/api/CatalogImportApi.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import { Entity, EntityName } from '@backstage/catalog-model'; +import { EntityName } from '@backstage/catalog-model'; import { createApiRef } from '@backstage/core'; +import { PartialEntity } from '../types'; export const catalogImportApiRef = createApiRef({ id: 'plugin.catalog-import.service', @@ -35,7 +36,7 @@ export type AnalyzeResult = type: 'repository'; url: string; integrationType: string; - generatedEntities: Entity[]; + generatedEntities: PartialEntity[]; }; export interface CatalogImportApi { @@ -43,7 +44,6 @@ export interface CatalogImportApi { submitPullRequest(options: { repositoryUrl: string; - integrationType: string; fileContent: string; title: string; body: string; diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index cefe74e8ba..324c4773b2 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -284,7 +284,6 @@ describe('CatalogImportClient', () => { await expect( catalogImportClient.submitPullRequest({ - integrationType: 'github', repositoryUrl: 'https://github.com/backstage/backstage', fileContent: 'some content', title: 'A title', diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 1cdd726a9a..265a3d3946 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -19,7 +19,6 @@ import { Entity, EntityName } from '@backstage/catalog-model'; import { ConfigApi, DiscoveryApi, OAuthApi } from '@backstage/core'; import { GitHubIntegrationConfig } from '@backstage/integration'; import { Octokit } from '@octokit/rest'; -import fetch from 'cross-fetch'; import { AnalyzeResult, CatalogImportApi } from './CatalogImportApi'; import { getGithubIntegrationConfig } from './GitHub'; @@ -94,20 +93,19 @@ export class CatalogImportClient implements CatalogImportApi { } async submitPullRequest({ - integrationType, repositoryUrl, fileContent, title, body, }: { repositoryUrl: string; - integrationType: string; fileContent: string; title: string; body: string; }): Promise<{ link: string; location: string }> { const ghConfig = getGithubIntegrationConfig(this.configApi, repositoryUrl); - if (integrationType === 'github' && ghConfig) { + + if (ghConfig) { return await this.submitGitHubPrToRepo({ ...ghConfig, fileContent, diff --git a/plugins/catalog-import/src/api/GitHub.ts b/plugins/catalog-import/src/api/GitHub.ts index 7805e8fb59..6a798ec201 100644 --- a/plugins/catalog-import/src/api/GitHub.ts +++ b/plugins/catalog-import/src/api/GitHub.ts @@ -15,28 +15,25 @@ */ import { ConfigApi } from '@backstage/core'; - -// TODO: (O5ten) Refactor into a core API instead of direct usage like this -// https://github.com/backstage/backstage/pull/3613#issuecomment-7408929430 -import { readGitHubIntegrationConfigs } from '@backstage/integration'; +import { ScmIntegrations } from '@backstage/integration'; import parseGitUrl from 'git-url-parse'; export const getGithubIntegrationConfig = ( config: ConfigApi, location: string, ) => { - const { name: repo, owner, resource: hostname } = parseGitUrl(location); + const { name: repo, owner } = parseGitUrl(location); + + const scmIntegrations = ScmIntegrations.fromConfig(config); + const githubIntegrationConfig = scmIntegrations.github.byUrl(location); - const configs = readGitHubIntegrationConfigs( - config.getOptionalConfigArray('integrations.github') ?? [], - ); - const githubIntegrationConfig = configs.find(v => v.host === hostname); if (!githubIntegrationConfig) { return undefined; } + return { repo, owner, - githubIntegrationConfig, + githubIntegrationConfig: githubIntegrationConfig.config, }; }; diff --git a/plugins/catalog-import/src/components/Buttons/index.tsx b/plugins/catalog-import/src/components/Buttons/index.tsx index 18f968a32b..93dd96b399 100644 --- a/plugins/catalog-import/src/components/Buttons/index.tsx +++ b/plugins/catalog-import/src/components/Buttons/index.tsx @@ -40,6 +40,7 @@ const useStyles = makeStyles(theme => ({ export const NextButton = ( props: ComponentProps & { loading?: boolean }, ) => { + const { loading, ...buttonProps } = props; const classes = useStyles(); return ( @@ -47,11 +48,11 @@ export const NextButton = (