From d937e32409db42d6dab3c1b5d7b0fc5d442edea5 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Thu, 27 Jan 2022 11:50:16 +0100 Subject: [PATCH 01/35] Differentiate between page height for mobile & desktop Signed-off-by: Philipp Hugenroth --- .../core-components/src/layout/Page/Page.tsx | 17 ++++++++++------- .../src/layout/Sidebar/MobileSidebar.tsx | 12 +++++++++++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/core-components/src/layout/Page/Page.tsx b/packages/core-components/src/layout/Page/Page.tsx index b013affee3..055fb25b40 100644 --- a/packages/core-components/src/layout/Page/Page.tsx +++ b/packages/core-components/src/layout/Page/Page.tsx @@ -14,34 +14,37 @@ * limitations under the License. */ -import React, { PropsWithChildren } from 'react'; +import React, { useContext } from 'react'; import { BackstageTheme } from '@backstage/theme'; import { makeStyles, ThemeProvider } from '@material-ui/core/styles'; +import { SidebarPinStateContext } from '..'; export type PageClassKey = 'root'; -const useStyles = makeStyles( +const useStyles = makeStyles( () => ({ - root: { + root: ({ isMobile }) => ({ display: 'grid', gridTemplateAreas: "'pageHeader pageHeader pageHeader' 'pageSubheader pageSubheader pageSubheader' 'pageNav pageContent pageSidebar'", gridTemplateRows: 'max-content auto 1fr', gridTemplateColumns: 'auto 1fr auto', - height: '100%', + height: isMobile ? '100%' : '100vh', overflowY: 'auto', - }, + }), }), { name: 'BackstagePage' }, ); type Props = { themeId: string; + children?: React.ReactNode; }; -export function Page(props: PropsWithChildren) { +export function Page(props: Props) { const { themeId, children } = props; - const classes = useStyles(); + const { isMobile } = useContext(SidebarPinStateContext); + const classes = useStyles({ isMobile }); return ( ({ diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx index 95947f9274..6734d4b53a 100644 --- a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx +++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx @@ -93,6 +93,10 @@ const useStyles = makeStyles(theme => ({ overlayHeaderClose: { color: theme.palette.bursts.fontColor, }, + + marginMobileSidebar: { + marginBottom: `${sidebarConfig.mobileSidebarHeight}px`, + }, })); const sortSidebarGroupsForPriority = (children: React.ReactElement[]) => @@ -117,7 +121,13 @@ const OverlayMenu = ({ anchor="bottom" open={open} onClose={onClose} - classes={{ paperAnchorBottom: classes.overlay }} + ModalProps={{ + BackdropProps: { classes: { root: classes.marginMobileSidebar } }, + }} + classes={{ + root: classes.marginMobileSidebar, + paperAnchorBottom: classes.overlay, + }} > {label} From f465b63b7f06ace665351d603d3eed2391197763 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Thu, 27 Jan 2022 12:01:55 +0100 Subject: [PATCH 02/35] Add changeset Signed-off-by: Philipp Hugenroth --- .changeset/gold-queens-clap.md | 5 +++++ packages/core-components/api-report.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/gold-queens-clap.md diff --git a/.changeset/gold-queens-clap.md b/.changeset/gold-queens-clap.md new file mode 100644 index 0000000000..252fbb1626 --- /dev/null +++ b/.changeset/gold-queens-clap.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fix an issue where changes related to the `MobileSidebar` prevented scrolling pages. Additionally improve the menu of the `MobileSidebar` to not overlay the `BottomNavigation`. diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index d8aef17007..7819dcf3fc 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -738,7 +738,7 @@ export type OverflowTooltipClassKey = 'container'; // Warning: (ae-missing-release-tag) "Page" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export function Page(props: PropsWithChildren): JSX.Element; +export function Page(props: Props_16): JSX.Element; // Warning: (ae-missing-release-tag) "PageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // From ae1bba9ebccae7c354b84b7a030dc0746cc598af Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Wed, 26 Jan 2022 16:31:33 -0500 Subject: [PATCH 03/35] Use server token for catalog identity client Signed-off-by: Joe Porpeglia --- packages/backend/src/plugins/auth.ts | 9 ++- .../packages/backend/src/plugins/auth.ts | 3 +- .../lib/catalog/CatalogIdentityClient.test.ts | 62 +++++++++---------- .../src/lib/catalog/CatalogIdentityClient.ts | 15 +++-- .../src/providers/atlassian/provider.ts | 3 +- .../src/providers/auth0/provider.ts | 3 +- .../src/providers/aws-alb/provider.ts | 4 +- .../src/providers/bitbucket/provider.ts | 3 +- .../src/providers/gcp-iap/provider.ts | 4 +- .../src/providers/github/provider.ts | 3 +- .../src/providers/gitlab/provider.ts | 3 +- .../src/providers/google/provider.ts | 3 +- .../src/providers/microsoft/provider.ts | 3 +- .../src/providers/oauth2-proxy/provider.ts | 4 +- .../src/providers/oauth2/provider.ts | 3 +- .../src/providers/oidc/provider.ts | 3 +- .../src/providers/okta/provider.ts | 3 +- .../src/providers/onelogin/provider.ts | 3 +- .../src/providers/saml/provider.ts | 3 +- plugins/auth-backend/src/providers/types.ts | 6 +- plugins/auth-backend/src/service/router.ts | 12 +++- .../src/service/standaloneServer.ts | 2 + 22 files changed, 96 insertions(+), 61 deletions(-) diff --git a/packages/backend/src/plugins/auth.ts b/packages/backend/src/plugins/auth.ts index 4e51518bc1..7f2b950c3c 100644 --- a/packages/backend/src/plugins/auth.ts +++ b/packages/backend/src/plugins/auth.ts @@ -23,6 +23,13 @@ export default async function createPlugin({ database, config, discovery, + tokenManager, }: PluginEnvironment): Promise { - return await createRouter({ logger, config, database, discovery }); + return await createRouter({ + logger, + config, + database, + discovery, + tokenManager, + }); } diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts index 52165104a2..f96c55910c 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts @@ -7,6 +7,7 @@ export default async function createPlugin({ database, config, discovery, + tokenManager, }: PluginEnvironment): Promise { - return await createRouter({ logger, config, database, discovery }); + return await createRouter({ logger, config, database, discovery, tokenManager }); } diff --git a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts index 0ddcaa6d2c..897233294f 100644 --- a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts +++ b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts @@ -14,13 +14,13 @@ * limitations under the License. */ +import { TokenManager } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { RELATION_MEMBER_OF, UserEntity, UserEntityV1alpha1, } from '@backstage/catalog-model'; -import { TokenIssuer } from '../../identity'; import { CatalogIdentityClient } from './CatalogIdentityClient'; describe('CatalogIdentityClient', () => { @@ -36,19 +36,19 @@ describe('CatalogIdentityClient', () => { refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), }; - const tokenIssuer: jest.Mocked = { - issueToken: jest.fn(), - listPublicKeys: jest.fn(), + const tokenManager: jest.Mocked = { + getToken: jest.fn(), + authenticate: jest.fn(), }; afterEach(() => jest.resetAllMocks()); it('findUser passes through the correct search params', async () => { catalogApi.getEntities.mockResolvedValueOnce({ items: [{} as UserEntity] }); - tokenIssuer.issueToken.mockResolvedValue('my-token'); + tokenManager.getToken.mockResolvedValue({ token: 'my-token' }); const client = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); await client.findUser({ annotations: { key: 'value' } }); @@ -62,11 +62,7 @@ describe('CatalogIdentityClient', () => { }, { token: 'my-token' }, ); - expect(tokenIssuer.issueToken).toHaveBeenCalledWith({ - claims: { - sub: 'backstage.io/auth-backend', - }, - }); + expect(tokenManager.getToken).toHaveBeenCalledWith(); }); it('resolveCatalogMembership resolves membership', async () => { @@ -114,35 +110,39 @@ describe('CatalogIdentityClient', () => { }, ]; catalogApi.getEntities.mockResolvedValueOnce({ items: mockUsers }); + tokenManager.getToken.mockResolvedValue({ token: 'my-token' }); const client = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const claims = await client.resolveCatalogMembership({ entityRefs: ['inigom', 'User:default/imontoya', 'User:reality/mpatinkin'], }); - expect(catalogApi.getEntities).toHaveBeenCalledWith({ - filter: [ - { - kind: 'user', - 'metadata.namespace': 'default', - 'metadata.name': 'inigom', - }, - { - kind: 'user', - 'metadata.namespace': 'default', - 'metadata.name': 'imontoya', - }, - { - kind: 'user', - 'metadata.namespace': 'reality', - 'metadata.name': 'mpatinkin', - }, - ], - }); + expect(catalogApi.getEntities).toHaveBeenCalledWith( + { + filter: [ + { + kind: 'user', + 'metadata.namespace': 'default', + 'metadata.name': 'inigom', + }, + { + kind: 'user', + 'metadata.namespace': 'default', + 'metadata.name': 'imontoya', + }, + { + kind: 'user', + 'metadata.namespace': 'reality', + 'metadata.name': 'mpatinkin', + }, + ], + }, + { token: 'my-token' }, + ); expect(claims).toMatchObject([ 'user:default/inigom', diff --git a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts index a1f915d152..8341b186a9 100644 --- a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts +++ b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts @@ -24,7 +24,7 @@ import { stringifyEntityRef, UserEntity, } from '@backstage/catalog-model'; -import { TokenIssuer } from '../../identity'; +import { TokenManager } from '@backstage/backend-common'; type UserQuery = { annotations: Record; @@ -40,11 +40,11 @@ type MemberClaimQuery = { */ export class CatalogIdentityClient { private readonly catalogApi: CatalogApi; - private readonly tokenIssuer: TokenIssuer; + private readonly tokenManager: TokenManager; - constructor(options: { catalogApi: CatalogApi; tokenIssuer: TokenIssuer }) { + constructor(options: { catalogApi: CatalogApi; tokenManager: TokenManager }) { this.catalogApi = options.catalogApi; - this.tokenIssuer = options.tokenIssuer; + this.tokenManager = options.tokenManager; } /** @@ -61,9 +61,7 @@ export class CatalogIdentityClient { } // TODO(Rugvip): cache the token - const token = await this.tokenIssuer.issueToken({ - claims: { sub: 'backstage.io/auth-backend' }, - }); + const { token } = await this.tokenManager.getToken(); const { items } = await this.catalogApi.getEntities({ filter }, { token }); if (items.length !== 1) { @@ -106,8 +104,9 @@ export class CatalogIdentityClient { 'metadata.namespace': ref.namespace, 'metadata.name': ref.name, })); + const { token } = await this.tokenManager.getToken(); const entities = await this.catalogApi - .getEntities({ filter }) + .getEntities({ filter }, { token }) .then(r => r.items); if (entityRefs.length !== entities.length) { diff --git a/plugins/auth-backend/src/providers/atlassian/provider.ts b/plugins/auth-backend/src/providers/atlassian/provider.ts index 9987a88407..2696fd233f 100644 --- a/plugins/auth-backend/src/providers/atlassian/provider.ts +++ b/plugins/auth-backend/src/providers/atlassian/provider.ts @@ -197,6 +197,7 @@ export const createAtlassianProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -208,7 +209,7 @@ export const createAtlassianProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = diff --git a/plugins/auth-backend/src/providers/auth0/provider.ts b/plugins/auth-backend/src/providers/auth0/provider.ts index dbd6924804..15578117ea 100644 --- a/plugins/auth-backend/src/providers/auth0/provider.ts +++ b/plugins/auth-backend/src/providers/auth0/provider.ts @@ -220,6 +220,7 @@ export const createAuth0Provider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -231,7 +232,7 @@ export const createAuth0Provider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/aws-alb/provider.ts b/plugins/auth-backend/src/providers/aws-alb/provider.ts index cc111b4aaf..12f7c7f4b4 100644 --- a/plugins/auth-backend/src/providers/aws-alb/provider.ts +++ b/plugins/auth-backend/src/providers/aws-alb/provider.ts @@ -241,7 +241,7 @@ export type AwsAlbProviderOptions = { export const createAwsAlbProvider = ( options?: AwsAlbProviderOptions, ): AuthProviderFactory => { - return ({ config, tokenIssuer, catalogApi, logger }) => { + return ({ config, tokenIssuer, catalogApi, logger, tokenManager }) => { const region = config.getString('region'); const issuer = config.getOptionalString('iss'); @@ -253,7 +253,7 @@ export const createAwsAlbProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/bitbucket/provider.ts b/plugins/auth-backend/src/providers/bitbucket/provider.ts index ff203e0a9d..4d5bdcf6f6 100644 --- a/plugins/auth-backend/src/providers/bitbucket/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucket/provider.ts @@ -273,6 +273,7 @@ export const createBitbucketProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -283,7 +284,7 @@ export const createBitbucketProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = diff --git a/plugins/auth-backend/src/providers/gcp-iap/provider.ts b/plugins/auth-backend/src/providers/gcp-iap/provider.ts index a54c7e9fb2..7816f68b76 100644 --- a/plugins/auth-backend/src/providers/gcp-iap/provider.ts +++ b/plugins/auth-backend/src/providers/gcp-iap/provider.ts @@ -102,7 +102,7 @@ export class GcpIapProvider implements AuthProviderRouteHandlers { export function createGcpIapProvider( options: GcpIapProviderOptions, ): AuthProviderFactory { - return ({ config, tokenIssuer, catalogApi, logger }) => { + return ({ config, tokenIssuer, catalogApi, logger, tokenManager }) => { const audience = config.getString('audience'); const authHandler = options.authHandler ?? defaultAuthHandler; @@ -111,7 +111,7 @@ export function createGcpIapProvider( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); return new GcpIapProvider({ diff --git a/plugins/auth-backend/src/providers/github/provider.ts b/plugins/auth-backend/src/providers/github/provider.ts index bef1a87b0a..9dc70cf60e 100644 --- a/plugins/auth-backend/src/providers/github/provider.ts +++ b/plugins/auth-backend/src/providers/github/provider.ts @@ -245,6 +245,7 @@ export const createGithubProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -270,7 +271,7 @@ export const createGithubProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/gitlab/provider.ts b/plugins/auth-backend/src/providers/gitlab/provider.ts index 5454065847..da816f2fd2 100644 --- a/plugins/auth-backend/src/providers/gitlab/provider.ts +++ b/plugins/auth-backend/src/providers/gitlab/provider.ts @@ -227,6 +227,7 @@ export const createGitlabProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -239,7 +240,7 @@ export const createGitlabProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index 44c22f757e..13c5093aa5 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -259,6 +259,7 @@ export const createGoogleProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -269,7 +270,7 @@ export const createGoogleProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index b4ef30f491..9249f643dc 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -267,6 +267,7 @@ export const createMicrosoftProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -281,7 +282,7 @@ export const createMicrosoftProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts index eceebc5924..24bb4d0362 100644 --- a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts @@ -182,12 +182,12 @@ export const createOauth2ProxyProvider = ( options: Oauth2ProxyProviderOptions, ): AuthProviderFactory => - ({ catalogApi, logger, tokenIssuer }) => { + ({ catalogApi, logger, tokenIssuer, tokenManager }) => { const signInResolver = options.signIn.resolver; const authHandler = options.authHandler; const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); return new Oauth2ProxyAuthProvider({ logger, diff --git a/plugins/auth-backend/src/providers/oauth2/provider.ts b/plugins/auth-backend/src/providers/oauth2/provider.ts index ec777c231b..8e69a3ee1d 100644 --- a/plugins/auth-backend/src/providers/oauth2/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2/provider.ts @@ -233,6 +233,7 @@ export const createOAuth2Provider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -249,7 +250,7 @@ export const createOAuth2Provider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/oidc/provider.ts b/plugins/auth-backend/src/providers/oidc/provider.ts index 0c820648e4..fa46294784 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.ts @@ -257,6 +257,7 @@ export const createOidcProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -272,7 +273,7 @@ export const createOidcProvider = ( const prompt = envConfig.getOptionalString('prompt'); const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/okta/provider.ts b/plugins/auth-backend/src/providers/okta/provider.ts index 30dd295d12..def0da694e 100644 --- a/plugins/auth-backend/src/providers/okta/provider.ts +++ b/plugins/auth-backend/src/providers/okta/provider.ts @@ -268,6 +268,7 @@ export const createOktaProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -286,7 +287,7 @@ export const createOktaProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = _options?.authHandler diff --git a/plugins/auth-backend/src/providers/onelogin/provider.ts b/plugins/auth-backend/src/providers/onelogin/provider.ts index ea84b402d5..a5ab4f658b 100644 --- a/plugins/auth-backend/src/providers/onelogin/provider.ts +++ b/plugins/auth-backend/src/providers/onelogin/provider.ts @@ -219,6 +219,7 @@ export const createOneLoginProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -230,7 +231,7 @@ export const createOneLoginProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/saml/provider.ts b/plugins/auth-backend/src/providers/saml/provider.ts index b9c8d89f5b..1ca8cf0d5d 100644 --- a/plugins/auth-backend/src/providers/saml/provider.ts +++ b/plugins/auth-backend/src/providers/saml/provider.ts @@ -187,12 +187,13 @@ export const createSamlProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => { const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 179d536f3c..b02e8d74b8 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { + PluginEndpointDiscovery, + TokenManager, +} from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; @@ -124,6 +127,7 @@ export type AuthProviderFactoryOptions = { globalConfig: AuthProviderConfig; config: Config; logger: Logger; + tokenManager: TokenManager; tokenIssuer: TokenIssuer; discovery: PluginEndpointDiscovery; catalogApi: CatalogApi; diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index 6fdd768498..bdb68929b1 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -25,6 +25,7 @@ import { import { PluginDatabaseManager, PluginEndpointDiscovery, + TokenManager, } from '@backstage/backend-common'; import { assertError, NotFoundError } from '@backstage/errors'; import { CatalogClient } from '@backstage/catalog-client'; @@ -41,13 +42,21 @@ export interface RouterOptions { database: PluginDatabaseManager; config: Config; discovery: PluginEndpointDiscovery; + tokenManager: TokenManager; providerFactories?: ProviderFactories; } export async function createRouter( options: RouterOptions, ): Promise { - const { logger, config, discovery, database, providerFactories } = options; + const { + logger, + config, + discovery, + database, + tokenManager, + providerFactories, + } = options; const router = Router(); const appUrl = config.getString('app.baseUrl'); @@ -105,6 +114,7 @@ export async function createRouter( globalConfig: { baseUrl: authUrl, appUrl, isOriginAllowed }, config: providersConfig.getConfig(providerId), logger, + tokenManager, tokenIssuer, discovery, catalogApi, diff --git a/plugins/auth-backend/src/service/standaloneServer.ts b/plugins/auth-backend/src/service/standaloneServer.ts index 15ffe1d053..4e416e8dc7 100644 --- a/plugins/auth-backend/src/service/standaloneServer.ts +++ b/plugins/auth-backend/src/service/standaloneServer.ts @@ -17,6 +17,7 @@ import { createServiceBuilder, loadBackendConfig, + ServerTokenManager, SingleHostDiscovery, useHotMemoize, } from '@backstage/backend-common'; @@ -58,6 +59,7 @@ export async function startStandaloneServer( }, }, discovery, + tokenManager: ServerTokenManager.noop(), }); const service = createServiceBuilder(module) From 2b028ae041a6c6e973838ef42e4b9cf1138fb842 Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Wed, 26 Jan 2022 17:00:22 -0500 Subject: [PATCH 04/35] Update api reports Signed-off-by: Joe Porpeglia --- plugins/auth-backend/api-report.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 3490ea317b..7cdc33f0e2 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -15,6 +15,7 @@ import { Logger as Logger_2 } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Profile } from 'passport'; +import { TokenManager } from '@backstage/backend-common'; import { TokenSet } from 'openid-client'; import { UserEntity } from '@backstage/catalog-model'; import { UserinfoResponse } from 'openid-client'; @@ -85,6 +86,7 @@ export type AuthProviderFactoryOptions = { globalConfig: AuthProviderConfig; config: Config; logger: Logger_2; + tokenManager: TokenManager; tokenIssuer: TokenIssuer; discovery: PluginEndpointDiscovery; catalogApi: CatalogApi; @@ -205,7 +207,7 @@ export const bitbucketUsernameSignInResolver: SignInResolver; // Warning: (ae-forgotten-export) The symbol "MemberClaimQuery" needs to be exported by the entry point index.d.ts @@ -671,6 +673,8 @@ export interface RouterOptions { // // (undocumented) providerFactories?: ProviderFactories; + // (undocumented) + tokenManager: TokenManager; } // @public (undocumented) From 55c0d91dfc5f837a19c9ed02e922337a68989c6a Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Wed, 26 Jan 2022 17:02:22 -0500 Subject: [PATCH 05/35] Fix formatting Signed-off-by: Joe Porpeglia --- .../default-app/packages/backend/src/plugins/auth.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts index f96c55910c..015c86466f 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts @@ -9,5 +9,11 @@ export default async function createPlugin({ discovery, tokenManager, }: PluginEnvironment): Promise { - return await createRouter({ logger, config, database, discovery, tokenManager }); + return await createRouter({ + logger, + config, + database, + discovery, + tokenManager, + }); } From 7023e7066b4fd760686e3658724a61ba615bd6d1 Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Wed, 26 Jan 2022 17:20:08 -0500 Subject: [PATCH 06/35] Remove todo Signed-off-by: Joe Porpeglia --- plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts index 8341b186a9..aecf018975 100644 --- a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts +++ b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts @@ -60,7 +60,6 @@ export class CatalogIdentityClient { filter[`metadata.annotations.${key}`] = value; } - // TODO(Rugvip): cache the token const { token } = await this.tokenManager.getToken(); const { items } = await this.catalogApi.getEntities({ filter }, { token }); From 5f9916b2fd5b9ef10449f639473ecfee4bd4015e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 27 Jan 2022 17:11:42 +0100 Subject: [PATCH 07/35] backend: switch example-app to be a file dep Signed-off-by: Patrik Oldsberg --- packages/backend/package.json | 2 +- yarn.lock | 67 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index c56a3d8ee0..af6fa9eec8 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -60,7 +60,7 @@ "@octokit/rest": "^18.5.3", "azure-devops-node-api": "^11.0.1", "dockerode": "^3.3.1", - "example-app": "^0.2.62", + "example-app": "file:../app", "express": "^4.17.1", "express-promise-router": "^4.1.0", "express-prom-bundle": "^6.3.6", diff --git a/yarn.lock b/yarn.lock index 28cafbf47a..7b593fb2ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11431,6 +11431,73 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +"example-app@file:packages/app": + version "0.2.62" + dependencies: + "@backstage/app-defaults" "^0.1.5" + "@backstage/catalog-model" "^0.9.10" + "@backstage/cli" "^0.13.0" + "@backstage/core-app-api" "^0.5.1" + "@backstage/core-components" "^0.8.6" + "@backstage/core-plugin-api" "^0.6.0" + "@backstage/integration-react" "^0.1.19" + "@backstage/plugin-airbrake" "^0.1.1" + "@backstage/plugin-apache-airflow" "^0.1.4" + "@backstage/plugin-api-docs" "^0.7.0" + "@backstage/plugin-azure-devops" "^0.1.12" + "@backstage/plugin-badges" "^0.2.20" + "@backstage/plugin-catalog" "^0.7.10" + "@backstage/plugin-catalog-graph" "^0.2.8" + "@backstage/plugin-catalog-import" "^0.7.10" + "@backstage/plugin-catalog-react" "^0.6.12" + "@backstage/plugin-circleci" "^0.2.35" + "@backstage/plugin-cloudbuild" "^0.2.33" + "@backstage/plugin-code-coverage" "^0.1.23" + "@backstage/plugin-cost-insights" "^0.11.18" + "@backstage/plugin-explore" "^0.3.27" + "@backstage/plugin-gcp-projects" "^0.3.15" + "@backstage/plugin-github-actions" "^0.4.33" + "@backstage/plugin-gocd" "^0.1.2" + "@backstage/plugin-graphiql" "^0.2.28" + "@backstage/plugin-home" "^0.4.12" + "@backstage/plugin-jenkins" "^0.5.18" + "@backstage/plugin-kafka" "^0.2.26" + "@backstage/plugin-kubernetes" "^0.5.5" + "@backstage/plugin-lighthouse" "^0.2.35" + "@backstage/plugin-newrelic" "^0.3.14" + "@backstage/plugin-newrelic-dashboard" "^0.1.4" + "@backstage/plugin-org" "^0.4.0" + "@backstage/plugin-pagerduty" "0.3.23" + "@backstage/plugin-rollbar" "^0.3.24" + "@backstage/plugin-scaffolder" "^0.12.0" + "@backstage/plugin-search" "^0.6.0" + "@backstage/plugin-sentry" "^0.3.34" + "@backstage/plugin-shortcuts" "^0.1.20" + "@backstage/plugin-tech-insights" "^0.1.6" + "@backstage/plugin-tech-radar" "^0.5.3" + "@backstage/plugin-techdocs" "^0.13.1" + "@backstage/plugin-todo" "^0.1.20" + "@backstage/plugin-user-settings" "^0.3.17" + "@backstage/search-common" "^0.2.2" + "@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" + "@octokit/rest" "^18.5.3" + "@roadiehq/backstage-plugin-buildkite" "^1.3.4" + "@roadiehq/backstage-plugin-github-insights" "^1.4.2" + "@roadiehq/backstage-plugin-github-pull-requests" "^1.3.2" + "@roadiehq/backstage-plugin-travis-ci" "^1.3.2" + history "^5.0.0" + prop-types "^15.7.2" + react "^17.0.2" + react-dom "^17.0.2" + react-hot-loader "^4.13.0" + react-router "6.0.0-beta.0" + react-router-dom "6.0.0-beta.0" + react-use "^17.2.4" + zen-observable "^0.8.15" + exec-sh@^0.3.2: version "0.3.4" resolved "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" From e39d88bd840b63945bba271f274f1eee6a9ccb7f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 27 Jan 2022 17:14:05 +0100 Subject: [PATCH 08/35] create-app: switch backend dep to use file target Signed-off-by: Patrik Oldsberg --- .changeset/witty-lamps-laugh.md | 13 +++++++++++++ .../default-app/packages/backend/package.json.hbs | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .changeset/witty-lamps-laugh.md diff --git a/.changeset/witty-lamps-laugh.md b/.changeset/witty-lamps-laugh.md new file mode 100644 index 0000000000..1ca4f4e4dc --- /dev/null +++ b/.changeset/witty-lamps-laugh.md @@ -0,0 +1,13 @@ +--- +'@backstage/create-app': patch +--- + +Switched the `app` dependency in the backend to use a file target rather than version. + +To apply this change to an existing app, make the following change to `packages/backend/package.json`: + +```diff + "dependencies": { +- "app": "0.0.0", ++ "app": "file:../app", +``` diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs index 96dc724a1e..2288b475a9 100644 --- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs @@ -14,7 +14,7 @@ "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "app": "0.0.0", + "app": "file:../app", "@backstage/backend-common": "^{{version '@backstage/backend-common'}}", "@backstage/backend-tasks": "^{{version '@backstage/backend-tasks'}}", "@backstage/catalog-model": "^{{version '@backstage/catalog-model'}}", From cef64b156177bfa0021cd65b3286ba05a40f9d1f Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Thu, 27 Jan 2022 16:18:43 -0500 Subject: [PATCH 09/35] Add changesets Signed-off-by: Joe Porpeglia --- .changeset/bright-buttons-rescue.md | 27 +++++++++++++++++++++++++++ .changeset/sour-chairs-double.md | 25 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 .changeset/bright-buttons-rescue.md create mode 100644 .changeset/sour-chairs-double.md diff --git a/.changeset/bright-buttons-rescue.md b/.changeset/bright-buttons-rescue.md new file mode 100644 index 0000000000..71a6b76fa2 --- /dev/null +++ b/.changeset/bright-buttons-rescue.md @@ -0,0 +1,27 @@ +--- +'@backstage/plugin-auth-backend': minor +--- + +**BREAKING** Added `tokenManager` as a required property for the auth-backend `createRouter` function. This dependency is used to issue server tokens that are used by the `CatalogIdentityClient` when looking up users and their group membership during authentication. + +These changes are **required** to `packages/backend/src/plugins/auth.ts`: + +```diff +export default async function createPlugin({ + logger, + database, + config, + discovery, ++ tokenManager, +}: PluginEnvironment): Promise { + return await createRouter({ + logger, + config, + database, + discovery, ++ tokenManager, + }); +} +``` + +**BREAKING** The `CatalogIdentityClient` constructor now expects a `TokenManager` instead of a `TokenIssuer`. The `TokenManager` interface is used to generate a server token when [resolving a user's identity and membership through the catalog](https://backstage.io/docs/auth/identity-resolver). Using server tokens for these requests allows the auth-backend to bypass authorization checks when permissions are enabled for Backstage. This change will break apps that rely on the user tokens that were previously used by the client. Refer to the ["Backend-to-backend Authentication" tutorial](https://backstage.io/docs/tutorials/backend-to-backend-auth) for more information on server token usage. diff --git a/.changeset/sour-chairs-double.md b/.changeset/sour-chairs-double.md new file mode 100644 index 0000000000..4f481e20e7 --- /dev/null +++ b/.changeset/sour-chairs-double.md @@ -0,0 +1,25 @@ +--- +'@backstage/create-app': patch +--- + +Added `tokenManager` as a required property for the auth-backend `createRouter` function. This dependency is used to issue server tokens that are used by the `CatalogIdentityClient` when looking up users and their group membership during authentication. + +These changes are **required** to `packages/backend/src/plugins/auth.ts`: + +```diff +export default async function createPlugin({ + logger, + database, + config, + discovery, ++ tokenManager, +}: PluginEnvironment): Promise { + return await createRouter({ + logger, + config, + database, + discovery, ++ tokenManager, + }); +} +``` From 6e112590065b5a194d4e7de7bc4f3bfbc4c0e53c Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Thu, 27 Jan 2022 17:49:46 -0500 Subject: [PATCH 10/35] Minor adjustments to backstage homepage templates blog post Signed-off-by: Joe Porpeglia Co-authored-by: Tim Hansen --- microsite/blog/2022-01-25-backstage-homepage-templates.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite/blog/2022-01-25-backstage-homepage-templates.md b/microsite/blog/2022-01-25-backstage-homepage-templates.md index 97a7b68869..7ed5ee92e3 100644 --- a/microsite/blog/2022-01-25-backstage-homepage-templates.md +++ b/microsite/blog/2022-01-25-backstage-homepage-templates.md @@ -9,7 +9,7 @@ _This blog post is co-authored by Emma Indal ([@emmaindal](https://github.com/em ![homepage template](assets/22-01-25/homepage-template-blog-post-header.png) -_TLDR;_ We’re excited to announce the arrival of homepage templates for Backstage. It can be intimidating to build up your own instance of Backstage, so we decided to make your life a bit easier by giving you an out-of-the-box homepage to hit the ground running. This template can be found in our [Backstage Storybook](https://backstage.io/storybook/), as well as future templates that we build. +_TLDR;_ We’re excited to announce the arrival of homepage templates for Backstage. It can be intimidating to build up your own instance of Backstage, so we decided to make your life a bit easier by giving you an out-of-the-box homepage to hit the ground running. This template can be found in our [Backstage Storybook](https://backstage.io/storybook/?path=/story/plugins-home-templates--default-template), as well as future templates that we build. @@ -23,7 +23,7 @@ But we also know that all organizations look different and have different needs. ## What are homepage templates? -A homepage template is just a template of what a homepage can look like. You can either copy it as a whole, or pick different components from it to use. The homepage templates live in our [Backstage Storybook](https://backstage.io/storybook/) and we hope to see this collection grow with contributions from you all. If you don’t want to use one of the templates, you can pick and choose from our collection of [homepage components](https://backstage.io/storybook/?path=/story/plugins-home-components) that you can use right out of the box and compose your own homepage. We’ve included the [SearchBar](https://backstage.io/storybook/?path=/story/plugins-home-components-searchbar--custom-styles), [CompanyLogo](https://backstage.io/storybook/?path=/story/plugins-home-components-companylogo--custom-logo) and [Toolkit](https://backstage.io/storybook/?path=/story/plugins-home-components-toolkit--default) components in our Backstage Storybook as of today. In the future, we plan on open sourcing the widely popular QuickAccess card, which includes Favorites, Frequently Visited, and Recently Visited options. +A homepage template is just a template of what a homepage can look like. You can either copy it as a whole, or pick different components from it to use. The homepage templates live in our [Backstage Storybook](https://backstage.io/storybook/?path=/story/plugins-home-templates--default-template) and we hope to see this collection grow with contributions from you all. If you don’t want to use one of the templates, you can pick and choose from our collection of [homepage components](https://backstage.io/storybook/?path=/story/plugins-home-components) that you can use right out of the box and compose your own homepage. We’ve included the [SearchBar](https://backstage.io/storybook/?path=/story/plugins-home-components-searchbar--custom-styles), [CompanyLogo](https://backstage.io/storybook/?path=/story/plugins-home-components-companylogo--custom-logo) and [Toolkit](https://backstage.io/storybook/?path=/story/plugins-home-components-toolkit--default) components in our Backstage Storybook as of today. In the future, we plan on open sourcing the widely popular QuickAccess card, which includes Favorites, Frequently Visited, and Recently Visited options. ![Composed Backstage homepage](assets/22-01-25/composed-backstage-homepage.png) _Composed homepage for the app using the default homepage template_ @@ -40,7 +40,7 @@ _Example of the homepage components in the Backstage UI Kit in Figma_ ## What’s next? -Some future templates that we have in mind are more dashboard-esque ones that display a variety of relevant data for your organization. We will also open source more homepage components such as Starred Entities ([[Home] Starred Entities homepage component #6906](https://github.com/backstage/backstage/issues/6906)) that you can use when you are composing your components. +Some future templates that we have in mind are more dashboard-esque ones that display a variety of relevant data for your organization. We will also open source more homepage components such as [Starred Entities](https://github.com/backstage/backstage/issues/6906) that you can use when you are composing your components. ## How to contribute From fac5f112b4847418e9d8bc6623cc064a3297de02 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jan 2022 04:18:50 +0000 Subject: [PATCH 11/35] chore(deps): bump prom-client from 13.2.0 to 14.0.1 Bumps [prom-client](https://github.com/siimon/prom-client) from 13.2.0 to 14.0.1. - [Release notes](https://github.com/siimon/prom-client/releases) - [Changelog](https://github.com/siimon/prom-client/blob/master/CHANGELOG.md) - [Commits](https://github.com/siimon/prom-client/compare/v13.2.0...v14.0.1) --- updated-dependencies: - dependency-name: prom-client dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .changeset/dependabot-f969614.md | 5 +++++ packages/backend/package.json | 2 +- plugins/catalog-backend/package.json | 2 +- yarn.lock | 20 ++++++++++---------- 4 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 .changeset/dependabot-f969614.md diff --git a/.changeset/dependabot-f969614.md b/.changeset/dependabot-f969614.md new file mode 100644 index 0000000000..c3c8890ec9 --- /dev/null +++ b/.changeset/dependabot-f969614.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +chore(deps): bump `prom-client` from 13.2.0 to 14.0.1 diff --git a/packages/backend/package.json b/packages/backend/package.json index c56a3d8ee0..4cfdc81c45 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -67,7 +67,7 @@ "knex": "^0.95.1", "pg": "^8.3.0", "pg-connection-string": "^2.3.0", - "prom-client": "^13.2.0", + "prom-client": "^14.0.1", "sqlite3": "^5.0.1", "winston": "^3.2.1" }, diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index d1137d599d..748ff77592 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -57,7 +57,7 @@ "luxon": "^2.0.2", "node-fetch": "^2.6.1", "p-limit": "^3.0.2", - "prom-client": "^13.2.0", + "prom-client": "^14.0.1", "uuid": "^8.0.0", "winston": "^3.2.1", "yaml": "^1.9.2", diff --git a/yarn.lock b/yarn.lock index 28cafbf47a..6a811bd482 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10635,18 +10635,18 @@ elliptic@^6.0.0: minimalistic-crypto-utils "^1.0.1" "embedded-techdocs-app@file:packages/embedded-techdocs-app": - version "0.2.60" + version "0.2.61" dependencies: "@backstage/app-defaults" "^0.1.5" "@backstage/catalog-model" "^0.9.10" - "@backstage/cli" "^0.12.0" + "@backstage/cli" "^0.13.0" "@backstage/config" "^0.1.13" - "@backstage/core-app-api" "^0.5.0" - "@backstage/core-components" "^0.8.5" + "@backstage/core-app-api" "^0.5.1" + "@backstage/core-components" "^0.8.6" "@backstage/core-plugin-api" "^0.6.0" "@backstage/integration-react" "^0.1.19" - "@backstage/plugin-catalog" "^0.7.9" - "@backstage/plugin-techdocs" "^0.13.0" + "@backstage/plugin-catalog" "^0.7.10" + "@backstage/plugin-techdocs" "^0.13.1" "@backstage/test-utils" "^0.2.3" "@backstage/theme" "^0.2.14" "@material-ui/core" "^4.11.0" @@ -19638,10 +19638,10 @@ progress@2.0.3: resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -prom-client@^13.2.0: - version "13.2.0" - resolved "https://registry.npmjs.org/prom-client/-/prom-client-13.2.0.tgz#99d13357912dd400f8911b77df19f7b328a93e92" - integrity sha512-wGr5mlNNdRNzEhRYXgboUU2LxHWIojxscJKmtG3R8f4/KiWqyYgXTLHs0+Ted7tG3zFT7pgHJbtomzZ1L0ARaQ== +prom-client@^14.0.1: + version "14.0.1" + resolved "https://registry.npmjs.org/prom-client/-/prom-client-14.0.1.tgz#bdd9583e02ec95429677c0e013712d42ef1f86a8" + integrity sha512-HxTArb6fkOntQHoRGvv4qd/BkorjliiuO2uSWC2KC17MUTKYttWdDoXX/vxOhQdkoECEM9BBH0pj2l8G8kev6w== dependencies: tdigest "^0.1.1" From 826e279e6204b5cc6d9505eac98983694ff524e3 Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Wed, 12 Jan 2022 16:45:14 +0200 Subject: [PATCH 12/35] feat(catalog-import): make catalog filename configurable Signed-off-by: Mikko Korhonen --- app-config.yaml | 2 ++ packages/create-app/templates/default-app/app-config.yaml.hbs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app-config.yaml b/app-config.yaml index b43a229ae9..38efb3bb87 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -194,6 +194,8 @@ integrations: secretAccessKey: ${AWS_SECRET_ACCESS_KEY} catalog: + import: + entityFilename: catalog-info.yaml rules: - allow: - Component diff --git a/packages/create-app/templates/default-app/app-config.yaml.hbs b/packages/create-app/templates/default-app/app-config.yaml.hbs index c804b4b561..380c7c5152 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -80,6 +80,8 @@ scaffolder: # see https://backstage.io/docs/features/software-templates/configuration for software template options catalog: + import: + entityFilename: catalog-info.yaml rules: - allow: [Component, System, API, Group, User, Resource, Location] locations: From b20709491de27d618b99d380bdcf1008bc28fea6 Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Thu, 13 Jan 2022 11:00:35 +0200 Subject: [PATCH 13/35] feat(catalog-import): expose catalog filename to frontend Signed-off-by: Mikko Korhonen --- plugins/catalog-import/config.d.ts | 33 +++++++++++++++++++++++++++++ plugins/catalog-import/package.json | 6 ++++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 plugins/catalog-import/config.d.ts diff --git a/plugins/catalog-import/config.d.ts b/plugins/catalog-import/config.d.ts new file mode 100644 index 0000000000..b5c5edb89a --- /dev/null +++ b/plugins/catalog-import/config.d.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2022 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 interface Config { + /** + * Configuration options for the catalog plugin. + */ + catalog?: { + /** + * List of import flow specific options and attributes + */ + import?: { + /** + * Catalog entity descriptor filename, defaults to "catalog-info.yaml" + * @visibility frontend + */ + entityFilename?: string; + }; + }; +} diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index ff9fcb24c2..5097f5cc9b 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -69,6 +69,8 @@ "msw": "^0.35.0" }, "files": [ - "dist" - ] + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" } From 581bed351228bd347c7326ea774527794a617893 Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Wed, 12 Jan 2022 17:04:00 +0200 Subject: [PATCH 14/35] feat(catalog-import): read catalog filename from app config Signed-off-by: Mikko Korhonen --- .../src/api/CatalogImportClient.ts | 23 ++++++++++++++----- .../ImportInfoCard/ImportInfoCard.tsx | 8 +++++-- .../PreviewCatalogInfoComponent.tsx | 8 ++++++- .../StepPrepareCreatePullRequest.tsx | 9 ++++++-- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index bc59657cad..1b84fba12f 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -87,13 +87,17 @@ export class CatalogImportClient implements CatalogImportApi { const ghConfig = getGithubIntegrationConfig(this.scmIntegrationsApi, url); if (!ghConfig) { const other = this.scmIntegrationsApi.byUrl(url); + const catalogFilename = + this.configApi.getOptionalString('catalog.import.entityFilename') ?? + 'catalog-info.yaml'; + if (other) { throw new Error( - `The ${other.title} integration only supports full URLs to catalog-info.yaml files. Did you try to pass in the URL of a directory instead?`, + `The ${other.title} integration only supports full URLs to ${catalogFilename} files. Did you try to pass in the URL of a directory instead?`, ); } throw new Error( - 'This URL was not recognized as a valid GitHub URL because there was no configured integration that matched the given host name. You could try to paste the full URL to a catalog-info.yaml file instead.', + `This URL was not recognized as a valid GitHub URL because there was no configured integration that matched the given host name. You could try to paste the full URL to a ${catalogFilename} file instead.`, ); } @@ -127,9 +131,12 @@ export class CatalogImportClient implements CatalogImportApi { const appTitle = this.configApi.getOptionalString('app.title') ?? 'Backstage'; const appBaseUrl = this.configApi.getString('app.baseUrl'); + const catalogFilename = + this.configApi.getOptionalString('catalog.import.entityFilename') ?? + 'catalog-info.yaml'; return { - title: 'Add catalog-info.yaml config file', + title: `Add ${catalogFilename} config file`, body: `This pull request adds a **Backstage entity metadata file** \ to this repository so that the component can be added to the \ [${appTitle} software catalog](${appBaseUrl}).\n\nAfter this pull request is merged, \ @@ -221,8 +228,10 @@ the component will become available.\n\nFor more information, read an \ auth: token, baseUrl: githubIntegrationConfig.apiBaseUrl, }); - const catalogFileName = 'catalog-info.yaml'; - const query = `repo:${owner}/${repo}+filename:${catalogFileName}`; + const catalogFilename = + this.configApi.getOptionalString('catalog.import.entityFilename') ?? + 'catalog-info.yaml'; + const query = `repo:${owner}/${repo}+filename:${catalogFilename}`; const searchResult = await octo.search.code({ q: query }).catch(e => { throw new Error( @@ -295,7 +304,9 @@ the component will become available.\n\nFor more information, read an \ }); const branchName = 'backstage-integration'; - const fileName = 'catalog-info.yaml'; + const fileName = + this.configApi.getOptionalString('catalog.import.entityFilename') ?? + 'catalog-info.yaml'; const repoData = await octo.repos .get({ diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx index 2fab223f20..ef72f79c8a 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -28,6 +28,10 @@ export const ImportInfoCard = () => { const integrations = configApi.getConfig('integrations'); const hasGithubIntegration = integrations.has('github'); + const catalogFilename = + configApi.getOptionalString('catalog.import.entityFilename') ?? + 'catalog-info.yaml'; + return ( { Example: https://github.com/backstage/backstage - The wizard discovers all catalog-info.yaml files in the + The wizard discovers all {catalogFilename} files in the repository, previews the entities, and adds them to the {appTitle}{' '} catalog. {catalogImportApi.preparePullRequest && ( If no entities are found, the wizard will prepare a Pull Request - that adds an example catalog-info.yaml and prepares + that adds an example {catalogFilename} and prepares the {appTitle} catalog to load all entities as soon as the Pull Request is merged. diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.tsx index d0f29c00e2..d97f3a58f6 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.tsx @@ -19,6 +19,7 @@ import { Card, CardContent, CardHeader } from '@material-ui/core'; import React from 'react'; import YAML from 'yaml'; import { CodeSnippet } from '@backstage/core-components'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { trimEnd } from 'lodash'; type Props = { @@ -32,11 +33,16 @@ export const PreviewCatalogInfoComponent = ({ entities, classes, }: Props) => { + const configApi = useApi(configApiRef); + const catalogFilename = + configApi.getOptionalString('catalog.import.entityFilename') ?? + 'catalog-info.yaml'; + return ( {`${trimEnd(repositoryUrl, '/')}/catalog-info.yaml`} + {`${trimEnd(repositoryUrl, '/')}/${catalogFilename}`} } /> diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx index 077d99c4ba..d511294b61 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; -import { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { configApiRef, errorApiRef, useApi } from '@backstage/core-plugin-api'; import { assertError } from '@backstage/errors'; import { catalogApiRef, @@ -102,10 +102,15 @@ export const StepPrepareCreatePullRequest = ({ const catalogApi = useApi(catalogApiRef); const catalogImportApi = useApi(catalogImportApiRef); const errorApi = useApi(errorApiRef); + const configApi = useApi(configApiRef); const [submitted, setSubmitted] = useState(false); const [error, setError] = useState(); + const catalogFilename = + configApi.getOptionalString('catalog.import.entityFilename') ?? + 'catalog-info.yaml'; + const { loading: prDefaultsLoading, value: prDefaults, @@ -193,7 +198,7 @@ export const StepPrepareCreatePullRequest = ({ <> You entered a link to a {analyzeResult.integrationType} repository but a{' '} - catalog-info.yaml could not be found. Use this form to open + {catalogFilename} could not be found. Use this form to open a Pull Request that creates one. From 1bd29cd9aecf9cef13476a69c17c5decc55b368d Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Thu, 13 Jan 2022 11:07:43 +0200 Subject: [PATCH 15/35] feat(catalog-import): make catalog import example paths customizable Signed-off-by: Mikko Korhonen --- .../ImportInfoCard/ImportInfoCard.tsx | 17 +++++++++++------ .../StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx | 4 +++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx index ef72f79c8a..4d78542e60 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -20,7 +20,15 @@ import { Chip, Typography } from '@material-ui/core'; import React from 'react'; import { catalogImportApiRef } from '../../api'; -export const ImportInfoCard = () => { +type Props = { + exampleLocationUrl?: string; + exampleRepositoryUrl?: string; +}; + +export const ImportInfoCard = ({ + exampleLocationUrl = 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', + exampleRepositoryUrl = 'https://github.com/backstage/backstage', +}: Props) => { const configApi = useApi(configApiRef); const appTitle = configApi.getOptional('app.title') || 'Backstage'; const catalogImportApi = useApi(catalogImportApiRef); @@ -45,10 +53,7 @@ export const ImportInfoCard = () => { Link to an existing entity file - Example:{' '} - - https://github.com/backstage/backstage/blob/master/catalog-info.yaml - + Example: {exampleLocationUrl} The wizard analyzes the file, previews the entities, and adds them to @@ -61,7 +66,7 @@ export const ImportInfoCard = () => { - Example: https://github.com/backstage/backstage + Example: {exampleRepositoryUrl} The wizard discovers all {catalogFilename} files in the diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx index 63f3c10fe3..83377d6b2f 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx @@ -36,6 +36,7 @@ type Props = { ) => void; disablePullRequest?: boolean; analysisUrl?: string; + exampleLocationUrl?: string; }; /** @@ -49,6 +50,7 @@ export const StepInitAnalyzeUrl = ({ onAnalysis, analysisUrl = '', disablePullRequest = false, + exampleLocationUrl = 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', }: Props) => { const errorApi = useApi(errorApiRef); const catalogImportApi = useApi(catalogImportApiRef); @@ -138,7 +140,7 @@ export const StepInitAnalyzeUrl = ({ fullWidth id="url" label="Repository URL" - placeholder="https://github.com/backstage/backstage/blob/master/catalog-info.yaml" + placeholder={exampleLocationUrl} helperText="Enter the full path to your entity file to start tracking your component" margin="normal" variant="outlined" From 307f17372e667f111a2fc1371102a9b407d1ba4b Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Thu, 13 Jan 2022 12:30:39 +0200 Subject: [PATCH 16/35] feat(catalog-import): make catalog import branch name customizable Signed-off-by: Mikko Korhonen --- app-config.yaml | 1 + .../create-app/templates/default-app/app-config.yaml.hbs | 1 + plugins/catalog-import/config.d.ts | 7 +++++++ plugins/catalog-import/src/api/CatalogImportClient.ts | 4 +++- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app-config.yaml b/app-config.yaml index 38efb3bb87..b84b5de2f2 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -196,6 +196,7 @@ integrations: catalog: import: entityFilename: catalog-info.yaml + pullRequestBranchName: backstage-integration rules: - allow: - Component diff --git a/packages/create-app/templates/default-app/app-config.yaml.hbs b/packages/create-app/templates/default-app/app-config.yaml.hbs index 380c7c5152..46e2ecbb05 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -82,6 +82,7 @@ scaffolder: catalog: import: entityFilename: catalog-info.yaml + pullRequestBranchName: backstage-integration rules: - allow: [Component, System, API, Group, User, Resource, Location] locations: diff --git a/plugins/catalog-import/config.d.ts b/plugins/catalog-import/config.d.ts index b5c5edb89a..0cc49e418b 100644 --- a/plugins/catalog-import/config.d.ts +++ b/plugins/catalog-import/config.d.ts @@ -28,6 +28,13 @@ export interface Config { * @visibility frontend */ entityFilename?: string; + /** + * A branch name used in pull request when registering existing component via UI + * Valid git refname required, see: https://git-scm.com/docs/git-check-ref-format + * Defaults to "backstage-integration" + * @visibility frontend + */ + pullRequestBranchName?: string; }; }; } diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 1b84fba12f..218814d2fb 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -303,7 +303,9 @@ the component will become available.\n\nFor more information, read an \ baseUrl: githubIntegrationConfig.apiBaseUrl, }); - const branchName = 'backstage-integration'; + const branchName = + this.configApi.getOptionalString('catalog.pullRequestBranchName') ?? + 'backstage-integration'; const fileName = this.configApi.getOptionalString('catalog.import.entityFilename') ?? 'catalog-info.yaml'; From 4d17cc54248c3ba00caba3b3969a77969414b815 Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Fri, 14 Jan 2022 09:35:16 +0200 Subject: [PATCH 17/35] test(catalog-import): update and tests for custom catalog filename and branch name Signed-off-by: Mikko Korhonen --- .../src/api/CatalogImportClient.test.ts | 168 ++++++++++++++++++ .../PreviewCatalogInfoComponent.test.tsx | 69 +++++-- .../StepPrepareCreatePullRequest.test.tsx | 7 +- 3 files changed, 228 insertions(+), 16 deletions(-) diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index 202a7aba85..fa63825af1 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -396,6 +396,84 @@ describe('CatalogImportClient', () => { ], }); }); + + it('should find location with custom catalog filename', async () => { + const repositoryUrl = 'https://github.com/acme-corp/our-awesome-api'; + const entityFilename = 'anvil.yaml'; + + catalogImportClient = new CatalogImportClient({ + discoveryApi, + scmAuthApi, + scmIntegrationsApi, + identityApi, + catalogApi, + configApi: new ConfigReader({ + catalog: { + import: { + entityFilename, + }, + }, + }), + }); + + (new Octokit().search.code as any as jest.Mock).mockImplementationOnce( + async params => ({ + data: { + total_count: 1, + items: [{ path: params.q.split('+filename:').slice(-1)[0] }], + }, + }), + ); + + catalogApi.addLocation.mockImplementation(async ({ type, target }) => ({ + location: { + id: 'id-0', + type: type ?? 'url', + target, + }, + entities: [ + { + apiVersion: '1', + kind: 'Location', + metadata: { + name: 'my-entity', + namespace: 'my-namespace', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'my-entity', + namespace: 'my-namespace', + }, + }, + ], + })); + + await expect( + catalogImportClient.analyzeUrl(repositoryUrl), + ).resolves.toEqual({ + locations: [ + { + entities: [ + { + kind: 'Location', + namespace: 'my-namespace', + name: 'my-entity', + }, + { + kind: 'Component', + namespace: 'my-namespace', + name: 'my-entity', + }, + ], + target: `${repositoryUrl}/blob/main/${entityFilename}`, + }, + ], + type: 'locations', + }); + }); }); describe('submitPullRequest', () => { @@ -443,6 +521,67 @@ describe('CatalogImportClient', () => { base: 'main', }); }); + + it('should create GitHub pull request with custom filename and branch name', async () => { + const entityFilename = 'anvil.yaml'; + const pullRequestBranchName = 'anvil-integration'; + + catalogImportClient = new CatalogImportClient({ + discoveryApi, + scmAuthApi, + scmIntegrationsApi, + identityApi, + catalogApi, + configApi: new ConfigReader({ + catalog: { + import: { + entityFilename, + pullRequestBranchName, + }, + }, + }), + }); + + await expect( + catalogImportClient.submitPullRequest({ + repositoryUrl: 'https://github.com/acme-corp/our-awesome-api', + fileContent: '', + title: `Add ${entityFilename} config file`, + body: `Add ${entityFilename} config file`, + }), + ).resolves.toEqual( + expect.objectContaining({ + link: 'http://pull/request/0', + location: `https://github.com/acme-corp/our-awesome-api/blob/main/${entityFilename}`, + }), + ); + + expect( + (new Octokit().git.createRef as any as jest.Mock).mock.calls[0][0], + ).toEqual( + expect.objectContaining({ + ref: `refs/heads/${pullRequestBranchName}`, + }), + ); + + expect( + (new Octokit().repos.createOrUpdateFileContents as any as jest.Mock) + .mock.calls[0][0], + ).toEqual( + expect.objectContaining({ + path: entityFilename, + branch: pullRequestBranchName, + }), + ); + + expect( + (new Octokit().pulls.create as any as jest.Mock).mock.calls[0][0], + ).toEqual( + expect.objectContaining({ + head: pullRequestBranchName, + }), + ); + }); }); describe('preparePullRequest', () => { @@ -452,5 +591,34 @@ describe('CatalogImportClient', () => { body: expect.any(String), }); }); + + test('should prepare pull request details with custom filename', async () => { + const entityFilename = 'anvil.yaml'; + const pullRequestBranchName = 'anvil-integration'; + + catalogImportClient = new CatalogImportClient({ + discoveryApi, + scmAuthApi, + scmIntegrationsApi, + identityApi, + catalogApi, + configApi: new ConfigReader({ + catalog: { + import: { + entityFilename, + pullRequestBranchName, + }, + }, + app: { + baseUrl: 'https://demo.backstage.io/', + }, + }), + }); + + await expect(catalogImportClient.preparePullRequest()).resolves.toEqual({ + title: `Add ${entityFilename} config file`, + body: expect.any(String), + }); + }); }); }); diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx index fe5e76c968..aac54e084a 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx @@ -15,6 +15,9 @@ */ import { Entity } from '@backstage/catalog-model'; +import { ApiProvider } from '@backstage/core-app-api'; +import { configApiRef } from '@backstage/core-plugin-api'; +import { TestApiRegistry, MockConfigApi } from '@backstage/test-utils'; import { makeStyles } from '@material-ui/core'; import { render, screen } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; @@ -44,13 +47,19 @@ const entities: Entity[] = [ }, ]; +const mockConfigApi = new MockConfigApi({}); + +const apis = TestApiRegistry.from([configApiRef, mockConfigApi]); + describe('', () => { it('renders without exploding', () => { render( - , + + + , ); const repositoryUrl = screen.getByText( @@ -67,11 +76,13 @@ describe('', () => { const { result } = renderHook(() => useStyles()); render( - , + + + , ); const repositoryUrl = screen.getByText( @@ -88,11 +99,13 @@ describe('', () => { const { result } = renderHook(() => useStyles()); render( - , + + + , ); const repositoryUrl = screen.getByText( @@ -104,4 +117,32 @@ describe('', () => { expect(kindText).toBeInTheDocument(); expect(kindText).not.toBeVisible(); }); + + it('renders with custom catalog filename', () => { + render( + + + , + ); + + const repositoryUrl = screen.getByText( + 'http://acme-corp/awesome-api/anvil.yaml', + ); + expect(repositoryUrl).toBeInTheDocument(); + expect(repositoryUrl).toBeVisible(); + }); }); diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index 3b6f353155..8d26657bb3 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -14,9 +14,9 @@ * limitations under the License. */ -import { errorApiRef } from '@backstage/core-plugin-api'; +import { configApiRef, errorApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { TestApiProvider } from '@backstage/test-utils'; +import { TestApiProvider, MockConfigApi } from '@backstage/test-utils'; import { TextField } from '@material-ui/core'; import { act, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -53,12 +53,15 @@ describe('', () => { post: jest.fn(), }; + const configApi = new MockConfigApi({}); + const Wrapper = ({ children }: { children?: React.ReactNode }) => ( {children} From b40159ff3a2b73782ca240eb1e1039bca966b757 Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Fri, 14 Jan 2022 09:50:22 +0200 Subject: [PATCH 18/35] chore(catalog-import): update README with relevant information how to customzie layout Obsolete instructions were used, updated with up-to-date information from changelog https://github.com/backstage/backstage/blob/master/plugins/catalog-import/CHANGELOG.md#minor-changes-1 Signed-off-by: Mikko Korhonen --- plugins/catalog-import/README.md | 61 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/plugins/catalog-import/README.md b/plugins/catalog-import/README.md index bad48a8486..f492619690 100644 --- a/plugins/catalog-import/README.md +++ b/plugins/catalog-import/README.md @@ -35,41 +35,42 @@ import { CatalogImportPage } from '@backstage/plugin-catalog-import'; ## Customizations -### Disable the creation of Pull Requests +A custom layout can be passed to the import page, as it's already +supported by the search page. If no custom layout is passed, the default layout +is used. -The pull request feature can be disabled by options that are passed to the `CatalogImportPage`: +```typescript +}> + +
+ + + + Start tracking your component in Backstage by adding it to the + software catalog. + + -```tsx -// packages/app/src/App.tsx + + + Hello World + -} -/> + + + + + + + ``` -### Customize the title and body of the Pull Request - -The pull request form is filled with a default title and body. -This can be configured by options that are passed to the `CatalogImportPage`: - -```tsx -// packages/app/src/App.tsx - - ({ - title: 'My title', - body: 'My **markdown** body', - }), - }} - /> - } -/> -``` +Previously it was possible to disable and customize the automatic pull request +feature by passing options to `` (`pullRequest.disable` and +`pullRequest.preparePullRequest`). This functionality is moved to the +`CatalogImportApi` which now provides an optional `preparePullRequest()` +function. The function can either be overridden to generate a different content +for the pull request, or removed to disable this feature. ## Development From 2e8764b95fa2095b7b99eed7e5613fc819c3e73c Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Fri, 14 Jan 2022 11:43:11 +0200 Subject: [PATCH 19/35] chore(catalog-import): add change set for import flow customizations Signed-off-by: Mikko Korhonen --- .changeset/tame-ads-exercise.md | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .changeset/tame-ads-exercise.md diff --git a/.changeset/tame-ads-exercise.md b/.changeset/tame-ads-exercise.md new file mode 100644 index 0000000000..a2e11393a6 --- /dev/null +++ b/.changeset/tame-ads-exercise.md @@ -0,0 +1,34 @@ +--- +'@backstage/plugin-catalog-import': minor +--- + +Make filename, branch name and examples URLs used in catalog import customizable. + +Catalog backend ingestion loop can be already configured to fetch targets with custom catalog filename (other than `catalog-info.yaml`). It's now possible to customize said filename and branch name used in pull requests created by catalog import flow too. This allows organizations to further customize Backstage experience and to better reflect their branding. + +Filename (default: `catalog-info.yaml`) and branch name (default: `backstage-integration`) used in pull requests can be configured in `app-config.yaml` as follows: + +```yaml +// app-config.yaml + +catalog: + import: + entityFilename: anvil.yaml + pullRequestBranchName: anvil-integration +``` + +Following React components have also been updated to accept optional props for providing example entity and repository paths: + +```tsx + +``` + +```tsx + +``` From e9b5f55a8b88adb7d4f589443d3f91c7f88ad40e Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Thu, 20 Jan 2022 11:49:35 +0200 Subject: [PATCH 20/35] chore(catalog-import): generate api report Signed-off-by: Mikko Korhonen --- plugins/catalog-import/api-report.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md index a1ad76f323..a85777c563 100644 --- a/plugins/catalog-import/api-report.md +++ b/plugins/catalog-import/api-report.md @@ -60,7 +60,7 @@ export const AutocompleteTextField: ({ helperText, errorHelperText, textFieldProps, -}: Props_4) => JSX.Element; +}: Props_5) => JSX.Element; // Warning: (ae-missing-release-tag) "CatalogImportApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -171,10 +171,14 @@ export const EntityListComponent: ({ withLinks, }: Props) => JSX.Element; +// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ImportInfoCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const ImportInfoCard: () => JSX.Element; +export const ImportInfoCard: ({ + exampleLocationUrl, + exampleRepositoryUrl, +}: Props_2) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ImportStepper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -184,7 +188,7 @@ export const ImportStepper: ({ initialUrl, generateStepper, variant, -}: Props_2) => JSX.Element; +}: Props_3) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "PreparePullRequestForm" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -196,7 +200,7 @@ export const PreparePullRequestForm: < defaultValues, onSubmit, render, -}: Props_5) => JSX.Element; +}: Props_6) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "PreviewCatalogInfoComponent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -206,7 +210,7 @@ export const PreviewCatalogInfoComponent: ({ repositoryUrl, entities, classes, -}: Props_6) => JSX.Element; +}: Props_7) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "PreviewPullRequestComponent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -216,7 +220,7 @@ export const PreviewPullRequestComponent: ({ title, description, classes, -}: Props_7) => JSX.Element; +}: Props_8) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "StepInitAnalyzeUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -226,7 +230,8 @@ export const StepInitAnalyzeUrl: ({ onAnalysis, analysisUrl, disablePullRequest, -}: Props_3) => JSX.Element; + exampleLocationUrl, +}: Props_4) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "StepPrepareCreatePullRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -237,7 +242,7 @@ export const StepPrepareCreatePullRequest: ({ onPrepare, onGoBack, renderFormFields, -}: Props_8) => JSX.Element; +}: Props_9) => JSX.Element; // Warnings were encountered during analysis: // From 2734946be07d78d50b5dfcd211019d57442b3148 Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Tue, 25 Jan 2022 09:17:53 +0200 Subject: [PATCH 21/35] test(catalog-import): migrate some tests to use TestApiProvider Signed-off-by: Mikko Korhonen --- .../PreviewCatalogInfoComponent.test.tsx | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx index aac54e084a..0a6960cdc7 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx @@ -15,9 +15,8 @@ */ import { Entity } from '@backstage/catalog-model'; -import { ApiProvider } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; -import { TestApiRegistry, MockConfigApi } from '@backstage/test-utils'; +import { MockConfigApi, TestApiProvider } from '@backstage/test-utils'; import { makeStyles } from '@material-ui/core'; import { render, screen } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; @@ -48,18 +47,17 @@ const entities: Entity[] = [ ]; const mockConfigApi = new MockConfigApi({}); - -const apis = TestApiRegistry.from([configApiRef, mockConfigApi]); +const apis = [[configApiRef, mockConfigApi]] as const; describe('', () => { it('renders without exploding', () => { render( - + - , + , ); const repositoryUrl = screen.getByText( @@ -76,13 +74,13 @@ describe('', () => { const { result } = renderHook(() => useStyles()); render( - + - , + , ); const repositoryUrl = screen.getByText( @@ -99,13 +97,13 @@ describe('', () => { const { result } = renderHook(() => useStyles()); render( - + - , + , ); const repositoryUrl = screen.getByText( @@ -120,23 +118,25 @@ describe('', () => { it('renders with custom catalog filename', () => { render( - - , + , ); const repositoryUrl = screen.getByText( From 9735b00b6aa634d6541cf8ca7aa71c2b686f2eec Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Tue, 25 Jan 2022 11:21:53 +0200 Subject: [PATCH 22/35] refactor(catalog-import): access catalog filename and branchname via hooks and helpers Signed-off-by: Mikko Korhonen --- plugins/catalog-import/package.json | 1 + .../src/api/CatalogImportClient.ts | 21 +++++----------- .../ImportInfoCard/ImportInfoCard.tsx | 5 ++-- .../PreviewCatalogInfoComponent.tsx | 7 ++---- .../StepPrepareCreatePullRequest.tsx | 8 +++---- .../catalog-import/src/components/helpers.ts | 15 ++++++++++++ plugins/catalog-import/src/hooks/index.ts | 17 +++++++++++++ .../src/hooks/useCatalogFilename.ts | 24 +++++++++++++++++++ 8 files changed, 70 insertions(+), 28 deletions(-) create mode 100644 plugins/catalog-import/src/hooks/index.ts create mode 100644 plugins/catalog-import/src/hooks/useCatalogFilename.ts diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 5097f5cc9b..2508543541 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -34,6 +34,7 @@ "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/core-components": "^0.8.6", + "@backstage/config": "^0.1.13", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 218814d2fb..60745923b4 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -32,6 +32,7 @@ import { PartialEntity } from '../types'; import { AnalyzeResult, CatalogImportApi } from './CatalogImportApi'; import { getGithubIntegrationConfig } from './GitHub'; import { trimEnd } from 'lodash'; +import { getBranchName, getCatalogFilename } from '../components/helpers'; export class CatalogImportClient implements CatalogImportApi { private readonly discoveryApi: DiscoveryApi; @@ -87,9 +88,7 @@ export class CatalogImportClient implements CatalogImportApi { const ghConfig = getGithubIntegrationConfig(this.scmIntegrationsApi, url); if (!ghConfig) { const other = this.scmIntegrationsApi.byUrl(url); - const catalogFilename = - this.configApi.getOptionalString('catalog.import.entityFilename') ?? - 'catalog-info.yaml'; + const catalogFilename = getCatalogFilename(this.configApi); if (other) { throw new Error( @@ -131,9 +130,7 @@ export class CatalogImportClient implements CatalogImportApi { const appTitle = this.configApi.getOptionalString('app.title') ?? 'Backstage'; const appBaseUrl = this.configApi.getString('app.baseUrl'); - const catalogFilename = - this.configApi.getOptionalString('catalog.import.entityFilename') ?? - 'catalog-info.yaml'; + const catalogFilename = getCatalogFilename(this.configApi); return { title: `Add ${catalogFilename} config file`, @@ -228,9 +225,7 @@ the component will become available.\n\nFor more information, read an \ auth: token, baseUrl: githubIntegrationConfig.apiBaseUrl, }); - const catalogFilename = - this.configApi.getOptionalString('catalog.import.entityFilename') ?? - 'catalog-info.yaml'; + const catalogFilename = getCatalogFilename(this.configApi); const query = `repo:${owner}/${repo}+filename:${catalogFilename}`; const searchResult = await octo.search.code({ q: query }).catch(e => { @@ -303,12 +298,8 @@ the component will become available.\n\nFor more information, read an \ baseUrl: githubIntegrationConfig.apiBaseUrl, }); - const branchName = - this.configApi.getOptionalString('catalog.pullRequestBranchName') ?? - 'backstage-integration'; - const fileName = - this.configApi.getOptionalString('catalog.import.entityFilename') ?? - 'catalog-info.yaml'; + const branchName = getBranchName(this.configApi); + const fileName = getCatalogFilename(this.configApi); const repoData = await octo.repos .get({ diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx index 4d78542e60..3e66e137eb 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -19,6 +19,7 @@ import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { Chip, Typography } from '@material-ui/core'; import React from 'react'; import { catalogImportApiRef } from '../../api'; +import { useCatalogFilename } from '../../hooks'; type Props = { exampleLocationUrl?: string; @@ -36,9 +37,7 @@ export const ImportInfoCard = ({ const integrations = configApi.getConfig('integrations'); const hasGithubIntegration = integrations.has('github'); - const catalogFilename = - configApi.getOptionalString('catalog.import.entityFilename') ?? - 'catalog-info.yaml'; + const catalogFilename = useCatalogFilename(); return ( { - const configApi = useApi(configApiRef); - const catalogFilename = - configApi.getOptionalString('catalog.import.entityFilename') ?? - 'catalog-info.yaml'; + const catalogFilename = useCatalogFilename(); return ( diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx index d511294b61..a79caaa0b9 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; -import { configApiRef, errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { assertError } from '@backstage/errors'; import { catalogApiRef, @@ -28,6 +28,7 @@ import { UnpackNestedValue, UseFormReturn } from 'react-hook-form'; import useAsync from 'react-use/lib/useAsync'; import YAML from 'yaml'; import { AnalyzeResult, catalogImportApiRef } from '../../api'; +import { useCatalogFilename } from '../../hooks'; import { PartialEntity } from '../../types'; import { BackButton, NextButton } from '../Buttons'; import { PrepareResult } from '../useImportState'; @@ -102,14 +103,11 @@ export const StepPrepareCreatePullRequest = ({ const catalogApi = useApi(catalogApiRef); const catalogImportApi = useApi(catalogImportApiRef); const errorApi = useApi(errorApiRef); - const configApi = useApi(configApiRef); const [submitted, setSubmitted] = useState(false); const [error, setError] = useState(); - const catalogFilename = - configApi.getOptionalString('catalog.import.entityFilename') ?? - 'catalog-info.yaml'; + const catalogFilename = useCatalogFilename(); const { loading: prDefaultsLoading, diff --git a/plugins/catalog-import/src/components/helpers.ts b/plugins/catalog-import/src/components/helpers.ts index 4240186459..b134a8726a 100644 --- a/plugins/catalog-import/src/components/helpers.ts +++ b/plugins/catalog-import/src/components/helpers.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import type { Config } from '@backstage/config'; import { UseFormRegisterReturn } from 'react-hook-form'; /** @@ -31,3 +32,17 @@ export function asInputRef(renderResult: UseFormRegisterReturn) { ...rest, }; } + +export function getCatalogFilename(config: Config): string { + return ( + config.getOptionalString('catalog.import.entityFilename') ?? + 'catalog-info.yaml' + ); +} + +export function getBranchName(config: Config): string { + return ( + config.getOptionalString('catalog.import.pullRequestBranchName') ?? + 'backstage-integration' + ); +} diff --git a/plugins/catalog-import/src/hooks/index.ts b/plugins/catalog-import/src/hooks/index.ts new file mode 100644 index 0000000000..afdfb0cbe2 --- /dev/null +++ b/plugins/catalog-import/src/hooks/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 { useCatalogFilename } from './useCatalogFilename'; diff --git a/plugins/catalog-import/src/hooks/useCatalogFilename.ts b/plugins/catalog-import/src/hooks/useCatalogFilename.ts new file mode 100644 index 0000000000..0e2d770d3e --- /dev/null +++ b/plugins/catalog-import/src/hooks/useCatalogFilename.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2022 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 { useApi, configApiRef } from '@backstage/core-plugin-api'; +import { getCatalogFilename } from '../components/helpers'; + +export function useCatalogFilename(): string { + const config = useApi(configApiRef); + + return getCatalogFilename(config); +} From bee418a36b7db3d8ebdfa82e2d43cede76e8a11d Mon Sep 17 00:00:00 2001 From: Mikko Korhonen Date: Tue, 25 Jan 2022 11:36:18 +0200 Subject: [PATCH 23/35] docs(catalog-import): update documentation about catalog filename customizations Signed-off-by: Mikko Korhonen --- plugins/catalog-import/README.md | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/plugins/catalog-import/README.md b/plugins/catalog-import/README.md index f492619690..86f3aecba9 100644 --- a/plugins/catalog-import/README.md +++ b/plugins/catalog-import/README.md @@ -35,6 +35,8 @@ import { CatalogImportPage } from '@backstage/plugin-catalog-import'; ## Customizations +### Custom layout + A custom layout can be passed to the import page, as it's already supported by the search page. If no custom layout is passed, the default layout is used. @@ -72,6 +74,37 @@ feature by passing options to `` (`pullRequest.disable` and function. The function can either be overridden to generate a different content for the pull request, or removed to disable this feature. +### Entity filename and branch name + +Entity filename (default: `catalog-info.yaml`) and branch name (default: `backstage-integration`) used in pull requests can be configured in `app-config.yaml` as follows: + +```yaml +// app-config.yaml + +catalog: + import: + entityFilename: anvil.yaml + pullRequestBranchName: anvil-integration +``` + +### Entity examples + +Following React components accept optional props for providing custom example entity and repository paths: + +```tsx + +``` + +```tsx + +``` + ## Development Use `yarn start` to run a [development version](./dev/index.tsx) of the plugin that can be used to validate each flow with mocked data. From a1d2d3966f9e9e4645b3233853b4b2bec1858aa0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jan 2022 09:25:38 +0000 Subject: [PATCH 24/35] chore(deps): bump graphql from 16.0.1 to 16.3.0 Bumps [graphql](https://github.com/graphql/graphql-js) from 16.0.1 to 16.3.0. - [Release notes](https://github.com/graphql/graphql-js/releases) - [Commits](https://github.com/graphql/graphql-js/compare/v16.0.1...v16.3.0) --- updated-dependencies: - dependency-name: graphql dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 88409fb1f9..1713c90998 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12879,9 +12879,9 @@ graphql@^15.5.1: integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== graphql@^16.0.0: - version "16.0.1" - resolved "https://registry.npmjs.org/graphql/-/graphql-16.0.1.tgz#93a13cd4e0e38ca8d0832e79614c8578bfd34f10" - integrity sha512-oPvCuu6dlLdiz8gZupJ47o1clgb72r1u8NDBcQYjcV6G/iEdmE11B1bBlkhXRvV0LisP/SXRFP7tT6AgaTjpzg== + version "16.3.0" + resolved "https://registry.npmjs.org/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05" + integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A== grouped-queue@^2.0.0: version "2.0.0" From 787847a676a3632f0494e021aff14205eca30882 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jan 2022 09:37:47 +0000 Subject: [PATCH 25/35] chore(deps): bump @microsoft/microsoft-graph-types from 2.11.0 to 2.13.0 Bumps [@microsoft/microsoft-graph-types](https://github.com/microsoftgraph/msgraph-typescript-typings) from 2.11.0 to 2.13.0. - [Release notes](https://github.com/microsoftgraph/msgraph-typescript-typings/releases) - [Commits](https://github.com/microsoftgraph/msgraph-typescript-typings/compare/2.11.0...2.13.0) --- updated-dependencies: - dependency-name: "@microsoft/microsoft-graph-types" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 88409fb1f9..7ed1abd978 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3683,9 +3683,9 @@ integrity sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA== "@microsoft/microsoft-graph-types@^2.6.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.11.0.tgz#0e1d3a0795855fc726e08836b1d3c4a72a8bcd00" - integrity sha512-v4Wuxp+kbcxeJGmb2UHbcukNr05XItFYXL+U3ReignI3Vl8tp1vfq0hkqP35Fun2QpqHJiu8Rkxj1MUF8d82ag== + version "2.13.0" + resolved "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.13.0.tgz#aa584e4897665df5a9c8869a226264cd6ec5882b" + integrity sha512-63FfWBLcyNo8tMP4oPcdqHQvk4ehuWpiUMjVLD7zJXPENIowpdwudP969AALkKzlwsjWImamdivGKd2Zc8Z1Uw== "@microsoft/tsdoc-config@~0.15.2": version "0.15.2" From 28a5f9d0b1505d7aa5ceba59cac7ee3f33cc2c66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jan 2022 09:40:00 +0000 Subject: [PATCH 26/35] chore(deps): bump passport from 0.4.1 to 0.5.2 Bumps [passport](https://github.com/jaredhanson/passport) from 0.4.1 to 0.5.2. - [Release notes](https://github.com/jaredhanson/passport/releases) - [Changelog](https://github.com/jaredhanson/passport/blob/master/CHANGELOG.md) - [Commits](https://github.com/jaredhanson/passport/compare/v0.4.1...v0.5.2) --- updated-dependencies: - dependency-name: passport dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .changeset/dependabot-9ec400d.md | 5 +++++ plugins/auth-backend/package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 .changeset/dependabot-9ec400d.md diff --git a/.changeset/dependabot-9ec400d.md b/.changeset/dependabot-9ec400d.md new file mode 100644 index 0000000000..1fd5a85477 --- /dev/null +++ b/.changeset/dependabot-9ec400d.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +chore(deps): bump `passport` from 0.4.1 to 0.5.2 diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 799ab4c414..5b4e4b22ba 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -58,7 +58,7 @@ "node-fetch": "^2.6.1", "node-cache": "^5.1.2", "openid-client": "^4.2.1", - "passport": "^0.4.1", + "passport": "^0.5.2", "passport-bitbucket-oauth2": "^0.1.2", "passport-github2": "^0.1.12", "passport-gitlab2": "^5.0.0", diff --git a/yarn.lock b/yarn.lock index 88409fb1f9..f0c650e935 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18832,10 +18832,10 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ= -passport@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" - integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== +passport@^0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/passport/-/passport-0.5.2.tgz#0cb38dd8a71552c8390dfa6a9a6f7f3909954bcf" + integrity sha512-w9n/Ot5I7orGD4y+7V3EFJCQEznE5RxHamUxcqLT2QoJY0f2JdN8GyHonYFvN0Vz+L6lUJfVhrk2aZz2LbuREw== dependencies: passport-strategy "1.x.x" pause "0.0.1" From 341bbbfe093fc338b4e345278ea6d85591e3bbf4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jan 2022 09:41:44 +0000 Subject: [PATCH 27/35] chore(deps): bump prop-types from 15.8.0 to 15.8.1 Bumps [prop-types](https://github.com/facebook/prop-types) from 15.8.0 to 15.8.1. - [Release notes](https://github.com/facebook/prop-types/releases) - [Changelog](https://github.com/facebook/prop-types/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/prop-types/compare/v15.8.0...v15.8.1) --- updated-dependencies: - dependency-name: prop-types dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 88409fb1f9..034d83e8c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19671,9 +19671,9 @@ promzard@^0.3.0: read "1" prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: - version "15.8.0" - resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.0.tgz#d237e624c45a9846e469f5f31117f970017ff588" - integrity sha512-fDGekdaHh65eI3lMi5OnErU6a8Ighg2KjcjQxO7m8VHyWjcPyj5kiOgV1LQDOOOgVy3+5FgjXvdSSX7B8/5/4g== + version "15.8.1" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== dependencies: loose-envify "^1.4.0" object-assign "^4.1.1" From 912b2d992532447c3337a6ab95a92ba8069345ba Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Fri, 28 Jan 2022 10:37:40 +0100 Subject: [PATCH 28/35] Note default ServerURL config in kroki how-to Signed-off-by: Eric Peterson --- docs/features/techdocs/how-to-guides.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 1885c1a961..863b4b3ecb 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -496,6 +496,13 @@ plugins: - kroki ``` +> Note: you will very likely want to set a `kroki` `ServerURL` configuration in your +> `mkdocs.yml` as well. The default value is the publicly hosted `kroki.io`. If +> you have sensitive information in your organization's diagrams, you should set +> up a [server of your own](https://docs.kroki.io/kroki/setup/install/) and use it +> instead. Check out [mkdocs-kroki-plugin config](https://github.com/AVATEAM-IT-SYSTEMHAUS/mkdocs-kroki-plugin#config) +> for more plugin configuration details. + 4. **Add mermaid code into techdocs:** ````md From 3e79214e37326397edc5adf9f8f63795c2648bcc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 28 Jan 2022 13:47:01 +0100 Subject: [PATCH 29/35] workflows/sync_release-manifest: support backfills Co-authored-by: blam Signed-off-by: Patrik Oldsberg --- .github/workflows/sync_release-manifest.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index e8a50904d0..730ba3c754 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -14,7 +14,8 @@ jobs: with: ref: ${{ github.event.inputs.version }} - name: Install dependencies - run: yarn install + # Just the deps for the assemble manifest script + run: npm install --global semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1 - name: Checkout versions uses: actions/checkout@v2 with: @@ -26,7 +27,10 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github versions workflow' - name: Create release + # This grabs the scripts from master in order to support backfills run: | + mkdir -p scripts + wget -O scripts/assemble-manifest.js https://raw.githubusercontent.com/backstage/backstage/master/scripts/assemble-manifest.js node scripts/assemble-manifest.js ${{ github.event.inputs.version }} cd versions git add . From ed6503c75b1ff5ed9687abc155359c544645b010 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 28 Jan 2022 14:03:47 +0100 Subject: [PATCH 30/35] workflows/sync_release-manifest: tweak install to make it work Co-authored-by: blam Signed-off-by: Patrik Oldsberg --- .github/workflows/sync_release-manifest.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index 730ba3c754..bef309bf30 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -13,19 +13,27 @@ jobs: uses: actions/checkout@v2 with: ref: ${{ github.event.inputs.version }} - - name: Install dependencies - # Just the deps for the assemble manifest script - run: npm install --global semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1 + + # Checkout backstage/versions into /versions, which is where store the output - name: Checkout versions uses: actions/checkout@v2 with: repository: backstage/versions path: versions token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} + - name: Configure Git run: | git config --global user.email noreply@backstage.io git config --global user.name 'Github versions workflow' + + - uses: actions/setup-node@v2 + with: + node-version: 16 + - name: Install dependencies + # Just the deps for the assemble manifest script + run: npm install semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1 + - name: Create release # This grabs the scripts from master in order to support backfills run: | From 6efb1eb42db39d0271c4981227207880822b12df Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 28 Jan 2022 14:04:43 +0100 Subject: [PATCH 31/35] Make SidebarPinStateContext import more clear Signed-off-by: Philipp Hugenroth --- packages/core-components/src/layout/Page/Page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-components/src/layout/Page/Page.tsx b/packages/core-components/src/layout/Page/Page.tsx index 055fb25b40..0b35a59d8f 100644 --- a/packages/core-components/src/layout/Page/Page.tsx +++ b/packages/core-components/src/layout/Page/Page.tsx @@ -17,7 +17,7 @@ import React, { useContext } from 'react'; import { BackstageTheme } from '@backstage/theme'; import { makeStyles, ThemeProvider } from '@material-ui/core/styles'; -import { SidebarPinStateContext } from '..'; +import { SidebarPinStateContext } from '../Sidebar/Page'; export type PageClassKey = 'root'; From a9ab9f439bf26d20f0b118acba23e4a511227332 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 28 Jan 2022 14:15:25 +0100 Subject: [PATCH 32/35] workflows/sync_release-manifest: move install to top Co-authored-by: blam Signed-off-by: Patrik Oldsberg --- .github/workflows/sync_release-manifest.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index bef309bf30..00e7630432 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -9,6 +9,14 @@ jobs: create-new-version: runs-on: ubuntu-latest steps: + # Setup node & install deps before checkout, keeping install quick + - uses: actions/setup-node@v2 + with: + node-version: 16 + - name: Install dependencies + # Just the deps for the assemble manifest script + run: npm install semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1 + - name: Checkout uses: actions/checkout@v2 with: @@ -27,13 +35,6 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github versions workflow' - - uses: actions/setup-node@v2 - with: - node-version: 16 - - name: Install dependencies - # Just the deps for the assemble manifest script - run: npm install semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1 - - name: Create release # This grabs the scripts from master in order to support backfills run: | From 2301c0a526a01249aa0db976a052ed815947a5b1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 28 Jan 2022 14:25:26 +0100 Subject: [PATCH 33/35] workflows/sync_release-manifest: checkout backstage into backstage Co-authored-by: blam Signed-off-by: Patrik Oldsberg --- .github/workflows/sync_release-manifest.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index 00e7630432..e83a61dcb7 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -20,14 +20,15 @@ jobs: - name: Checkout uses: actions/checkout@v2 with: + path: backstage ref: ${{ github.event.inputs.version }} - # Checkout backstage/versions into /versions, which is where store the output + # Checkout backstage/versions into /backstage/versions, which is where store the output - name: Checkout versions uses: actions/checkout@v2 with: repository: backstage/versions - path: versions + path: backstage/versions token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} - name: Configure Git @@ -38,6 +39,7 @@ jobs: - name: Create release # This grabs the scripts from master in order to support backfills run: | + cd backstage mkdir -p scripts wget -O scripts/assemble-manifest.js https://raw.githubusercontent.com/backstage/backstage/master/scripts/assemble-manifest.js node scripts/assemble-manifest.js ${{ github.event.inputs.version }} From 7427a1d2c7f679005d689e6e1500bc2dc7e94485 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 28 Jan 2022 14:58:40 +0100 Subject: [PATCH 34/35] scripts/assemble-manifest: gracefully skip tag redirect Co-authored-by: blam Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- scripts/assemble-manifest.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/assemble-manifest.js b/scripts/assemble-manifest.js index 03b6f51516..f68a83447d 100755 --- a/scripts/assemble-manifest.js +++ b/scripts/assemble-manifest.js @@ -58,6 +58,8 @@ async function main() { ); const tag = version.includes('next') ? 'next' : 'main'; const tagPath = path.resolve('versions', 'v1', 'tags', tag); + + // Check if there's an existing version for the tag, and that it's not newer than the one we're adding if (await fs.pathExists(tagPath)) { const currentTag = await fs.readJSON( path.resolve(tagPath, 'manifest.json'), @@ -66,9 +68,11 @@ async function main() { console.log( `Skipping update of ${tagPath} since current current ${tag} version is ${currentTag.releaseVersion}`, ); - process.exit(1); + return; } } + + // Switch the tag to our new version await fs.remove(tagPath); await fs.ensureSymlink(path.join('..', 'releases', version), tagPath); } From 66cea3a7914f8bc2e494fcad5ac155b0ac368235 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 28 Jan 2022 15:01:55 +0100 Subject: [PATCH 35/35] workflows/sync_release-manifest: prettier Co-authored-by: blam Signed-off-by: Patrik Oldsberg --- .github/workflows/sync_release-manifest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index e83a61dcb7..4fc5d20708 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -9,7 +9,7 @@ jobs: create-new-version: runs-on: ubuntu-latest steps: - # Setup node & install deps before checkout, keeping install quick + # Setup node & install deps before checkout, keeping install quick - uses: actions/setup-node@v2 with: node-version: 16