From 877f46c1777f16acf84b3884a2a5c5ab59bf90d5 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 29 Jan 2021 16:15:34 -0500 Subject: [PATCH 01/25] Support custom status codes --- .../reader/components/TechDocsNotFound.test.tsx | 17 +++++++++++++++++ .../src/reader/components/TechDocsNotFound.tsx | 5 +++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/plugins/techdocs/src/reader/components/TechDocsNotFound.test.tsx b/plugins/techdocs/src/reader/components/TechDocsNotFound.test.tsx index d3c98fec78..c6562ec8ad 100644 --- a/plugins/techdocs/src/reader/components/TechDocsNotFound.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsNotFound.test.tsx @@ -41,3 +41,20 @@ describe('', ( expect(rendered.getByTestId('go-back-link')).toBeDefined(); }); }); + +describe('', () => { + it('should render with a custom status code, custom error message and go back link', () => { + const rendered = render( + wrapInTestApp( + , + ), + ); + rendered.getByText(/This is a custom error message/i); + rendered.getByText(/500/i); + rendered.getByText(/Looks like someone dropped the mic!/i); + expect(rendered.getByTestId('go-back-link')).toBeDefined(); + }); +}); diff --git a/plugins/techdocs/src/reader/components/TechDocsNotFound.tsx b/plugins/techdocs/src/reader/components/TechDocsNotFound.tsx index cdacc1cb7e..04f2106161 100644 --- a/plugins/techdocs/src/reader/components/TechDocsNotFound.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsNotFound.tsx @@ -19,9 +19,10 @@ import { ErrorPage, useApi, configApiRef } from '@backstage/core'; type Props = { errorMessage?: string; + statusCode?: number; }; -export const TechDocsNotFound = ({ errorMessage }: Props) => { +export const TechDocsNotFound = ({ errorMessage, statusCode }: Props) => { const techdocsBuilder = useApi(configApiRef).getOptionalString( 'techdocs.builder', ); @@ -37,7 +38,7 @@ export const TechDocsNotFound = ({ errorMessage }: Props) => { return ( From cb61bc8cbb3c0d58dcfc4d74aaeeeb38bb6df263 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 29 Jan 2021 16:16:14 -0500 Subject: [PATCH 02/25] Hardcode file not found status --- plugins/techdocs/src/reader/components/Reader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 1264e2b6eb..c9e76ddeeb 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -155,7 +155,7 @@ export const Reader = ({ entityId, onReady }: Props) => { ]); if (error) { - return ; + return ; } return ( From 45de779d5fa75721dd8bb1865c3e63a8ba8c4976 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 29 Jan 2021 16:20:07 -0500 Subject: [PATCH 03/25] Add changeset --- .changeset/green-rabbits-burn.md | 5 +++++ plugins/techdocs/src/api.ts | 24 ++++++++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 .changeset/green-rabbits-burn.md diff --git a/.changeset/green-rabbits-burn.md b/.changeset/green-rabbits-burn.md new file mode 100644 index 0000000000..5af68c2000 --- /dev/null +++ b/.changeset/green-rabbits-burn.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Enhance API calls to support trapping 500 errors from techdocs-backend diff --git a/plugins/techdocs/src/api.ts b/plugins/techdocs/src/api.ts index 3a950aeeb3..5f2cf924d7 100644 --- a/plugins/techdocs/src/api.ts +++ b/plugins/techdocs/src/api.ts @@ -119,14 +119,22 @@ export class TechDocsStorageApi implements TechDocsStorage { `${url.endsWith('/') ? url : `${url}/`}index.html`, ); - if (request.status === 404) { - let errorMessage = 'Page not found. '; - // path is empty for the home page of an entity's docs site - if (!path) { - errorMessage += - 'This could be because there is no index.md file in the root of the docs directory of this repository.'; - } - throw new Error(errorMessage); + let errorMessage = ''; + switch (request.status) { + case 404: + errorMessage = 'Page not found. '; + // path is empty for the home page of an entity's docs site + if (!path) { + errorMessage += + 'This could be because there is no index.md file in the root of the docs directory of this repository.'; + } + throw new Error(errorMessage); + case 500: + errorMessage = 'Could not generate documentation. '; + throw new Error(errorMessage); + default: + // Do nothing + break; } return request.text(); From 96dbdfbb41a65524411cce4544abd1f64fba4ded Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Sun, 31 Jan 2021 22:02:25 -0500 Subject: [PATCH 04/25] Update error message --- plugins/techdocs/src/api.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/techdocs/src/api.ts b/plugins/techdocs/src/api.ts index 5f2cf924d7..fc007503fa 100644 --- a/plugins/techdocs/src/api.ts +++ b/plugins/techdocs/src/api.ts @@ -130,7 +130,8 @@ export class TechDocsStorageApi implements TechDocsStorage { } throw new Error(errorMessage); case 500: - errorMessage = 'Could not generate documentation. '; + errorMessage = + 'Could not generate documentation or an error in the TechDocs backend. '; throw new Error(errorMessage); default: // Do nothing From 7716d1d709d3258a86ca3f9cd1ca2d5536e7f805 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 2 Feb 2021 23:47:25 +0100 Subject: [PATCH 05/25] kafka: migrate to new composability API --- .changeset/sixty-lemons-agree.md | 5 +++++ plugins/kafka/dev/index.tsx | 4 ++-- plugins/kafka/src/Router.tsx | 23 ++++++++++++++++++----- plugins/kafka/src/index.ts | 12 ++++++++++-- plugins/kafka/src/plugin.test.ts | 4 ++-- plugins/kafka/src/plugin.ts | 13 ++++++++++++- 6 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 .changeset/sixty-lemons-agree.md diff --git a/.changeset/sixty-lemons-agree.md b/.changeset/sixty-lemons-agree.md new file mode 100644 index 0000000000..7fc438b433 --- /dev/null +++ b/.changeset/sixty-lemons-agree.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kafka': patch +--- + +Migrate to new composability API, exporting the plugin instance as `kafkaPlugin`, entity content as `EntityKafkaContent`, and entity conditional as `isKafkaAvailable`. diff --git a/plugins/kafka/dev/index.tsx b/plugins/kafka/dev/index.tsx index 264d6f801f..5506d47026 100644 --- a/plugins/kafka/dev/index.tsx +++ b/plugins/kafka/dev/index.tsx @@ -14,6 +14,6 @@ * limitations under the License. */ import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src/plugin'; +import { kafkaPlugin } from '../src/plugin'; -createDevApp().registerPlugin(plugin).render(); +createDevApp().registerPlugin(kafkaPlugin).render(); diff --git a/plugins/kafka/src/Router.tsx b/plugins/kafka/src/Router.tsx index b445f8f408..13503fefe8 100644 --- a/plugins/kafka/src/Router.tsx +++ b/plugins/kafka/src/Router.tsx @@ -17,7 +17,7 @@ import { Entity } from '@backstage/catalog-model'; import React from 'react'; import { Route, Routes } from 'react-router'; - +import { useEntity } from '@backstage/plugin-catalog-react'; import { rootCatalogKafkaRouteRef } from './plugin'; import { KAFKA_CONSUMER_GROUP_ANNOTATION } from './constants'; import { KafkaTopicsForConsumer } from './components/ConsumerGroupOffsets/ConsumerGroupOffsets'; @@ -26,10 +26,23 @@ import { MissingAnnotationEmptyState } from '@backstage/core'; export const isPluginApplicableToEntity = (entity: Entity) => Boolean(entity.metadata.annotations?.[KAFKA_CONSUMER_GROUP_ANNOTATION]); -export const Router = ({ entity }: { entity: Entity }) => { - return !isPluginApplicableToEntity(entity) ? ( - - ) : ( +type Props = { + /** @deprecated The entity is now grabbed from context instead */ + entity?: Entity; +}; + +export const Router = (_props: Props) => { + const { entity } = useEntity(); + + if (!isPluginApplicableToEntity(entity)) { + return ( + + ); + } + + return ( { it('should export plugin', () => { - expect(plugin).toBeDefined(); + expect(kafkaPlugin).toBeDefined(); }); }); diff --git a/plugins/kafka/src/plugin.ts b/plugins/kafka/src/plugin.ts index 878a7f56e9..832099a30c 100644 --- a/plugins/kafka/src/plugin.ts +++ b/plugins/kafka/src/plugin.ts @@ -16,6 +16,7 @@ import { createApiFactory, createPlugin, + createRoutableExtension, createRouteRef, discoveryApiRef, } from '@backstage/core'; @@ -27,7 +28,7 @@ export const rootCatalogKafkaRouteRef = createRouteRef({ title: 'Kafka', }); -export const plugin = createPlugin({ +export const kafkaPlugin = createPlugin({ id: 'kafka', apis: [ createApiFactory({ @@ -36,4 +37,14 @@ export const plugin = createPlugin({ factory: ({ discoveryApi }) => new KafkaBackendClient({ discoveryApi }), }), ], + routes: { + entityContent: rootCatalogKafkaRouteRef, + }, }); + +export const EntityKafkaContent = kafkaPlugin.provide( + createRoutableExtension({ + component: () => import('./Router').then(m => m.Router), + mountPoint: rootCatalogKafkaRouteRef, + }), +); From 64b9efac2e12a8523451e98f8ce12055beb61ef5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 2 Feb 2021 23:51:30 +0100 Subject: [PATCH 06/25] kubernets: migrate to new composability API --- .changeset/shy-maps-guess.md | 5 +++++ plugins/kubernetes/dev/index.tsx | 4 ++-- plugins/kubernetes/package.json | 1 + plugins/kubernetes/src/Router.tsx | 11 +++++++++-- plugins/kubernetes/src/index.ts | 6 +++++- plugins/kubernetes/src/plugin.test.ts | 4 ++-- plugins/kubernetes/src/plugin.ts | 13 ++++++++++++- 7 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 .changeset/shy-maps-guess.md diff --git a/.changeset/shy-maps-guess.md b/.changeset/shy-maps-guess.md new file mode 100644 index 0000000000..2a50d3d461 --- /dev/null +++ b/.changeset/shy-maps-guess.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes': patch +--- + +Migrate to new composability API, exporting the plugin instance as `kubernetesPlugin` and entity content as `EntityKubernetesContent`. diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx index f352fb9c34..de93d21348 100644 --- a/plugins/kubernetes/dev/index.tsx +++ b/plugins/kubernetes/dev/index.tsx @@ -14,6 +14,6 @@ * limitations under the License. */ import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src'; +import { kubernetesPlugin } from '../src'; -createDevApp().registerPlugin(plugin).render(); +createDevApp().registerPlugin(kubernetesPlugin).render(); diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 1d985c0d10..3dc53a9ea4 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -32,6 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.0", + "@backstage/plugin-catalog-react": "^0.0.1", "@backstage/config": "^0.1.2", "@backstage/core": "^0.5.0", "@backstage/plugin-kubernetes-backend": "^0.2.6", diff --git a/plugins/kubernetes/src/Router.tsx b/plugins/kubernetes/src/Router.tsx index 20a4c04285..36851b3c46 100644 --- a/plugins/kubernetes/src/Router.tsx +++ b/plugins/kubernetes/src/Router.tsx @@ -16,15 +16,22 @@ import React from 'react'; import { Entity } from '@backstage/catalog-model'; +import { useEntity } from '@backstage/plugin-catalog-react'; import { Route, Routes } from 'react-router-dom'; - import { rootCatalogKubernetesRouteRef } from './plugin'; import { KubernetesContent } from './components/KubernetesContent'; import { MissingAnnotationEmptyState } from '@backstage/core'; const KUBERNETES_ANNOTATION = 'backstage.io/kubernetes-id'; -export const Router = ({ entity }: { entity: Entity }) => { +type Props = { + /** @deprecated The entity is now grabbed from context instead */ + entity?: Entity; +}; + +export const Router = (_props: Props) => { + const { entity } = useEntity(); + const kubernetesAnnotationValue = entity.metadata.annotations?.[KUBERNETES_ANNOTATION]; diff --git a/plugins/kubernetes/src/index.ts b/plugins/kubernetes/src/index.ts index 8b5969666c..eca6b068f1 100644 --- a/plugins/kubernetes/src/index.ts +++ b/plugins/kubernetes/src/index.ts @@ -13,5 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { plugin } from './plugin'; +export { + kubernetesPlugin, + kubernetesPlugin as plugin, + EntityKubernetesContent, +} from './plugin'; export { Router } from './Router'; diff --git a/plugins/kubernetes/src/plugin.test.ts b/plugins/kubernetes/src/plugin.test.ts index 20c50a813a..f176b7f451 100644 --- a/plugins/kubernetes/src/plugin.test.ts +++ b/plugins/kubernetes/src/plugin.test.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { plugin } from './plugin'; +import { kubernetesPlugin } from './plugin'; describe('kubernetes', () => { it('should export plugin', () => { - expect(plugin).toBeDefined(); + expect(kubernetesPlugin).toBeDefined(); }); }); diff --git a/plugins/kubernetes/src/plugin.ts b/plugins/kubernetes/src/plugin.ts index cff9e1468b..af29df3dcc 100644 --- a/plugins/kubernetes/src/plugin.ts +++ b/plugins/kubernetes/src/plugin.ts @@ -19,6 +19,7 @@ import { createRouteRef, discoveryApiRef, googleAuthApiRef, + createRoutableExtension, } from '@backstage/core'; import { KubernetesBackendClient } from './api/KubernetesBackendClient'; import { kubernetesApiRef } from './api/types'; @@ -30,7 +31,7 @@ export const rootCatalogKubernetesRouteRef = createRouteRef({ title: 'Kubernetes', }); -export const plugin = createPlugin({ +export const kubernetesPlugin = createPlugin({ id: 'kubernetes', apis: [ createApiFactory({ @@ -47,4 +48,14 @@ export const plugin = createPlugin({ }, }), ], + routes: { + entityContent: rootCatalogKubernetesRouteRef, + }, }); + +export const EntityKubernetesContent = kubernetesPlugin.provide( + createRoutableExtension({ + component: () => import('./Router').then(m => m.Router), + mountPoint: rootCatalogKubernetesRouteRef, + }), +); From c5ab91ce3c697da8453123e64ad574c692356fe1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 2 Feb 2021 23:57:50 +0100 Subject: [PATCH 07/25] newrelic: migrate to new composability API --- .changeset/shiny-falcons-marry.md | 5 +++++ plugins/newrelic/dev/index.tsx | 4 ++-- plugins/newrelic/src/index.ts | 6 +++++- plugins/newrelic/src/plugin.test.ts | 4 ++-- plugins/newrelic/src/plugin.ts | 14 +++++++++++++- 5 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 .changeset/shiny-falcons-marry.md diff --git a/.changeset/shiny-falcons-marry.md b/.changeset/shiny-falcons-marry.md new file mode 100644 index 0000000000..4dda68d693 --- /dev/null +++ b/.changeset/shiny-falcons-marry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-newrelic': patch +--- + +Migrate to new composability API, exporting the plugin instance as `newRelicPlugin`, and the root page as `NewRelicPage`. diff --git a/plugins/newrelic/dev/index.tsx b/plugins/newrelic/dev/index.tsx index 812a5585d4..9ca421f94a 100644 --- a/plugins/newrelic/dev/index.tsx +++ b/plugins/newrelic/dev/index.tsx @@ -15,6 +15,6 @@ */ import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src/plugin'; +import { newRelicPlugin } from '../src/plugin'; -createDevApp().registerPlugin(plugin).render(); +createDevApp().registerPlugin(newRelicPlugin).render(); diff --git a/plugins/newrelic/src/index.ts b/plugins/newrelic/src/index.ts index 3a0a0fe2d3..aa4e990d6c 100644 --- a/plugins/newrelic/src/index.ts +++ b/plugins/newrelic/src/index.ts @@ -14,4 +14,8 @@ * limitations under the License. */ -export { plugin } from './plugin'; +export { + newRelicPlugin, + newRelicPlugin as plugin, + NewRelicPage, +} from './plugin'; diff --git a/plugins/newrelic/src/plugin.test.ts b/plugins/newrelic/src/plugin.test.ts index 17429a95e0..f2e8fde924 100644 --- a/plugins/newrelic/src/plugin.test.ts +++ b/plugins/newrelic/src/plugin.test.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { plugin } from './plugin'; +import { newRelicPlugin } from './plugin'; describe('newrelic', () => { it('should export plugin', () => { - expect(plugin).toBeDefined(); + expect(newRelicPlugin).toBeDefined(); }); }); diff --git a/plugins/newrelic/src/plugin.ts b/plugins/newrelic/src/plugin.ts index 5f5ba88617..d89aa813e9 100644 --- a/plugins/newrelic/src/plugin.ts +++ b/plugins/newrelic/src/plugin.ts @@ -19,6 +19,7 @@ import { createPlugin, createRouteRef, discoveryApiRef, + createRoutableExtension, } from '@backstage/core'; import { NewRelicClient, newRelicApiRef } from './api'; import NewRelicComponent from './components/NewRelicComponent'; @@ -28,7 +29,7 @@ export const rootRouteRef = createRouteRef({ title: 'newrelic', }); -export const plugin = createPlugin({ +export const newRelicPlugin = createPlugin({ id: 'newrelic', apis: [ createApiFactory({ @@ -40,4 +41,15 @@ export const plugin = createPlugin({ register({ router }) { router.addRoute(rootRouteRef, NewRelicComponent); }, + routes: { + root: rootRouteRef, + }, }); + +export const NewRelicPage = newRelicPlugin.provide( + createRoutableExtension({ + component: () => + import('./components/NewRelicComponent').then(m => m.default), + mountPoint: rootRouteRef, + }), +); From 4253f23ee29c351126b3c4cd72f4659eb5398593 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 4 Feb 2021 17:06:24 +0100 Subject: [PATCH 08/25] yarn.lock: sync after release --- package.json | 1 + yarn.lock | 32 ++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index fd130fcbbd..ad0ce2cd57 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "resolutions": { "**/@roadiehq/**/@backstage/core": "*", + "**/@roadiehq/**/@backstage/plugin-catalog": "*", "**/@roadiehq/**/@backstage/catalog-model": "*" }, "version": "1.0.0", diff --git a/yarn.lock b/yarn.lock index 482ce1f737..45f8a8b4fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2583,7 +2583,7 @@ to-fast-properties "^2.0.0" "@backstage/catalog-model@^0.2.0": - version "0.7.0" + version "0.7.1" dependencies: "@backstage/config" "^0.1.2" "@types/json-schema" "^7.0.5" @@ -2595,7 +2595,7 @@ yup "^0.29.3" "@backstage/catalog-model@^0.3.0": - version "0.7.0" + version "0.7.1" dependencies: "@backstage/config" "^0.1.2" "@types/json-schema" "^7.0.5" @@ -2607,11 +2607,11 @@ yup "^0.29.3" "@backstage/core@^0.3.0": - version "0.5.0" + version "0.6.0" dependencies: "@backstage/config" "^0.1.2" "@backstage/core-api" "^0.2.8" - "@backstage/theme" "^0.2.2" + "@backstage/theme" "^0.2.3" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.45" @@ -2645,6 +2645,30 @@ remark-gfm "^1.0.0" zen-observable "^0.8.15" +"@backstage/plugin-catalog@^0.2.0", "@backstage/plugin-catalog@^0.2.1": + version "0.3.0" + dependencies: + "@backstage/catalog-client" "^0.3.5" + "@backstage/catalog-model" "^0.7.1" + "@backstage/core" "^0.6.0" + "@backstage/plugin-catalog-react" "^0.0.2" + "@backstage/plugin-scaffolder" "^0.4.2" + "@backstage/theme" "^0.2.3" + "@material-ui/core" "^4.11.0" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.45" + "@types/react" "^16.9" + classnames "^2.2.6" + git-url-parse "^11.4.4" + moment "^2.26.0" + react "^16.13.1" + react-dom "^16.13.1" + react-helmet "6.1.0" + react-router "6.0.0-beta.0" + react-router-dom "6.0.0-beta.0" + react-use "^15.3.3" + swr "^0.3.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" From 0009804a843bd5ad3b150a3bf8d2a6fc0c2407e5 Mon Sep 17 00:00:00 2001 From: "Alex C. Bilimoria" <11621050+acbilimoria@users.noreply.github.com> Date: Thu, 4 Feb 2021 09:58:41 -0700 Subject: [PATCH 09/25] Update docker run command in deployment-other.md --- docs/getting-started/deployment-other.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/deployment-other.md b/docs/getting-started/deployment-other.md index 418a6b3dd3..e92b54d08b 100644 --- a/docs/getting-started/deployment-other.md +++ b/docs/getting-started/deployment-other.md @@ -90,7 +90,7 @@ $ docker build -t example-deployment . To run the image locally you can run: ```sh -$ docker run -p -it 7000:7000 example-deployment +$ docker run -it -p 7000:7000 example-deployment ``` You should then start to get logs in your terminal, and then you can open your From accdfeb30b019ce7ece3b080d1a7779d17650672 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 4 Feb 2021 00:38:45 +0100 Subject: [PATCH 10/25] gitops-profiles: migrate to new composability API --- .changeset/two-dogs-search.md | 5 ++++ plugins/gitops-profiles/dev/index.tsx | 4 +-- plugins/gitops-profiles/src/index.ts | 8 ++++- plugins/gitops-profiles/src/plugin.test.ts | 4 +-- plugins/gitops-profiles/src/plugin.ts | 34 ++++++++++++++++++++-- plugins/gitops-profiles/src/routes.ts | 1 + 6 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 .changeset/two-dogs-search.md diff --git a/.changeset/two-dogs-search.md b/.changeset/two-dogs-search.md new file mode 100644 index 0000000000..5f673c0cfb --- /dev/null +++ b/.changeset/two-dogs-search.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-gitops-profiles': patch +--- + +Migrated to new composability API, exporting the plugin instance as `gitopsProfilesPlugin` and pages as `GitopsProfilesClusterListPage`, `GitopsProfilesClusterPage`, and `GitopsProfilesCreatePage`. diff --git a/plugins/gitops-profiles/dev/index.tsx b/plugins/gitops-profiles/dev/index.tsx index 812a5585d4..c164e4005d 100644 --- a/plugins/gitops-profiles/dev/index.tsx +++ b/plugins/gitops-profiles/dev/index.tsx @@ -15,6 +15,6 @@ */ import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src/plugin'; +import { gitopsProfilesPlugin } from '../src/plugin'; -createDevApp().registerPlugin(plugin).render(); +createDevApp().registerPlugin(gitopsProfilesPlugin).render(); diff --git a/plugins/gitops-profiles/src/index.ts b/plugins/gitops-profiles/src/index.ts index d67bc6a864..876c7c3263 100644 --- a/plugins/gitops-profiles/src/index.ts +++ b/plugins/gitops-profiles/src/index.ts @@ -14,5 +14,11 @@ * limitations under the License. */ -export { plugin } from './plugin'; +export { + gitopsProfilesPlugin, + gitopsProfilesPlugin as plugin, + GitopsProfilesClusterListPage, + GitopsProfilesClusterPage, + GitopsProfilesCreatePage, +} from './plugin'; export * from './api'; diff --git a/plugins/gitops-profiles/src/plugin.test.ts b/plugins/gitops-profiles/src/plugin.test.ts index 19bc49eba7..fa26902f2b 100644 --- a/plugins/gitops-profiles/src/plugin.test.ts +++ b/plugins/gitops-profiles/src/plugin.test.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { plugin } from './plugin'; +import { gitopsProfilesPlugin } from './plugin'; describe('gitops-profiles', () => { it('should export plugin', () => { - expect(plugin).toBeDefined(); + expect(gitopsProfilesPlugin).toBeDefined(); }); }); diff --git a/plugins/gitops-profiles/src/plugin.ts b/plugins/gitops-profiles/src/plugin.ts index 45820644f7..98a0067969 100644 --- a/plugins/gitops-profiles/src/plugin.ts +++ b/plugins/gitops-profiles/src/plugin.ts @@ -14,7 +14,11 @@ * limitations under the License. */ -import { createPlugin, createApiFactory } from '@backstage/core'; +import { + createPlugin, + createApiFactory, + createRoutableExtension, +} from '@backstage/core'; import ProfileCatalog from './components/ProfileCatalog'; import ClusterPage from './components/ClusterPage'; import ClusterList from './components/ClusterList'; @@ -25,7 +29,7 @@ import { } from './routes'; import { gitOpsApiRef, GitOpsRestApi } from './api'; -export const plugin = createPlugin({ +export const gitopsProfilesPlugin = createPlugin({ id: 'gitops-profiles', apis: [ createApiFactory(gitOpsApiRef, new GitOpsRestApi('http://localhost:3008')), @@ -35,4 +39,30 @@ export const plugin = createPlugin({ router.addRoute(gitOpsClusterDetailsRoute, ClusterPage); router.addRoute(gitOpsClusterCreateRoute, ProfileCatalog); }, + routes: { + listPage: gitOpsClusterListRoute, + detailsPage: gitOpsClusterDetailsRoute, + createPage: gitOpsClusterCreateRoute, + }, }); + +export const GitopsProfilesClusterListPage = gitopsProfilesPlugin.provide( + createRoutableExtension({ + component: () => import('./components/ClusterList').then(m => m.default), + mountPoint: gitOpsClusterListRoute, + }), +); + +export const GitopsProfilesClusterPage = gitopsProfilesPlugin.provide( + createRoutableExtension({ + component: () => import('./components/ClusterPage').then(m => m.default), + mountPoint: gitOpsClusterDetailsRoute, + }), +); + +export const GitopsProfilesCreatePage = gitopsProfilesPlugin.provide( + createRoutableExtension({ + component: () => import('./components/ProfileCatalog').then(m => m.default), + mountPoint: gitOpsClusterCreateRoute, + }), +); diff --git a/plugins/gitops-profiles/src/routes.ts b/plugins/gitops-profiles/src/routes.ts index f9bdefa806..28be85bd38 100644 --- a/plugins/gitops-profiles/src/routes.ts +++ b/plugins/gitops-profiles/src/routes.ts @@ -28,6 +28,7 @@ export const gitOpsClusterDetailsRoute = createRouteRef({ icon: NoIcon, path: '/gitops-cluster/:owner/:repo', title: 'GitOps Cluster details', + params: ['owner', 'repo'], }); export const gitOpsClusterCreateRoute = createRouteRef({ From b288a291ee393f15f711e84d3e86d8fa8929a81e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 4 Feb 2021 00:52:33 +0100 Subject: [PATCH 11/25] pagerduty: migrate to new composability API --- .changeset/perfect-ladybugs-listen.md | 5 +++++ plugins/pagerduty/dev/index.tsx | 4 ++-- plugins/pagerduty/package.json | 1 + plugins/pagerduty/src/components/PagerDutyCard.tsx | 5 ++++- plugins/pagerduty/src/index.ts | 7 ++++++- plugins/pagerduty/src/plugin.test.ts | 4 ++-- plugins/pagerduty/src/plugin.ts | 12 +++++++++++- 7 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 .changeset/perfect-ladybugs-listen.md diff --git a/.changeset/perfect-ladybugs-listen.md b/.changeset/perfect-ladybugs-listen.md new file mode 100644 index 0000000000..2f9e65c1d9 --- /dev/null +++ b/.changeset/perfect-ladybugs-listen.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-pagerduty': patch +--- + +Migrated to new composability API, exporting the plugin instance as `pagerDutyPlugin`, entity card as `EntityPagerDutyCard`, and entity conditional as `isPagerDutyAvailable`. diff --git a/plugins/pagerduty/dev/index.tsx b/plugins/pagerduty/dev/index.tsx index 264d6f801f..ad46c0ca9e 100644 --- a/plugins/pagerduty/dev/index.tsx +++ b/plugins/pagerduty/dev/index.tsx @@ -14,6 +14,6 @@ * limitations under the License. */ import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src/plugin'; +import { pagerDutyPlugin } from '../src/plugin'; -createDevApp().registerPlugin(plugin).render(); +createDevApp().registerPlugin(pagerDutyPlugin).render(); diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index a5db20e9ab..afd41dcc46 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -31,6 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.1", + "@backstage/plugin-catalog-react": "^0.0.2", "@backstage/core": "^0.6.0", "@backstage/theme": "^0.2.3", "@material-ui/core": "^4.11.0", diff --git a/plugins/pagerduty/src/components/PagerDutyCard.tsx b/plugins/pagerduty/src/components/PagerDutyCard.tsx index 5fb2cd7f4a..f7360c01d6 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard.tsx @@ -16,6 +16,7 @@ import React, { useState, useCallback } from 'react'; import { useApi, Progress, HeaderIconLinkRow } from '@backstage/core'; import { Entity } from '@backstage/catalog-model'; +import { useEntity } from '@backstage/plugin-catalog-react'; import { Button, makeStyles, @@ -56,11 +57,13 @@ export const isPluginApplicableToEntity = (entity: Entity) => Boolean(entity.metadata.annotations?.[PAGERDUTY_INTEGRATION_KEY]); type Props = { + /** @deprecated The entity is now grabbed from context instead */ entity: Entity; }; -export const PagerDutyCard = ({ entity }: Props) => { +export const PagerDutyCard = (_props: Props) => { const classes = useStyles(); + const { entity } = useEntity(); const api = useApi(pagerDutyApiRef); const [showDialog, setShowDialog] = useState(false); const [refreshIncidents, setRefreshIncidents] = useState(false); diff --git a/plugins/pagerduty/src/index.ts b/plugins/pagerduty/src/index.ts index 4ecd4edcc6..2dfedab164 100644 --- a/plugins/pagerduty/src/index.ts +++ b/plugins/pagerduty/src/index.ts @@ -13,9 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { plugin } from './plugin'; +export { + pagerDutyPlugin, + pagerDutyPlugin as plugin, + EntityPagerDutyCard, +} from './plugin'; export { isPluginApplicableToEntity, + isPluginApplicableToEntity as isPagerDutyAvailable, PagerDutyCard, } from './components/PagerDutyCard'; export { diff --git a/plugins/pagerduty/src/plugin.test.ts b/plugins/pagerduty/src/plugin.test.ts index 8d4545ac12..c1175ab384 100644 --- a/plugins/pagerduty/src/plugin.test.ts +++ b/plugins/pagerduty/src/plugin.test.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { plugin } from './plugin'; +import { pagerDutyPlugin } from './plugin'; describe('pagerduty', () => { it('should export plugin', () => { - expect(plugin).toBeDefined(); + expect(pagerDutyPlugin).toBeDefined(); }); }); diff --git a/plugins/pagerduty/src/plugin.ts b/plugins/pagerduty/src/plugin.ts index 34796f491e..fbe827b90d 100644 --- a/plugins/pagerduty/src/plugin.ts +++ b/plugins/pagerduty/src/plugin.ts @@ -19,6 +19,7 @@ import { createRouteRef, discoveryApiRef, configApiRef, + createComponentExtension, } from '@backstage/core'; import { pagerDutyApiRef, PagerDutyClient } from './api'; @@ -27,7 +28,7 @@ export const rootRouteRef = createRouteRef({ title: 'pagerduty', }); -export const plugin = createPlugin({ +export const pagerDutyPlugin = createPlugin({ id: 'pagerduty', apis: [ createApiFactory({ @@ -38,3 +39,12 @@ export const plugin = createPlugin({ }), ], }); + +export const EntityPagerDutyCard = pagerDutyPlugin.provide( + createComponentExtension({ + component: { + lazy: () => + import('./components/PagerDutyCard').then(m => m.PagerDutyCard), + }, + }), +); From b3f0c38112be1afddc30fe4260ce3ed7dc160d18 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 4 Feb 2021 12:02:28 +0100 Subject: [PATCH 12/25] search: migrate to new composability API --- .changeset/cyan-lies-flow.md | 5 +++++ plugins/search/dev/index.tsx | 4 ++-- plugins/search/src/index.ts | 12 ++++++++++-- plugins/search/src/plugin.test.ts | 4 ++-- plugins/search/src/plugin.ts | 22 ++++++++++++++++++---- 5 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 .changeset/cyan-lies-flow.md diff --git a/.changeset/cyan-lies-flow.md b/.changeset/cyan-lies-flow.md new file mode 100644 index 0000000000..e7da9fab0a --- /dev/null +++ b/.changeset/cyan-lies-flow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': minor +--- + +Migrated to new composability API, exporting the plugin instance as `searchPlugin`, and page as `SearchPage`. Due to the old router component also being called `SearchPage`, this is a breaking change. The old page component is now exported as `Router`, which can be used to maintain the old behavior. diff --git a/plugins/search/dev/index.tsx b/plugins/search/dev/index.tsx index 264d6f801f..e6e97ead6d 100644 --- a/plugins/search/dev/index.tsx +++ b/plugins/search/dev/index.tsx @@ -14,6 +14,6 @@ * limitations under the License. */ import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src/plugin'; +import { searchPlugin } from '../src/plugin'; -createDevApp().registerPlugin(plugin).render(); +createDevApp().registerPlugin(searchPlugin).render(); diff --git a/plugins/search/src/index.ts b/plugins/search/src/index.ts index 77ad7f9266..572d75bea5 100644 --- a/plugins/search/src/index.ts +++ b/plugins/search/src/index.ts @@ -13,5 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { plugin } from './plugin'; -export * from './components'; +export { searchPlugin, searchPlugin as plugin, SearchPage } from './plugin'; +export { + Filters, + FiltersButton, + SearchBar, + SearchPage as Router, + SearchResult, + SidebarSearch, +} from './components'; +export type { FiltersState } from './components'; diff --git a/plugins/search/src/plugin.test.ts b/plugins/search/src/plugin.test.ts index 92b8d5bcbf..902faeaf9e 100644 --- a/plugins/search/src/plugin.test.ts +++ b/plugins/search/src/plugin.test.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { plugin } from './plugin'; +import { searchPlugin } from './plugin'; describe('search', () => { it('should export plugin', () => { - expect(plugin).toBeDefined(); + expect(searchPlugin).toBeDefined(); }); }); diff --git a/plugins/search/src/plugin.ts b/plugins/search/src/plugin.ts index 44c7bcb042..37503b7751 100644 --- a/plugins/search/src/plugin.ts +++ b/plugins/search/src/plugin.ts @@ -13,17 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createPlugin, createRouteRef } from '@backstage/core'; -import { SearchPage } from './components/SearchPage'; +import { + createPlugin, + createRouteRef, + createRoutableExtension, +} from '@backstage/core'; +import { SearchPage as SearchPageComponent } from './components/SearchPage'; export const rootRouteRef = createRouteRef({ path: '/search', title: 'search', }); -export const plugin = createPlugin({ +export const searchPlugin = createPlugin({ id: 'search', register({ router }) { - router.addRoute(rootRouteRef, SearchPage); + router.addRoute(rootRouteRef, SearchPageComponent); + }, + routes: { + root: rootRouteRef, }, }); + +export const SearchPage = searchPlugin.provide( + createRoutableExtension({ + component: () => import('./components/SearchPage').then(m => m.SearchPage), + mountPoint: rootRouteRef, + }), +); From 9ec66c3459d170d4bdd698e6f8b1d29b56ad9df0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 4 Feb 2021 19:57:44 +0100 Subject: [PATCH 13/25] register-component: migrated to new composability API --- .changeset/funny-students-shout.md | 5 ++++ plugins/register-component/dev/index.tsx | 4 +-- plugins/register-component/src/index.ts | 6 ++++- plugins/register-component/src/plugin.test.ts | 4 +-- plugins/register-component/src/plugin.ts | 27 ++++++++++++++++--- 5 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 .changeset/funny-students-shout.md diff --git a/.changeset/funny-students-shout.md b/.changeset/funny-students-shout.md new file mode 100644 index 0000000000..97b273c687 --- /dev/null +++ b/.changeset/funny-students-shout.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-register-component': patch +--- + +Migrated to new composability API, exporting the plugin instance as `registerComponentPlugin`, and page as `RegisterComponentPage`. diff --git a/plugins/register-component/dev/index.tsx b/plugins/register-component/dev/index.tsx index 812a5585d4..3304d0874f 100644 --- a/plugins/register-component/dev/index.tsx +++ b/plugins/register-component/dev/index.tsx @@ -15,6 +15,6 @@ */ import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src/plugin'; +import { registerComponentPlugin } from '../src/plugin'; -createDevApp().registerPlugin(plugin).render(); +createDevApp().registerPlugin(registerComponentPlugin).render(); diff --git a/plugins/register-component/src/index.ts b/plugins/register-component/src/index.ts index ff7857cacd..56bcd06fde 100644 --- a/plugins/register-component/src/index.ts +++ b/plugins/register-component/src/index.ts @@ -14,5 +14,9 @@ * limitations under the License. */ -export { plugin } from './plugin'; +export { + registerComponentPlugin, + registerComponentPlugin as plugin, + RegisterComponentPage, +} from './plugin'; export { Router } from './components/Router'; diff --git a/plugins/register-component/src/plugin.test.ts b/plugins/register-component/src/plugin.test.ts index 1e61060202..2b6ad48bcf 100644 --- a/plugins/register-component/src/plugin.test.ts +++ b/plugins/register-component/src/plugin.test.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { plugin } from './plugin'; +import { registerComponentPlugin } from './plugin'; describe('register-component', () => { it('should export plugin', () => { - expect(plugin).toBeDefined(); + expect(registerComponentPlugin).toBeDefined(); }); }); diff --git a/plugins/register-component/src/plugin.ts b/plugins/register-component/src/plugin.ts index 17f99917c8..d3727158e5 100644 --- a/plugins/register-component/src/plugin.ts +++ b/plugins/register-component/src/plugin.ts @@ -14,8 +14,29 @@ * limitations under the License. */ -import { createPlugin } from '@backstage/core'; +import { + createPlugin, + createRoutableExtension, + createRouteRef, +} from '@backstage/core'; -export const plugin = createPlugin({ - id: 'register-component', +const rootRouteRef = createRouteRef({ + title: 'Register Component', }); + +export const registerComponentPlugin = createPlugin({ + id: 'register-component', + routes: { + root: rootRouteRef, + }, +}); + +export const RegisterComponentPage = registerComponentPlugin.provide( + createRoutableExtension({ + component: () => + import('./components/RegisterComponentPage').then( + m => m.RegisterComponentPage, + ), + mountPoint: rootRouteRef, + }), +); From 41af18227fd4893a24f39cb8512556bee2e63e58 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 4 Feb 2021 20:07:12 +0100 Subject: [PATCH 14/25] techdocs: migrate to new composability API --- .changeset/ninety-houses-shout.md | 5 +++++ plugins/techdocs/dev/index.tsx | 4 ++-- plugins/techdocs/src/Router.tsx | 10 +++++++++- plugins/techdocs/src/index.ts | 7 ++++++- plugins/techdocs/src/plugin.test.ts | 4 ++-- plugins/techdocs/src/plugin.ts | 21 ++++++++++++++++++++- 6 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 .changeset/ninety-houses-shout.md diff --git a/.changeset/ninety-houses-shout.md b/.changeset/ninety-houses-shout.md new file mode 100644 index 0000000000..845decc74c --- /dev/null +++ b/.changeset/ninety-houses-shout.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Migrated to new composability API, exporting the plugin instance as `techdocsPlugin`, the top-level page as `TechdocsPage`, and the entity content as `EntityTechdocsContent`. diff --git a/plugins/techdocs/dev/index.tsx b/plugins/techdocs/dev/index.tsx index 42fa9a9ec4..4cf74c9622 100644 --- a/plugins/techdocs/dev/index.tsx +++ b/plugins/techdocs/dev/index.tsx @@ -16,7 +16,7 @@ import { configApiRef, discoveryApiRef } from '@backstage/core'; import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src/plugin'; +import { techdocsPlugin } from '../src/plugin'; import { TechDocsDevStorageApi } from './api'; import { techdocsStorageApiRef } from '../src'; @@ -30,5 +30,5 @@ createDevApp() discoveryApi, }), }) - .registerPlugin(plugin) + .registerPlugin(techdocsPlugin) .render(); diff --git a/plugins/techdocs/src/Router.tsx b/plugins/techdocs/src/Router.tsx index 262f542ee6..b220912174 100644 --- a/plugins/techdocs/src/Router.tsx +++ b/plugins/techdocs/src/Router.tsx @@ -16,6 +16,7 @@ import React from 'react'; import { Entity } from '@backstage/catalog-model'; +import { useEntity } from '@backstage/plugin-catalog-react'; import { Route, Routes } from 'react-router-dom'; import { MissingAnnotationEmptyState } from '@backstage/core'; import { @@ -38,7 +39,14 @@ export const Router = () => { ); }; -export const EmbeddedDocsRouter = ({ entity }: { entity: Entity }) => { +type Props = { + /** @deprecated The entity is now grabbed from context instead */ + entity?: Entity; +}; + +export const EmbeddedDocsRouter = (_props: Props) => { + const { entity } = useEntity(); + const projectId = entity.metadata.annotations?.[TECHDOCS_ANNOTATION]; if (!projectId) { diff --git a/plugins/techdocs/src/index.ts b/plugins/techdocs/src/index.ts index 1726e0daf3..30c143e31f 100644 --- a/plugins/techdocs/src/index.ts +++ b/plugins/techdocs/src/index.ts @@ -14,7 +14,12 @@ * limitations under the License. */ -export { plugin } from './plugin'; +export { + techdocsPlugin, + techdocsPlugin as plugin, + TechdocsPage, + EntityTechdocsContent, +} from './plugin'; export { Router, EmbeddedDocsRouter } from './Router'; export * from './reader'; export * from './api'; diff --git a/plugins/techdocs/src/plugin.test.ts b/plugins/techdocs/src/plugin.test.ts index e750be9ac3..52f072627c 100644 --- a/plugins/techdocs/src/plugin.test.ts +++ b/plugins/techdocs/src/plugin.test.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { plugin } from './plugin'; +import { techdocsPlugin } from './plugin'; describe('techdocs', () => { it('should export plugin', () => { - expect(plugin).toBeDefined(); + expect(techdocsPlugin).toBeDefined(); }); }); diff --git a/plugins/techdocs/src/plugin.ts b/plugins/techdocs/src/plugin.ts index 982b749f2c..0b4063c237 100644 --- a/plugins/techdocs/src/plugin.ts +++ b/plugins/techdocs/src/plugin.ts @@ -35,6 +35,7 @@ import { createApiFactory, configApiRef, discoveryApiRef, + createRoutableExtension, } from '@backstage/core'; import { techdocsStorageApiRef, @@ -58,7 +59,7 @@ export const rootCatalogDocsRouteRef = createRouteRef({ title: 'Docs', }); -export const plugin = createPlugin({ +export const techdocsPlugin = createPlugin({ id: 'techdocs', apis: [ createApiFactory({ @@ -80,4 +81,22 @@ export const plugin = createPlugin({ }), }), ], + routes: { + root: rootRouteRef, + entityContent: rootCatalogDocsRouteRef, + }, }); + +export const TechdocsPage = techdocsPlugin.provide( + createRoutableExtension({ + component: () => import('./Router').then(m => m.Router), + mountPoint: rootRouteRef, + }), +); + +export const EntityTechdocsContent = techdocsPlugin.provide( + createRoutableExtension({ + component: () => import('./Router').then(m => m.EmbeddedDocsRouter), + mountPoint: rootCatalogDocsRouteRef, + }), +); From 7c789117881a4654822383ebfcdea88066b1a9bd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 4 Feb 2021 20:36:18 +0100 Subject: [PATCH 15/25] pagerduty: fix entity card tests --- .../src/components/PagerDutyCard.test.tsx | 17 +++++++++++++---- .../pagerduty/src/components/PagerDutyCard.tsx | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/plugins/pagerduty/src/components/PagerDutyCard.test.tsx b/plugins/pagerduty/src/components/PagerDutyCard.test.tsx index a6615aee82..a719a27f86 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard.test.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard.test.tsx @@ -17,6 +17,7 @@ import React from 'react'; import { render, waitFor, fireEvent, act } from '@testing-library/react'; import { PagerDutyCard } from './PagerDutyCard'; import { Entity } from '@backstage/catalog-model'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; import { wrapInTestApp } from '@backstage/test-utils'; import { alertApiRef, @@ -80,7 +81,9 @@ describe('PageDutyCard', () => { const { getByText, queryByTestId } = render( wrapInTestApp( - + + + , ), ); @@ -99,7 +102,9 @@ describe('PageDutyCard', () => { const { getByText, queryByTestId } = render( wrapInTestApp( - + + + , ), ); @@ -114,7 +119,9 @@ describe('PageDutyCard', () => { const { getByText, queryByTestId } = render( wrapInTestApp( - + + + , ), ); @@ -134,7 +141,9 @@ describe('PageDutyCard', () => { const { getByText, queryByTestId, getByTestId, getByRole } = render( wrapInTestApp( - + + + , ), ); diff --git a/plugins/pagerduty/src/components/PagerDutyCard.tsx b/plugins/pagerduty/src/components/PagerDutyCard.tsx index f7360c01d6..e03fb0fdbe 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard.tsx @@ -58,7 +58,7 @@ export const isPluginApplicableToEntity = (entity: Entity) => type Props = { /** @deprecated The entity is now grabbed from context instead */ - entity: Entity; + entity?: Entity; }; export const PagerDutyCard = (_props: Props) => { From ee65c94555e786f83209355d66d451a85ec30709 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 5 Feb 2021 12:25:38 +0100 Subject: [PATCH 16/25] backend-common: ignore rate limiting errors in UrlReader integration tests --- packages/backend-common/src/reading/integration.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/backend-common/src/reading/integration.test.ts b/packages/backend-common/src/reading/integration.test.ts index 18f87636a5..16fdf3ff58 100644 --- a/packages/backend-common/src/reading/integration.test.ts +++ b/packages/backend-common/src/reading/integration.test.ts @@ -71,7 +71,11 @@ function withRetries(count: number, fn: () => Promise) { error = err; } } - throw error; + if (!error.message.match(/rate limit|Too Many Requests/)) { + throw error; + } else { + console.warn('Request was rate limited', error); + } }; } From 0e640893dfeb944a84c4c7ec993e1af5f3696253 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 5 Feb 2021 13:56:53 +0100 Subject: [PATCH 17/25] test-utils: add mountedRoutes option to wrapInTestApp --- .../src/testUtils/appWrappers.test.tsx | 27 +++++++++++++++ .../test-utils/src/testUtils/appWrappers.tsx | 34 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/packages/test-utils/src/testUtils/appWrappers.test.tsx b/packages/test-utils/src/testUtils/appWrappers.test.tsx index 29f8d97793..4899f07061 100644 --- a/packages/test-utils/src/testUtils/appWrappers.test.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.test.tsx @@ -21,9 +21,11 @@ import { Route, Routes } from 'react-router'; import { withLogCollector } from '@backstage/test-utils-core'; import { useApi, + useRouteRef, errorApiRef, ApiProvider, ApiRegistry, + createRouteRef, } from '@backstage/core-api'; import { MockErrorApi } from './apis'; @@ -113,4 +115,29 @@ describe('wrapInTestApp', () => { expect(rendered.getByText('foo')).toBeInTheDocument(); expect(mockErrorApi.getErrors()).toEqual([{ error: new Error('NOPE') }]); }); + + it('should allow route refs to be mounted on specific paths', async () => { + const aRouteRef = createRouteRef({ title: 'A' }); + const bRouteRef = createRouteRef({ title: 'B', params: ['name'] }); + + const MyComponent = () => { + const a = useRouteRef(aRouteRef); + const b = useRouteRef(bRouteRef); + return ( +
+
Link A: {a()}
+
Link B: {b({ name: 'x' })}
+
+ ); + }; + + const rendered = await renderInTestApp(, { + mountedRoutes: { + '/my-a-path': aRouteRef, + '/my-b-path/:name': bRouteRef, + }, + }); + expect(rendered.getByText('Link A: /my-a-path')).toBeInTheDocument(); + expect(rendered.getByText('Link B: /my-b-path/x')).toBeInTheDocument(); + }); }); diff --git a/packages/test-utils/src/testUtils/appWrappers.tsx b/packages/test-utils/src/testUtils/appWrappers.tsx index 1f6c7622b8..cc67a5b707 100644 --- a/packages/test-utils/src/testUtils/appWrappers.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.tsx @@ -21,6 +21,9 @@ import { lightTheme } from '@backstage/theme'; import privateExports, { defaultSystemIcons, BootErrorPageProps, + RouteRef, + createPlugin, + createRoutableExtension, } from '@backstage/core-api'; import { RenderResult } from '@testing-library/react'; import { renderWithEffects } from '@backstage/test-utils-core'; @@ -44,6 +47,22 @@ type TestAppOptions = { * Initial route entries to pass along as `initialEntries` to the router. */ routeEntries?: string[]; + + /** + * An object of paths to mount route ref on, with the key being the path and the value + * being the RouteRef that the path will be bound to. This allows the route refs to be + * used by `useRouteRef` in the rendered elements. + * + * @example + * wrapInTestApp(, { + * mountedRoutes: { + * '/my-path': myRouteRef, + * } + * }) + * // ... + * const link = useRouteRef(myRouteRef) + */ + mountedRoutes?: { [path: string]: RouteRef }; }; /** @@ -90,12 +109,27 @@ export function wrapInTestApp( Wrapper = () => Component as React.ReactElement; } + const routePlugin = createPlugin({ id: 'mock-route-plugin' }); + const routeElements = Object.entries(options.mountedRoutes ?? {}).map( + ([path, routeRef]) => { + const PageComponent = () =>
Mounted at {path}
; + const Page = routePlugin.provide( + createRoutableExtension({ + component: async () => PageComponent, + mountPoint: routeRef, + }), + ); + return } />; + }, + ); + const AppProvider = app.getProvider(); const AppRouter = app.getRouter(); return ( + {routeElements} {/* The path of * here is needed to be set as a catch all, so it will render the wrapper element * and work with nested routes if they exist too */} } /> From 8f3443427287abf6408d686739bc2fc84043fe27 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 5 Feb 2021 10:49:12 -0500 Subject: [PATCH 18/25] Rename green-rabbits-burn.md to techdocs-green-rabbits-burn.md --- .../{green-rabbits-burn.md => techdocs-green-rabbits-burn.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changeset/{green-rabbits-burn.md => techdocs-green-rabbits-burn.md} (100%) diff --git a/.changeset/green-rabbits-burn.md b/.changeset/techdocs-green-rabbits-burn.md similarity index 100% rename from .changeset/green-rabbits-burn.md rename to .changeset/techdocs-green-rabbits-burn.md From fd933c4239e4099034f6c0bafd6a124f5d78f85b Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 5 Feb 2021 10:50:11 -0500 Subject: [PATCH 19/25] Add comment TODO --- plugins/techdocs/src/reader/components/Reader.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index c9e76ddeeb..f1937ae8a8 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -155,6 +155,8 @@ export const Reader = ({ entityId, onReady }: Props) => { ]); if (error) { + // TODO Enhance API call to return customize error objects so we can identify which we ran into + // For now this defaults to display error code 404 return ; } From 2ab3b3f0e3614de2faed69f23387b2969de4d510 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 5 Feb 2021 17:49:41 +0100 Subject: [PATCH 20/25] core-api: fix type inference of createRouteRef --- packages/core-api/src/routing/RouteRef.ts | 23 ++++++++++++++++---- packages/core-api/src/routing/hooks.test.tsx | 3 ++- packages/core-api/src/routing/index.ts | 2 +- packages/core-api/src/routing/types.ts | 8 ------- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/core-api/src/routing/RouteRef.ts b/packages/core-api/src/routing/RouteRef.ts index 4c2da34098..3f48d70827 100644 --- a/packages/core-api/src/routing/RouteRef.ts +++ b/packages/core-api/src/routing/RouteRef.ts @@ -14,7 +14,16 @@ * limitations under the License. */ -import { RouteRefConfig, RouteRef } from './types'; +import { RouteRef } from './types'; +import { IconComponent } from '../icons'; + +export type RouteRefConfig = { + params?: Array; + /** @deprecated Route refs no longer decide their own path */ + path?: string; + icon?: IconComponent; + title: string; +}; export class AbsoluteRouteRef { constructor(private readonly config: RouteRefConfig) {} @@ -38,9 +47,15 @@ export class AbsoluteRouteRef { } export function createRouteRef< - ParamKeys extends string, - Params extends { [param in string]: string } = { [name in ParamKeys]: string } ->(config: RouteRefConfig): RouteRef { + Params extends { [param in ParamKey]: string }, + ParamKey extends string = never +>(config: { + params?: ParamKey[]; + /** @deprecated Route refs no longer decide their own path */ + path?: string; + icon?: IconComponent; + title: string; +}): RouteRef { return new AbsoluteRouteRef(config); } diff --git a/packages/core-api/src/routing/hooks.test.tsx b/packages/core-api/src/routing/hooks.test.tsx index 3dbeaf8e3e..84a8314807 100644 --- a/packages/core-api/src/routing/hooks.test.tsx +++ b/packages/core-api/src/routing/hooks.test.tsx @@ -39,8 +39,9 @@ import { createRouteRef, createExternalRouteRef, ExternalRouteRef, + RouteRefConfig, } from './RouteRef'; -import { RouteRef, RouteRefConfig } from './types'; +import { RouteRef } from './types'; const mockConfig = (extra?: Partial>) => ({ path: '/unused', diff --git a/packages/core-api/src/routing/index.ts b/packages/core-api/src/routing/index.ts index 9564b3b225..af71e0c3e9 100644 --- a/packages/core-api/src/routing/index.ts +++ b/packages/core-api/src/routing/index.ts @@ -16,11 +16,11 @@ export type { RouteRef, - RouteRefConfig, AbsoluteRouteRef, ConcreteRoute, MutableRouteRef, } from './types'; export { FlatRoutes } from './FlatRoutes'; export { createRouteRef } from './RouteRef'; +export type { RouteRefConfig } from './RouteRef'; export { useRouteRef } from './hooks'; diff --git a/packages/core-api/src/routing/types.ts b/packages/core-api/src/routing/types.ts index 99a20c31e9..5f9376c1d2 100644 --- a/packages/core-api/src/routing/types.ts +++ b/packages/core-api/src/routing/types.ts @@ -45,14 +45,6 @@ export type AbsoluteRouteRef = RouteRef<{}>; */ export type MutableRouteRef = RouteRef<{}>; -export type RouteRefConfig = { - params?: Array; - /** @deprecated Route refs no longer decide their own path */ - path?: string; - icon?: IconComponent; - title: string; -}; - // A duplicate of the react-router RouteObject, but with routeRef added export interface BackstageRouteObject { caseSensitive: boolean; From b51ee6ece987552331c8673ba7452ab4bcd95575 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 5 Feb 2021 17:56:01 +0100 Subject: [PATCH 21/25] added changesets --- .changeset/poor-sheep-give.md | 5 +++++ .changeset/tricky-dancers-rush.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/poor-sheep-give.md create mode 100644 .changeset/tricky-dancers-rush.md diff --git a/.changeset/poor-sheep-give.md b/.changeset/poor-sheep-give.md new file mode 100644 index 0000000000..4c52594b35 --- /dev/null +++ b/.changeset/poor-sheep-give.md @@ -0,0 +1,5 @@ +--- +'@backstage/test-utils': patch +--- + +Added `mountedRoutes` option to `wrapInTestApp`, allowing routes to be associated to concrete paths to make `useRouteRef` usable in tested components. diff --git a/.changeset/tricky-dancers-rush.md b/.changeset/tricky-dancers-rush.md new file mode 100644 index 0000000000..301b23d98e --- /dev/null +++ b/.changeset/tricky-dancers-rush.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Fixed type inference of `createRouteRef`. From fb53eb7cb4057a33ae76f09fa1f009334adf1f51 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Fri, 5 Feb 2021 19:41:39 +0100 Subject: [PATCH 22/25] Don't respond to a request twice if an entity has not been found. --- .changeset/fluffy-hats-hug.md | 5 +++++ plugins/catalog-backend/src/service/router.ts | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 .changeset/fluffy-hats-hug.md diff --git a/.changeset/fluffy-hats-hug.md b/.changeset/fluffy-hats-hug.md new file mode 100644 index 0000000000..b3d06337fd --- /dev/null +++ b/.changeset/fluffy-hats-hug.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Don't respond to a request twice if an entity has not been found. diff --git a/plugins/catalog-backend/src/service/router.ts b/plugins/catalog-backend/src/service/router.ts index 43c2967233..6064164e31 100644 --- a/plugins/catalog-backend/src/service/router.ts +++ b/plugins/catalog-backend/src/service/router.ts @@ -76,8 +76,9 @@ export async function createRouter( ); if (!entities.length) { res.status(404).send(`No entity with uid ${uid}`); + } else { + res.status(200).send(entities[0]); } - res.status(200).send(entities[0]); }) .delete('/entities/by-uid/:uid', async (req, res) => { const { uid } = req.params; @@ -99,8 +100,9 @@ export async function createRouter( .send( `No entity with kind ${kind} namespace ${namespace} name ${name}`, ); + } else { + res.status(200).send(entities[0]); } - res.status(200).send(entities[0]); }); } From 7cdd586e579643f1213096323d11c8d4e4fe7465 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 6 Feb 2021 01:19:20 +0100 Subject: [PATCH 23/25] create-app: update changelog to put more emphasis on plugin-catalog-react migration --- packages/create-app/CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 01432ba150..5e8ff0e9b1 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -4,9 +4,9 @@ ### Patch Changes -- 019fe39a0: `@backstage/plugin-catalog` stopped exporting hooks and helpers for other - plugins. They are migrated to `@backstage/plugin-catalog-react`. - Change both your dependencies and imports to the new package. +- 019fe39a0: **BREAKING CHANGE**: The `useEntity` hooks has been moved from `@backstage/plugin-catalog` to `@backstage/plugin-catalog-react`. + To apply this change to an existing app, add `@backstage/plugin-catalog-react` to your dependencies in `packages/app/package.json`, and update + the import inside `packages/app/src/components/catalog/EntityPage.tsx` as well as any other places you were using `useEntity` or any other functions that were moved to `@backstage/plugin-catalog-react`. - 436ca3f62: Remove techdocs.requestUrl and techdocs.storageUrl from app-config.yaml - Updated dependencies [ceef4dd89] - Updated dependencies [720149854] From bee68316675ad51de20a750a980a2cc488a80bf0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 6 Feb 2021 10:13:24 +0100 Subject: [PATCH 24/25] Update packages/create-app/CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw --- packages/create-app/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 5e8ff0e9b1..13b854972a 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -4,7 +4,7 @@ ### Patch Changes -- 019fe39a0: **BREAKING CHANGE**: The `useEntity` hooks has been moved from `@backstage/plugin-catalog` to `@backstage/plugin-catalog-react`. +- 019fe39a0: **BREAKING CHANGE**: The `useEntity` hook has been moved from `@backstage/plugin-catalog` to `@backstage/plugin-catalog-react`. To apply this change to an existing app, add `@backstage/plugin-catalog-react` to your dependencies in `packages/app/package.json`, and update the import inside `packages/app/src/components/catalog/EntityPage.tsx` as well as any other places you were using `useEntity` or any other functions that were moved to `@backstage/plugin-catalog-react`. - 436ca3f62: Remove techdocs.requestUrl and techdocs.storageUrl from app-config.yaml From 1585732a7bf9e67a0506c378d08c7698706f2c2d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 7 Feb 2021 20:10:54 +0100 Subject: [PATCH 25/25] core-api: document createRouteRef type inference logic --- packages/core-api/src/routing/RouteRef.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/core-api/src/routing/RouteRef.ts b/packages/core-api/src/routing/RouteRef.ts index 3f48d70827..0a3df49b58 100644 --- a/packages/core-api/src/routing/RouteRef.ts +++ b/packages/core-api/src/routing/RouteRef.ts @@ -47,7 +47,12 @@ export class AbsoluteRouteRef { } export function createRouteRef< + // Params is the type that we care about and the one to be embedded in the route ref. + // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string} Params extends { [param in ParamKey]: string }, + // ParamKey is here to make sure the Params type properly has its keys narrowed down + // to only the elements of params. Defaulting to never makes sure we end up with + // Param = {} if the params array is empty. ParamKey extends string = never >(config: { params?: ParamKey[];