From c6fdddec77341830a4ca04e90de255e6cba7fc37 Mon Sep 17 00:00:00 2001 From: djamaile Date: Tue, 23 Nov 2021 22:40:03 +0100 Subject: [PATCH 001/316] feat: hide owned selector picker if user doesn't own an entity Signed-off-by: djamaile --- .changeset/modern-buses-protect.md | 5 +++++ .../UserListPicker/UserListPicker.tsx | 22 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 .changeset/modern-buses-protect.md diff --git a/.changeset/modern-buses-protect.md b/.changeset/modern-buses-protect.md new file mode 100644 index 0000000000..d943d6c06a --- /dev/null +++ b/.changeset/modern-buses-protect.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +when a user doesn't own any entity, the user won't get the option to select on owned diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index f861355762..e5658feec9 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -176,12 +176,14 @@ export const UserListPicker = ({ setEntitiesWithoutUserFilter(backendEntities.filter(filterFn)); }, [filters, backendEntities]); + const totalOwnedUserEntities = entitiesWithoutUserFilter.filter(entity => + ownedFilter.filterEntity(entity), + ).length; + function getFilterCount(id: UserListFilterKind) { switch (id) { case 'owned': - return entitiesWithoutUserFilter.filter(entity => - ownedFilter.filterEntity(entity), - ).length; + return totalOwnedUserEntities; case 'starred': return entitiesWithoutUserFilter.filter(entity => starredFilter.filterEntity(entity), @@ -191,6 +193,20 @@ export const UserListPicker = ({ } } + function removeListItem( + arr: ButtonGroup[], + itemID: 'all' | 'owned' | 'starred', + ): ButtonGroup[] { + const index = arr[0].items.map(item => item.id).indexOf(itemID); + arr[0].items.splice(index, 1); + return arr; + } + + // should we do the same for starred? + if (totalOwnedUserEntities < 1) { + removeListItem(filterGroups, 'owned'); + } + return ( {filterGroups.map(group => ( From 26e8a1fc1d7f8f40c4dc4d5c8d297a36cd5783a3 Mon Sep 17 00:00:00 2001 From: djamaile Date: Sun, 28 Nov 2021 23:53:11 +0100 Subject: [PATCH 002/316] feat: hide owned selector picker for user and groups and redirect to all of user owns nothing Signed-off-by: djamaile --- .../UserListPicker/UserListPicker.tsx | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index e5658feec9..594f2f37d3 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -122,17 +122,7 @@ export const UserListPicker = ({ const classes = useStyles(); const configApi = useApi(configApiRef); const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; - - // Remove group items that aren't in availableFilters and exclude - // any now-empty groups. - const filterGroups = getFilterGroups(orgName) - .map(filterGroup => ({ - ...filterGroup, - items: filterGroup.items.filter( - ({ id }) => !availableFilters || availableFilters.includes(id), - ), - })) - .filter(({ items }) => !!items.length); + const [filterGroups, setFilterGroups] = useState(); const { filters, updateFilters, backendEntities, queryParameters } = useEntityListProvider(); @@ -193,23 +183,38 @@ export const UserListPicker = ({ } } - function removeListItem( - arr: ButtonGroup[], - itemID: 'all' | 'owned' | 'starred', - ): ButtonGroup[] { - const index = arr[0].items.map(item => item.id).indexOf(itemID); - arr[0].items.splice(index, 1); - return arr; - } + const removeOwnedFromItemList = (itemList: ButtonGroup[]) => { + const index = itemList[0].items.map(item => item.id).indexOf('owned'); + itemList[0].items.splice(index, 1); + return itemList; + }; - // should we do the same for starred? - if (totalOwnedUserEntities < 1) { - removeListItem(filterGroups, 'owned'); - } + useEffect(() => { + // Remove group items that aren't in availableFilters and exclude + // any now-empty groups. + const defaultFilterGroups = getFilterGroups(orgName) + .map(filterGroup => ({ + ...filterGroup, + items: filterGroup.items.filter( + ({ id }) => !availableFilters || availableFilters.includes(id), + ), + })) + .filter(({ items }) => !!items.length); + if (totalOwnedUserEntities < 1) { + setSelectedUserFilter('all'); + } + if (['group', 'user'].some(kind => kind === queryParameters.kind)) { + setFilterGroups(removeOwnedFromItemList(defaultFilterGroups)); + } + return () => + setFilterGroups(prevState => + prevState !== defaultFilterGroups ? defaultFilterGroups : prevState, + ); + }, [totalOwnedUserEntities, queryParameters, availableFilters, orgName]); return ( - {filterGroups.map(group => ( + {filterGroups?.map(group => ( {group.name} From 5f44cf9fec6e2899ef4c9a64d3e1a82122f33ee7 Mon Sep 17 00:00:00 2001 From: djamaile Date: Mon, 29 Nov 2021 00:23:58 +0100 Subject: [PATCH 003/316] feat: trying useCallback approach Signed-off-by: djamaile --- .../UserListPicker/UserListPicker.tsx | 56 ++++++++++++------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index 594f2f37d3..f2db87a101 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -33,7 +33,13 @@ import { import SettingsIcon from '@material-ui/icons/Settings'; import StarIcon from '@material-ui/icons/Star'; import { compact } from 'lodash'; -import React, { Fragment, useEffect, useMemo, useState } from 'react'; +import React, { + Fragment, + useCallback, + useEffect, + useMemo, + useState, +} from 'react'; import { UserListFilter } from '../../filters'; import { useEntityListProvider, @@ -122,7 +128,30 @@ export const UserListPicker = ({ const classes = useStyles(); const configApi = useApi(configApiRef); const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; - const [filterGroups, setFilterGroups] = useState(); + // Remove group items that aren't in availableFilters and exclude + // any now-empty groups. + const initialFilterGroup = getFilterGroups(orgName) + .map(filterGroup => ({ + ...filterGroup, + items: filterGroup.items.filter( + ({ id }) => !availableFilters || availableFilters.includes(id), + ), + })) + .filter(({ items }) => !!items.length); + const [filterGroups, setFilterGroups] = + useState(initialFilterGroup); + const setDefaultFilterGroups = useCallback(() => { + setFilterGroups( + getFilterGroups(orgName) + .map(filterGroup => ({ + ...filterGroup, + items: filterGroup.items.filter( + ({ id }) => !availableFilters || availableFilters.includes(id), + ), + })) + .filter(({ items }) => !!items.length), + ); + }, [availableFilters, orgName]); const { filters, updateFilters, backendEntities, queryParameters } = useEntityListProvider(); @@ -190,31 +219,20 @@ export const UserListPicker = ({ }; useEffect(() => { - // Remove group items that aren't in availableFilters and exclude - // any now-empty groups. - const defaultFilterGroups = getFilterGroups(orgName) - .map(filterGroup => ({ - ...filterGroup, - items: filterGroup.items.filter( - ({ id }) => !availableFilters || availableFilters.includes(id), - ), - })) - .filter(({ items }) => !!items.length); if (totalOwnedUserEntities < 1) { setSelectedUserFilter('all'); } if (['group', 'user'].some(kind => kind === queryParameters.kind)) { - setFilterGroups(removeOwnedFromItemList(defaultFilterGroups)); - } - return () => - setFilterGroups(prevState => - prevState !== defaultFilterGroups ? defaultFilterGroups : prevState, + setFilterGroups(currentFilterGroups => + removeOwnedFromItemList(currentFilterGroups), ); - }, [totalOwnedUserEntities, queryParameters, availableFilters, orgName]); + } + return () => setDefaultFilterGroups(); + }, [totalOwnedUserEntities, queryParameters, setDefaultFilterGroups]); return ( - {filterGroups?.map(group => ( + {filterGroups.map(group => ( {group.name} From 7c6cb5a12fc92ad6ce27478da157f6c259f642c0 Mon Sep 17 00:00:00 2001 From: djamaile Date: Wed, 1 Dec 2021 22:46:23 +0100 Subject: [PATCH 004/316] chore: remove callback function Signed-off-by: djamaile --- .../UserListPicker/UserListPicker.tsx | 64 ++++++++----------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index f2db87a101..a36f5f78b8 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -33,13 +33,7 @@ import { import SettingsIcon from '@material-ui/icons/Settings'; import StarIcon from '@material-ui/icons/Star'; import { compact } from 'lodash'; -import React, { - Fragment, - useCallback, - useEffect, - useMemo, - useState, -} from 'react'; +import React, { Fragment, useEffect, useMemo, useState } from 'react'; import { UserListFilter } from '../../filters'; import { useEntityListProvider, @@ -128,30 +122,7 @@ export const UserListPicker = ({ const classes = useStyles(); const configApi = useApi(configApiRef); const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; - // Remove group items that aren't in availableFilters and exclude - // any now-empty groups. - const initialFilterGroup = getFilterGroups(orgName) - .map(filterGroup => ({ - ...filterGroup, - items: filterGroup.items.filter( - ({ id }) => !availableFilters || availableFilters.includes(id), - ), - })) - .filter(({ items }) => !!items.length); - const [filterGroups, setFilterGroups] = - useState(initialFilterGroup); - const setDefaultFilterGroups = useCallback(() => { - setFilterGroups( - getFilterGroups(orgName) - .map(filterGroup => ({ - ...filterGroup, - items: filterGroup.items.filter( - ({ id }) => !availableFilters || availableFilters.includes(id), - ), - })) - .filter(({ items }) => !!items.length), - ); - }, [availableFilters, orgName]); + const [filterGroups, setFilterGroups] = useState([]); const { filters, updateFilters, backendEntities, queryParameters } = useEntityListProvider(); @@ -212,6 +183,12 @@ export const UserListPicker = ({ } } + useEffect(() => { + if (totalOwnedUserEntities < 1) { + setSelectedUserFilter('all'); + } + }, [totalOwnedUserEntities]); + const removeOwnedFromItemList = (itemList: ButtonGroup[]) => { const index = itemList[0].items.map(item => item.id).indexOf('owned'); itemList[0].items.splice(index, 1); @@ -219,16 +196,25 @@ export const UserListPicker = ({ }; useEffect(() => { - if (totalOwnedUserEntities < 1) { - setSelectedUserFilter('all'); - } + // Remove group items that aren't in availableFilters and exclude + // any now-empty groups. + const initialFilterGroup = getFilterGroups(orgName) + .map(filterGroup => ({ + ...filterGroup, + items: filterGroup.items.filter( + ({ id }) => !availableFilters || availableFilters.includes(id), + ), + })) + .filter(({ items }) => !!items.length); + // TODO: avoid hardcoding kinds here if (['group', 'user'].some(kind => kind === queryParameters.kind)) { - setFilterGroups(currentFilterGroups => - removeOwnedFromItemList(currentFilterGroups), - ); + setFilterGroups(removeOwnedFromItemList(initialFilterGroup)); } - return () => setDefaultFilterGroups(); - }, [totalOwnedUserEntities, queryParameters, setDefaultFilterGroups]); + return () => + setFilterGroups(prevState => + prevState !== initialFilterGroup ? initialFilterGroup : prevState, + ); + }, [queryParameters, availableFilters, orgName]); return ( From 4a0292c67b420b55d69313c0830308a97b6aa8ac Mon Sep 17 00:00:00 2001 From: djamaile Date: Sat, 4 Dec 2021 16:59:33 +0100 Subject: [PATCH 005/316] refactor: remove useEffect functionality Signed-off-by: djamaile --- backstage.json | 3 + .../UserListPicker/UserListPicker.tsx | 81 +++++++------------ 2 files changed, 34 insertions(+), 50 deletions(-) create mode 100644 backstage.json diff --git a/backstage.json b/backstage.json new file mode 100644 index 0000000000..77e9232b75 --- /dev/null +++ b/backstage.json @@ -0,0 +1,3 @@ +{ + "version": "0.4.5" +} diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index a36f5f78b8..867c5230d4 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -122,16 +122,24 @@ export const UserListPicker = ({ const classes = useStyles(); const configApi = useApi(configApiRef); const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; - const [filterGroups, setFilterGroups] = useState([]); - + const userAndGroupFilterIds = ['starred', 'all']; const { filters, updateFilters, backendEntities, queryParameters } = useEntityListProvider(); + // Remove group items that aren't in availableFilters and exclude + // any now-empty groups. + const filterGroups = getFilterGroups(orgName) + .map(filterGroup => ({ + ...filterGroup, + items: filterGroup.items.filter(({ id }) => + ['group', 'user'].some(kind => kind === queryParameters.kind) + ? userAndGroupFilterIds.includes(id) + : !availableFilters || availableFilters.includes(id), + ), + })) + .filter(({ items }) => !!items.length); const { isStarredEntity } = useStarredEntities(); const { isOwnedEntity } = useEntityOwnership(); - const [selectedUserFilter, setSelectedUserFilter] = useState( - [queryParameters.user].flat()[0] ?? initialFilter, - ); // Static filters; used for generating counts of potentially unselected kinds const ownedFilter = useMemo( @@ -143,18 +151,6 @@ export const UserListPicker = ({ [isOwnedEntity, isStarredEntity], ); - useEffect(() => { - updateFilters({ - user: selectedUserFilter - ? new UserListFilter( - selectedUserFilter as UserListFilterKind, - isOwnedEntity, - isStarredEntity, - ) - : undefined, - }); - }, [selectedUserFilter, isOwnedEntity, isStarredEntity, updateFilters]); - // To show proper counts for each section, apply all other frontend filters _except_ the user // filter that's controlled by this picker. const [entitiesWithoutUserFilter, setEntitiesWithoutUserFilter] = @@ -170,6 +166,24 @@ export const UserListPicker = ({ ownedFilter.filterEntity(entity), ).length; + const [selectedUserFilter, setSelectedUserFilter] = useState( + totalOwnedUserEntities < 1 + ? 'all' + : [queryParameters.user].flat()[0] ?? initialFilter, + ); + + useEffect(() => { + updateFilters({ + user: selectedUserFilter + ? new UserListFilter( + selectedUserFilter as UserListFilterKind, + isOwnedEntity, + isStarredEntity, + ) + : undefined, + }); + }, [selectedUserFilter, isOwnedEntity, isStarredEntity, updateFilters]); + function getFilterCount(id: UserListFilterKind) { switch (id) { case 'owned': @@ -183,39 +197,6 @@ export const UserListPicker = ({ } } - useEffect(() => { - if (totalOwnedUserEntities < 1) { - setSelectedUserFilter('all'); - } - }, [totalOwnedUserEntities]); - - const removeOwnedFromItemList = (itemList: ButtonGroup[]) => { - const index = itemList[0].items.map(item => item.id).indexOf('owned'); - itemList[0].items.splice(index, 1); - return itemList; - }; - - useEffect(() => { - // Remove group items that aren't in availableFilters and exclude - // any now-empty groups. - const initialFilterGroup = getFilterGroups(orgName) - .map(filterGroup => ({ - ...filterGroup, - items: filterGroup.items.filter( - ({ id }) => !availableFilters || availableFilters.includes(id), - ), - })) - .filter(({ items }) => !!items.length); - // TODO: avoid hardcoding kinds here - if (['group', 'user'].some(kind => kind === queryParameters.kind)) { - setFilterGroups(removeOwnedFromItemList(initialFilterGroup)); - } - return () => - setFilterGroups(prevState => - prevState !== initialFilterGroup ? initialFilterGroup : prevState, - ); - }, [queryParameters, availableFilters, orgName]); - return ( {filterGroups.map(group => ( From 95881167dcf1ab29b4f1dd803cb07d7949bd2800 Mon Sep 17 00:00:00 2001 From: djamaile Date: Tue, 7 Dec 2021 23:50:09 +0100 Subject: [PATCH 006/316] chore: some clean up Signed-off-by: djamaile --- .changeset/modern-buses-protect.md | 4 ++- .../UserListPicker/UserListPicker.tsx | 25 ++++++++++--------- .../src/hooks/useEntityListProvider.test.tsx | 19 ++++++++++++-- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/.changeset/modern-buses-protect.md b/.changeset/modern-buses-protect.md index d943d6c06a..2aed52eca0 100644 --- a/.changeset/modern-buses-protect.md +++ b/.changeset/modern-buses-protect.md @@ -2,4 +2,6 @@ '@backstage/plugin-catalog-react': patch --- -when a user doesn't own any entity, the user won't get the option to select on owned +When a user has zero owned entities when viewing an entity kind in the catalog +page, it will be automatically redirected to see all the entities. Furthermore, +for the kind User and Group there are no longer the owned selector. diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index 867c5230d4..9aafdf1437 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -122,15 +122,17 @@ export const UserListPicker = ({ const classes = useStyles(); const configApi = useApi(configApiRef); const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; - const userAndGroupFilterIds = ['starred', 'all']; const { filters, updateFilters, backendEntities, queryParameters } = useEntityListProvider(); + // Remove group items that aren't in availableFilters and exclude // any now-empty groups. + const userAndGroupFilterIds = ['starred', 'all']; const filterGroups = getFilterGroups(orgName) .map(filterGroup => ({ ...filterGroup, items: filterGroup.items.filter(({ id }) => + // TODO: avoid hardcoding kinds here ['group', 'user'].some(kind => kind === queryParameters.kind) ? userAndGroupFilterIds.includes(id) : !availableFilters || availableFilters.includes(id), @@ -155,21 +157,13 @@ export const UserListPicker = ({ // filter that's controlled by this picker. const [entitiesWithoutUserFilter, setEntitiesWithoutUserFilter] = useState(backendEntities); - useEffect(() => { - const filterFn = reduceEntityFilters( - compact(Object.values({ ...filters, user: undefined })), - ); - setEntitiesWithoutUserFilter(backendEntities.filter(filterFn)); - }, [filters, backendEntities]); - const totalOwnedUserEntities = entitiesWithoutUserFilter.filter(entity => ownedFilter.filterEntity(entity), ).length; - const [selectedUserFilter, setSelectedUserFilter] = useState( - totalOwnedUserEntities < 1 - ? 'all' - : [queryParameters.user].flat()[0] ?? initialFilter, + totalOwnedUserEntities > 0 + ? [queryParameters.user].flat()[0] ?? initialFilter + : 'all', ); useEffect(() => { @@ -184,6 +178,13 @@ export const UserListPicker = ({ }); }, [selectedUserFilter, isOwnedEntity, isStarredEntity, updateFilters]); + useEffect(() => { + const filterFn = reduceEntityFilters( + compact(Object.values({ ...filters, user: undefined })), + ); + setEntitiesWithoutUserFilter(backendEntities.filter(filterFn)); + }, [filters, backendEntities]); + function getFilterCount(id: UserListFilterKind) { switch (id) { case 'owned': diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index b96f63304a..fd5cf3b9dd 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -137,12 +137,27 @@ describe('', () => { const { result, waitFor } = renderHook(() => useEntityListProvider(), { wrapper, initialProps: { - userFilter: 'owned', + userFilter: 'all', }, }); await waitFor(() => !!result.current.entities.length); expect(result.current.backendEntities.length).toBe(2); - expect(result.current.entities.length).toBe(1); + + act(() => + result.current.updateFilters({ + user: new UserListFilter( + 'owned', + entity => entity.metadata.name === 'component-1', + () => true, + ), + }), + ); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBe(2); + expect(result.current.entities.length).toBe(1); + expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); + }); }); it('resolves query param filter values', async () => { From 30e3fbb34b9679db783c24c9b238ba46c35178b3 Mon Sep 17 00:00:00 2001 From: djamaile Date: Thu, 9 Dec 2021 23:23:58 +0100 Subject: [PATCH 007/316] chore: remove backstage.json Signed-off-by: djamaile --- backstage.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 backstage.json diff --git a/backstage.json b/backstage.json deleted file mode 100644 index 77e9232b75..0000000000 --- a/backstage.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "version": "0.4.5" -} From fbc20dc18e82a7c558408b297256bba3402957e6 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 21 Dec 2021 09:15:16 +0100 Subject: [PATCH 008/316] ADR: Use node-fetch for data fetching Signed-off-by: Johan Haals --- .../adr013-use-node-fetch.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/architecture-decisions/adr013-use-node-fetch.md diff --git a/docs/architecture-decisions/adr013-use-node-fetch.md b/docs/architecture-decisions/adr013-use-node-fetch.md new file mode 100644 index 0000000000..8a6f61545d --- /dev/null +++ b/docs/architecture-decisions/adr013-use-node-fetch.md @@ -0,0 +1,22 @@ +--- +id: adrs-adr013 +title: 'ADR013: Use node-fetch for data fetching' +description: Architecture Decision Record (ADR) for HTTP data fetching packages +--- + +## Context + +Using multiple HTTP packages for data fetching increases the complexity and the +support burden of keeping said package up to date. + +## Decision + +Node packages should use the `node-fetch` package for HTTP data fetching. +Isomorphic packages should use the `cross-fetch` as a development dependency and +rely on the built-in `fetch` API. + +## Consequences + +We will gradually transition away from third party packages such as `axios`, +`got` and others. Once we have transitioned to `node-fetch` we will add lint +rules to enforce this decision. From e5703a34829635733bd66c0c54e36c7b6bd59741 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 21 Dec 2021 11:21:04 +0100 Subject: [PATCH 009/316] Add fetch examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Johan Haals --- .../adr013-use-node-fetch.md | 59 +++++++++++++++++-- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/docs/architecture-decisions/adr013-use-node-fetch.md b/docs/architecture-decisions/adr013-use-node-fetch.md index 8a6f61545d..d802988ae4 100644 --- a/docs/architecture-decisions/adr013-use-node-fetch.md +++ b/docs/architecture-decisions/adr013-use-node-fetch.md @@ -1,7 +1,8 @@ --- id: adrs-adr013 -title: 'ADR013: Use node-fetch for data fetching' -description: Architecture Decision Record (ADR) for HTTP data fetching packages +title: 'ADR013: Proper use of HTTP fetching libraries' +# prettier-ignore +description: Architecture Decision Record (ADR) for the proper use of fetchApiRef, node-fetch, and cross-fetch for data fetching. --- ## Context @@ -11,9 +12,57 @@ support burden of keeping said package up to date. ## Decision -Node packages should use the `node-fetch` package for HTTP data fetching. -Isomorphic packages should use the `cross-fetch` as a development dependency and -rely on the built-in `fetch` API. +Backend (node) packages should use the `node-fetch` package for HTTP data +fetching. Example: + +```ts +import fetch from 'node-fetch'; +import { ResponseError } from '@backstage/errors'; + +const response = await fetch('https://example.com/api/v1/users.json'); +if (!response.ok) { + throw await ResponseError.fromResponse(response); +} +const users = await response.json(); +``` + +Frontend plugins and packages should prefer to use the +[`fetchApiRef`](https://backstage.io/docs/reference/core-plugin-api.fetchapiref). +It uses `cross-fetch` internally. Example: + +```ts +import { useApi } from '@backstage/core-plugin-api'; +const { fetch } = useApi(fetchApiRef); + +const response = await fetch('https://example.com/api/v1/users.json'); +if (!response.ok) { + throw await ResponseError.fromResponse(response); +} +const users = await response.json(); +``` + +Isomorphic packages should have a dependency on the `cross-fetch` package for +mocking and type definitions. Preferably, classes and functions in isomorphic +packages should accept an argument of type `typeof fetch` to let callers supply +their preferred implementation of `fetch`. This lets them adorn the calls with +auth or other information, and track metrics etc, in a cross-platform way. +Example: + +```ts +import crossFetch from 'cross-fetch'; + +export class MyClient { + private readonly fetch: typeof crossFetch; + + constructor(options: { fetch?: typeof crossFetch }) { + this.fetch = options.fetch || crossFetch; + } + + async users() { + return await this.fetch('https://example.com/api/v1/users.json'); + } +} +``` ## Consequences From 1d260170907fb0cef2a4fc07e143919036897b6e Mon Sep 17 00:00:00 2001 From: "jean-philippe.blary" Date: Tue, 21 Dec 2021 13:42:20 +0100 Subject: [PATCH 010/316] fix(cli): skip findPackages if not inside a monorepo Signed-off-by: jean-philippe.blary --- .changeset/light-singers-double.md | 5 +++++ packages/cli/src/lib/config.ts | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 .changeset/light-singers-double.md diff --git a/.changeset/light-singers-double.md b/.changeset/light-singers-double.md new file mode 100644 index 0000000000..e21017373d --- /dev/null +++ b/.changeset/light-singers-double.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Fix issue with plugin:serve for Plugins not using Lerna monorepo. diff --git a/packages/cli/src/lib/config.ts b/packages/cli/src/lib/config.ts index f85db276b2..986e409e58 100644 --- a/packages/cli/src/lib/config.ts +++ b/packages/cli/src/lib/config.ts @@ -44,9 +44,17 @@ export async function loadCliConfig(options: Options) { const project = new Project(paths.targetDir); const packages = await project.getPackages(); - const localPackageNames = options.fromPackage - ? findPackages(packages, options.fromPackage) - : packages.map((p: any) => p.name); + let localPackageNames; + if (options.fromPackage) { + if (packages.length) { + localPackageNames = findPackages(packages, options.fromPackage); + } else { + // No packages: it means that it's not a monorepo (e.g. standalone plugin) + localPackageNames = [options.fromPackage]; + } + } else { + localPackageNames = packages.map((p: any) => p.name); + } const schema = await loadConfigSchema({ dependencies: localPackageNames, From 3bc9681263b7cf8b6d1d35c16b10da8dd34d12c6 Mon Sep 17 00:00:00 2001 From: Suzanne Daniels Date: Wed, 22 Dec 2021 10:07:32 +0100 Subject: [PATCH 011/316] Fixing image for PAT creation Signed-off-by: Suzanne Daniels --- docs/getting-started/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md index bcb792e7aa..55285e7f4e 100644 --- a/docs/getting-started/configuration.md +++ b/docs/getting-started/configuration.md @@ -215,7 +215,7 @@ days for expiration. If you have a hard time picking a number, we suggest to go for 7 days, it's a lucky number.

