From f7b3c2f1b0264f9ffa95fcdce2f89223374d1680 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 1 Mar 2022 09:59:12 +0000 Subject: [PATCH 01/13] Initial commit Signed-off-by: Karan Shah --- .../EntityAirbrakeWidget.tsx | 109 +++++++++++------- 1 file changed, 65 insertions(+), 44 deletions(-) diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx index b11116aeef..93bf490fa8 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import { Entity } from '@backstage/catalog-model'; -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { Grid, Typography } from '@material-ui/core'; import { EmptyState, @@ -36,59 +36,80 @@ const useStyles = makeStyles(() => ({ }, })); +enum ComponentState { + Loading, + NoProjectId, + Error, + Loaded, +} + export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { const classes = useStyles(); const projectId = useProjectId(entity); const errorApi = useApi(errorApiRef); const airbrakeApi = useApi(airbrakeApiRef); - - const { loading, value, error } = useAsync( - () => airbrakeApi.fetchGroups(projectId), - [airbrakeApi, projectId], + const [componentState, setComponentState] = useState( + ComponentState.Loading, ); - useEffect(() => { - if (error) { - errorApi.post(error); - } - }, [error, errorApi]); - - if (loading || !projectId || error) { - return ( - - {loading && } - - {!loading && !projectId && ( - - )} - - {!loading && error && ( - - )} - - ); + if (!projectId) { + setComponentState(ComponentState.NoProjectId); } - return ( - - {value?.groups?.map(group => ( - - {group.errors?.map(groupError => ( - - - {groupError.message} - - + const { loading, value, error } = useAsync(async () => { + const result = await airbrakeApi.fetchGroups(projectId); + setComponentState(ComponentState.Loaded); + return result; + }, [airbrakeApi, projectId]); + + if (loading) { + setComponentState(ComponentState.Loading); + } + + if (componentState !== ComponentState.NoProjectId && error) { + setComponentState(ComponentState.Error); + } + + useEffect(() => { + if (componentState === ComponentState.Error && error) { + errorApi.post(error); + } + }, [componentState, error, errorApi]); + + switch (componentState) { + case ComponentState.Loaded: + return ( + + {value?.groups?.map(group => ( + + {group.errors?.map(groupError => ( + + + {groupError.message} + + + ))} + ))} - ))} - - ); + ); + case ComponentState.NoProjectId: + return ( + + ); + case ComponentState.Loading: + return ; + case ComponentState.Error: + default: + return ( + + ); + } }; From 393c97da851f0028abeb9aa8d34c4d2628a410db Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 1 Mar 2022 10:08:57 +0000 Subject: [PATCH 02/13] Wrap state changes with useEffect to stop infinite re-rendering Signed-off-by: Karan Shah --- .../EntityAirbrakeWidget.tsx | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx index 93bf490fa8..f85ebbf8a9 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -53,9 +53,11 @@ export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { ComponentState.Loading, ); - if (!projectId) { - setComponentState(ComponentState.NoProjectId); - } + useEffect(() => { + if (!projectId) { + setComponentState(ComponentState.NoProjectId); + } + }, [projectId]); const { loading, value, error } = useAsync(async () => { const result = await airbrakeApi.fetchGroups(projectId); @@ -63,16 +65,15 @@ export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { return result; }, [airbrakeApi, projectId]); - if (loading) { - setComponentState(ComponentState.Loading); - } - - if (componentState !== ComponentState.NoProjectId && error) { - setComponentState(ComponentState.Error); - } + useEffect(() => { + if (loading) { + setComponentState(ComponentState.Loading); + } + }, [loading]); useEffect(() => { - if (componentState === ComponentState.Error && error) { + if (componentState !== ComponentState.NoProjectId && error) { + setComponentState(ComponentState.Error); errorApi.post(error); } }, [componentState, error, errorApi]); From 9caa47d98f273cd9fcaeaccfbc67d865a8b7904b Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 1 Mar 2022 11:50:28 +0000 Subject: [PATCH 03/13] Handle no project ID being present Signed-off-by: Karan Shah --- plugins/airbrake/src/api/ProductionApi.ts | 10 +++++ .../EntityAirbrakeWidget.tsx | 37 +++++++++++++------ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/plugins/airbrake/src/api/ProductionApi.ts b/plugins/airbrake/src/api/ProductionApi.ts index 21ca19ee7d..abd8c8863f 100644 --- a/plugins/airbrake/src/api/ProductionApi.ts +++ b/plugins/airbrake/src/api/ProductionApi.ts @@ -18,10 +18,20 @@ import { Groups } from './airbrakeGroups'; import { AirbrakeApi } from './AirbrakeApi'; import { DiscoveryApi } from '@backstage/core-plugin-api'; +export class NoProjectIdError extends Error { + constructor() { + super('Project ID is not present'); + } +} + export class ProductionAirbrakeApi implements AirbrakeApi { constructor(private readonly discoveryApi: DiscoveryApi) {} async fetchGroups(projectId: string): Promise { + if (!projectId) { + throw new NoProjectIdError(); + } + const baseUrl = await this.discoveryApi.getBaseUrl('airbrake'); const apiUrl = `${baseUrl}/api/v4/projects/${projectId}/groups`; diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx index f85ebbf8a9..affb822f64 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -29,6 +29,7 @@ import { ErrorApi, errorApiRef, useApi } from '@backstage/core-plugin-api'; import { airbrakeApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import { AIRBRAKE_PROJECT_ID_ANNOTATION, useProjectId } from '../useProjectId'; +import { NoProjectIdError } from '../../api/ProductionApi'; const useStyles = makeStyles(() => ({ multilineText: { @@ -56,14 +57,35 @@ export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { useEffect(() => { if (!projectId) { setComponentState(ComponentState.NoProjectId); + } else { + setComponentState(ComponentState.Loading); } }, [projectId]); const { loading, value, error } = useAsync(async () => { - const result = await airbrakeApi.fetchGroups(projectId); - setComponentState(ComponentState.Loaded); - return result; - }, [airbrakeApi, projectId]); + try { + const result = await airbrakeApi.fetchGroups(projectId); + setComponentState(ComponentState.Loaded); + return result; + } catch (e) { + if (e instanceof NoProjectIdError) { + setComponentState(ComponentState.NoProjectId); + } else { + setComponentState(ComponentState.Error); + } + throw e; + } + }, [componentState, airbrakeApi, projectId]); + + useEffect(() => { + if ( + componentState === ComponentState.Error && + error && + !(error instanceof NoProjectIdError) + ) { + errorApi.post(error); + } + }, [componentState, error, errorApi]); useEffect(() => { if (loading) { @@ -71,13 +93,6 @@ export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { } }, [loading]); - useEffect(() => { - if (componentState !== ComponentState.NoProjectId && error) { - setComponentState(ComponentState.Error); - errorApi.post(error); - } - }, [componentState, error, errorApi]); - switch (componentState) { case ComponentState.Loaded: return ( From c1cb49008b14a68c918bc80c12b21b5fead790ad Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 1 Mar 2022 16:20:29 +0000 Subject: [PATCH 04/13] Refactor the error to AirbrakeApi Signed-off-by: Karan Shah --- plugins/airbrake/src/api/AirbrakeApi.ts | 6 ++++++ plugins/airbrake/src/api/ProductionApi.ts | 8 +------- plugins/airbrake/src/api/mock/MockApi.ts | 7 +++++-- .../EntityAirbrakeWidget/EntityAirbrakeWidget.tsx | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/plugins/airbrake/src/api/AirbrakeApi.ts b/plugins/airbrake/src/api/AirbrakeApi.ts index a29aa3eca7..672b1f92f4 100644 --- a/plugins/airbrake/src/api/AirbrakeApi.ts +++ b/plugins/airbrake/src/api/AirbrakeApi.ts @@ -24,3 +24,9 @@ export const airbrakeApiRef = createApiRef({ export interface AirbrakeApi { fetchGroups(projectId: string): Promise; } + +export class NoProjectIdError extends Error { + constructor() { + super('Project ID is not present'); + } +} diff --git a/plugins/airbrake/src/api/ProductionApi.ts b/plugins/airbrake/src/api/ProductionApi.ts index abd8c8863f..7d1d88a2a4 100644 --- a/plugins/airbrake/src/api/ProductionApi.ts +++ b/plugins/airbrake/src/api/ProductionApi.ts @@ -15,15 +15,9 @@ */ import { Groups } from './airbrakeGroups'; -import { AirbrakeApi } from './AirbrakeApi'; +import { AirbrakeApi, NoProjectIdError } from './AirbrakeApi'; import { DiscoveryApi } from '@backstage/core-plugin-api'; -export class NoProjectIdError extends Error { - constructor() { - super('Project ID is not present'); - } -} - export class ProductionAirbrakeApi implements AirbrakeApi { constructor(private readonly discoveryApi: DiscoveryApi) {} diff --git a/plugins/airbrake/src/api/mock/MockApi.ts b/plugins/airbrake/src/api/mock/MockApi.ts index dbb1d5c049..f362fbbcaa 100644 --- a/plugins/airbrake/src/api/mock/MockApi.ts +++ b/plugins/airbrake/src/api/mock/MockApi.ts @@ -15,7 +15,7 @@ */ import { Groups } from '../airbrakeGroups'; -import { AirbrakeApi } from '../AirbrakeApi'; +import { AirbrakeApi, NoProjectIdError } from '../AirbrakeApi'; import mockGroupsData from './airbrakeGroupsApiMock.json'; export class MockAirbrakeApi implements AirbrakeApi { @@ -25,7 +25,10 @@ export class MockAirbrakeApi implements AirbrakeApi { this.waitTimeInMillis = waitTimeInMillis; } - fetchGroups(): Promise { + fetchGroups(projectId: string): Promise { + if (!projectId) { + return Promise.reject(new NoProjectIdError()); + } return new Promise(resolve => { setTimeout(() => resolve(mockGroupsData), this.waitTimeInMillis); }); diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx index affb822f64..6ec820efa6 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -29,7 +29,7 @@ import { ErrorApi, errorApiRef, useApi } from '@backstage/core-plugin-api'; import { airbrakeApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import { AIRBRAKE_PROJECT_ID_ANNOTATION, useProjectId } from '../useProjectId'; -import { NoProjectIdError } from '../../api/ProductionApi'; +import { NoProjectIdError } from '../../api/AirbrakeApi'; const useStyles = makeStyles(() => ({ multilineText: { From 5d98a4263eb94a316d0ed956baaad8ea6e254865 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 2 Mar 2022 00:15:26 +0000 Subject: [PATCH 05/13] Added working tests, one of which fails because of a bug in the code that needs to be fixed Signed-off-by: Karan Shah --- plugins/airbrake/src/api/ProductionApi.test.ts | 7 +++++++ .../EntityAirbrakeWidget.test.tsx | 14 +++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/plugins/airbrake/src/api/ProductionApi.test.ts b/plugins/airbrake/src/api/ProductionApi.test.ts index f09127b4c2..41aef38a27 100644 --- a/plugins/airbrake/src/api/ProductionApi.test.ts +++ b/plugins/airbrake/src/api/ProductionApi.test.ts @@ -20,6 +20,7 @@ import mockGroupsData from './mock/airbrakeGroupsApiMock.json'; import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/test-utils'; import { localDiscoveryApi } from './mock'; +import { NoProjectIdError } from './AirbrakeApi'; describe('The production Airbrake API', () => { const productionApi = new ProductionAirbrakeApi(localDiscoveryApi); @@ -53,4 +54,10 @@ describe('The production Airbrake API', () => { await expect(productionApi.fetchGroups('123456')).rejects.toThrow(); }); + + it('throws if project ID is empty', async () => { + await expect(productionApi.fetchGroups('')).rejects.toThrowError( + NoProjectIdError, + ); + }); }); diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx index ee14a17f9a..6211500b10 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx @@ -23,9 +23,9 @@ import { setupRequestMockHandlers, TestApiProvider, } from '@backstage/test-utils'; -import { createEntity } from '../../api'; import { airbrakeApiRef, + createEntity, localDiscoveryApi, MockAirbrakeApi, ProductionAirbrakeApi, @@ -52,15 +52,23 @@ describe('EntityAirbrakeContent', () => { } }); - it('states that the annotation is missing if no project ID annotation is provided', async () => { + it('states that the annotation is missing if no project ID annotation is provided but does not error', async () => { + const mockErrorApi = new MockErrorApi({ collect: true }); + const widget = await renderInTestApp( - + , ); await expect( widget.findByText('Missing Annotation'), ).resolves.toBeInTheDocument(); + expect(mockErrorApi.getErrors().length).toBe(0); }); it('states that an error occurred if the API call fails', async () => { From ec430528591bf7643c6e417da38ed064331575e1 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 2 Mar 2022 10:23:16 +0000 Subject: [PATCH 06/13] Remove an unneeded dependency Signed-off-by: Karan Shah --- .../components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx index 6ec820efa6..327da881a3 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -75,7 +75,7 @@ export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { } throw e; } - }, [componentState, airbrakeApi, projectId]); + }, [airbrakeApi, projectId]); useEffect(() => { if ( From c5a462bff14c41e84f782538d067c490700aca4d Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 2 Mar 2022 10:30:13 +0000 Subject: [PATCH 07/13] Add a changeset Signed-off-by: Karan Shah --- .changeset/giant-bottles-eat.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/giant-bottles-eat.md diff --git a/.changeset/giant-bottles-eat.md b/.changeset/giant-bottles-eat.md new file mode 100644 index 0000000000..d37343bfe4 --- /dev/null +++ b/.changeset/giant-bottles-eat.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-airbrake': patch +--- + +Fix a bug where API calls were being made and errors were being added to the snack bar when no project ID was present. This is a common use case for components that haven't added the Airbrake plugin annotation to their `catalog-info.yaml`. From 4239b8dba6c490bc7cc97722e43c9699e3d849bf Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Thu, 3 Mar 2022 15:15:58 +0000 Subject: [PATCH 08/13] Don't check exceptions Signed-off-by: Karan Shah --- .../EntityAirbrakeWidget.test.tsx | 2 +- .../EntityAirbrakeWidget.tsx | 26 +++---------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx index 6211500b10..64f1f11223 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx @@ -34,7 +34,7 @@ import { errorApiRef } from '@backstage/core-plugin-api'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -describe('EntityAirbrakeContent', () => { +describe('EntityAirbrakeWidget', () => { const worker = setupServer(); setupRequestMockHandlers(worker); diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx index 327da881a3..29260427a9 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -29,7 +29,6 @@ import { ErrorApi, errorApiRef, useApi } from '@backstage/core-plugin-api'; import { airbrakeApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import { AIRBRAKE_PROJECT_ID_ANNOTATION, useProjectId } from '../useProjectId'; -import { NoProjectIdError } from '../../api/AirbrakeApi'; const useStyles = makeStyles(() => ({ multilineText: { @@ -54,38 +53,21 @@ export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { ComponentState.Loading, ); - useEffect(() => { - if (!projectId) { - setComponentState(ComponentState.NoProjectId); - } else { - setComponentState(ComponentState.Loading); - } - }, [projectId]); - - const { loading, value, error } = useAsync(async () => { + const { loading, value } = useAsync(async () => { try { const result = await airbrakeApi.fetchGroups(projectId); setComponentState(ComponentState.Loaded); return result; } catch (e) { - if (e instanceof NoProjectIdError) { + if (!projectId) { setComponentState(ComponentState.NoProjectId); } else { setComponentState(ComponentState.Error); + errorApi.post(e); } throw e; } - }, [airbrakeApi, projectId]); - - useEffect(() => { - if ( - componentState === ComponentState.Error && - error && - !(error instanceof NoProjectIdError) - ) { - errorApi.post(error); - } - }, [componentState, error, errorApi]); + }, [airbrakeApi, errorApi, projectId]); useEffect(() => { if (loading) { From c51587701b1f386e7e023fd278f25344e4f9ca11 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Thu, 3 Mar 2022 23:48:10 +0000 Subject: [PATCH 09/13] Remove all `useState` from EntityAirbrakeWidget.tsx Signed-off-by: Karan Shah --- plugins/airbrake/package.json | 1 + plugins/airbrake/src/api/AirbrakeApi.ts | 3 +- .../EntityAirbrakeWidget.test.tsx | 28 ++++------ .../EntityAirbrakeWidget.tsx | 55 ++++++++----------- 4 files changed, 37 insertions(+), 50 deletions(-) diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 7342fdd839..47dc6b31c9 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -27,6 +27,7 @@ "@backstage/core-components": "^0.8.10", "@backstage/core-plugin-api": "^0.7.0", "@backstage/dev-utils": "^0.2.23", + "@backstage/errors": "^0.2.2", "@backstage/plugin-catalog-react": "^0.7.0", "@backstage/test-utils": "^0.2.6", "@backstage/theme": "^0.2.15", diff --git a/plugins/airbrake/src/api/AirbrakeApi.ts b/plugins/airbrake/src/api/AirbrakeApi.ts index 672b1f92f4..3abe745b5b 100644 --- a/plugins/airbrake/src/api/AirbrakeApi.ts +++ b/plugins/airbrake/src/api/AirbrakeApi.ts @@ -16,6 +16,7 @@ import { Groups } from './airbrakeGroups'; import { createApiRef } from '@backstage/core-plugin-api'; +import { CustomErrorBase } from '@backstage/errors'; export const airbrakeApiRef = createApiRef({ id: 'plugin.airbrake.service', @@ -25,7 +26,7 @@ export interface AirbrakeApi { fetchGroups(projectId: string): Promise; } -export class NoProjectIdError extends Error { +export class NoProjectIdError extends CustomErrorBase { constructor() { super('Project ID is not present'); } diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx index 64f1f11223..e8d09b5e65 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx @@ -18,7 +18,6 @@ import React from 'react'; import { EntityAirbrakeWidget } from './EntityAirbrakeWidget'; import exampleData from '../../api/mock/airbrakeGroupsApiMock.json'; import { - MockErrorApi, renderInTestApp, setupRequestMockHandlers, TestApiProvider, @@ -30,7 +29,6 @@ import { MockAirbrakeApi, ProductionAirbrakeApi, } from '../../api'; -import { errorApiRef } from '@backstage/core-plugin-api'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; @@ -53,14 +51,9 @@ describe('EntityAirbrakeWidget', () => { }); it('states that the annotation is missing if no project ID annotation is provided but does not error', async () => { - const mockErrorApi = new MockErrorApi({ collect: true }); - const widget = await renderInTestApp( , @@ -68,7 +61,9 @@ describe('EntityAirbrakeWidget', () => { await expect( widget.findByText('Missing Annotation'), ).resolves.toBeInTheDocument(); - expect(mockErrorApi.getErrors().length).toBe(0); + expect( + widget.queryByText(/.*Failed fetching Airbrake groups.*/), + ).not.toBeInTheDocument(); }); it('states that an error occurred if the API call fails', async () => { @@ -80,14 +75,10 @@ describe('EntityAirbrakeWidget', () => { }, ), ); - const mockErrorApi = new MockErrorApi({ collect: true }); const widget = await renderInTestApp( , @@ -96,9 +87,10 @@ describe('EntityAirbrakeWidget', () => { await expect( widget.findByText(/.*there was an issue communicating with Airbrake.*/), ).resolves.toBeInTheDocument(); - expect(mockErrorApi.getErrors().length).toBe(1); - expect(mockErrorApi.getErrors()[0].error.message).toStrictEqual( - 'Failed fetching Airbrake groups', - ); + expect( + widget.getByRole('heading', { + name: /.*Failed fetching Airbrake groups.*/, + }), + ).toBeInTheDocument(); }); }); diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx index 29260427a9..f235a3e2f5 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -14,10 +14,11 @@ * limitations under the License. */ import { Entity } from '@backstage/catalog-model'; -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { Grid, Typography } from '@material-ui/core'; import { EmptyState, + ErrorPanel, InfoCard, MissingAnnotationEmptyState, Progress, @@ -25,7 +26,7 @@ import { import hash from 'object-hash'; import { makeStyles } from '@material-ui/core/styles'; import { BackstageTheme } from '@backstage/theme'; -import { ErrorApi, errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { useApi } from '@backstage/core-plugin-api'; import { airbrakeApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import { AIRBRAKE_PROJECT_ID_ANNOTATION, useProjectId } from '../useProjectId'; @@ -47,33 +48,22 @@ export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { const classes = useStyles(); const projectId = useProjectId(entity); - const errorApi = useApi(errorApiRef); const airbrakeApi = useApi(airbrakeApiRef); - const [componentState, setComponentState] = useState( - ComponentState.Loading, - ); + let componentState = ComponentState.Loading; - const { loading, value } = useAsync(async () => { - try { - const result = await airbrakeApi.fetchGroups(projectId); - setComponentState(ComponentState.Loaded); - return result; - } catch (e) { - if (!projectId) { - setComponentState(ComponentState.NoProjectId); - } else { - setComponentState(ComponentState.Error); - errorApi.post(e); - } - throw e; - } - }, [airbrakeApi, errorApi, projectId]); + const { loading, value, error } = useAsync(() => { + return airbrakeApi.fetchGroups(projectId); + }, [airbrakeApi, projectId]); - useEffect(() => { - if (loading) { - setComponentState(ComponentState.Loading); - } - }, [loading]); + if (loading) { + componentState = ComponentState.Loading; + } else if (!projectId) { + componentState = ComponentState.NoProjectId; + } else if (error) { + componentState = ComponentState.Error; + } else if (value) { + componentState = ComponentState.Loaded; + } switch (componentState) { case ComponentState.Loaded: @@ -103,11 +93,14 @@ export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { case ComponentState.Error: default: return ( - + <> + + + ); } }; From 358fc79ff01f4a52b1e55b618869dfa7126ce85d Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Fri, 4 Mar 2022 14:30:52 +0000 Subject: [PATCH 10/13] Remove any changes with ADOPTERS.md Signed-off-by: Karan Shah --- ADOPTERS.md | 202 ++++++++++++++++++++++++++-------------------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index d22978cca9..5aad5dcf72 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -2,104 +2,104 @@ _If you're using Backstage in your organization, please try to add your company name to this list. This really helps the project to gain momentum and credibility. It's a small contribution back to the project with a big impact._ -| Organization | Contact | Description of Use | -| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. | -| [bol.com](https://www.bol.com) | [@sagacity](https://github.com/sagacity) | Initial work being done to unify platform tooling. | -| [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. | -| [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up | -| [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. | -| [SDA SE](https://sda.se) | [@dschwank](https://github.com/dschwank), [@iammnils](https://github.com/iammnils) | Central place for developing and sharing services in our insurance ecosystem. | -| [H-E-B](https://www.heb.com) | [@german-j-rodriguez](https://github.com/german-j-rodriguez) | Initial work on Engineering Portal service platform. | -| [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications | -| [Kiwi.com](https://kiwi.com) | [@aexvir](https://github.com/aexvir) | Replacing the frontend of [The Zoo](https://github.com/kiwicom/the-zoo), their service registry. | -| [Voi](https://www.voiscooters.com/) | [@K-Phoen](https://github.com/K-Phoen) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | -| [Talkdesk](https://www.talkdesk.com) | [@jaime-talkdesk](https://github.com/jaime-talkdesk) | Initial work for Engineering Portal and Self Provisioning to R&D | -| [Wealthsimple](https://www.wealthsimple.com) | [@andrewthauer](https://github.com/andrewthauer) | Developer portal, service catalog, documentation and tooling | -| [Grab](https://www.grab.com) | [@althafh](https://github.com/althafh) | Initial work as a unified interface for all of Grab's internal tooling | -| [Telenor Sweden](https://www.telenor.se) | [@O5ten](https://github.com/O5ten) | Building a developer portal for scaffolding projects towards our unified build environment and microservice stacks | -| [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. | -| [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. | -| [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. | -| [Expedia Group](https://www.expediagroup.com) | [Mike Turner](mailto:miturner@expediagroup.com), [Sneha Kumar](mailto:snkumar@expediagroup.com), [@guillermomanzo](https://github.com/guillermomanzo), [Erik Lindgren](https://github.com/lindgren) | EG Common Developer Toolkit | -| [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go | -| [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling | -| [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. | -| [Trendyol](https://trendyol.com) | [Gamze Senturk](https://github.com/gmzsenturk), [Mert Can Bilgic](https://github.com/mertcb) | The Developer Portal has been called `Pandora`. Provides an overview of Trendyol tech ecosystem. TechDocs, Catalog, Custom Plugins and Theme. | -| [Peloton](https://www.onepeloton.com/) | [Jim Haughwout](https://github.com/JimHaughwout) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. | -| [TELUS](https://telus.com) | [Seb Barre](https://github.com/sbarre) | The Go-to place to find answers about development and delivery at TELUS. | -| [Brex](https://www.brex.com/) | [Vamsi Chitters](https://github.com/vamsikc) | A centralized UI to understand how a service fits in the whole Brex architecture and manage a team’s engineering dependencies. | -| [Oriflame](https://www.oriflame.com/) | [Oriflame](https://github.com/oriflame) | Internal developer portal for services, single page apps and packages overview, API documentation, technical guides, tech-radar and more. | -| [Booz Allen Hamilton](https://www.boozallen.com/) | [Jason Miller](https://github.com/JasonMiller-BAH) | Developer portal for a full-stack software development ecosystem that accelerates consistent and repeatable Modern Software Development practices for internal innovation and investments. | -| [Netflix](https://www.netflix.com/) | [bleathem](https://github.com/bleathem) | Our Backstage implementation will be the front door to a unified experience connecting our internal platform products across important workflows with integrated knowledge and support. | -| [b.well](https://www.icanbwell.com/) | [Jacob Rosales](https://github.com/jrosales) | Foundation for our engineering portal and cloud insights. | -| [PagerDuty](https://www.pagerduty.com/) | [Mark Shaw](https://github.com/markshawtoronto) | Developer portal, initially focused on software templates and tech-docs. | -| [MoonShiner](https://moonshiner.at) | [Fabian Hippmann](https://github.com/FabianHippmann) | Developer portal - helps us keep track of our customer projects, onboard new developers & improve our development process 🌕🚀🧑‍🚀 | -| [FundApps](https://www.fundapps.co/) | [Elliot Greenwood](https://github.com/egnwd) | Developer Portal - A place for us to keep track of our projects and documentation for all services and processes | -| [DAZN](https://dazn.com/) | [Lou Bichard](https://twitter.com/loujaybee), [Marco Crivellaro](https://github.com/crivetechie), [Alex Hollerith](mailto:alex.hollerith@dazn.com) | Ingesting all of DAZN's repos for the catalog, migrating our internal platform apps (pull request boards, release information, inner source marketplace etc) to Backstage plugins (where applicable). | -| [HelloFresh](https://www.hellofresh.de/) | [@iammuho](https://github.com/iammuho), [@ElenaForester](https://github.com/ElenaForester), [@diegomarangoni](https://github.com/diegomarangoni) | Our developer portal at HelloFresh - Spread across an organisation of 500+ engineers globally. | -| [FactSet](https://www.factset.com/) | [@kuangp](https://github.com/kuangp) | Developer portal to provide discoverability to all internal components, APIs, documentation, and scaffold templates with integrations to our internal infrastructure tools. | -| [Workrise](https://www.workrise.com/) | [Michael Rode](https://github.com/michaelrode) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | -| [RedVentures](https://www.redventures.com/) | [Chris Diaz](https://github.com/codingdiaz) | Developer portal that brings everything an engineer needs to provide value into a single pane of glass. | -| [MavTek](https://www.mavtek.com/) | [@fgascon](https://github.com/fgascon) | Developer portal focused on standardizing practices, centralizing documentation and streamlining developer practices. | -| [QuintoAndar](https://www.quintoandar.com.br/) | [@quintoandar](https://github.com/quintoandar) | Developer portal, services catalog and centralization of service metrics. | -| [empathy.co](https://empathy.co/) | [@guillermotti](https://github.com/guillermotti) | Developer portal for tech docs, service catalog, plugin discovery and much more. | -| [creditas.com](https://creditas.com/) | [@aureliosaraiva](https://github.com/aureliosaraiva) [@Creditas](https://github.com/creditas) | Centralization of all services, standards, documentation, etc. We started the deployment process. | -| [Prisjakt](https://www.prisjakt.nu) / [PriceSpy](https://pricespy.co.uk) | [@kennylindahl](https://github.com/kennylindahl) | Internal developer portal - Documentation, scaffolding, software catalog, TechRadar, Gitlab org data integration | -| [Powerspike](https://powerspike.tv/) | [@trelore](https://github.com/trelore) | Developer portal for documentation of core libraries and repositories. | -| [2U](https://2u.com) | [Andrew Thal](https://github.com/athal7) | Development team home-base, promoting service discoverability, resource dependencies, and tech radar | -| [Taxfix](https://taxfix.de/) | [Sami Ur Rehman](https://github.com/samiurrehman92) | Developer's portal with software catalog at it's core. Hosts API Specs, Tech Docs, Tech Radar and some custom plugins. | -| [Busuu](https://busuu.com/) | [Adam Tester](https://github.com/adamtester) | Developer portal with service catalog, API docs, Event docs, service templating, and cost insights. | -| [Loadsmart](https://loadsmart.com/) | [Loadsmart](https://github.com/loadsmart) | Improve services visibility and operations for service owners and developers. | -| [Monzo](https://monzo.com/) | [@WillSewell](https://github.com/WillSewell), [@joechrisellis](https://github.com/joechrisellis) | Developer portal showing metadata and docs for over 2000 microservices. We have built a number of plugins such as a UI for our system to measure [software excellence](https://monzo.com/blog/2021/09/15/how-we-measure-software-excellence), and a UI to show deployment and config change events. | -| [Vaimo](https://www.vaimo.com) | [@vaimo-magnus](https://github.com/vaimo-magnus) | Developer Portal for our developers at Vaimo, currently docs and self-service towards our internal PaaS based on k8s. Plans to extend the catalog into Projects, Environments etc | -| [Wayfair](https://www.wayfair.com) | [@fransan](https://github.com/fransan), [@errskipower](https://github.com/errskipower), [@hrrs](https://github.com/hrrs) | Developer portal for service catalog, technical documentation, and APIs. | -| [CircleHD](https://www.circlehd.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe | -| [CastDesk](https://castdesk.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe | -| [Santagostino](https://santagostino.it) | [@santagostino](https://github.com/santagostino) | Developer portal, gateway to our infrastructure, documentation, service catalog and internal tooling. | -| [Peak](https://peak.ai) | [Luke Beamish](https://github.com/lukebeamish-peak) | Developer portal for all internal engineers to access documentation and tooling. | -| [Gelato](https://gelato.com/) | [Dmitry Makarenko](https://github.com/dmitry-makarenko-gelato) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal and third-party systems🚀. | -| [GoCardless](https://gocardless.com/) | [James Turley](https://github.com/tragiclifestories) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal systems. | -| [Box](https://www.box.com) | [@kielosz](https://github.com/kielosz), [@jluk-box](https://github.com/jluk-box), [@ptychu](https://github.com/ptychu), [@alexrybch](https://github.com/alexrybch), [@szubster](https://github.com/szubster) | Developer portal for service catalog, integration with internal systems, new service onboarding. | -| [Bazaarvoice](https://www.bazaarvoice.com) | [@niallmccullagh](https://github.com/niallmccullagh) | Developer portal for service catalog and scaffolds, publishing Github docs and API documentation, visualising our internal tech radar and our product engineering org structure. | -| [Krateo PlatformOps](https://www.krateo.io) | [@projectkerberus](https://github.com/projectkerberus) | A multi-cloud control plane to create, manage and deploy any kind of resource easily and centrally via a Developer Portal that centralizes via a self-service catalog the templating and ownership of services, the available documentation, the overview of the components that compose an entire domain and all the data of the service lifecycle. | -| [Adevinta](https://www.adevinta.com) | [Ray Sinnema](https://github.com/RemonSinnema) | Showcase shared services to our internal customers. | -| [Splunk](https://www.splunk.com) | [@tonytamsf](https://github.com/tonytamsf) | Developer portal as a centralized place to find people, services, documentation, escalation policies and give bravos. This portal is also being used as a centralized search engine for engineering specific documentation. | -| [SoundCloud](https://www.soundcloud.com) | [Julio Zynger](https://github.com/julioz) | Developer portal as a [humane registry](https://martinfowler.com/bliki/HumaneRegistry.html) for the organization: catalog of people, services, documentation, feature toggles, escalation policies, etc. | -| [Volvofinans Bank](https://www.volvofinans.se) | [Johan Hammar](https://github.com/johanhammar) | Developer portal enabling engineers to manage and explore software and documentation. | -| [Palo Alto Networks](https://www.paloaltonetworks.com) | [Jeremy Guarini](https://github.com/jeremyguarini), [Brian Lomeland](https://github.com/bbbmmmlll), [Palo Alto Networks](https://github.com/PaloAltoNetworks) | Developer portal, service catalog, documentation and tooling | -| [Signal Iduna Group](https://www.signal-iduna.de/) | [Jonas Thomsen](https://github.com/JoThomsen) | Developer Portal, documentation, monitoring, service catalog for our insurance ecosystem | -| [Tradeshift](https://www.tradeshift.com/) | [Soren Mathiasen](https://github.com/sorenmat) | Developer Portal: documentation, monitoring, service templates, service catalog for our micro services | -| [Unity](https://unity.com) | [Ted Cordery](https://github.com/TeddyBallGame) | A centralized service catalog with documentation for our service engineers. | -| [PicPay](https://www.picpay.com) | [Luis Baroni](https://github.com/lcsbaroni), [Renata Poluceno](https://github.com/renatapoluceno), [PicPay](https://github.com/picpay) | Developer portal for building services throught templates, service catalog with ownership of services, documentation and metrics providing autonomy and visibility for all. | -| [Epic Games](https://www.epicgames.com) | [Brian Jung](https://github.com/brian-at-epic), [Jeff Goldian](https://github.com/jeffgoldian-Epic) | Developer Portal: Service Catalog, Documentation, Software Templates and more making our internal teams' lives easier! | -| [Globo](https://globo.com) | [Carlos Gusmão](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. | -| [QBE](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly 🚀 | -| [GoTo](https://www.goto.com) | [Lorenzo Orsatti](https://github.com/lorsatti) | Improve onboarding experience of new developers. Discover faster and painlessly developer documentation, API definitions and team information. Provide useful dev metrics in a central place. Provide easy-to-use templates for new services. | -| [Telstra](https://www.telstra.com.au) | [@kiranpatel11](https://github.com/kiranpatel11), [JasonC](https://github.com/JasonC17) | Primary usage: software catalog and templates
Emerging usage : TechDocs, Explore Ecosystem, TechRadar, etc | -| [Mosaico](https://www.mosaico.com.br/) | [Wédney Yuri](https://github.com/wedneyyuri),[@tino.milton](https://github.com/miltonjacomini) | A centralized service catalog of our documentation for our service engineers. | -| [Mox Bank](https://www.mox.com/) | [Nick Laqua](https://github.com/nick-laqua-dragon) | "Single pane of glass" developer portal for providing a best-in-class developer experience to our product teams and making Mox the best tech environment in Hongkong 🥰🚀 | -| [Keyloop](https://www.keyloop.com/) | [Andre Wanlin](https://github.com/awanlin) | Future-motive Developer Portal to help our teams create technology to make everything about buying and owning a car better. 🚗 | -| [Simply Business](https://sbtech.simplybusiness.co.uk/) | [@addersuk](https://github.com/addersuk), [@LightningStairs](https://github.com/LightningStairs), [@punitcse](https://github.com/punitcse), [@moltenice](https://github.com/moltenice) | Central developer portal to access everything a developer needs such as docs, internal service catalog, and the ability to quickly create a new service from a template. Internally developed Backstage plugins allow us to customise the experience to how we work. | -| [Overwolf](https://www.overwolf.com) | [@tomwolfgang](https://github.com/tomwolfgang) | Dev portal - software catalog, tech-docs, scaffolding | -| [Hotmart](https://www.hotmart.com) | [@fabioviana-hotmart](https://github.com/fabioviana-hotmart) | The main Developers Portal to centralize docs, applications and technical metrics. | -| [EF Education First](https://www.ef.com) | [Daan Boerlage](https://github.com/runebaas), [Rafał Nowosielski](https://github.com/rnowosielski) | Our developer portal - primarily used for cataloging and scaffolding with the ambition to expand with more feature adoptions over time | -| [Power Home Remodeling](https://www.techatpower.com) | [Ben Langfeld](https://github.com/benlangfeld) | Developer portal to our internal services, build on open-source software (including Kubernetes) in our own datacenters. Our Portal allows our team members to navigate inherant complexity and standardise. | -| [Livspace](https://www.livspace.com) | [Praveen Kumar](https://github.com/praveen-livspace) | Developer portal, service catalog, tech docs, API docs and plugins | -| [Just Eat Takeaway](https://www.justeattakeaway.com) | [Kim Wilson](https://github.com/kwilson541) | Our developer portal which centralises applications, reduces cognitive load and provides teams insights. | -| [Hopin](https://hopin.com) | [Vladimir Glafirov](https://github.com/vglafirov), [Chloe Lee](https://github.com/msfuko) | Developer portal to streamline the development practices. Integrated with service catalog, software templates, application monitoring, tech docs and plugins. | -| [HBO Max](https://hbomax.com) | [@mdb](https://github.com/mdb), [@nesta219](https://github.com/nesta219), [@nmische](https://github.com/nmische), [@hbomark](https://github.com/hbomark) | Developer portal hosting service catalog and API documentation, as well as cloud infrastructure details, operational visibility tools, and a custom plugin for browsing notable platform change events, such as deployments and configuration updates. | -| [RCHLO](https://www.riachuelo.com.br) & [MIDWAY](https://www.midway.com.br) | [@marcosborges](https://github.com/marcosborges), [@defaultbr](https://github.com/defaultbr) | Self-Service Platform | -| [HP Inc](https://www.hp.com) | [Damon Kaswell](https://github.com/dekoding) | DevEx engagement hub (dev portal: docs, standards, Q&A) and extensive assets catalog (APIs, services, code, data, etc.) for the pan-HP internal developer community. | -| [VMware](https://www.vmware.com) | [@mpriamo](https://github.com/mpriamo), [@krisapplegate](https://github.com/krisapplegate) | Part of [Tanzu Application Platform](https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/index.html) offering; internal developer portal | -| [Ualá](https://www.uala.com.ar/) | [Santiago Bernal](https://github.com/sabernal) | Initial work being done to centralize documentation for all our microservices and APIs, as well as scaffolding new services and tracking code quality | -| [IKEA IT AB](https://www.ingka.com) | [@bjornramberg](https://github.com/bjornramberg), [@supriyachitale](https://github.com/supriyachitale) | Supporting engineers at scale with self serve access and connecting the dots of our engineering platform and services, enabling product teams to move faster and go further, and unleashing innovation, reuse and co-creation across the organisation. | -| [Invitae](https://www.invitae.com/en) | [@ryan-hanchett](https://github.com/ryan-hanchett), [@gmandler42](https://github.com/gmandler42) | Centralized Developer Experience portal, putting all of our tooling behind a single pane of glass and creating a living service catalog. | -| [Fortum](https://www.fortum.com/) | [@brunoamaroalmeida](https://github.com/brunoamaroalmeida), [@dhaval-vithalani](https://github.com/dhaval-vithalani), [@sunilkumarmohanty](https://github.com/sunilkumarmohanty) | A central portal containing information about our applications, services, processes and other software assets to be used by Fortum software engineering community. | -| [Procore](https://www.procore.com/jobs/engineering) | [@shayon](https://github.com/Shayon), [@jamesdabbs-procore](https://github.com/jamesdabbs-procore) | Developer portal - centralized software catalog and templates to enable self serve and reduce cognitive load. | -| [Bradesco](https://banco.bradesco/html/classic/sobre/index.shtm) | [@danilosoarescardoso](https://github.com/danilosoarescardoso) | Centralized developer portal with software catalog, software templates, techdocs and some plugins from community and by our own. | -| [SeatGeek](https://seatgeek.com) | [@zhammer](https://github.com/zhammer) | Software catalog and documentation platform | -| [Grupo Boticário](https://www.grupoboticario.com.br/) | [@chicoribas](https://github.com/chicoribas), [@fndiaz](https://github.com/fndiaz), [@digogid](https://github.com/digogid), [@manumbs](https://github.com/manumbs), [@haooliveira84](https://github.com/haooliveira84), [@Rhullyam](https://github.com/Rhullyam) | Centralized developer portal with catalog, documentation, and software templates to build a ready to go application, including pipelines (CI/CD) and cloud services provisioning | -| [Snyk](https://snyk.io/) | [@robcresswell](https://github.com/robcresswell) | Developer portal for software discovery, API documentation and templating | -| [Stilingue](https://www.stilingue.com.br/) | [@stilingue-inteligencia-artificial](https://github.com/Stilingue-IA), [@bbviana](https://github.com/bbviana) | Developer portal, services catalog and centralization of metrics from Grafana, Sentry and GCP. Furthermore, centralization of documentation and infra details like DNS, Network services, SSL and so on. | -| [TUI Group](https://www.tuigroup.com/) | [Simon Stamm](https://github.com/simonstamm), [Christian Rudolph](https://github.com/ChrisRu82) | Developer portal for all engineer to provide discoverability to all internal components, APIs, documentation and to scaffold templates with integrations to our internal tools extended by plugins from our community. | +| Organization | Contact | Description of Use | +| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. | +| [bol.com](https://www.bol.com) | [@sagacity](https://github.com/sagacity) | Initial work being done to unify platform tooling. | +| [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. | +| [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up | +| [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. | +| [SDA SE](https://sda.se) | [@dschwank](https://github.com/dschwank), [@iammnils](https://github.com/iammnils) | Central place for developing and sharing services in our insurance ecosystem. | +| [H-E-B](https://www.heb.com) | [@german-j-rodriguez](https://github.com/german-j-rodriguez) | Initial work on Engineering Portal service platform. | +| [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications | +| [Kiwi.com](https://kiwi.com) | [@aexvir](https://github.com/aexvir) | Replacing the frontend of [The Zoo](https://github.com/kiwicom/the-zoo), their service registry. | +| [Voi](https://www.voiscooters.com/) | [@K-Phoen](https://github.com/K-Phoen) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | +| [Talkdesk](https://www.talkdesk.com) | [@jaime-talkdesk](https://github.com/jaime-talkdesk) | Initial work for Engineering Portal and Self Provisioning to R&D | +| [Wealthsimple](https://www.wealthsimple.com) | [@andrewthauer](https://github.com/andrewthauer) | Developer portal, service catalog, documentation and tooling | +| [Grab](https://www.grab.com) | [@althafh](https://github.com/althafh) | Initial work as a unified interface for all of Grab's internal tooling | +| [Telenor Sweden](https://www.telenor.se) | [@O5ten](https://github.com/O5ten) | Building a developer portal for scaffolding projects towards our unified build environment and microservice stacks | +| [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. | +| [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. | +| [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. | +| [Expedia Group](https://www.expediagroup.com) | [Mike Turner](mailto:miturner@expediagroup.com), [Sneha Kumar](mailto:snkumar@expediagroup.com), [@guillermomanzo](https://github.com/guillermomanzo), [Erik Lindgren](https://github.com/lindgren) | EG Common Developer Toolkit | +| [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go | +| [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling | +| [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. | +| [Trendyol](https://trendyol.com) | [Gamze Senturk](https://github.com/gmzsenturk), [Mert Can Bilgic](https://github.com/mertcb) | The Developer Portal has been called `Pandora`. Provides an overview of Trendyol tech ecosystem. TechDocs, Catalog, Custom Plugins and Theme. | +| [Peloton](https://www.onepeloton.com/) | [Jim Haughwout](https://github.com/JimHaughwout) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. | +| [TELUS](https://telus.com) | [Seb Barre](https://github.com/sbarre) | The Go-to place to find answers about development and delivery at TELUS. | +| [Brex](https://www.brex.com/) | [Vamsi Chitters](https://github.com/vamsikc) | A centralized UI to understand how a service fits in the whole Brex architecture and manage a team’s engineering dependencies. | +| [Oriflame](https://www.oriflame.com/) | [Oriflame](https://github.com/oriflame) | Internal developer portal for services, single page apps and packages overview, API documentation, technical guides, tech-radar and more. | +| [Booz Allen Hamilton](https://www.boozallen.com/) | [Jason Miller](https://github.com/JasonMiller-BAH) | Developer portal for a full-stack software development ecosystem that accelerates consistent and repeatable Modern Software Development practices for internal innovation and investments. | +| [Netflix](https://www.netflix.com/) | [bleathem](https://github.com/bleathem) | Our Backstage implementation will be the front door to a unified experience connecting our internal platform products across important workflows with integrated knowledge and support. | +| [b.well](https://www.icanbwell.com/) | [Jacob Rosales](https://github.com/jrosales) | Foundation for our engineering portal and cloud insights. | +| [PagerDuty](https://www.pagerduty.com/) | [Mark Shaw](https://github.com/markshawtoronto) | Developer portal, initially focused on software templates and tech-docs. | +| [MoonShiner](https://moonshiner.at) | [Fabian Hippmann](https://github.com/FabianHippmann) | Developer portal - helps us keep track of our customer projects, onboard new developers & improve our development process 🌕🚀🧑‍🚀 | +| [FundApps](https://www.fundapps.co/) | [Elliot Greenwood](https://github.com/egnwd) | Developer Portal - A place for us to keep track of our projects and documentation for all services and processes | +| [DAZN](https://dazn.com/) | [Lou Bichard](https://twitter.com/loujaybee), [Marco Crivellaro](https://github.com/crivetechie), [Alex Hollerith](mailto:alex.hollerith@dazn.com) | Ingesting all of DAZN's repos for the catalog, migrating our internal platform apps (pull request boards, release information, inner source marketplace etc) to Backstage plugins (where applicable). | +| [HelloFresh](https://www.hellofresh.de/) | [@iammuho](https://github.com/iammuho), [@ElenaForester](https://github.com/ElenaForester), [@diegomarangoni](https://github.com/diegomarangoni) | Our developer portal at HelloFresh - Spread across an organisation of 500+ engineers globally. | +| [FactSet](https://www.factset.com/) | [@kuangp](https://github.com/kuangp) | Developer portal to provide discoverability to all internal components, APIs, documentation, and scaffold templates with integrations to our internal infrastructure tools. | +| [Workrise](https://www.workrise.com/) | [Michael Rode](https://github.com/michaelrode) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | +| [RedVentures](https://www.redventures.com/) | [Chris Diaz](https://github.com/codingdiaz) | Developer portal that brings everything an engineer needs to provide value into a single pane of glass. | +| [MavTek](https://www.mavtek.com/) | [@fgascon](https://github.com/fgascon) | Developer portal focused on standardizing practices, centralizing documentation and streamlining developer practices. | +| [QuintoAndar](https://www.quintoandar.com.br/) | [@quintoandar](https://github.com/quintoandar) | Developer portal, services catalog and centralization of service metrics. | +| [empathy.co](https://empathy.co/) | [@guillermotti](https://github.com/guillermotti) | Developer portal for tech docs, service catalog, plugin discovery and much more. | +| [creditas.com](https://creditas.com/) | [@aureliosaraiva](https://github.com/aureliosaraiva) [@Creditas](https://github.com/creditas) | Centralization of all services, standards, documentation, etc. We started the deployment process. | +| [Prisjakt](https://www.prisjakt.nu) / [PriceSpy](https://pricespy.co.uk) | [@kennylindahl](https://github.com/kennylindahl) | Internal developer portal - Documentation, scaffolding, software catalog, TechRadar, Gitlab org data integration | +| [Powerspike](https://powerspike.tv/) | [@trelore](https://github.com/trelore) | Developer portal for documentation of core libraries and repositories. | +| [2U](https://2u.com) | [Andrew Thal](https://github.com/athal7) | Development team home-base, promoting service discoverability, resource dependencies, and tech radar | +| [Taxfix](https://taxfix.de/) | [Sami Ur Rehman](https://github.com/samiurrehman92) | Developer's portal with software catalog at it's core. Hosts API Specs, Tech Docs, Tech Radar and some custom plugins. | +| [Busuu](https://busuu.com/) | [Adam Tester](https://github.com/adamtester) | Developer portal with service catalog, API docs, Event docs, service templating, and cost insights. | +| [Loadsmart](https://loadsmart.com/) | [Loadsmart](https://github.com/loadsmart) | Improve services visibility and operations for service owners and developers. | +| [Monzo](https://monzo.com/) | [@WillSewell](https://github.com/WillSewell), [@joechrisellis](https://github.com/joechrisellis) | Developer portal showing metadata and docs for over 2000 microservices. We have built a number of plugins such as a UI for our system to measure [software excellence](https://monzo.com/blog/2021/09/15/how-we-measure-software-excellence), and a UI to show deployment and config change events. | +| [Vaimo](https://www.vaimo.com) | [@vaimo-magnus](https://github.com/vaimo-magnus) | Developer Portal for our developers at Vaimo, currently docs and self-service towards our internal PaaS based on k8s. Plans to extend the catalog into Projects, Environments etc | +| [Wayfair](https://www.wayfair.com) | [@fransan](https://github.com/fransan), [@errskipower](https://github.com/errskipower), [@hrrs](https://github.com/hrrs) | Developer portal for service catalog, technical documentation, and APIs. | +| [CircleHD](https://www.circlehd.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe | +| [CastDesk](https://castdesk.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe | +| [Santagostino](https://santagostino.it) | [@santagostino](https://github.com/santagostino) | Developer portal, gateway to our infrastructure, documentation, service catalog and internal tooling. | +| [Peak](https://peak.ai) | [Luke Beamish](https://github.com/lukebeamish-peak) | Developer portal for all internal engineers to access documentation and tooling. | +| [Gelato](https://gelato.com/) | [Dmitry Makarenko](https://github.com/dmitry-makarenko-gelato) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal and third-party systems🚀. | +| [GoCardless](https://gocardless.com/) | [James Turley](https://github.com/tragiclifestories) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal systems. | +| [Box](https://www.box.com) | [@kielosz](https://github.com/kielosz), [@jluk-box](https://github.com/jluk-box), [@ptychu](https://github.com/ptychu), [@alexrybch](https://github.com/alexrybch), [@szubster](https://github.com/szubster) | Developer portal for service catalog, integration with internal systems, new service onboarding. | +| [Bazaarvoice](https://www.bazaarvoice.com) | [@niallmccullagh](https://github.com/niallmccullagh) | Developer portal for service catalog and scaffolds, publishing Github docs and API documentation, visualising our internal tech radar and our product engineering org structure. | +| [Krateo PlatformOps](https://www.krateo.io) | [@projectkerberus](https://github.com/projectkerberus) | A multi-cloud control plane to create, manage and deploy any kind of resource easily and centrally via a Developer Portal that centralizes via a self-service catalog the templating and ownership of services, the available documentation, the overview of the components that compose an entire domain and all the data of the service lifecycle. | +| [Adevinta](https://www.adevinta.com) | [Ray Sinnema](https://github.com/RemonSinnema) | Showcase shared services to our internal customers. | +| [Splunk](https://www.splunk.com) | [@tonytamsf](https://github.com/tonytamsf) | Developer portal as a centralized place to find people, services, documentation, escalation policies and give bravos. This portal is also being used as a centralized search engine for engineering specific documentation. | +| [SoundCloud](https://www.soundcloud.com) | [Julio Zynger](https://github.com/julioz) | Developer portal as a [humane registry](https://martinfowler.com/bliki/HumaneRegistry.html) for the organization: catalog of people, services, documentation, feature toggles, escalation policies, etc. | +| [Volvofinans Bank](https://www.volvofinans.se) | [Johan Hammar](https://github.com/johanhammar) | Developer portal enabling engineers to manage and explore software and documentation. | +| [Palo Alto Networks](https://www.paloaltonetworks.com) | [Jeremy Guarini](https://github.com/jeremyguarini), [Brian Lomeland](https://github.com/bbbmmmlll), [Palo Alto Networks](https://github.com/PaloAltoNetworks) | Developer portal, service catalog, documentation and tooling | +| [Signal Iduna Group](https://www.signal-iduna.de/) | [Jonas Thomsen](https://github.com/JoThomsen) | Developer Portal, documentation, monitoring, service catalog for our insurance ecosystem | +| [Tradeshift](https://www.tradeshift.com/) | [Soren Mathiasen](https://github.com/sorenmat) | Developer Portal: documentation, monitoring, service templates, service catalog for our micro services | +| [Unity](https://unity.com) | [Ted Cordery](https://github.com/TeddyBallGame) | A centralized service catalog with documentation for our service engineers. | +| [PicPay](https://www.picpay.com) | [Luis Baroni](https://github.com/lcsbaroni), [Renata Poluceno](https://github.com/renatapoluceno), [PicPay](https://github.com/picpay) | Developer portal for building services throught templates, service catalog with ownership of services, documentation and metrics providing autonomy and visibility for all. | +| [Epic Games](https://www.epicgames.com) | [Brian Jung](https://github.com/brian-at-epic), [Jeff Goldian](https://github.com/jeffgoldian-Epic) | Developer Portal: Service Catalog, Documentation, Software Templates and more making our internal teams' lives easier! | +| [Globo](https://globo.com) | [Carlos Gusmão](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. | +| [QBE](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly 🚀 | +| [GoTo](https://www.goto.com) | [Lorenzo Orsatti](https://github.com/lorsatti) | Improve onboarding experience of new developers. Discover faster and painlessly developer documentation, API definitions and team information. Provide useful dev metrics in a central place. Provide easy-to-use templates for new services. | +| [Telstra](https://www.telstra.com.au) | [@kiranpatel11](https://github.com/kiranpatel11), [JasonC](https://github.com/JasonC17) | Primary usage: software catalog and templates
Emerging usage : TechDocs, Explore Ecosystem, TechRadar, etc | +| [Mosaico](https://www.mosaico.com.br/) | [Wédney Yuri](https://github.com/wedneyyuri),[@tino.milton](https://github.com/miltonjacomini) | A centralized service catalog of our documentation for our service engineers. | +| [Mox Bank](https://www.mox.com/) | [Nick Laqua](https://github.com/nick-laqua-dragon) | "Single pane of glass" developer portal for providing a best-in-class developer experience to our product teams and making Mox the best tech environment in Hongkong 🥰🚀 | +| [Keyloop](https://www.keyloop.com/) | [Andre Wanlin](https://github.com/awanlin) | Future-motive Developer Portal to help our teams create technology to make everything about buying and owning a car better. 🚗 | +| [Simply Business](https://sbtech.simplybusiness.co.uk/) | [@addersuk](https://github.com/addersuk), [@LightningStairs](https://github.com/LightningStairs), [@punitcse](https://github.com/punitcse), [@moltenice](https://github.com/moltenice) | Central developer portal to access everything a developer needs such as docs, internal service catalog, and the ability to quickly create a new service from a template. Internally developed Backstage plugins allow us to customise the experience to how we work. | +| [Overwolf](https://www.overwolf.com) | [@tomwolfgang](https://github.com/tomwolfgang) | Dev portal - software catalog, tech-docs, scaffolding | +| [Hotmart](https://www.hotmart.com) | [@fabioviana-hotmart](https://github.com/fabioviana-hotmart) | The main Developers Portal to centralize docs, applications and technical metrics. | +| [EF Education First](https://www.ef.com) | [Daan Boerlage](https://github.com/runebaas), [Rafał Nowosielski](https://github.com/rnowosielski) | Our developer portal - primarily used for cataloging and scaffolding with the ambition to expand with more feature adoptions over time | +| [Power Home Remodeling](https://www.techatpower.com) | [Ben Langfeld](https://github.com/benlangfeld) | Developer portal to our internal services, build on open-source software (including Kubernetes) in our own datacenters. Our Portal allows our team members to navigate inherant complexity and standardise. | +| [Livspace](https://www.livspace.com) | [Praveen Kumar](https://github.com/praveen-livspace) | Developer portal, service catalog, tech docs, API docs and plugins | +| [Just Eat Takeaway](https://www.justeattakeaway.com) | [Kim Wilson](https://github.com/kwilson541) | Our developer portal which centralises applications, reduces cognitive load and provides teams insights. | +| [Hopin](https://hopin.com) | [Vladimir Glafirov](https://github.com/vglafirov), [Chloe Lee](https://github.com/msfuko) | Developer portal to streamline the development practices. Integrated with service catalog, software templates, application monitoring, tech docs and plugins. | +| [HBO Max](https://hbomax.com) | [@mdb](https://github.com/mdb), [@nesta219](https://github.com/nesta219), [@nmische](https://github.com/nmische), [@hbomark](https://github.com/hbomark) | Developer portal hosting service catalog and API documentation, as well as cloud infrastructure details, operational visibility tools, and a custom plugin for browsing notable platform change events, such as deployments and configuration updates. | +| [RCHLO](https://www.riachuelo.com.br) & [MIDWAY](https://www.midway.com.br) | [@marcosborges](https://github.com/marcosborges), [@defaultbr](https://github.com/defaultbr) | Self-Service Platform | +| [HP Inc](https://www.hp.com) | [Damon Kaswell](https://github.com/dekoding) | DevEx engagement hub (dev portal: docs, standards, Q&A) and extensive assets catalog (APIs, services, code, data, etc.) for the pan-HP internal developer community. | +| [VMware](https://www.vmware.com) | [@mpriamo](https://github.com/mpriamo), [@krisapplegate](https://github.com/krisapplegate) | Part of [Tanzu Application Platform](https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/index.html) offering; internal developer portal | +| [Ualá](https://www.uala.com.ar/) | [Santiago Bernal](https://github.com/sabernal) | Initial work being done to centralize documentation for all our microservices and APIs, as well as scaffolding new services and tracking code quality | +| [IKEA IT AB](https://www.ingka.com) | [@bjornramberg](https://github.com/bjornramberg), [@supriyachitale](https://github.com/supriyachitale) | Supporting engineers at scale with self serve access and connecting the dots of our engineering platform and services, enabling product teams to move faster and go further, and unleashing innovation, reuse and co-creation across the organisation. | +| [Invitae](https://www.invitae.com/en) | [@ryan-hanchett](https://github.com/ryan-hanchett), [@gmandler42](https://github.com/gmandler42) | Centralized Developer Experience portal, putting all of our tooling behind a single pane of glass and creating a living service catalog. | +| [Fortum](https://www.fortum.com/) | [@brunoamaroalmeida](https://github.com/brunoamaroalmeida), [@dhaval-vithalani](https://github.com/dhaval-vithalani), [@sunilkumarmohanty](https://github.com/sunilkumarmohanty) | A central portal containing information about our applications, services, processes and other software assets to be used by Fortum software engineering community. | +| [Procore](https://www.procore.com/jobs/engineering) | [@shayon](https://github.com/Shayon), [@jamesdabbs-procore](https://github.com/jamesdabbs-procore) | Developer portal - centralized software catalog and templates to enable self serve and reduce cognitive load. | +| [Bradesco](https://banco.bradesco/html/classic/sobre/index.shtm) | [@danilosoarescardoso](https://github.com/danilosoarescardoso) | Centralized developer portal with software catalog, software templates, techdocs and some plugins from community and by our own. | +| [SeatGeek](https://seatgeek.com) | [@zhammer](https://github.com/zhammer) | Software catalog and documentation platform | +| [Grupo Boticário](https://www.grupoboticario.com.br/) | [@chicoribas](https://github.com/chicoribas), [@fndiaz](https://github.com/fndiaz), [@digogid](https://github.com/digogid), [@manumbs](https://github.com/manumbs), [@haooliveira84](https://github.com/haooliveira84), [@Rhullyam](https://github.com/Rhullyam) | Centralized developer portal with catalog, documentation, and software templates to build a ready to go application, including pipelines (CI/CD) and cloud services provisioning | +| [Snyk](https://snyk.io/) | [@robcresswell](https://github.com/robcresswell) | Developer portal for software discovery, API documentation and templating | +| [Stilingue](https://www.stilingue.com.br/) | [@stilingue-inteligencia-artificial](https://github.com/Stilingue-IA), [@bbviana](https://github.com/bbviana) | Developer portal, services catalog and centralization of metrics from Grafana, Sentry and GCP. Furthermore, centralization of documentation and infra details like DNS, Network services, SSL and so on. | +| [TUI Group](https://www.tuigroup.com/) | [Simon Stamm](https://github.com/simonstamm), [Christian Rudolph](https://github.com/ChrisRu82) | Developer portal for all engineer to provide discoverability to all internal components, APIs, documentation and to scaffold templates with integrations to our internal tools extended by plugins from our community. | From 12deed2614b5a9768bf36bb4d899c1e3f4acd4a8 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 9 Mar 2022 14:46:59 +0000 Subject: [PATCH 11/13] Address further concerns - Remove custom error - Remove enums - The API no longer checks validity of its input, the calling useAsync call does that Signed-off-by: Karan Shah --- plugins/airbrake/src/api/AirbrakeApi.ts | 7 -- plugins/airbrake/src/api/ProductionApi.ts | 6 +- plugins/airbrake/src/api/mock/MockApi.ts | 7 +- .../EntityAirbrakeWidget.tsx | 90 ++++++++----------- 4 files changed, 40 insertions(+), 70 deletions(-) diff --git a/plugins/airbrake/src/api/AirbrakeApi.ts b/plugins/airbrake/src/api/AirbrakeApi.ts index 3abe745b5b..a29aa3eca7 100644 --- a/plugins/airbrake/src/api/AirbrakeApi.ts +++ b/plugins/airbrake/src/api/AirbrakeApi.ts @@ -16,7 +16,6 @@ import { Groups } from './airbrakeGroups'; import { createApiRef } from '@backstage/core-plugin-api'; -import { CustomErrorBase } from '@backstage/errors'; export const airbrakeApiRef = createApiRef({ id: 'plugin.airbrake.service', @@ -25,9 +24,3 @@ export const airbrakeApiRef = createApiRef({ export interface AirbrakeApi { fetchGroups(projectId: string): Promise; } - -export class NoProjectIdError extends CustomErrorBase { - constructor() { - super('Project ID is not present'); - } -} diff --git a/plugins/airbrake/src/api/ProductionApi.ts b/plugins/airbrake/src/api/ProductionApi.ts index 7d1d88a2a4..21ca19ee7d 100644 --- a/plugins/airbrake/src/api/ProductionApi.ts +++ b/plugins/airbrake/src/api/ProductionApi.ts @@ -15,17 +15,13 @@ */ import { Groups } from './airbrakeGroups'; -import { AirbrakeApi, NoProjectIdError } from './AirbrakeApi'; +import { AirbrakeApi } from './AirbrakeApi'; import { DiscoveryApi } from '@backstage/core-plugin-api'; export class ProductionAirbrakeApi implements AirbrakeApi { constructor(private readonly discoveryApi: DiscoveryApi) {} async fetchGroups(projectId: string): Promise { - if (!projectId) { - throw new NoProjectIdError(); - } - const baseUrl = await this.discoveryApi.getBaseUrl('airbrake'); const apiUrl = `${baseUrl}/api/v4/projects/${projectId}/groups`; diff --git a/plugins/airbrake/src/api/mock/MockApi.ts b/plugins/airbrake/src/api/mock/MockApi.ts index f362fbbcaa..dbb1d5c049 100644 --- a/plugins/airbrake/src/api/mock/MockApi.ts +++ b/plugins/airbrake/src/api/mock/MockApi.ts @@ -15,7 +15,7 @@ */ import { Groups } from '../airbrakeGroups'; -import { AirbrakeApi, NoProjectIdError } from '../AirbrakeApi'; +import { AirbrakeApi } from '../AirbrakeApi'; import mockGroupsData from './airbrakeGroupsApiMock.json'; export class MockAirbrakeApi implements AirbrakeApi { @@ -25,10 +25,7 @@ export class MockAirbrakeApi implements AirbrakeApi { this.waitTimeInMillis = waitTimeInMillis; } - fetchGroups(projectId: string): Promise { - if (!projectId) { - return Promise.reject(new NoProjectIdError()); - } + fetchGroups(): Promise { return new Promise(resolve => { setTimeout(() => resolve(mockGroupsData), this.waitTimeInMillis); }); diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx index f235a3e2f5..6c2e4b8686 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -37,70 +37,54 @@ const useStyles = makeStyles(() => ({ }, })); -enum ComponentState { - Loading, - NoProjectId, - Error, - Loaded, -} - export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { const classes = useStyles(); const projectId = useProjectId(entity); const airbrakeApi = useApi(airbrakeApiRef); - let componentState = ComponentState.Loading; const { loading, value, error } = useAsync(() => { + if (!projectId) { + return Promise.resolve(undefined); + } + return airbrakeApi.fetchGroups(projectId); }, [airbrakeApi, projectId]); - if (loading) { - componentState = ComponentState.Loading; - } else if (!projectId) { - componentState = ComponentState.NoProjectId; - } else if (error) { - componentState = ComponentState.Error; + if (!projectId) { + return ( + + ); + } else if (loading) { + return ; } else if (value) { - componentState = ComponentState.Loaded; + return ( + + {value.groups?.map(group => ( + + {group.errors?.map(groupError => ( + + + {groupError.message} + + + ))} + + ))} + + ); } - switch (componentState) { - case ComponentState.Loaded: - return ( - - {value?.groups?.map(group => ( - - {group.errors?.map(groupError => ( - - - {groupError.message} - - - ))} - - ))} - - ); - case ComponentState.NoProjectId: - return ( - - ); - case ComponentState.Loading: - return ; - case ComponentState.Error: - default: - return ( - <> - - - - ); - } + return ( + <> + {error && } + + + ); }; From b0e575d29a271e77eb33f7a021961ff1d55ce9fe Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 9 Mar 2022 14:49:43 +0000 Subject: [PATCH 12/13] Remove unneeded test since the code no longer has this logic Signed-off-by: Karan Shah --- plugins/airbrake/src/api/ProductionApi.test.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/airbrake/src/api/ProductionApi.test.ts b/plugins/airbrake/src/api/ProductionApi.test.ts index 41aef38a27..f09127b4c2 100644 --- a/plugins/airbrake/src/api/ProductionApi.test.ts +++ b/plugins/airbrake/src/api/ProductionApi.test.ts @@ -20,7 +20,6 @@ import mockGroupsData from './mock/airbrakeGroupsApiMock.json'; import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/test-utils'; import { localDiscoveryApi } from './mock'; -import { NoProjectIdError } from './AirbrakeApi'; describe('The production Airbrake API', () => { const productionApi = new ProductionAirbrakeApi(localDiscoveryApi); @@ -54,10 +53,4 @@ describe('The production Airbrake API', () => { await expect(productionApi.fetchGroups('123456')).rejects.toThrow(); }); - - it('throws if project ID is empty', async () => { - await expect(productionApi.fetchGroups('')).rejects.toThrowError( - NoProjectIdError, - ); - }); }); From 880a1a495d2b62b938ae47a27c2741bbbf678596 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 9 Mar 2022 14:53:41 +0000 Subject: [PATCH 13/13] We don't need @backstage/errors anymore Signed-off-by: Karan Shah --- plugins/airbrake/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index b779ff5c08..5ccd9033d5 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -27,7 +27,6 @@ "@backstage/core-components": "^0.9.0", "@backstage/core-plugin-api": "^0.8.0", "@backstage/dev-utils": "^0.2.24", - "@backstage/errors": "^0.2.2", "@backstage/plugin-catalog-react": "^0.8.0", "@backstage/test-utils": "^0.3.0", "@backstage/theme": "^0.2.15",