- Screenshot of the GitHub OAuth creation page + Screenshot of the GitHub Personal Access Token creation page

Set the scope to your likings. For this tutorial, selecting "repo" should be From e90a2f49e1c7f25c6b98e7d696e86cc098e422ff Mon Sep 17 00:00:00 2001 From: moltenice Date: Wed, 22 Dec 2021 14:22:11 +0000 Subject: [PATCH 012/316] Add in the plugin marketplace entry for Airbrake Signed-off-by: Karan Shah --- microsite/data/plugins/airbrake.yaml | 9 +++++++++ microsite/static/img/airbrake.svg | 1 + 2 files changed, 10 insertions(+) create mode 100644 microsite/data/plugins/airbrake.yaml create mode 100644 microsite/static/img/airbrake.svg diff --git a/microsite/data/plugins/airbrake.yaml b/microsite/data/plugins/airbrake.yaml new file mode 100644 index 0000000000..0ebb5b6950 --- /dev/null +++ b/microsite/data/plugins/airbrake.yaml @@ -0,0 +1,9 @@ +--- +title: Airbrake +author: Simply Business +authorUrl: https://sbtech.simplybusiness.co.uk/ +category: Monitoring +description: Access Airbrake error monitoring and other integrations from within Backstage +documentation: https://github.com/backstage/backstage/blob/master/plugins/api-docs/README.md +iconUrl: img/airbrake.svg +npmPackageName: '@backstage/plugin-airbrake' diff --git a/microsite/static/img/airbrake.svg b/microsite/static/img/airbrake.svg new file mode 100644 index 0000000000..8241e375bc --- /dev/null +++ b/microsite/static/img/airbrake.svg @@ -0,0 +1 @@ + From 5cd6880dbe3de998562a43e4cda28b2959334c40 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 22 Dec 2021 14:59:19 +0000 Subject: [PATCH 013/316] Generate the initial plugin code Signed-off-by: Karan Shah --- .github/CODEOWNERS | 79 ++++++------- microsite/data/plugins/airbrake.yaml | 4 +- packages/app/package.json | 5 +- packages/app/src/App.tsx | 2 + plugins/airbrake/.eslintrc.js | 3 + plugins/airbrake/README.md | 13 +++ plugins/airbrake/dev/index.tsx | 27 +++++ plugins/airbrake/package.json | 50 +++++++++ .../ExampleComponent.test.tsx | 47 ++++++++ .../ExampleComponent/ExampleComponent.tsx | 53 +++++++++ .../src/components/ExampleComponent/index.ts | 16 +++ .../ExampleFetchComponent.test.tsx | 40 +++++++ .../ExampleFetchComponent.tsx | 105 ++++++++++++++++++ .../components/ExampleFetchComponent/index.ts | 16 +++ plugins/airbrake/src/index.ts | 16 +++ plugins/airbrake/src/plugin.test.ts | 22 ++++ plugins/airbrake/src/plugin.ts | 37 ++++++ plugins/airbrake/src/routes.ts | 20 ++++ plugins/airbrake/src/setupTests.ts | 17 +++ 19 files changed, 529 insertions(+), 43 deletions(-) create mode 100644 plugins/airbrake/.eslintrc.js create mode 100644 plugins/airbrake/README.md create mode 100644 plugins/airbrake/dev/index.tsx create mode 100644 plugins/airbrake/package.json create mode 100644 plugins/airbrake/src/components/ExampleComponent/ExampleComponent.test.tsx create mode 100644 plugins/airbrake/src/components/ExampleComponent/ExampleComponent.tsx create mode 100644 plugins/airbrake/src/components/ExampleComponent/index.ts create mode 100644 plugins/airbrake/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx create mode 100644 plugins/airbrake/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx create mode 100644 plugins/airbrake/src/components/ExampleFetchComponent/index.ts create mode 100644 plugins/airbrake/src/index.ts create mode 100644 plugins/airbrake/src/plugin.test.ts create mode 100644 plugins/airbrake/src/plugin.ts create mode 100644 plugins/airbrake/src/routes.ts create mode 100644 plugins/airbrake/src/setupTests.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9cc5a2378e..e47ddc8262 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,42 +4,43 @@ # The last matching pattern takes precedence. # https://help.github.com/articles/about-codeowners/ -* @backstage/reviewers -/docs/features/techdocs @backstage/techdocs-core -/docs/features/search @backstage/techdocs-core -/docs/assets/search @backstage/techdocs-core -/plugins/allure @backstage/reviewers @deepak-bhardwaj-ps -/plugins/circleci @backstage/reviewers @adamdmharvey -/plugins/code-coverage @backstage/reviewers @alde @nissayeva -/plugins/code-coverage-backend @backstage/reviewers @alde @nissayeva -/plugins/cost-insights @backstage/silver-lining -/plugins/cloudbuild @backstage/reviewers @trivago/ebarrios -/plugins/search @backstage/techdocs-core -/plugins/search-* @backstage/techdocs-core -/plugins/techdocs @backstage/techdocs-core -/plugins/techdocs-backend @backstage/techdocs-core -/plugins/ilert @backstage/reviewers @yacut -/plugins/home @backstage/techdocs-core -/plugins/azure-devops @backstage/reviewers @marleypowell @awanlin -/plugins/azure-devops-backend @backstage/reviewers @marleypowell @awanlin -/plugins/azure-devops-common @backstage/reviewers @marleypowell @awanlin -/plugins/jenkins @backstage/reviewers @timja -/plugins/jenkins-backend @backstage/reviewers @timja -/plugins/kafka @backstage/reviewers @nirga -/plugins/kafka-backend @backstage/reviewers @nirga -/plugins/scaffolder-backend-module-yeoman @backstage/reviewers @pawelmitka -/plugins/scaffolder-backend-module-rails @backstage/reviewers @angeliski -/plugins/git-release-manager @backstage/reviewers @erikengervall -/tech-insights-backend @backstage/reviewers @xantier @iain-b -/tech-insights-backend-module-jsonfc @backstage/reviewers @xantier @iain-b -/tech-insights-tech-insights-common @backstage/reviewers @xantier @iain-b -/tech-insights-tech-insights-node @backstage/reviewers @xantier @iain-b -/packages/embedded-techdocs-app @backstage/techdocs-core -/packages/search-common @backstage/techdocs-core -/packages/techdocs-cli @backstage/techdocs-core -/packages/techdocs-common @backstage/techdocs-core -/.changeset/cost-insights-* @backstage/reviewers @backstage/silver-lining -/.changeset/search-* @backstage/techdocs-core -/.changeset/techdocs-* @backstage/techdocs-core -/cypress/src/integration/plugins/techdocs.spec.ts @backstage/techdocs-core -/plugins/apache-airflow @backstage/reviewers @cmpadden +* @backstage/maintainers +/.changeset/cost-insights-* @backstage/reviewers @backstage/silver-lining +/.changeset/search-* @backstage/techdocs-core +/.changeset/techdocs-* @backstage/techdocs-core +/cypress/src/integration/plugins/techdocs.spec.ts @backstage/techdocs-core +/docs/assets/search @backstage/techdocs-core +/docs/features/search @backstage/techdocs-core +/docs/features/techdocs @backstage/techdocs-core +/packages/embedded-techdocs-app @backstage/techdocs-core +/packages/search-common @backstage/techdocs-core +/packages/techdocs-cli @backstage/techdocs-core +/packages/techdocs-common @backstage/techdocs-core +/plugins/airbrake @simplybusiness/silversmiths +/plugins/allure @backstage/reviewers @deepak-bhardwaj-ps +/plugins/apache-airflow @backstage/reviewers @cmpadden +/plugins/azure-devops @backstage/reviewers @marleypowell @awanlin +/plugins/azure-devops-backend @backstage/reviewers @marleypowell @awanlin +/plugins/azure-devops-common @backstage/reviewers @marleypowell @awanlin +/plugins/circleci @backstage/reviewers @adamdmharvey +/plugins/cloudbuild @backstage/reviewers @trivago/ebarrios +/plugins/code-coverage @backstage/reviewers @alde @nissayeva +/plugins/code-coverage-backend @backstage/reviewers @alde @nissayeva +/plugins/cost-insights @backstage/silver-lining +/plugins/git-release-manager @backstage/reviewers @erikengervall +/plugins/home @backstage/techdocs-core +/plugins/ilert @backstage/reviewers @yacut +/plugins/jenkins @backstage/reviewers @timja +/plugins/jenkins-backend @backstage/reviewers @timja +/plugins/kafka @backstage/reviewers @nirga +/plugins/kafka-backend @backstage/reviewers @nirga +/plugins/scaffolder-backend-module-rails @backstage/reviewers @angeliski +/plugins/scaffolder-backend-module-yeoman @backstage/reviewers @pawelmitka +/plugins/search @backstage/techdocs-core +/plugins/search-* @backstage/techdocs-core +/plugins/techdocs @backstage/techdocs-core +/plugins/techdocs-backend @backstage/techdocs-core +/tech-insights-backend @backstage/reviewers @xantier @iain-b +/tech-insights-backend-module-jsonfc @backstage/reviewers @xantier @iain-b +/tech-insights-tech-insights-common @backstage/reviewers @xantier @iain-b +/tech-insights-tech-insights-node @backstage/reviewers @xantier @iain-b diff --git a/microsite/data/plugins/airbrake.yaml b/microsite/data/plugins/airbrake.yaml index 0ebb5b6950..d22639fc20 100644 --- a/microsite/data/plugins/airbrake.yaml +++ b/microsite/data/plugins/airbrake.yaml @@ -1,9 +1,9 @@ --- title: Airbrake author: Simply Business -authorUrl: https://sbtech.simplybusiness.co.uk/ +authorUrl: https://github.com/simplybusiness/ category: Monitoring description: Access Airbrake error monitoring and other integrations from within Backstage -documentation: https://github.com/backstage/backstage/blob/master/plugins/api-docs/README.md +documentation: https://github.com/backstage/backstage/blob/master/plugins/airbrake/README.md iconUrl: img/airbrake.svg npmPackageName: '@backstage/plugin-airbrake' diff --git a/packages/app/package.json b/packages/app/package.json index 1f609858f6..14f3fa0594 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -11,9 +11,10 @@ "@backstage/core-components": "^0.8.1", "@backstage/core-plugin-api": "^0.3.1", "@backstage/integration-react": "^0.1.15", + "@backstage/plugin-airbrake": "^0.0.0", + "@backstage/plugin-apache-airflow": "^0.1.0", "@backstage/plugin-api-docs": "^0.6.18", "@backstage/plugin-azure-devops": "^0.1.7", - "@backstage/plugin-apache-airflow": "^0.1.0", "@backstage/plugin-badges": "^0.2.16", "@backstage/plugin-catalog": "^0.7.4", "@backstage/plugin-catalog-graph": "^0.2.3", @@ -41,12 +42,12 @@ "@backstage/plugin-search": "^0.5.1", "@backstage/plugin-sentry": "^0.3.30", "@backstage/plugin-shortcuts": "^0.1.15", + "@backstage/plugin-tech-insights": "^0.1.1", "@backstage/plugin-tech-radar": "^0.4.13", "@backstage/plugin-techdocs": "^0.12.10", "@backstage/plugin-todo": "^0.1.16", "@backstage/plugin-user-settings": "^0.3.13", "@backstage/search-common": "^0.2.0", - "@backstage/plugin-tech-insights": "^0.1.1", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 59f107c70d..487918faa8 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -88,6 +88,7 @@ import * as plugins from './plugins'; import { techDocsPage } from './components/techdocs/TechDocsPage'; import { ApacheAirflowPage } from '@backstage/plugin-apache-airflow'; +import { AirbrakePage } from '@backstage/plugin-airbrake'; const app = createApp({ apis, @@ -220,6 +221,7 @@ const routes = ( } /> } /> } /> + } /> ); diff --git a/plugins/airbrake/.eslintrc.js b/plugins/airbrake/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/plugins/airbrake/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/plugins/airbrake/README.md b/plugins/airbrake/README.md new file mode 100644 index 0000000000..fe1cbfce13 --- /dev/null +++ b/plugins/airbrake/README.md @@ -0,0 +1,13 @@ +# airbrake + +Welcome to the airbrake plugin! + +_This plugin was created through the Backstage CLI_ + +## Getting started + +Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/airbrake](http://localhost:3000/airbrake). + +You can also serve the plugin in isolation by running `yarn start` in the plugin directory. +This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads. +It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory. diff --git a/plugins/airbrake/dev/index.tsx b/plugins/airbrake/dev/index.tsx new file mode 100644 index 0000000000..67de050404 --- /dev/null +++ b/plugins/airbrake/dev/index.tsx @@ -0,0 +1,27 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { createDevApp } from '@backstage/dev-utils'; +import { airbrakePlugin, AirbrakePage } from '../src/plugin'; + +createDevApp() + .registerPlugin(airbrakePlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/airbrake', + }) + .render(); diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json new file mode 100644 index 0000000000..d9b957803b --- /dev/null +++ b/plugins/airbrake/package.json @@ -0,0 +1,50 @@ +{ + "name": "@backstage/plugin-airbrake", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "scripts": { + "build": "backstage-cli plugin:build", + "start": "backstage-cli plugin:serve", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "diff": "backstage-cli plugin:diff", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/core-components": "^0.8.1", + "@backstage/core-plugin-api": "^0.3.1", + "@backstage/theme": "^0.2.14", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.57", + "react-use": "^17.2.4" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "^0.10.2", + "@backstage/core-app-api": "^0.2.1", + "@backstage/dev-utils": "^0.2.14", + "@backstage/test-utils": "^0.1.24", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^11.2.5", + "@testing-library/user-event": "^13.1.8", + "@types/jest": "*", + "@types/node": "*", + "msw": "^0.35.0", + "cross-fetch": "^3.0.6" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/airbrake/src/components/ExampleComponent/ExampleComponent.test.tsx b/plugins/airbrake/src/components/ExampleComponent/ExampleComponent.test.tsx new file mode 100644 index 0000000000..993a8e7a9e --- /dev/null +++ b/plugins/airbrake/src/components/ExampleComponent/ExampleComponent.test.tsx @@ -0,0 +1,47 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { ExampleComponent } from './ExampleComponent'; +import { ThemeProvider } from '@material-ui/core'; +import { lightTheme } from '@backstage/theme'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { + setupRequestMockHandlers, + renderInTestApp, +} from '@backstage/test-utils'; + +describe('ExampleComponent', () => { + const server = setupServer(); + // Enable sane handlers for network requests + setupRequestMockHandlers(server); + + // setup mock response + beforeEach(() => { + server.use( + rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))), + ); + }); + + it('should render', async () => { + const rendered = await renderInTestApp( + + + , + ); + expect(rendered.getByText('Welcome to airbrake!')).toBeInTheDocument(); + }); +}); diff --git a/plugins/airbrake/src/components/ExampleComponent/ExampleComponent.tsx b/plugins/airbrake/src/components/ExampleComponent/ExampleComponent.tsx new file mode 100644 index 0000000000..bc6a9360a9 --- /dev/null +++ b/plugins/airbrake/src/components/ExampleComponent/ExampleComponent.tsx @@ -0,0 +1,53 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { Typography, Grid } from '@material-ui/core'; +import { + InfoCard, + Header, + Page, + Content, + ContentHeader, + HeaderLabel, + SupportButton, +} from '@backstage/core-components'; +import { ExampleFetchComponent } from '../ExampleFetchComponent'; + +export const ExampleComponent = () => ( + +
+ + +
+ + + A description of your plugin goes here. + + + + + + All content should be wrapped in a card like this. + + + + + + + + +
+); diff --git a/plugins/airbrake/src/components/ExampleComponent/index.ts b/plugins/airbrake/src/components/ExampleComponent/index.ts new file mode 100644 index 0000000000..212740dcdb --- /dev/null +++ b/plugins/airbrake/src/components/ExampleComponent/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { ExampleComponent } from './ExampleComponent'; diff --git a/plugins/airbrake/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx b/plugins/airbrake/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx new file mode 100644 index 0000000000..5123bce8ed --- /dev/null +++ b/plugins/airbrake/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx @@ -0,0 +1,40 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { render } from '@testing-library/react'; +import { ExampleFetchComponent } from './ExampleFetchComponent'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; + +describe('ExampleFetchComponent', () => { + const server = setupServer(); + // Enable sane handlers for network requests + setupRequestMockHandlers(server); + + // setup mock response + beforeEach(() => { + server.use( + rest.get('https://randomuser.me/*', (_, res, ctx) => + res(ctx.status(200), ctx.delay(2000), ctx.json({})), + ), + ); + }); + it('should render', async () => { + const rendered = render(); + expect(await rendered.findByTestId('progress')).toBeInTheDocument(); + }); +}); diff --git a/plugins/airbrake/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx b/plugins/airbrake/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx new file mode 100644 index 0000000000..d7b9716439 --- /dev/null +++ b/plugins/airbrake/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx @@ -0,0 +1,105 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import { Table, TableColumn, Progress } from '@backstage/core-components'; +import Alert from '@material-ui/lab/Alert'; +import { useAsync } from 'react-use'; + +const useStyles = makeStyles({ + avatar: { + height: 32, + width: 32, + borderRadius: '50%', + }, +}); + +type User = { + gender: string; // "male" + name: { + title: string; // "Mr", + first: string; // "Duane", + last: string; // "Reed" + }; + location: object; // {street: {number: 5060, name: "Hickory Creek Dr"}, city: "Albany", state: "New South Wales",…} + email: string; // "duane.reed@example.com" + login: object; // {uuid: "4b785022-9a23-4ab9-8a23-cb3fb43969a9", username: "blackdog796", password: "patch",…} + dob: object; // {date: "1983-06-22T12:30:23.016Z", age: 37} + registered: object; // {date: "2006-06-13T18:48:28.037Z", age: 14} + phone: string; // "07-2154-5651" + cell: string; // "0405-592-879" + id: { + name: string; // "TFN", + value: string; // "796260432" + }; + picture: { medium: string }; // {medium: "https://randomuser.me/api/portraits/men/95.jpg",…} + nat: string; // "AU" +}; + +type DenseTableProps = { + users: User[]; +}; + +export const DenseTable = ({ users }: DenseTableProps) => { + const classes = useStyles(); + + const columns: TableColumn[] = [ + { title: 'Avatar', field: 'avatar' }, + { title: 'Name', field: 'name' }, + { title: 'Email', field: 'email' }, + { title: 'Nationality', field: 'nationality' }, + ]; + + const data = users.map(user => { + return { + avatar: ( + {user.name.first} + ), + name: `${user.name.first} ${user.name.last}`, + email: user.email, + nationality: user.nat, + }; + }); + + return ( + + ); +}; + +export const ExampleFetchComponent = () => { + const { value, loading, error } = useAsync(async (): Promise => { + const response = await fetch('https://randomuser.me/api/?results=20'); + const data = await response.json(); + return data.results; + }, []); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + return ; +}; diff --git a/plugins/airbrake/src/components/ExampleFetchComponent/index.ts b/plugins/airbrake/src/components/ExampleFetchComponent/index.ts new file mode 100644 index 0000000000..c17896a0f4 --- /dev/null +++ b/plugins/airbrake/src/components/ExampleFetchComponent/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { ExampleFetchComponent } from './ExampleFetchComponent'; diff --git a/plugins/airbrake/src/index.ts b/plugins/airbrake/src/index.ts new file mode 100644 index 0000000000..9a75b3bbea --- /dev/null +++ b/plugins/airbrake/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { airbrakePlugin, AirbrakePage } from './plugin'; diff --git a/plugins/airbrake/src/plugin.test.ts b/plugins/airbrake/src/plugin.test.ts new file mode 100644 index 0000000000..ab78fb2549 --- /dev/null +++ b/plugins/airbrake/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { airbrakePlugin } from './plugin'; + +describe('airbrake', () => { + it('should export plugin', () => { + expect(airbrakePlugin).toBeDefined(); + }); +}); diff --git a/plugins/airbrake/src/plugin.ts b/plugins/airbrake/src/plugin.ts new file mode 100644 index 0000000000..63c9ec3acc --- /dev/null +++ b/plugins/airbrake/src/plugin.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + createPlugin, + createRoutableExtension, +} from '@backstage/core-plugin-api'; + +import { rootRouteRef } from './routes'; + +export const airbrakePlugin = createPlugin({ + id: 'airbrake', + routes: { + root: rootRouteRef, + }, +}); + +export const AirbrakePage = airbrakePlugin.provide( + createRoutableExtension({ + name: 'AirbrakePage', + component: () => + import('./components/ExampleComponent').then(m => m.ExampleComponent), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/airbrake/src/routes.ts b/plugins/airbrake/src/routes.ts new file mode 100644 index 0000000000..52672267fe --- /dev/null +++ b/plugins/airbrake/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createRouteRef } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'airbrake', +}); diff --git a/plugins/airbrake/src/setupTests.ts b/plugins/airbrake/src/setupTests.ts new file mode 100644 index 0000000000..fc6dbd98f8 --- /dev/null +++ b/plugins/airbrake/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; From e3b11376cb93a5637e192dea7dc1f375f5a75bf6 Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Wed, 22 Dec 2021 10:22:12 -0600 Subject: [PATCH 014/316] fix: enforce cookie ssl in production Signed-off-by: Fidel Coria --- plugins/auth-backend/src/service/router.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index 6a96d421da..6451207d2d 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -68,7 +68,8 @@ export async function createRouter( if (secret) { router.use(cookieParser(secret)); // TODO: Configure the server-side session storage. The default MemoryStore is not designed for production - router.use(session({ secret, saveUninitialized: false, resave: false })); + const enforceCookieSSL = process.env.NODE_ENV === 'production'; + router.use(session({ secret, saveUninitialized: false, resave: false, cookie: { secure: enforceCookieSSL } })); router.use(passport.initialize()); router.use(passport.session()); } else { From eb48e78886d10960ae316164de322bf0042bdbdb Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Wed, 22 Dec 2021 10:27:14 -0600 Subject: [PATCH 015/316] add changeset Signed-off-by: Fidel Coria --- .changeset/twenty-hornets-train.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/twenty-hornets-train.md diff --git a/.changeset/twenty-hornets-train.md b/.changeset/twenty-hornets-train.md new file mode 100644 index 0000000000..492404b573 --- /dev/null +++ b/.changeset/twenty-hornets-train.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Enforce cookie ssl protection when in production for auth-backend sessions From 5801adbd18509948219c4b8b0b17a43b1892d8f7 Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Wed, 22 Dec 2021 10:47:36 -0600 Subject: [PATCH 016/316] use authUrl for condition Signed-off-by: Fidel Coria --- plugins/auth-backend/src/service/router.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index 6451207d2d..deef6ddcf0 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -68,8 +68,15 @@ export async function createRouter( if (secret) { router.use(cookieParser(secret)); // TODO: Configure the server-side session storage. The default MemoryStore is not designed for production - const enforceCookieSSL = process.env.NODE_ENV === 'production'; - router.use(session({ secret, saveUninitialized: false, resave: false, cookie: { secure: enforceCookieSSL } })); + const enforceCookieSSL = authUrl.startsWith('https'); + router.use( + session({ + secret, + saveUninitialized: false, + resave: false, + cookie: { secure: enforceCookieSSL }, + }), + ); router.use(passport.initialize()); router.use(passport.session()); } else { From 27073a49a128a5f86efcca70404c2b8aaafbe6aa Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Wed, 22 Dec 2021 10:50:11 -0600 Subject: [PATCH 017/316] fix spelling in changeset Signed-off-by: Fidel Coria --- .changeset/twenty-hornets-train.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/twenty-hornets-train.md b/.changeset/twenty-hornets-train.md index 492404b573..957bfd00da 100644 --- a/.changeset/twenty-hornets-train.md +++ b/.changeset/twenty-hornets-train.md @@ -2,4 +2,4 @@ '@backstage/plugin-auth-backend': patch --- -Enforce cookie ssl protection when in production for auth-backend sessions +Enforce cookie SSL protection when in production for auth-backend sessions From c5e175cde95ceba6e324fdc06343f140e077ab4f Mon Sep 17 00:00:00 2001 From: Colton Padden Date: Wed, 22 Dec 2021 14:14:31 -0500 Subject: [PATCH 018/316] remove axios dependency from rollbar-backend Signed-off-by: Colton Padden --- .changeset/plenty-flies-repair.md | 5 +++ plugins/rollbar-backend/package.json | 4 ++- .../src/api/RollbarApi.test.ts | 34 ++++++++++++++++++- plugins/rollbar-backend/src/api/RollbarApi.ts | 13 +++---- 4 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 .changeset/plenty-flies-repair.md diff --git a/.changeset/plenty-flies-repair.md b/.changeset/plenty-flies-repair.md new file mode 100644 index 0000000000..7e9690a7f3 --- /dev/null +++ b/.changeset/plenty-flies-repair.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-rollbar-backend': patch +--- + +Replace the usage of `axios` with `node-fetch` in the Rollbar API diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 6fbecdbc3d..3c7cbd5ee9 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -33,8 +33,8 @@ "dependencies": { "@backstage/backend-common": "^0.9.12", "@backstage/config": "^0.1.10", + "@backstage/test-utils": "^0.1.24", "@types/express": "^4.17.6", - "axios": "^0.24.0", "camelcase-keys": "^6.2.2", "compression": "^1.7.4", "cors": "^2.8.5", @@ -44,12 +44,14 @@ "helmet": "^4.0.0", "lodash": "^4.17.21", "morgan": "^1.10.0", + "node-fetch": "^2.6.1", "winston": "^3.2.1", "yn": "^4.0.0" }, "devDependencies": { "@backstage/cli": "^0.10.0", "@types/supertest": "^2.0.8", + "msw": "^0.36.3", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/rollbar-backend/src/api/RollbarApi.test.ts b/plugins/rollbar-backend/src/api/RollbarApi.test.ts index 66a3955f3a..8936bb1839 100644 --- a/plugins/rollbar-backend/src/api/RollbarApi.test.ts +++ b/plugins/rollbar-backend/src/api/RollbarApi.test.ts @@ -14,7 +14,12 @@ * limitations under the License. */ -import { getRequestHeaders } from './RollbarApi'; +import { getRequestHeaders, RollbarApi } from './RollbarApi'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { getVoidLogger } from '@backstage/backend-common'; +import { RollbarProject } from './types'; describe('RollbarApi', () => { describe('getRequestHeaders', () => { @@ -26,4 +31,31 @@ describe('RollbarApi', () => { }); }); }); + + describe('getAllProjects', () => { + const server = setupServer(); + setupRequestMockHandlers(server); + + const mockBaseUrl = 'https://api.rollbar.com/api/1'; + + const mockProjects: RollbarProject[] = [ + { id: 123, name: 'abc', accountId: 1, status: 'enabled' }, + { id: 456, name: 'xyz', accountId: 1, status: 'enabled' }, + ]; + + const setupHandlers = () => { + server.use( + rest.get(`${mockBaseUrl}/projects`, (_, res, ctx) => { + return res(ctx.json({ result: mockProjects })); + }), + ); + }; + + it('should return all projects with a name attribute', async () => { + setupHandlers(); + const api = new RollbarApi('my-access-token', getVoidLogger()); + const projects = await api.getAllProjects(); + expect(projects).toEqual(mockProjects); + }); + }); }); diff --git a/plugins/rollbar-backend/src/api/RollbarApi.ts b/plugins/rollbar-backend/src/api/RollbarApi.ts index 67d0535942..245164b531 100644 --- a/plugins/rollbar-backend/src/api/RollbarApi.ts +++ b/plugins/rollbar-backend/src/api/RollbarApi.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import axios from 'axios'; import { Logger } from 'winston'; import camelcaseKeys from 'camelcase-keys'; import { buildQuery } from '../util'; @@ -25,6 +24,7 @@ import { RollbarProjectAccessToken, RollbarTopActiveItem, } from './types'; +import fetch from 'node-fetch'; const baseUrl = 'https://api.rollbar.com/api/1'; @@ -110,11 +110,12 @@ export class RollbarApi { this.logger.info(`Calling Rollbar REST API, ${fullUrl}`); } - return axios - .get(fullUrl, getRequestHeaders(accessToken || this.accessToken || '')) - .then(response => - camelcaseKeys(response?.data?.result, { deep: true }), - ); + return fetch( + fullUrl, + getRequestHeaders(accessToken || this.accessToken || ''), + ) + .then(response => response.json()) + .then(json => camelcaseKeys(json?.result, { deep: true })); } private async getForProject( From f0f81f6cc7a56e71e462987dee5850deb28f4917 Mon Sep 17 00:00:00 2001 From: Colton Padden Date: Wed, 22 Dec 2021 14:23:16 -0500 Subject: [PATCH 019/316] remove got dependency from auth-backend Signed-off-by: Colton Padden --- .changeset/chatty-gifts-fry.md | 5 ++++ plugins/auth-backend/package.json | 1 - .../src/providers/microsoft/provider.ts | 25 +++++++++---------- 3 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 .changeset/chatty-gifts-fry.md diff --git a/.changeset/chatty-gifts-fry.md b/.changeset/chatty-gifts-fry.md new file mode 100644 index 0000000000..25f0a70bd9 --- /dev/null +++ b/.changeset/chatty-gifts-fry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Replaces the usage of `got` with `node-fetch` in the `getUserPhoto` method of the Microsoft provider diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index c7d208eef2..5a7769c0fb 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -46,7 +46,6 @@ "express-promise-router": "^4.1.0", "express-session": "^1.17.1", "fs-extra": "9.1.0", - "got": "^11.5.2", "helmet": "^4.0.0", "jose": "^1.27.1", "jwt-decode": "^3.1.0", diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index 2dc259fe74..66bb32cfdd 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -45,7 +45,7 @@ import { SignInResolver, } from '../types'; import { Logger } from 'winston'; -import got from 'got'; +import fetch from 'node-fetch'; type PrivateInfo = { refreshToken: string; @@ -173,19 +173,18 @@ export class MicrosoftAuthProvider implements OAuthHandlers { private getUserPhoto(accessToken: string): Promise { return new Promise(resolve => { - got - .get('https://graph.microsoft.com/v1.0/me/photos/48x48/$value', { - encoding: 'binary', - responseType: 'buffer', - headers: { - Authorization: `Bearer ${accessToken}`, - }, - }) - .then(photoData => { - const photoURL = `data:image/jpeg;base64,${Buffer.from( - photoData.body, + fetch('https://graph.microsoft.com/v1.0/me/photos/48x48/$value', { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }) + .then(response => response.arrayBuffer()) + .then(arrayBuffer => { + console.log(Buffer.from(arrayBuffer).toString('utf-8')); + const imageUrl = `data:image/jpeg;base64,${Buffer.from( + arrayBuffer, ).toString('base64')}`; - resolve(photoURL); + resolve(imageUrl); }) .catch(error => { this.logger.warn( From 22bb6fad0c9b675822083b08dbd6cd2b8aab45a9 Mon Sep 17 00:00:00 2001 From: Colton Padden Date: Wed, 22 Dec 2021 14:23:27 -0500 Subject: [PATCH 020/316] update yarn.lock after axios and got top-level dependency removal Signed-off-by: Colton Padden --- yarn.lock | 96 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 19 deletions(-) diff --git a/yarn.lock b/yarn.lock index 422531d3a4..1a91885e6c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4927,7 +4927,7 @@ "@types/set-cookie-parser" "^2.4.0" set-cookie-parser "^2.4.6" -"@mswjs/interceptors@^0.12.6": +"@mswjs/interceptors@^0.12.6", "@mswjs/interceptors@^0.12.7": version "0.12.7" resolved "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.12.7.tgz#0d1cd4cd31a0f663e0455993951201faa09d0909" integrity sha512-eGjZ3JRAt0Fzi5FgXiV/P3bJGj0NqsN7vBS0J0FO2AQRQ0jCKQS4lEFm4wvlSgKQNfeuc/Vz6d81VtU3Gkx/zg== @@ -9996,13 +9996,6 @@ axios@^0.21.1, axios@^0.21.4: dependencies: follow-redirects "^1.14.0" -axios@^0.24.0: - version "0.24.0" - resolved "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" - integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== - dependencies: - follow-redirects "^1.14.4" - axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" @@ -11104,6 +11097,14 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4. escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@4.1.1, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" + integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -11123,14 +11124,6 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" - integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - change-case-all@1.0.14: version "1.0.14" resolved "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.14.tgz#bac04da08ad143278d0ac3dda7eccd39280bfba1" @@ -15248,7 +15241,7 @@ fn.name@1.x.x: resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.4: +follow-redirects@^1.0.0, follow-redirects@^1.14.0: version "1.14.6" resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz#8cfb281bbc035b3c067d6cd975b0f6ade6e855cd" integrity sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A== @@ -16096,7 +16089,7 @@ google-p12-pem@^3.0.3: dependencies: node-forge "^0.10.0" -got@^11.5.2, got@^11.8.0, got@^11.8.2: +got@^11.8.0, got@^11.8.2: version "11.8.2" resolved "https://registry.npmjs.org/got/-/got-11.8.2.tgz#7abb3959ea28c31f3576f1576c1effce23f33599" integrity sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ== @@ -17242,7 +17235,7 @@ inquirer@^8.0.0: strip-ansi "^6.0.0" through "^2.3.6" -inquirer@^8.1.1: +inquirer@^8.1.1, inquirer@^8.2.0: version "8.2.0" resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a" integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ== @@ -21383,6 +21376,32 @@ msw@^0.35.0: type-fest "^1.2.2" yargs "^17.0.1" +msw@^0.36.3: + version "0.36.3" + resolved "https://registry.npmjs.org/msw/-/msw-0.36.3.tgz#7feb243a5fcf563806d45edc027bc36144741170" + integrity sha512-Itzp/QhKaleZoslXDrNik3ramW9ynqzOdbwydX2ehBSSaZd5QoiAl/bHYcV33R6CEZcJgIX1N4s+G6XkF/bhkA== + dependencies: + "@mswjs/cookies" "^0.1.6" + "@mswjs/interceptors" "^0.12.7" + "@open-draft/until" "^1.0.3" + "@types/cookie" "^0.4.1" + "@types/inquirer" "^8.1.3" + "@types/js-levenshtein" "^1.1.0" + chalk "4.1.1" + chokidar "^3.4.2" + cookie "^0.4.1" + graphql "^15.5.1" + headers-utils "^3.0.2" + inquirer "^8.2.0" + is-node-process "^1.0.1" + js-levenshtein "^1.1.6" + node-fetch "^2.6.1" + path-to-regexp "^6.2.0" + statuses "^2.0.0" + strict-event-emitter "^0.2.0" + type-fest "^1.2.2" + yargs "^17.3.0" + multicast-dns-service-types@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" @@ -22997,6 +23016,11 @@ path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" +path-to-regexp@^6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz#f7b3803336104c346889adece614669230645f38" + integrity sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg== + path-type@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -26969,6 +26993,15 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + "string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.6: version "4.0.6" resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" @@ -27066,6 +27099,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.0: version "7.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -29943,6 +29983,11 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^21.0.0: + version "21.0.0" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55" + integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA== + yargs-parser@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-3.2.0.tgz#5081355d19d9d0c8c5d81ada908cb4e6d186664f" @@ -30007,6 +30052,19 @@ yargs@^17.1.1: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^17.3.0: + version "17.3.0" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz#295c4ffd0eef148ef3e48f7a2e0f58d0e4f26b1c" + integrity sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + yargs@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/yargs/-/yargs-5.0.0.tgz#3355144977d05757dbb86d6e38ec056123b3a66e" From da676a49ab9998a40432d02e453359f164d22dd4 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Wed, 22 Dec 2021 22:16:49 +0100 Subject: [PATCH 021/316] fixes api auth bug in techdocs backend Signed-off-by: Erik Larsson --- .changeset/seven-tomatoes-smash.md | 5 +++++ .../techdocs-backend/src/search/DefaultTechDocsCollator.ts | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/seven-tomatoes-smash.md diff --git a/.changeset/seven-tomatoes-smash.md b/.changeset/seven-tomatoes-smash.md new file mode 100644 index 0000000000..e76e9aa4e2 --- /dev/null +++ b/.changeset/seven-tomatoes-smash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': minor +--- + +fixes api auth bug in techdocs backend diff --git a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts index fa8a1156fe..1d3a3dbc3a 100644 --- a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts +++ b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts @@ -123,6 +123,11 @@ export class DefaultTechDocsCollator implements DocumentCollator { techDocsBaseUrl, entityInfo, ), + { + headers: { + Authorization: `Bearer ${token}`, + }, + }, ); const searchIndex = await searchIndexResponse.json(); From bc0c76e89dc465d008c1c33f367eed03370c86aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Dec 2021 04:08:20 +0000 Subject: [PATCH 022/316] build(deps): bump typescript-json-schema from 0.51.0 to 0.52.0 Bumps [typescript-json-schema](https://github.com/YousefED/typescript-json-schema) from 0.51.0 to 0.52.0. - [Release notes](https://github.com/YousefED/typescript-json-schema/releases) - [Commits](https://github.com/YousefED/typescript-json-schema/compare/v0.51.0...v0.52.0) --- updated-dependencies: - dependency-name: typescript-json-schema dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- packages/config-loader/package.json | 2 +- yarn.lock | 71 +++++++++-------------------- 2 files changed, 22 insertions(+), 51 deletions(-) diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 78f8da3443..dbe4ecb67c 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -42,7 +42,7 @@ "json-schema-merge-allof": "^0.8.1", "json-schema-traverse": "^1.0.0", "node-fetch": "^2.6.1", - "typescript-json-schema": "^0.51.0", + "typescript-json-schema": "^0.52.0", "yaml": "^1.9.2", "yup": "^0.32.9" }, diff --git a/yarn.lock b/yarn.lock index fe8a92d1a5..b054dc8182 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6975,11 +6975,6 @@ resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== -"@tsconfig/node16@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz#a6ca6a9a0ff366af433f42f5f0e124794ff6b8f1" - integrity sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA== - "@tsconfig/node16@^1.0.2": version "1.0.2" resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" @@ -25833,6 +25828,11 @@ safe-stable-stringify@^1.1.0: resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz#c8a220ab525cd94e60ebf47ddc404d610dc5d84a" integrity sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw== +safe-stable-stringify@^2.2.0: + version "2.3.1" + resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73" + integrity sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -28088,23 +28088,7 @@ ts-log@^2.2.3: resolved "https://registry.npmjs.org/ts-log/-/ts-log-2.2.3.tgz#4da5640fe25a9fb52642cd32391c886721318efb" integrity sha512-XvB+OdKSJ708Dmf9ore4Uf/q62AYDTzFcAdxc8KNML1mmAWywRFVt/dn1KYJH8Agt5UJNujfM3znU5PxgAzA2w== -ts-node@^10.0.0: - version "10.0.0" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz#05f10b9a716b0b624129ad44f0ea05dac84ba3be" - integrity sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg== - dependencies: - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - source-map-support "^0.5.17" - yn "3.1.1" - -ts-node@^10.2.1, ts-node@^10.4.0: +ts-node@^10.0.0, ts-node@^10.2.1, ts-node@^10.4.0: version "10.4.0" resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== @@ -28323,33 +28307,33 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-json-schema@^0.51.0: - version "0.51.0" - resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.51.0.tgz#e2abff69b8564c98c0edef2c13d55ef10fd71427" - integrity sha512-POhWbUNs2oaBti1W9k/JwS+uDsaZD9J/KQiZ/iXRQEOD0lTn9VmshIls9tn+A9X6O+smPjeEz5NEy6WTkCCzrQ== +typescript-json-schema@^0.52.0: + version "0.52.0" + resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.52.0.tgz#954560ec90e5486e8f7a5b7706ec59286a708e29" + integrity sha512-3ZdHzx116gZ+D9LmMl5/+d1G3Rpt8baWngKzepYWHnXbAa8Winv64CmFRqLlMKneE1c40yugYDFcWdyX1FjGzQ== dependencies: "@types/json-schema" "^7.0.9" "@types/node" "^16.9.2" glob "^7.1.7" - json-stable-stringify "^1.0.1" + safe-stable-stringify "^2.2.0" ts-node "^10.2.1" - typescript "~4.2.3" + typescript "~4.4.4" yargs "^17.1.1" -typescript@^4.0.3, typescript@~4.2.3: - version "4.2.4" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" - integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== +typescript@^4.0.3, typescript@~4.5.2: + version "4.5.4" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8" + integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== typescript@~4.3.5: version "4.3.5" resolved "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== -typescript@~4.5.2: - version "4.5.4" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8" - integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== +typescript@~4.4.4: + version "4.4.4" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" + integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== ua-parser-js@^0.7.18: version "0.7.28" @@ -29941,20 +29925,7 @@ yargs@^16.1.1, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.0.0, yargs@^17.0.1: - version "17.0.1" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.0.1.tgz#6a1ced4ed5ee0b388010ba9fd67af83b9362e0bb" - integrity sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -yargs@^17.1.1: +yargs@^17.0.0, yargs@^17.0.1, yargs@^17.1.1: version "17.2.1" resolved "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz#e2c95b9796a0e1f7f3bf4427863b42e0418191ea" integrity sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q== From 489d491b8c9126dffc735d742402d46f5c4c7ac8 Mon Sep 17 00:00:00 2001 From: mufaddal motiwala Date: Thu, 23 Dec 2021 13:01:11 +0530 Subject: [PATCH 023/316] remove css from index.html Signed-off-by: mufaddal motiwala --- packages/app/public/index.html | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/app/public/index.html b/packages/app/public/index.html index 8273576b01..885fb6c228 100644 --- a/packages/app/public/index.html +++ b/packages/app/public/index.html @@ -42,11 +42,6 @@ href="<%= publicPath %>/safari-pinned-tab.svg" color="#5bbad5" /> - <%= config.getString('app.title') %> <% if (config.has('app.googleAnalyticsTrackingId')) { %> @@ -103,7 +98,7 @@ <% } %> - +
- - From 79b342bd3669ccc65d14aef0043fd3da4f9f61bf Mon Sep 17 00:00:00 2001 From: mufaddal motiwala Date: Thu, 23 Dec 2021 15:27:21 +0530 Subject: [PATCH 025/316] remove inline and internal CSS Signed-off-by: mufaddal motiwala --- .changeset/chatty-wombats-buy.md | 23 +++++++++++++++++++ .../packages/app/public/index.html | 7 +----- 2 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 .changeset/chatty-wombats-buy.md diff --git a/.changeset/chatty-wombats-buy.md b/.changeset/chatty-wombats-buy.md new file mode 100644 index 0000000000..2eec31a5c7 --- /dev/null +++ b/.changeset/chatty-wombats-buy.md @@ -0,0 +1,23 @@ +--- +'@backstage/create-app': patch +--- + +removed inline and internal CSS from index.html + +To make this change to an existing app, apply the following changes to the `app/public/index.html` file: +Remove internal style + +```diff + - +``` + +Remove inline style from the body tag + +```diff +- ++ +``` diff --git a/packages/create-app/templates/default-app/packages/app/public/index.html b/packages/create-app/templates/default-app/packages/app/public/index.html index 1bd6001a51..a936c73602 100644 --- a/packages/create-app/templates/default-app/packages/app/public/index.html +++ b/packages/create-app/templates/default-app/packages/app/public/index.html @@ -42,11 +42,6 @@ href="<%= publicPath %>/safari-pinned-tab.svg" color="#5bbad5" /> - <%= config.getString('app.title') %> <% if (config.has('app.googleAnalyticsTrackingId')) { %>