From d0c47ec505bbfa4e77ec546fffd4b201d0463cb3 Mon Sep 17 00:00:00 2001 From: Guilherme Oenning Date: Tue, 16 Nov 2021 11:34:52 +0000 Subject: [PATCH 01/61] fix incorrect class name on module-jsonfc Signed-off-by: goenning --- plugins/tech-insights-backend-module-jsonfc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tech-insights-backend-module-jsonfc/README.md b/plugins/tech-insights-backend-module-jsonfc/README.md index 48c1e69919..7b5d48bf62 100644 --- a/plugins/tech-insights-backend-module-jsonfc/README.md +++ b/plugins/tech-insights-backend-module-jsonfc/README.md @@ -24,7 +24,7 @@ and modify the `techInsights.ts` file to contain a reference to the FactCheckers + logger, +}), - const builder = new DefaultTechInsightsBuilder({ + const builder = buildTechInsightsContext({ logger, config, database, From 2a0703d212d6a544d3a9ed894e94e029b18ef623 Mon Sep 17 00:00:00 2001 From: Guilherme Oenning Date: Tue, 16 Nov 2021 11:35:17 +0000 Subject: [PATCH 02/61] fix incorrect class name on backend Signed-off-by: goenning --- plugins/tech-insights-backend/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/tech-insights-backend/README.md b/plugins/tech-insights-backend/README.md index e2cc1c0252..764ad860b8 100644 --- a/plugins/tech-insights-backend/README.md +++ b/plugins/tech-insights-backend/README.md @@ -22,7 +22,7 @@ do this by creating a file called `packages/backend/src/plugins/techInsights.ts` ```ts import { createRouter, - DefaultTechInsightsBuilder, + buildTechInsightsContext, } from '@backstage/plugin-tech-insights-backend'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; @@ -33,7 +33,7 @@ export default async function createPlugin({ discovery, database, }: PluginEnvironment): Promise { - const builder = new DefaultTechInsightsBuilder({ + const builder = buildTechInsightsContext({ logger, config, database, From 1c37c3c26cbdeded48b9a033d39ba3ee29266e12 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 16 Nov 2021 18:35:00 +0100 Subject: [PATCH 03/61] core-app-api: deprecate ApiRegistry Signed-off-by: Patrik Oldsberg --- packages/core-app-api/api-report.md | 2 +- packages/core-app-api/src/apis/system/ApiRegistry.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index 48b89a6951..cb6ad27cf8 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -126,7 +126,7 @@ export type ApiProviderProps = { children: ReactNode; }; -// @public +// @public @deprecated export class ApiRegistry implements ApiHolder { constructor(apis: Map); // Warning: (ae-forgotten-export) The symbol "ApiRegistryBuilder" needs to be exported by the entry point index.d.ts diff --git a/packages/core-app-api/src/apis/system/ApiRegistry.ts b/packages/core-app-api/src/apis/system/ApiRegistry.ts index 29c8b1cfe4..2d12fcfb35 100644 --- a/packages/core-app-api/src/apis/system/ApiRegistry.ts +++ b/packages/core-app-api/src/apis/system/ApiRegistry.ts @@ -36,6 +36,7 @@ class ApiRegistryBuilder { * A registry for utility APIs. * * @public + * @deprecated Will be removed, use {@link @backstage/test-utils#TestApiProvider} instead. */ export class ApiRegistry implements ApiHolder { static builder() { From 57591f57547143d73a70e5a52e94267a9ccc200b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 16 Nov 2021 18:47:50 +0100 Subject: [PATCH 04/61] test-utils: add TestApiProvider Signed-off-by: Patrik Oldsberg --- packages/test-utils/api-report.md | 13 +++ .../src/testUtils/TestApiProvider.tsx | 94 +++++++++++++++++++ packages/test-utils/src/testUtils/index.tsx | 2 + 3 files changed, 109 insertions(+) create mode 100644 packages/test-utils/src/testUtils/TestApiProvider.tsx diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md index 62a8d9f601..38656137a3 100644 --- a/packages/test-utils/api-report.md +++ b/packages/test-utils/api-report.md @@ -5,6 +5,7 @@ ```ts import { AnalyticsApi } from '@backstage/core-plugin-api'; import { AnalyticsEvent } from '@backstage/core-plugin-api'; +import { ApiRef } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; import { ErrorApi } from '@backstage/core-plugin-api'; import { ErrorApiError } from '@backstage/core-plugin-api'; @@ -175,6 +176,18 @@ export function setupRequestMockHandlers(worker: { // @public export type SyncLogCollector = () => void; +// @public +export const TestApiProvider: ({ + apis, + children, +}: TestApiProviderProps) => JSX.Element; + +// @public +export type TestApiProviderProps = { + apis: [...TestApiProviderPropsApiPairs]; + children: ReactNode; +}; + // @public export type TestAppOptions = { routeEntries?: string[]; diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx new file mode 100644 index 0000000000..272da8c807 --- /dev/null +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -0,0 +1,94 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { ReactNode } from 'react'; +import { ApiProvider } from '@backstage/core-app-api'; +import { ApiRef, ApiHolder } from '@backstage/core-plugin-api'; + +type TestApiProviderPropsApiPair = TApi extends infer TImpl + ? [ApiRef, Partial] + : never; + +/** @ignore */ +type TestApiProviderPropsApiPairs = { + [TIndex in keyof TApiPairs]: TestApiProviderPropsApiPair; +}; + +/** + * Properties for the {@link TestApiProvider} component. + * + * @public + */ +export type TestApiProviderProps = { + apis: [...TestApiProviderPropsApiPairs]; + children: ReactNode; +}; + +/** @internal */ +class TestApiRegistry implements ApiHolder { + constructor(private readonly apis: Map) {} + + get(api: ApiRef): T | undefined { + return this.apis.get(api.id) as T | undefined; + } +} + +/** + * An API provider that lets you provide any number of API implementations in + * a test, without necessarily having to implement the full APIs. + * + * A migration from `ApiRegistry` and `ApiProvider` might look like this, from: + * + * ```tsx + * renderInTestApp( + * + * {...} + * + * ) + * ``` + * + * To the following: + * + * ```tsx + * renderInTestApp( + * + * {...} + * + * ) + * ``` + * + * Note that the cast to `IdentityApi` is no longer needed as long as the mock API + * implements a subset of the `IdentityApi`. + * + * @public + **/ +export const TestApiProvider = ({ + apis, + children, +}: TestApiProviderProps) => { + return ( + [api.id, impl]))) + } + children={children} + /> + ); +}; diff --git a/packages/test-utils/src/testUtils/index.tsx b/packages/test-utils/src/testUtils/index.tsx index 7d93d606cc..d48767d3cd 100644 --- a/packages/test-utils/src/testUtils/index.tsx +++ b/packages/test-utils/src/testUtils/index.tsx @@ -22,3 +22,5 @@ export * from './msw'; export * from './Keyboard'; export * from './logCollector'; export * from './testingLibrary'; +export { TestApiProvider } from './TestApiProvider'; +export type { TestApiProviderProps } from './TestApiProvider'; From 5f6d97d044bb0c8e802e4e002b01bd43f32ce6de Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 16 Nov 2021 21:26:29 +0100 Subject: [PATCH 05/61] test-utils: add TestApiRegistry Signed-off-by: Patrik Oldsberg --- .../src/apis/system/ApiRegistry.ts | 2 +- packages/test-utils/api-report.md | 12 +++- .../src/testUtils/TestApiProvider.tsx | 58 ++++++++++++++----- packages/test-utils/src/testUtils/index.tsx | 2 +- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/packages/core-app-api/src/apis/system/ApiRegistry.ts b/packages/core-app-api/src/apis/system/ApiRegistry.ts index 2d12fcfb35..e433381dd1 100644 --- a/packages/core-app-api/src/apis/system/ApiRegistry.ts +++ b/packages/core-app-api/src/apis/system/ApiRegistry.ts @@ -36,7 +36,7 @@ class ApiRegistryBuilder { * A registry for utility APIs. * * @public - * @deprecated Will be removed, use {@link @backstage/test-utils#TestApiProvider} instead. + * @deprecated Will be removed, use {@link @backstage/test-utils#TestApiProvider} or {@link @backstage/test-utils#TestApiRegistry} instead. */ export class ApiRegistry implements ApiHolder { static builder() { diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md index 38656137a3..5bb552563b 100644 --- a/packages/test-utils/api-report.md +++ b/packages/test-utils/api-report.md @@ -5,6 +5,7 @@ ```ts import { AnalyticsApi } from '@backstage/core-plugin-api'; import { AnalyticsEvent } from '@backstage/core-plugin-api'; +import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; import { ErrorApi } from '@backstage/core-plugin-api'; @@ -184,10 +185,19 @@ export const TestApiProvider: ({ // @public export type TestApiProviderProps = { - apis: [...TestApiProviderPropsApiPairs]; + apis: readonly [...TestApiProviderPropsApiPairs]; children: ReactNode; }; +// @public +export class TestApiRegistry implements ApiHolder { + // (undocumented) + get(api: ApiRef): T | undefined; + static with( + ...apis: readonly [...TestApiProviderPropsApiPairs] + ): TestApiRegistry; +} + // @public export type TestAppOptions = { routeEntries?: string[]; diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index 272da8c807..92be0ffd77 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -18,8 +18,9 @@ import React, { ReactNode } from 'react'; import { ApiProvider } from '@backstage/core-app-api'; import { ApiRef, ApiHolder } from '@backstage/core-plugin-api'; +/** @ignore */ type TestApiProviderPropsApiPair = TApi extends infer TImpl - ? [ApiRef, Partial] + ? readonly [ApiRef, Partial] : never; /** @ignore */ @@ -33,22 +34,58 @@ type TestApiProviderPropsApiPairs = { * @public */ export type TestApiProviderProps = { - apis: [...TestApiProviderPropsApiPairs]; + apis: readonly [...TestApiProviderPropsApiPairs]; children: ReactNode; }; -/** @internal */ -class TestApiRegistry implements ApiHolder { - constructor(private readonly apis: Map) {} +/** + * The `TestApiRegistry` is an {@link @backstage/core-plugin-api#ApiHolder} implementation + * that is particularly well suited for development and test environments such as + * unit tests, storybooks, and isolated plugin development setups. + * + * @public + */ +export class TestApiRegistry implements ApiHolder { + /** + * Creates a new {@link TestApiRegistry} with a list of API implementation pairs. + * + * Similar to the {@link TestApiProvider}, there is no need to provide a full + * implementation of each API, it's enough to implement the methods that are tested. + * + * @example + * ```ts + * const apis = TestApiRegistry.with( + * [configApiRef, new ConfigReader({})], + * [identityApiRef, { getUserId: () => 'tester' }], + * ); + * ``` + * + * @public + * @param apis - A list of pairs mapping an ApiRef to its respective implementation. + */ + static with( + ...apis: readonly [...TestApiProviderPropsApiPairs] + ) { + return new TestApiRegistry( + new Map(apis.map(([api, impl]) => [api.id, impl])), + ); + } + private constructor(private readonly apis: Map) {} + + /** {@inheritdoc @backstage/core-plugin-api#ApiHolder.get} */ get(api: ApiRef): T | undefined { return this.apis.get(api.id) as T | undefined; } } /** - * An API provider that lets you provide any number of API implementations in - * a test, without necessarily having to implement the full APIs. + * The `TestApiProvider` is a Utility API context provider that is particularly + * well suited for development and test environments such as unit tests, storybooks, + * and isolated plugin development setups. + * + * It lets you provide any number of API implementations, without necessarily + * having to fully implement each of the APIs. * * A migration from `ApiRegistry` and `ApiProvider` might look like this, from: * @@ -84,11 +121,6 @@ export const TestApiProvider = ({ children, }: TestApiProviderProps) => { return ( - [api.id, impl]))) - } - children={children} - /> + ); }; diff --git a/packages/test-utils/src/testUtils/index.tsx b/packages/test-utils/src/testUtils/index.tsx index d48767d3cd..c778c5c837 100644 --- a/packages/test-utils/src/testUtils/index.tsx +++ b/packages/test-utils/src/testUtils/index.tsx @@ -22,5 +22,5 @@ export * from './msw'; export * from './Keyboard'; export * from './logCollector'; export * from './testingLibrary'; -export { TestApiProvider } from './TestApiProvider'; +export { TestApiProvider, TestApiRegistry } from './TestApiProvider'; export type { TestApiProviderProps } from './TestApiProvider'; From 417f80c0c8b3704a3cdebc74a53b42cb41ef889d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 17 Nov 2021 10:44:02 +0100 Subject: [PATCH 06/61] test-utils: add tests for TestApiProvider & Registry Signed-off-by: Patrik Oldsberg --- .../src/testUtils/TestApiProvider.test.tsx | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 packages/test-utils/src/testUtils/TestApiProvider.test.tsx diff --git a/packages/test-utils/src/testUtils/TestApiProvider.test.tsx b/packages/test-utils/src/testUtils/TestApiProvider.test.tsx new file mode 100644 index 0000000000..7bffd39a4a --- /dev/null +++ b/packages/test-utils/src/testUtils/TestApiProvider.test.tsx @@ -0,0 +1,136 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { createApiRef, useApiHolder } from '@backstage/core-plugin-api'; +import { TestApiProvider } from './TestApiProvider'; +import { render, screen } from '@testing-library/react'; +import { TestApiRegistry } from '.'; + +const xApiRef = createApiRef<{ a: string; b: number }>({ + id: 'x', +}); +const yApiRef = createApiRef({ + id: 'y', +}); + +function Verifier() { + const holder = useApiHolder(); + const x = holder.get(xApiRef); + const y = holder.get(yApiRef); + + return ( +
+ {x ? ( + + x={x.a},{x.b} + + ) : ( + no x + )} + {y ? y={y} : no y} +
+ ); +} + +describe('TestApiProvider', () => { + it('should provide APIs', () => { + render( + + + , + ); + expect(screen.getByText('x=a,3')).toBeInTheDocument(); + expect(screen.getByText('y=y')).toBeInTheDocument(); + }); + + it('should provide partial APIs', () => { + render( + + + , + ); + expect(screen.getByText('x=a,')).toBeInTheDocument(); + expect(screen.getByText('no y')).toBeInTheDocument(); + }); + + it('should require partial implementations to still match types', () => { + render( + // @ts-expect-error + + + , + ); + expect(screen.getByText('x=3,')).toBeInTheDocument(); + expect(screen.getByText('no y')).toBeInTheDocument(); + }); + + it('should allow empty APIs', () => { + render( + + + , + ); + expect(screen.getByText('no x')).toBeInTheDocument(); + expect(screen.getByText('no y')).toBeInTheDocument(); + }); +}); + +describe('TestApiRegistry', () => { + it('should be created with APIs', () => { + const x = { a: 'a', b: 3 }; + const y = 'y'; + const registry = TestApiRegistry.with([xApiRef, x], [yApiRef, y]); + + expect(registry.get(xApiRef)).toBe(x); + expect(registry.get(yApiRef)).toBe(y); + }); + + it('should allow partial implementations', () => { + const x = { a: 'a' }; + const registry = TestApiRegistry.with([xApiRef, x]); + + expect(registry.get(xApiRef)).toBe(x); + expect(registry.get(yApiRef)).toBeUndefined(); + }); + + it('should require partial implementations to match types', () => { + const x = { a: 2 }; + // @ts-expect-error + const registry = TestApiRegistry.with([xApiRef, x]); + + expect(registry.get(xApiRef)).toBe(x); + expect(registry.get(yApiRef)).toBeUndefined(); + }); + + it('should prefer last duplicate API that was provided', () => { + const x1 = { a: 'a' }; + const x2 = { a: 's' }; + const x3 = { a: 'd' }; + const registry = TestApiRegistry.with( + [xApiRef, x1], + [xApiRef, x2], + [xApiRef, x3], + ); + + expect(registry.get(xApiRef)).toBe(x3); + }); +}); From b811fadaec2976b977960c483db95a2c1bc94a1b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 17 Nov 2021 10:45:39 +0100 Subject: [PATCH 07/61] core-*: migrate to using TestApiProvider Signed-off-by: Patrik Oldsberg --- .../src/routing/FeatureFlagged.test.tsx | 7 +- .../src/routing/FlatRoutes.test.tsx | 7 +- .../AlertDisplay/AlertDisplay.test.tsx | 84 ++++++++----------- .../CopyTextButton/CopyTextButton.test.tsx | 33 ++++---- .../DismissableBanner.stories.tsx | 29 +++---- .../DismissableBanner.test.tsx | 12 ++- .../src/components/Link/Link.test.tsx | 11 ++- .../ErrorBoundary/ErrorBoundary.test.tsx | 12 +-- .../src/layout/Header/Header.test.tsx | 18 ++-- .../HomepageTimer/HomepageTimer.test.tsx | 12 +-- .../src/extensions/useElementFilter.test.tsx | 11 +-- 11 files changed, 108 insertions(+), 128 deletions(-) diff --git a/packages/core-app-api/src/routing/FeatureFlagged.test.tsx b/packages/core-app-api/src/routing/FeatureFlagged.test.tsx index 2b05c8f61d..d1b45c39d1 100644 --- a/packages/core-app-api/src/routing/FeatureFlagged.test.tsx +++ b/packages/core-app-api/src/routing/FeatureFlagged.test.tsx @@ -16,14 +16,15 @@ import React from 'react'; import { FeatureFlagged } from './FeatureFlagged'; import { render } from '@testing-library/react'; -import { ApiProvider, ApiRegistry, LocalStorageFeatureFlags } from '../apis'; +import { LocalStorageFeatureFlags } from '../apis'; +import { TestApiProvider } from '@backstage/test-utils'; import { featureFlagsApiRef } from '@backstage/core-plugin-api'; const mockFeatureFlagsApi = new LocalStorageFeatureFlags(); const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - + {children} - + ); describe('FeatureFlagged', () => { diff --git a/packages/core-app-api/src/routing/FlatRoutes.test.tsx b/packages/core-app-api/src/routing/FlatRoutes.test.tsx index 0df296cc59..ca247d46cd 100644 --- a/packages/core-app-api/src/routing/FlatRoutes.test.tsx +++ b/packages/core-app-api/src/routing/FlatRoutes.test.tsx @@ -17,17 +17,18 @@ import { render, RenderResult } from '@testing-library/react'; import React, { ReactNode } from 'react'; import { MemoryRouter, Route, Routes, useOutlet } from 'react-router-dom'; -import { ApiProvider, ApiRegistry, LocalStorageFeatureFlags } from '../apis'; +import { LocalStorageFeatureFlags } from '../apis'; import { featureFlagsApiRef } from '@backstage/core-plugin-api'; import { AppContext } from '../app'; import { AppContextProvider } from '../app/AppContext'; import { FlatRoutes } from './FlatRoutes'; +import { TestApiProvider } from '@backstage/test-utils'; const mockFeatureFlagsApi = new LocalStorageFeatureFlags(); const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - + {children} - + ); function makeRouteRenderer(node: ReactNode) { diff --git a/packages/core-components/src/components/AlertDisplay/AlertDisplay.test.tsx b/packages/core-components/src/components/AlertDisplay/AlertDisplay.test.tsx index d6bf990f8a..477057f31b 100644 --- a/packages/core-components/src/components/AlertDisplay/AlertDisplay.test.tsx +++ b/packages/core-components/src/components/AlertDisplay/AlertDisplay.test.tsx @@ -17,78 +17,66 @@ import React from 'react'; import { AlertDisplay } from './AlertDisplay'; import { alertApiRef } from '@backstage/core-plugin-api'; -import { - ApiProvider, - ApiRegistry, - AlertApiForwarder, -} from '@backstage/core-app-api'; +import { AlertApiForwarder } from '@backstage/core-app-api'; import Observable from 'zen-observable'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; const TEST_MESSAGE = 'TEST_MESSAGE'; describe('', () => { it('renders without exploding', async () => { - const apiRegistry = ApiRegistry.from([ - [alertApiRef, new AlertApiForwarder()], - ]); - const { queryByText } = await renderInTestApp( - + - , + , ); expect(queryByText(TEST_MESSAGE)).not.toBeInTheDocument(); }); it('renders with message', async () => { - const apiRegistry = ApiRegistry.from([ - [ - alertApiRef, - { - post() {}, - alert$() { - return Observable.of({ message: TEST_MESSAGE }); - }, - }, - ], - ]); - const { queryByText } = await renderInTestApp( - + - , + , ); expect(queryByText(TEST_MESSAGE)).toBeInTheDocument(); }); describe('with multiple messages', () => { - let apiRegistry: ApiRegistry; - - beforeEach(() => { - apiRegistry = ApiRegistry.from([ - [ - alertApiRef, - { - post() {}, - alert$() { - return Observable.of( - { message: 'message one' }, - { message: 'message two' }, - { message: 'message three' }, - ); - }, + const apis = [ + [ + alertApiRef, + { + post() {}, + alert$() { + return Observable.of( + { message: 'message one' }, + { message: 'message two' }, + { message: 'message three' }, + ); }, - ], - ]); - }); + }, + ] as const, + ] as const; it('renders first message', async () => { const { queryByText } = await renderInTestApp( - + - , + , ); expect(queryByText('message one')).toBeInTheDocument(); @@ -96,9 +84,9 @@ describe('', () => { it('renders a count of remaining messages', async () => { const { queryByText } = await renderInTestApp( - + - , + , ); expect(queryByText('(2 older messages)')).toBeInTheDocument(); diff --git a/packages/core-components/src/components/CopyTextButton/CopyTextButton.test.tsx b/packages/core-components/src/components/CopyTextButton/CopyTextButton.test.tsx index b84d3919e8..a9532dd79b 100644 --- a/packages/core-components/src/components/CopyTextButton/CopyTextButton.test.tsx +++ b/packages/core-components/src/components/CopyTextButton/CopyTextButton.test.tsx @@ -17,10 +17,9 @@ import React from 'react'; import { fireEvent } from '@testing-library/react'; import { act } from 'react-dom/test-utils'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { CopyTextButton } from './CopyTextButton'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; -import { errorApiRef, ErrorApi } from '@backstage/core-plugin-api'; +import { errorApiRef } from '@backstage/core-plugin-api'; import { useCopyToClipboard } from 'react-use'; jest.mock('popper.js', () => { @@ -51,22 +50,18 @@ const props = { tooltipText: 'mockTooltip', }; -const apiRegistry = ApiRegistry.from([ - [ - errorApiRef, - { - post: jest.fn(), - error$: jest.fn(), - } as ErrorApi, - ], -]); +const mockErrorApi = { + post: jest.fn(), + error$: jest.fn(), +}; +const apis = [[errorApiRef, mockErrorApi] as const] as const; describe('', () => { it('renders without exploding', async () => { const { getByTitle, queryByText } = await renderInTestApp( - + - , + , ); expect(getByTitle('mockTooltip')).toBeInTheDocument(); expect(queryByText('mockTooltip')).not.toBeInTheDocument(); @@ -80,9 +75,9 @@ describe('', () => { spy.mockReturnValue([{}, copy]); const rendered = await renderInTestApp( - + - , + , ); const button = rendered.getByTitle('mockTooltip'); fireEvent.click(button); @@ -101,10 +96,10 @@ describe('', () => { spy.mockReturnValue([{ error }, jest.fn()]); await renderInTestApp( - + - , + , ); - expect(apiRegistry.get(errorApiRef)?.post).toHaveBeenCalledWith(error); + expect(mockErrorApi.post).toHaveBeenCalledWith(error); }); }); diff --git a/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx b/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx index e0e9a89c9f..5487d2e7b5 100644 --- a/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx +++ b/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx @@ -18,12 +18,13 @@ import React from 'react'; import { DismissableBanner } from './DismissableBanner'; import Link from '@material-ui/core/Link'; import Typography from '@material-ui/core/Typography'; -import { ApiProvider, ApiRegistry, WebStorage } from '@backstage/core-app-api'; +import { WebStorage } from '@backstage/core-app-api'; import { ErrorApi, storageApiRef, StorageApi, } from '@backstage/core-plugin-api'; +import { TestApiProvider } from '@backstage/test-utils'; export default { title: 'Feedback/DismissableBanner', @@ -37,47 +38,47 @@ const createWebStorage = (): StorageApi => { return WebStorage.create({ errorApi }); }; -const apis = ApiRegistry.from([[storageApiRef, createWebStorage()]]); +const apis = [[storageApiRef, createWebStorage()] as const]; export const Default = () => (
- + - +
); export const Error = () => (
- + - +
); export const EmojisIncluded = () => (
- + - +
); export const WithLink = () => (
- + @@ -90,29 +91,29 @@ export const WithLink = () => ( variant="info" id="linked_dismissable" /> - +
); export const Fixed = () => (
- + - +
); export const Warning = () => (
- + - +
); diff --git a/packages/core-components/src/components/DismissableBanner/DismissableBanner.test.tsx b/packages/core-components/src/components/DismissableBanner/DismissableBanner.test.tsx index ddc119369b..50b1fd33eb 100644 --- a/packages/core-components/src/components/DismissableBanner/DismissableBanner.test.tsx +++ b/packages/core-components/src/components/DismissableBanner/DismissableBanner.test.tsx @@ -16,13 +16,17 @@ import React from 'react'; import { fireEvent } from '@testing-library/react'; -import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { + renderWithEffects, + TestApiRegistry, + wrapInTestApp, +} from '@backstage/test-utils'; import { DismissableBanner } from './DismissableBanner'; -import { ApiRegistry, ApiProvider, WebStorage } from '@backstage/core-app-api'; +import { ApiProvider, WebStorage } from '@backstage/core-app-api'; import { storageApiRef, StorageApi } from '@backstage/core-plugin-api'; describe('', () => { - let apis: ApiRegistry; + let apis: TestApiRegistry; const mockErrorApi = { post: jest.fn(), error$: jest.fn() }; const createWebStorage = (): StorageApi => { return WebStorage.create({ @@ -31,7 +35,7 @@ describe('', () => { }; beforeEach(() => { - apis = ApiRegistry.from([[storageApiRef, createWebStorage()]]); + apis = TestApiRegistry.with([storageApiRef, createWebStorage()]); }); it('renders the message and the popover', async () => { diff --git a/packages/core-components/src/components/Link/Link.test.tsx b/packages/core-components/src/components/Link/Link.test.tsx index df1bcfac03..2d00aad827 100644 --- a/packages/core-components/src/components/Link/Link.test.tsx +++ b/packages/core-components/src/components/Link/Link.test.tsx @@ -16,8 +16,11 @@ import React from 'react'; import { render, fireEvent, waitFor } from '@testing-library/react'; -import { MockAnalyticsApi, wrapInTestApp } from '@backstage/test-utils'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { + MockAnalyticsApi, + TestApiProvider, + wrapInTestApp, +} from '@backstage/test-utils'; import { analyticsApiRef } from '@backstage/core-plugin-api'; import { isExternalUri, Link } from './Link'; import { Route, Routes } from 'react-router'; @@ -48,11 +51,11 @@ describe('', () => { const { getByText } = render( wrapInTestApp( - + {linkText} - , + , ), ); diff --git a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx index a1c45bff4d..361ad123bf 100644 --- a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx +++ b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx @@ -20,9 +20,9 @@ import { ErrorBoundary } from './ErrorBoundary'; import { MockErrorApi, renderInTestApp, + TestApiProvider, withLogCollector, } from '@backstage/test-utils'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; type BombProps = { @@ -41,25 +41,25 @@ const Bomb = ({ shouldThrow }: BombProps) => { describe('', () => { it('should render error boundary with and without error', async () => { const { error } = await withLogCollector(['error'], async () => { - const apis = ApiRegistry.with(errorApiRef, new MockErrorApi()); + const errorApi = new MockErrorApi(); const { rerender, queryByRole, getByRole, getByText } = await renderInTestApp( - + - , + , ); expect(queryByRole('alert')).not.toBeInTheDocument(); expect(getByText(/working component/i)).toBeInTheDocument(); rerender( - + - , + , ); expect(getByRole('alert')).toBeInTheDocument(); diff --git a/packages/core-components/src/layout/Header/Header.test.tsx b/packages/core-components/src/layout/Header/Header.test.tsx index 69d46cd102..776e39045c 100644 --- a/packages/core-components/src/layout/Header/Header.test.tsx +++ b/packages/core-components/src/layout/Header/Header.test.tsx @@ -15,13 +15,9 @@ */ import React from 'react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { Header } from './Header'; -import { - ApiRegistry, - ConfigReader, - ApiProvider, -} from '@backstage/core-app-api'; +import { ConfigReader } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; jest.mock('react-helmet', () => { @@ -72,14 +68,12 @@ describe('
', () => { }); it('should use app.title', async () => { - const apiRegistry = ApiRegistry.with( - configApiRef, - new ConfigReader({ app: { title: 'Blah' } }), - ); const rendered = await renderInTestApp( - +
, - , + , ); rendered.getAllByText(/Title | Blah/); }); diff --git a/packages/core-components/src/layout/HomepageTimer/HomepageTimer.test.tsx b/packages/core-components/src/layout/HomepageTimer/HomepageTimer.test.tsx index 1d4bf6954a..3d9dfe70a1 100644 --- a/packages/core-components/src/layout/HomepageTimer/HomepageTimer.test.tsx +++ b/packages/core-components/src/layout/HomepageTimer/HomepageTimer.test.tsx @@ -14,16 +14,12 @@ * limitations under the License. */ -import { renderWithEffects } from '@backstage/test-utils'; +import { renderWithEffects, TestApiProvider } from '@backstage/test-utils'; import { HomepageTimer } from './HomepageTimer'; import React from 'react'; import { lightTheme } from '@backstage/theme'; import { ThemeProvider } from '@material-ui/core/styles'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ConfigReader } from '@backstage/core-app-api'; import { ConfigApi, configApiRef } from '@backstage/core-plugin-api'; it('changes default timezone to GMT', async () => { @@ -41,9 +37,9 @@ it('changes default timezone to GMT', async () => { const rendered = await renderWithEffects( - + - + , ); diff --git a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx index 4d42a0c969..8795ecdded 100644 --- a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx +++ b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx @@ -18,11 +18,8 @@ import { useElementFilter } from './useElementFilter'; import { renderHook } from '@testing-library/react-hooks'; import { attachComponentData } from './componentData'; import { featureFlagsApiRef } from '../apis'; -import { - ApiProvider, - ApiRegistry, - LocalStorageFeatureFlags, -} from '@backstage/core-app-api'; +import { LocalStorageFeatureFlags } from '@backstage/core-app-api'; +import { TestApiProvider } from '@backstage/test-utils'; const WRAPPING_COMPONENT_KEY = 'core.blob.testing'; const INNER_COMPONENT_KEY = 'core.blob2.testing'; @@ -45,9 +42,9 @@ const FeatureFlagComponent = (_props: { attachComponentData(FeatureFlagComponent, 'core.featureFlagged', true); const mockFeatureFlagsApi = new LocalStorageFeatureFlags(); const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - + {children} - + ); describe('useElementFilter', () => { From 000190de69035e5cd92eb7f20c70c2401bb52f54 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 17 Nov 2021 11:48:42 +0100 Subject: [PATCH 08/61] changesets: add changeset for ApiRegistry deprecation Signed-off-by: Patrik Oldsberg --- .changeset/wet-seas-deliver.md | 63 ++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .changeset/wet-seas-deliver.md diff --git a/.changeset/wet-seas-deliver.md b/.changeset/wet-seas-deliver.md new file mode 100644 index 0000000000..0b440cbb46 --- /dev/null +++ b/.changeset/wet-seas-deliver.md @@ -0,0 +1,63 @@ +--- +'@backstage/core-app-api': patch +'@backstage/test-utils': patch +--- + +The `ApiRegistry` from `@backstage/core-app-api` class has been deprecated and will be removed in a future release. To replace it, we have introduced two new helpers that are exported from `@backstage/test-utils`, namely `TestApiProvider` and `TestApiRegistry`. + +These two new helpers are more tailored for writing tests and development setups, as they allow for partial implementations of each of the APIs. + +When migrating existing code it is typically best to prefer usage of `TestApiProvider` when possible, so for example the following code: + +```tsx +render( + + {...} + +) +``` + +Would be migrated to this: + +```tsx +render( + + {...} + +) +``` + +In cases where the `ApiProvider` is used in a more standalone way, for example to reuse a set of APIs across multiple tests, the `TestApiRegistry` can be used instead. Note that the `TestApiRegistry` only has a single static factory method, `.with()`, and it is slightly different from the existing `.with()` method on `ApiRegistry`. + +Usage that looks like this: + +```ts +const apis = ApiRegistry.with( + identityApiRef, + mockIdentityApi as unknown as IdentityApi, +).with(configApiRef, new ConfigReader({})); +``` + +OR like this: + +```ts +const apis = ApiRegistry.from([ + [identityApiRef, mockIdentityApi as unknown as IdentityApi], + [configApiRef, new ConfigReader({})], +]); +``` + +Would be migrated to this: + +```ts +const apis = TestApiRegistry.with( + [identityApiRef, mockIdentityApi], + [configApiRef, new ConfigReader({})], +); +``` + +If your app is still using the `ApiRegistry` to construct the `apis` for `createApp`, we recommend that you move over to use the new method of supplying API factories instead, using `createApiFactory`. From 154c77bf7f02b11c3480fcb1194902d8495073a1 Mon Sep 17 00:00:00 2001 From: Joon Park Date: Wed, 27 Oct 2021 13:09:04 +0100 Subject: [PATCH 09/61] EntitiesSearchFilter type refactor The current EntitiesSearchFilter's matchValueExists field is a bit confusing - it's not immediately clear the nuances of its behavior until you closely examine the implementation in NextEntitiesCatalog. By splitting the filter into to distinct types (one for key and another for key + value) as well as renaming the fields, I think this expresses the intent of the filters more cleanly. This also allows filtering by negation for key + value filters, which is not possible with the current implementation). Signed-off-by: Joon Park --- plugins/catalog-backend/src/catalog/index.ts | 2 ++ plugins/catalog-backend/src/catalog/types.ts | 24 +++++++++++++------ .../src/service/request/basicEntityFilter.ts | 8 +++---- .../request/parseEntityFilterParams.ts | 15 +++++++----- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/index.ts b/plugins/catalog-backend/src/catalog/index.ts index 885a2f5389..460aefddba 100644 --- a/plugins/catalog-backend/src/catalog/index.ts +++ b/plugins/catalog-backend/src/catalog/index.ts @@ -23,6 +23,8 @@ export type { EntityUpsertResponse, PageInfo, EntitiesSearchFilter, + EntitiesKeyFilter, + EntitiesValuesFilter, EntityFilter, EntityPagination, } from './types'; diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index df693bfd42..3f74f2ee98 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -39,7 +39,7 @@ export type EntityPagination = { /** * Matches rows in the entities_search table. */ -export type EntitiesSearchFilter = { +export type EntitiesValuesFilter = { /** * The key to match on. * @@ -50,18 +50,28 @@ export type EntitiesSearchFilter = { /** * Match on plain equality of values. * - * If undefined, this factor is not taken into account. Otherwise, match on + * Match on * values that are equal to any of the given array items. Matches are always * case insensitive. */ - matchValueIn?: string[]; + values: string[]; - /** - * Match on existence of key. - */ - matchValueExists?: boolean; + negate?: boolean; }; +export type EntitiesKeyFilter = { + /** + * The key to match on. + * + * Matches are always case insensitive. + */ + key: string; + + negate?: boolean; +}; + +export type EntitiesSearchFilter = EntitiesValuesFilter | EntitiesKeyFilter; + export type PageInfo = | { hasNextPage: false; diff --git a/plugins/catalog-backend/src/service/request/basicEntityFilter.ts b/plugins/catalog-backend/src/service/request/basicEntityFilter.ts index 1cf9ca95f0..cdc736e232 100644 --- a/plugins/catalog-backend/src/service/request/basicEntityFilter.ts +++ b/plugins/catalog-backend/src/service/request/basicEntityFilter.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { EntitiesSearchFilter, EntityFilter } from '../../catalog'; +import { EntitiesValuesFilter, EntityFilter } from '../../catalog'; /** * Forms a full EntityFilter based on a single key-value(s) object. @@ -22,7 +22,7 @@ import { EntitiesSearchFilter, EntityFilter } from '../../catalog'; export function basicEntityFilter( items: Record, ): EntityFilter { - const filtersByKey: Record = {}; + const filtersByKey: Record = {}; for (const [key, value] of Object.entries(items)) { const values = [value].flat(); @@ -30,9 +30,9 @@ export function basicEntityFilter( const f = key in filtersByKey ? filtersByKey[key] - : (filtersByKey[key] = { key, matchValueIn: [] }); + : (filtersByKey[key] = { key, values: [] }); - f.matchValueIn!.push(...values); + f.values!.push(...values); } return { anyOf: [{ allOf: Object.values(filtersByKey) }] }; diff --git a/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts b/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts index 452958b7ae..e779c193cb 100644 --- a/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts +++ b/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts @@ -15,7 +15,11 @@ */ import { InputError } from '@backstage/errors'; -import { EntitiesSearchFilter, EntityFilter } from '../../catalog'; +import { + EntitiesSearchFilter, + EntitiesValuesFilter, + EntityFilter, +} from '../../catalog'; import { parseStringsParam } from './common'; /** @@ -75,11 +79,10 @@ export function parseEntityFilterString( const f = key in filtersByKey ? filtersByKey[key] : (filtersByKey[key] = { key }); - if (value === undefined) { - f.matchValueExists = true; - } else { - f.matchValueIn = f.matchValueIn || []; - f.matchValueIn.push(value); + if (value !== undefined) { + const valuesFilter = f as EntitiesValuesFilter; + valuesFilter.values = valuesFilter.values || []; + valuesFilter.values.push(value); } } From 5f1de0fc60a07fd258d83d6eb1e07dd993374b1b Mon Sep 17 00:00:00 2001 From: Joon Park Date: Tue, 9 Nov 2021 15:11:07 +0000 Subject: [PATCH 10/61] Allow negation through nesting a "not" object. Signed-off-by: Joon Park --- plugins/catalog-backend/src/catalog/types.ts | 25 ++------- .../src/service/NextEntitiesCatalog.test.ts | 51 ++++++++++++++++--- .../src/service/NextEntitiesCatalog.ts | 40 +++++++++------ 3 files changed, 73 insertions(+), 43 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 3f74f2ee98..2a18783679 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -25,6 +25,7 @@ import { Entity, EntityRelationSpec } from '@backstage/catalog-model'; export type EntityFilter = | { allOf: EntityFilter[] } | { anyOf: EntityFilter[] } + | { not: EntityFilter } | EntitiesSearchFilter; /** @@ -39,7 +40,7 @@ export type EntityPagination = { /** * Matches rows in the entities_search table. */ -export type EntitiesValuesFilter = { +export type EntitiesSearchFilter = { /** * The key to match on. * @@ -50,28 +51,12 @@ export type EntitiesValuesFilter = { /** * Match on plain equality of values. * - * Match on - * values that are equal to any of the given array items. Matches are always - * case insensitive. + * Match on values that are equal to any of the given array items. Matches are + * always case insensitive. */ - values: string[]; - - negate?: boolean; + values?: string[]; }; -export type EntitiesKeyFilter = { - /** - * The key to match on. - * - * Matches are always case insensitive. - */ - key: string; - - negate?: boolean; -}; - -export type EntitiesSearchFilter = EntitiesValuesFilter | EntitiesKeyFilter; - export type PageInfo = | { hasNextPage: false; diff --git a/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts index 32d5fa843e..c968b6de82 100644 --- a/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts @@ -282,7 +282,6 @@ describe('NextEntitiesCatalog', () => { const testFilter = { key: 'spec.test', - matchValueExists: true, }; const request = { filter: testFilter }; const { entities } = await catalog.entities(request); @@ -292,6 +291,41 @@ describe('NextEntitiesCatalog', () => { }, ); + it.each(databases.eachSupportedId())( + 'should return correct entity for negation filter', + async databaseId => { + const { knex } = await createDatabase(databaseId); + const entity1: Entity = { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'one' }, + spec: {}, + }; + const entity2: Entity = { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'two' }, + spec: { + test: 'test value', + }, + }; + await addEntityToSearch(knex, entity1); + await addEntityToSearch(knex, entity2); + const catalog = new NextEntitiesCatalog(knex); + + const testFilter = { + not: { + key: 'spec.test', + }, + }; + const request = { filter: testFilter }; + const { entities } = await catalog.entities(request); + + expect(entities.length).toBe(1); + expect(entities[0]).toEqual(entity1); + }, + ); + it.each(databases.eachSupportedId())( 'should return correct entity for nested filter', async databaseId => { @@ -328,24 +362,27 @@ describe('NextEntitiesCatalog', () => { const testFilter1 = { key: 'metadata.org', - matchValueExists: true, - matchValueIn: ['b'], + values: ['b'], }; const testFilter2 = { key: 'metadata.desc', - matchValueExists: true, }; const testFilter3 = { key: 'metadata.color', - matchValueExists: true, - matchValueIn: ['blue'], + values: ['blue'], + }; + const testFilter4 = { + not: { + key: 'metadata.color', + values: ['red'], + }, }; const request = { filter: { allOf: [ testFilter1, { - anyOf: [testFilter2, testFilter3], + anyOf: [testFilter2, testFilter3, testFilter4], }, ], }, diff --git a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts index 1c615f862a..ccce1395d7 100644 --- a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts @@ -78,33 +78,30 @@ function stringifyPagination(input: { limit: number; offset: number }) { function addCondition( queryBuilder: Knex.QueryBuilder, db: Knex, - { key, matchValueIn, matchValueExists }: EntitiesSearchFilter, + filter: EntitiesSearchFilter, + negate: boolean = false, ) { // NOTE(freben): This used to be a set of OUTER JOIN, which may seem to // make a lot of sense. However, it had abysmal performance on sqlite // when datasets grew large, so we're using IN instead. const matchQuery = db('search') .select('entity_id') - .where(function keyFilter() { - this.andWhere({ key: key.toLowerCase() }); - if (matchValueExists !== false && matchValueIn) { - if (matchValueIn.length === 1) { - this.andWhere({ value: matchValueIn[0].toLowerCase() }); - } else if (matchValueIn.length > 1) { + .where({ key: filter.key.toLowerCase() }) + .andWhere(function keyFilter() { + if (filter.values) { + if (filter.values.length === 1) { + this.where({ value: filter.values[0].toLowerCase() }); + } else if (filter.values.length > 1) { this.andWhere( 'value', 'in', - matchValueIn.map(v => v.toLowerCase()), + filter.values.map(v => v.toLowerCase()), ); } } }); // Explicitly evaluate matchValueExists as a boolean since it may be undefined - queryBuilder.andWhere( - 'entity_id', - matchValueExists === false ? 'not in' : 'in', - matchQuery, - ); + queryBuilder.andWhere('entity_id', negate ? 'not in' : 'in', matchQuery); } function isEntitiesSearchFilter( @@ -125,21 +122,32 @@ function isOrEntityFilter( return filter.hasOwnProperty('anyOf'); } +function isNegationEntityFilter( + filter: { not: EntityFilter } | EntityFilter, +): filter is { not: EntityFilter } { + return filter.hasOwnProperty('not'); +} + function parseFilter( filter: EntityFilter, query: Knex.QueryBuilder, db: Knex, + negate: boolean = false, ): Knex.QueryBuilder { if (isEntitiesSearchFilter(filter)) { return query.andWhere(function filterFunction() { - addCondition(this, db, filter); + addCondition(this, db, filter, negate); }); } + if (isNegationEntityFilter(filter)) { + return parseFilter(filter.not, query, db, true); + } + if (isOrEntityFilter(filter)) { return query.andWhere(function filterFunction() { for (const subFilter of filter.anyOf ?? []) { - this.orWhere(subQuery => parseFilter(subFilter, subQuery, db)); + this.orWhere(subQuery => parseFilter(subFilter, subQuery, db, negate)); } }); } @@ -147,7 +155,7 @@ function parseFilter( if (isAndEntityFilter(filter)) { return query.andWhere(function filterFunction() { for (const subFilter of filter.allOf ?? []) { - this.andWhere(subQuery => parseFilter(subFilter, subQuery, db)); + this.andWhere(subQuery => parseFilter(subFilter, subQuery, db, negate)); } }); } From 8d1309bf7d567752acb21da5f48cda5abfcba19c Mon Sep 17 00:00:00 2001 From: Joon Park Date: Tue, 16 Nov 2021 12:53:37 +0000 Subject: [PATCH 11/61] Fix complex negation bug Signed-off-by: Joon Park --- .../src/service/NextEntitiesCatalog.test.ts | 43 ++++++++++++++++++- .../src/service/NextEntitiesCatalog.ts | 28 ++++-------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts index c968b6de82..ee86e78c6b 100644 --- a/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts @@ -327,7 +327,7 @@ describe('NextEntitiesCatalog', () => { ); it.each(databases.eachSupportedId())( - 'should return correct entity for nested filter', + 'should return correct entities for nested filter', async databaseId => { const { knex } = await createDatabase(databaseId); const entity1: Entity = { @@ -394,5 +394,46 @@ describe('NextEntitiesCatalog', () => { expect(entities).toContainEqual(entity4); }, ); + + it.each(databases.eachSupportedId())( + 'should return correct entities for complex negation filter', + async databaseId => { + const { knex } = await createDatabase(databaseId); + const entity1: Entity = { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'one', org: 'a', desc: 'description' }, + spec: {}, + }; + const entity2: Entity = { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'two', org: 'b', desc: 'description' }, + spec: {}, + }; + await addEntityToSearch(knex, entity1); + await addEntityToSearch(knex, entity2); + const catalog = new NextEntitiesCatalog(knex); + + const testFilter1 = { + key: 'metadata.org', + values: ['b'], + }; + const testFilter2 = { + key: 'metadata.desc', + }; + const request = { + filter: { + not: { + allOf: [testFilter1, testFilter2], + }, + }, + }; + const { entities } = await catalog.entities(request); + + expect(entities.length).toBe(1); + expect(entities).toContainEqual(entity1); + }, + ); }); }); diff --git a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts index ccce1395d7..0f2fb9494c 100644 --- a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts @@ -110,12 +110,6 @@ function isEntitiesSearchFilter( return filter.hasOwnProperty('key'); } -function isAndEntityFilter( - filter: { allOf: EntityFilter[] } | EntityFilter, -): filter is { allOf: EntityFilter[] } { - return filter.hasOwnProperty('allOf'); -} - function isOrEntityFilter( filter: { anyOf: EntityFilter[] } | EntityFilter, ): filter is { anyOf: EntityFilter[] } { @@ -141,26 +135,20 @@ function parseFilter( } if (isNegationEntityFilter(filter)) { - return parseFilter(filter.not, query, db, true); + return parseFilter(filter.not, query, db, !negate); } - if (isOrEntityFilter(filter)) { - return query.andWhere(function filterFunction() { + return query[negate ? 'andWhereNot' : 'andWhere'](function filterFunction() { + if (isOrEntityFilter(filter)) { for (const subFilter of filter.anyOf ?? []) { - this.orWhere(subQuery => parseFilter(subFilter, subQuery, db, negate)); + this.orWhere(subQuery => parseFilter(subFilter, subQuery, db)); } - }); - } - - if (isAndEntityFilter(filter)) { - return query.andWhere(function filterFunction() { + } else { for (const subFilter of filter.allOf ?? []) { - this.andWhere(subQuery => parseFilter(subFilter, subQuery, db, negate)); + this.andWhere(subQuery => parseFilter(subFilter, subQuery, db)); } - }); - } - - return query; + } + }); } export class NextEntitiesCatalog implements EntitiesCatalog { From b5c54795047f90cf407e92c59e560705c94b0ae4 Mon Sep 17 00:00:00 2001 From: Joon Park Date: Tue, 16 Nov 2021 13:06:31 +0000 Subject: [PATCH 12/61] Fix tests Signed-off-by: Joon Park --- plugins/catalog-backend/src/catalog/index.ts | 2 -- .../legacy/database/CommonDatabase.test.ts | 28 +------------------ .../src/legacy/database/CommonDatabase.ts | 25 ++++++++--------- .../src/legacy/service/router.test.ts | 6 ++-- .../src/service/NextEntitiesCatalog.ts | 1 - .../src/service/NextRouter.test.ts | 6 ++-- .../request/parseEntityFilterParams.test.ts | 24 ++++++++-------- 7 files changed, 30 insertions(+), 62 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/index.ts b/plugins/catalog-backend/src/catalog/index.ts index 460aefddba..885a2f5389 100644 --- a/plugins/catalog-backend/src/catalog/index.ts +++ b/plugins/catalog-backend/src/catalog/index.ts @@ -23,8 +23,6 @@ export type { EntityUpsertResponse, PageInfo, EntitiesSearchFilter, - EntitiesKeyFilter, - EntitiesValuesFilter, EntityFilter, EntityPagination, } from './types'; diff --git a/plugins/catalog-backend/src/legacy/database/CommonDatabase.test.ts b/plugins/catalog-backend/src/legacy/database/CommonDatabase.test.ts index ca2e6c2934..8b72b470a6 100644 --- a/plugins/catalog-backend/src/legacy/database/CommonDatabase.test.ts +++ b/plugins/catalog-backend/src/legacy/database/CommonDatabase.test.ts @@ -536,9 +536,7 @@ describe('CommonDatabase', () => { filter: { anyOf: [ { - allOf: [ - { key: 'metadata.annotations.foo', matchValueExists: true }, - ], + allOf: [{ key: 'metadata.annotations.foo' }], }, ], }, @@ -558,30 +556,6 @@ describe('CommonDatabase', () => { }, ]), ); - - const nonExistRows = await db.transaction(async tx => - db.entities(tx, { - filter: { - anyOf: [ - { - allOf: [ - { key: 'metadata.annotations.foo', matchValueExists: false }, - ], - }, - ], - }, - }), - ); - - expect(nonExistRows.entities.length).toEqual(1); - expect(nonExistRows.entities).toEqual( - expect.arrayContaining([ - { - locationId: undefined, - entity: expect.objectContaining({ kind: 'k3' }), - }, - ]), - ); }); }); diff --git a/plugins/catalog-backend/src/legacy/database/CommonDatabase.ts b/plugins/catalog-backend/src/legacy/database/CommonDatabase.ts index 6a150f7583..3ea8696437 100644 --- a/plugins/catalog-backend/src/legacy/database/CommonDatabase.ts +++ b/plugins/catalog-backend/src/legacy/database/CommonDatabase.ts @@ -224,7 +224,8 @@ export class CommonDatabase implements Database { if ( request?.filter && (request.filter.hasOwnProperty('key') || - request.filter.hasOwnProperty('allOf')) + request.filter.hasOwnProperty('allOf') || + request.filter.hasOwnProperty('not')) ) { throw new Error( 'Filters for the legacy CommonDatabase must obey the { anyOf: [{ allOf: [] }] } format.', @@ -236,13 +237,14 @@ export class CommonDatabase implements Database { for (const filter of singleFilter.allOf) { if ( filter.hasOwnProperty('anyOf') || - filter.hasOwnProperty('allOf') + filter.hasOwnProperty('allOf') || + filter.hasOwnProperty('not') ) { throw new Error( 'Nested filters are not supported in the legacy CommonDatabase', ); } - const { key, matchValueIn, matchValueExists } = filter; + const { key, values } = filter; // NOTE(freben): This used to be a set of OUTER JOIN, which may seem to // make a lot of sense. However, it had abysmal performance on sqlite // when datasets grew large, so we're using IN instead. @@ -250,24 +252,19 @@ export class CommonDatabase implements Database { .select('entity_id') .where(function keyFilter() { this.andWhere({ key: key.toLowerCase() }); - if (matchValueExists !== false && matchValueIn) { - if (matchValueIn.length === 1) { - this.andWhere({ value: matchValueIn[0].toLowerCase() }); - } else if (matchValueIn.length > 1) { + if (values) { + if (values.length === 1) { + this.andWhere({ value: values[0].toLowerCase() }); + } else if (values.length > 1) { this.andWhere( 'value', 'in', - matchValueIn.map(v => v.toLowerCase()), + values.map(v => v.toLowerCase()), ); } } }); - // Explicitly evaluate matchValueExists as a boolean since it may be undefined - this.andWhere( - 'id', - matchValueExists === false ? 'not in' : 'in', - matchQuery, - ); + this.andWhere('id', 'in', matchQuery); } }); } diff --git a/plugins/catalog-backend/src/legacy/service/router.test.ts b/plugins/catalog-backend/src/legacy/service/router.test.ts index edc7d852ac..0ff5a44ed0 100644 --- a/plugins/catalog-backend/src/legacy/service/router.test.ts +++ b/plugins/catalog-backend/src/legacy/service/router.test.ts @@ -115,11 +115,11 @@ describe('createRouter readonly disabled', () => { anyOf: [ { allOf: [ - { key: 'a', matchValueIn: ['1', '2'] }, - { key: 'b', matchValueIn: ['3'] }, + { key: 'a', values: ['1', '2'] }, + { key: 'b', values: ['3'] }, ], }, - { allOf: [{ key: 'c', matchValueIn: ['4'] }] }, + { allOf: [{ key: 'c', values: ['4'] }] }, ], }, }); diff --git a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts index 0f2fb9494c..8c2de9d7c1 100644 --- a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts @@ -100,7 +100,6 @@ function addCondition( } } }); - // Explicitly evaluate matchValueExists as a boolean since it may be undefined queryBuilder.andWhere('entity_id', negate ? 'not in' : 'in', matchQuery); } diff --git a/plugins/catalog-backend/src/service/NextRouter.test.ts b/plugins/catalog-backend/src/service/NextRouter.test.ts index 57911c74fb..6bc4481425 100644 --- a/plugins/catalog-backend/src/service/NextRouter.test.ts +++ b/plugins/catalog-backend/src/service/NextRouter.test.ts @@ -104,11 +104,11 @@ describe('createNextRouter readonly disabled', () => { anyOf: [ { allOf: [ - { key: 'a', matchValueIn: ['1', '2'] }, - { key: 'b', matchValueIn: ['3'] }, + { key: 'a', values: ['1', '2'] }, + { key: 'b', values: ['3'] }, ], }, - { allOf: [{ key: 'c', matchValueIn: ['4'] }] }, + { allOf: [{ key: 'c', values: ['4'] }] }, ], }, }); diff --git a/plugins/catalog-backend/src/service/request/parseEntityFilterParams.test.ts b/plugins/catalog-backend/src/service/request/parseEntityFilterParams.test.ts index fc22a638de..f9fc596cb9 100644 --- a/plugins/catalog-backend/src/service/request/parseEntityFilterParams.test.ts +++ b/plugins/catalog-backend/src/service/request/parseEntityFilterParams.test.ts @@ -28,7 +28,7 @@ describe('parseEntityFilterParams', () => { it('supports single-string format', () => { const result = parseEntityFilterParams({ filter: 'a=1' })!; expect(result).toEqual({ - anyOf: [{ allOf: [{ key: 'a', matchValueIn: ['1'] }] }], + anyOf: [{ allOf: [{ key: 'a', values: ['1'] }] }], }); }); @@ -38,8 +38,8 @@ describe('parseEntityFilterParams', () => { }); expect(result).toEqual({ anyOf: [ - { allOf: [{ key: 'a', matchValueIn: ['1'] }] }, - { allOf: [{ key: 'b', matchValueIn: ['2'] }] }, + { allOf: [{ key: 'a', values: ['1'] }] }, + { allOf: [{ key: 'b', values: ['2'] }] }, ], }); }); @@ -50,11 +50,11 @@ describe('parseEntityFilterParams', () => { }); expect(result).toEqual({ anyOf: [ - { allOf: [{ key: 'a', matchValueIn: ['1'] }] }, + { allOf: [{ key: 'a', values: ['1'] }] }, { allOf: [ - { key: 'b', matchValueIn: ['2', '3'] }, - { key: 'c', matchValueIn: ['4'] }, + { key: 'b', values: ['2', '3'] }, + { key: 'c', values: ['4'] }, ], }, ], @@ -70,17 +70,17 @@ describe('parseEntityFilterString', () => { it('works for the happy path', () => { expect(parseEntityFilterString('')).toBeUndefined(); expect(parseEntityFilterString('a=1,b=2,a=3,c,d=')).toEqual([ - { key: 'a', matchValueIn: ['1', '3'] }, - { key: 'b', matchValueIn: ['2'] }, - { key: 'c', matchValueExists: true }, - { key: 'd', matchValueIn: [''] }, + { key: 'a', values: ['1', '3'] }, + { key: 'b', values: ['2'] }, + { key: 'c' }, + { key: 'd', values: [''] }, ]); }); it('trims values', () => { expect(parseEntityFilterString(' a = 1 , b = 2 , a = 3 ')).toEqual([ - { key: 'a', matchValueIn: ['1', '3'] }, - { key: 'b', matchValueIn: ['2'] }, + { key: 'a', values: ['1', '3'] }, + { key: 'b', values: ['2'] }, ]); }); From 7f82ce9f511878b98946c59e97e1c64c3168be73 Mon Sep 17 00:00:00 2001 From: Joon Park Date: Tue, 16 Nov 2021 13:54:55 +0000 Subject: [PATCH 13/61] API reports and Changelog Signed-off-by: Joon Park --- .changeset/smart-fans-complain.md | 42 +++++++++++++++++++ plugins/catalog-backend/api-report.md | 12 +++--- .../src/service/request/basicEntityFilter.ts | 4 +- .../request/parseEntityFilterParams.ts | 11 ++--- 4 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 .changeset/smart-fans-complain.md diff --git a/.changeset/smart-fans-complain.md b/.changeset/smart-fans-complain.md new file mode 100644 index 0000000000..db404f110d --- /dev/null +++ b/.changeset/smart-fans-complain.md @@ -0,0 +1,42 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +**BREAKING** EntitiesSearchFilter fields have changed. + +EntitiesSearchFilter now has only two fields: `key` and `value`. The `matchValueIn` and `matchValueExists` fields are no longer are supported. Previous filters written using the `matchValueIn` and `matchValueExists` fields can be rewritten as follows: + +Filtering by existence of key only: + +```diff + filter: { + { + key: 'abc', +- matchValueExists: true, + }, + } +``` + +Filtering by key and values: + +```diff + filter: { + { + key: 'abc', +- matchValueExists: true, +- matchValueIn: ['xyz'], ++ values: ['xyz'], + }, + } +``` + +Negation of filters can now be achieved through a `not` object: + +``` +filter: { + not: { + key: 'abc', + values: ['xyz'], + }, +} +``` diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 6660912dda..5008cf02f1 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -846,8 +846,7 @@ export type EntitiesResponse = { // @public export type EntitiesSearchFilter = { key: string; - matchValueIn?: string[]; - matchValueExists?: boolean; + values?: string[]; }; // Warning: (ae-missing-release-tag) "entity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -877,6 +876,9 @@ export type EntityFilter = | { anyOf: EntityFilter[]; } + | { + not: EntityFilter; + } | EntitiesSearchFilter; // Warning: (ae-missing-release-tag) "EntityPagination" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -1546,9 +1548,9 @@ export class UrlReaderProcessor implements CatalogProcessor { // Warnings were encountered during analysis: // -// src/catalog/types.d.ts:97:8 - (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// src/catalog/types.d.ts:98:8 - (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// src/catalog/types.d.ts:99:8 - (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// src/catalog/types.d.ts:94:8 - (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// src/catalog/types.d.ts:95:8 - (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// src/catalog/types.d.ts:96:8 - (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters // src/ingestion/processors/GithubMultiOrgReaderProcessor.d.ts:23:9 - (ae-forgotten-export) The symbol "GithubMultiOrgConfig" needs to be exported by the entry point index.d.ts // src/ingestion/types.d.ts:8:8 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // src/legacy/database/types.d.ts:98:8 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen diff --git a/plugins/catalog-backend/src/service/request/basicEntityFilter.ts b/plugins/catalog-backend/src/service/request/basicEntityFilter.ts index cdc736e232..36448e0304 100644 --- a/plugins/catalog-backend/src/service/request/basicEntityFilter.ts +++ b/plugins/catalog-backend/src/service/request/basicEntityFilter.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { EntitiesValuesFilter, EntityFilter } from '../../catalog'; +import { EntitiesSearchFilter, EntityFilter } from '../../catalog'; /** * Forms a full EntityFilter based on a single key-value(s) object. @@ -22,7 +22,7 @@ import { EntitiesValuesFilter, EntityFilter } from '../../catalog'; export function basicEntityFilter( items: Record, ): EntityFilter { - const filtersByKey: Record = {}; + const filtersByKey: Record = {}; for (const [key, value] of Object.entries(items)) { const values = [value].flat(); diff --git a/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts b/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts index e779c193cb..1ea5d44b2c 100644 --- a/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts +++ b/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts @@ -15,11 +15,7 @@ */ import { InputError } from '@backstage/errors'; -import { - EntitiesSearchFilter, - EntitiesValuesFilter, - EntityFilter, -} from '../../catalog'; +import { EntitiesSearchFilter, EntityFilter } from '../../catalog'; import { parseStringsParam } from './common'; /** @@ -80,9 +76,8 @@ export function parseEntityFilterString( key in filtersByKey ? filtersByKey[key] : (filtersByKey[key] = { key }); if (value !== undefined) { - const valuesFilter = f as EntitiesValuesFilter; - valuesFilter.values = valuesFilter.values || []; - valuesFilter.values.push(value); + f.values = f.values || []; + f.values.push(value); } } From efe1eab1ecf870946c3152be1e897c243d1a3da5 Mon Sep 17 00:00:00 2001 From: Ainhoa Larumbe Date: Wed, 17 Nov 2021 16:46:10 +0000 Subject: [PATCH 14/61] add displayName to text in indexed document for user entities Signed-off-by: Ainhoa Larumbe --- .../src/search/DefaultCatalogCollator.ts | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index a28a7645c4..5458b9054a 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -15,7 +15,7 @@ */ import { PluginEndpointDiscovery } from '@backstage/backend-common'; -import { Entity } from '@backstage/catalog-model'; +import { Entity, UserEntity } from '@backstage/catalog-model'; import { IndexableDocument, DocumentCollator } from '@backstage/search-common'; import { Config } from '@backstage/config'; import { @@ -81,6 +81,23 @@ export class DefaultCatalogCollator implements DocumentCollator { return formatted.toLowerCase(); } + protected isUserEntity(entity: Entity): entity is UserEntity { + return entity.kind === 'User'; + } + + protected getDocumentText(entity: Entity): string { + let documentText = entity.metadata.description || ''; + if (this.isUserEntity(entity)) { + if (entity.spec?.profile?.displayName && entity.metadata.description) { + // combine displayName and description + documentText = `${entity.spec?.profile?.displayName} : ${entity.metadata.description}`; + } else { + documentText = entity.spec?.profile?.displayName || documentText; + } + } + return documentText; + } + async execute() { const response = await this.catalogClient.getEntities({ filter: this.filter, @@ -93,7 +110,7 @@ export class DefaultCatalogCollator implements DocumentCollator { kind: entity.kind, name: entity.metadata.name, }), - text: entity.metadata.description || '', + text: this.getDocumentText(entity), componentType: entity.spec?.type?.toString() || 'other', namespace: entity.metadata.namespace || 'default', kind: entity.kind, From eddb82ab7cb8143ccc91c1cb4b48d6989fb398cc Mon Sep 17 00:00:00 2001 From: Ainhoa Larumbe Date: Wed, 17 Nov 2021 16:51:07 +0000 Subject: [PATCH 15/61] add changeset Signed-off-by: Ainhoa Larumbe --- .changeset/smooth-vans-boil.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/smooth-vans-boil.md diff --git a/.changeset/smooth-vans-boil.md b/.changeset/smooth-vans-boil.md new file mode 100644 index 0000000000..39b2ea386f --- /dev/null +++ b/.changeset/smooth-vans-boil.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Index User entities by displayName to be able to search by full name. Added displayName (if present) to the 'text' field in the indexed document. From 2dc6eb8fdd671b68298279672dc260bdb2177442 Mon Sep 17 00:00:00 2001 From: goenning Date: Wed, 17 Nov 2021 18:52:57 +0000 Subject: [PATCH 16/61] factRefs to factIds Signed-off-by: goenning --- plugins/tech-insights-backend-module-jsonfc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tech-insights-backend-module-jsonfc/README.md b/plugins/tech-insights-backend-module-jsonfc/README.md index 7b5d48bf62..c0f992ffc7 100644 --- a/plugins/tech-insights-backend-module-jsonfc/README.md +++ b/plugins/tech-insights-backend-module-jsonfc/README.md @@ -59,7 +59,7 @@ export const exampleCheck: TechInsightJsonRuleCheck = { name: 'demodatacheck', // A human readable name of this check to be displayed in the UI type: JSON_RULE_ENGINE_CHECK_TYPE, // Type identifier of the check. Used to run logic against, determine persistence option to use and render correct components on the UI description: 'A fact check for demoing purposes', // A description to be displayed in the UI - factRefs: ['demo-poc.factretriever'], // References to fact containers that this check uses. See documentation on FactRetrievers for more information on these + factIds: ['documentation-number-factretriever'], // References to fact ids that this check uses. See documentation on FactRetrievers for more information on these rule: { // The actual rule conditions: { From 0c92f73a111b3c3d40ddbc3d1a0e28fca0324f4a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 18 Nov 2021 10:37:12 +0100 Subject: [PATCH 17/61] test-utils: TestApiRegistry.with -> .from Signed-off-by: Patrik Oldsberg --- .changeset/wet-seas-deliver.md | 2 +- .../DismissableBanner/DismissableBanner.test.tsx | 2 +- packages/test-utils/api-report.md | 2 +- .../test-utils/src/testUtils/TestApiProvider.test.tsx | 8 ++++---- packages/test-utils/src/testUtils/TestApiProvider.tsx | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.changeset/wet-seas-deliver.md b/.changeset/wet-seas-deliver.md index 0b440cbb46..f625e093f5 100644 --- a/.changeset/wet-seas-deliver.md +++ b/.changeset/wet-seas-deliver.md @@ -54,7 +54,7 @@ const apis = ApiRegistry.from([ Would be migrated to this: ```ts -const apis = TestApiRegistry.with( +const apis = TestApiRegistry.from( [identityApiRef, mockIdentityApi], [configApiRef, new ConfigReader({})], ); diff --git a/packages/core-components/src/components/DismissableBanner/DismissableBanner.test.tsx b/packages/core-components/src/components/DismissableBanner/DismissableBanner.test.tsx index 50b1fd33eb..e62b3fa82d 100644 --- a/packages/core-components/src/components/DismissableBanner/DismissableBanner.test.tsx +++ b/packages/core-components/src/components/DismissableBanner/DismissableBanner.test.tsx @@ -35,7 +35,7 @@ describe('', () => { }; beforeEach(() => { - apis = TestApiRegistry.with([storageApiRef, createWebStorage()]); + apis = TestApiRegistry.from([storageApiRef, createWebStorage()]); }); it('renders the message and the popover', async () => { diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md index 5bb552563b..a1f22a7a64 100644 --- a/packages/test-utils/api-report.md +++ b/packages/test-utils/api-report.md @@ -193,7 +193,7 @@ export type TestApiProviderProps = { export class TestApiRegistry implements ApiHolder { // (undocumented) get(api: ApiRef): T | undefined; - static with( + static from( ...apis: readonly [...TestApiProviderPropsApiPairs] ): TestApiRegistry; } diff --git a/packages/test-utils/src/testUtils/TestApiProvider.test.tsx b/packages/test-utils/src/testUtils/TestApiProvider.test.tsx index 7bffd39a4a..d3f84f854a 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.test.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.test.tsx @@ -98,7 +98,7 @@ describe('TestApiRegistry', () => { it('should be created with APIs', () => { const x = { a: 'a', b: 3 }; const y = 'y'; - const registry = TestApiRegistry.with([xApiRef, x], [yApiRef, y]); + const registry = TestApiRegistry.from([xApiRef, x], [yApiRef, y]); expect(registry.get(xApiRef)).toBe(x); expect(registry.get(yApiRef)).toBe(y); @@ -106,7 +106,7 @@ describe('TestApiRegistry', () => { it('should allow partial implementations', () => { const x = { a: 'a' }; - const registry = TestApiRegistry.with([xApiRef, x]); + const registry = TestApiRegistry.from([xApiRef, x]); expect(registry.get(xApiRef)).toBe(x); expect(registry.get(yApiRef)).toBeUndefined(); @@ -115,7 +115,7 @@ describe('TestApiRegistry', () => { it('should require partial implementations to match types', () => { const x = { a: 2 }; // @ts-expect-error - const registry = TestApiRegistry.with([xApiRef, x]); + const registry = TestApiRegistry.from([xApiRef, x]); expect(registry.get(xApiRef)).toBe(x); expect(registry.get(yApiRef)).toBeUndefined(); @@ -125,7 +125,7 @@ describe('TestApiRegistry', () => { const x1 = { a: 'a' }; const x2 = { a: 's' }; const x3 = { a: 'd' }; - const registry = TestApiRegistry.with( + const registry = TestApiRegistry.from( [xApiRef, x1], [xApiRef, x2], [xApiRef, x3], diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index 92be0ffd77..43774b7267 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -63,7 +63,7 @@ export class TestApiRegistry implements ApiHolder { * @public * @param apis - A list of pairs mapping an ApiRef to its respective implementation. */ - static with( + static from( ...apis: readonly [...TestApiProviderPropsApiPairs] ) { return new TestApiRegistry( @@ -121,6 +121,6 @@ export const TestApiProvider = ({ children, }: TestApiProviderProps) => { return ( - + ); }; From 000c12384e83726d0cac3bf24424b0dc3be34a2b Mon Sep 17 00:00:00 2001 From: Ainhoa Larumbe Date: Thu, 18 Nov 2021 09:46:09 +0000 Subject: [PATCH 18/61] update api-report Signed-off-by: Ainhoa Larumbe --- plugins/catalog-backend/api-report.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 6660912dda..6c8c9a8f82 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -32,6 +32,7 @@ import { Router } from 'express'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { ScmIntegrations } from '@backstage/integration'; import { UrlReader } from '@backstage/backend-common'; +import { UserEntity } from '@backstage/catalog-model'; import { Validators } from '@backstage/catalog-model'; // Warning: (ae-missing-release-tag) "AddLocationResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -764,6 +765,10 @@ export class DefaultCatalogCollator implements DocumentCollator { }, ): DefaultCatalogCollator; // (undocumented) + protected getDocumentText(entity: Entity): string; + // (undocumented) + protected isUserEntity(entity: Entity): entity is UserEntity; + // (undocumented) protected locationTemplate: string; // (undocumented) readonly type: string; From 7ff56c23309ae0da66f3561aa425615ba27e3dee Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 18 Nov 2021 11:28:26 +0100 Subject: [PATCH 19/61] test-utils: doc + API report fixup Signed-off-by: Patrik Oldsberg --- packages/test-utils/api-report.md | 3 +-- packages/test-utils/src/testUtils/TestApiProvider.tsx | 6 +++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md index a1f22a7a64..83c209122d 100644 --- a/packages/test-utils/api-report.md +++ b/packages/test-utils/api-report.md @@ -191,11 +191,10 @@ export type TestApiProviderProps = { // @public export class TestApiRegistry implements ApiHolder { - // (undocumented) - get(api: ApiRef): T | undefined; static from( ...apis: readonly [...TestApiProviderPropsApiPairs] ): TestApiRegistry; + get(api: ApiRef): T | undefined; } // @public diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index 43774b7267..4408fc5b36 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -73,7 +73,11 @@ export class TestApiRegistry implements ApiHolder { private constructor(private readonly apis: Map) {} - /** {@inheritdoc @backstage/core-plugin-api#ApiHolder.get} */ + /** + * Returns an implementation of the API. + * + * @public + */ get(api: ApiRef): T | undefined { return this.apis.get(api.id) as T | undefined; } From d3248fb8c9577f3ad4268d206c8ad5555171eddd Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Thu, 18 Nov 2021 11:52:40 +0100 Subject: [PATCH 20/61] add techdocs search capabilities to default app Signed-off-by: Emma Indal --- .../app/src/components/search/SearchPage.tsx | 15 +++++++++++++++ .../packages/backend/src/plugins/search.ts | 10 +++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx index 7b3c2b29d4..50ffbadb76 100644 --- a/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx @@ -2,10 +2,13 @@ import React from 'react'; import { makeStyles, Theme, Grid, List, Paper } from '@material-ui/core'; import { CatalogResultListItem } from '@backstage/plugin-catalog'; +import { DocsResultListItem } from '@backstage/plugin-techdocs'; + import { SearchBar, SearchFilter, SearchResult, + SearchType, DefaultResultListItem, } from '@backstage/plugin-search'; import { Content, Header, Page } from '@backstage/core-components'; @@ -39,6 +42,11 @@ const SearchPage = () => { + { result={document} /> ); + case 'techdocs': + return ( + + ); default: return ( Date: Thu, 18 Nov 2021 12:39:48 +0100 Subject: [PATCH 21/61] add changeset Signed-off-by: Emma Indal --- .changeset/large-pears-agree.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/large-pears-agree.md diff --git a/.changeset/large-pears-agree.md b/.changeset/large-pears-agree.md new file mode 100644 index 0000000000..60f755eff0 --- /dev/null +++ b/.changeset/large-pears-agree.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +DefaultTechDocsCollator is now included in the search backend, and the Search Page updated with the SearchType component that includes the techdocs type From 860254207c7e85dcbc62486f60f018c4dcb42fbe Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Thu, 18 Nov 2021 14:45:06 +0100 Subject: [PATCH 22/61] prettier Signed-off-by: Emma Indal --- .../templates/default-app/packages/backend/src/plugins/search.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts index 5f8ac204ba..63e196235c 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts @@ -24,7 +24,6 @@ export default async function createPlugin({ collator: DefaultCatalogCollator.fromConfig(config, { discovery }), }); - // collator gathers entities from techdocs. indexBuilder.addCollator({ defaultRefreshIntervalSeconds: 600, From 4d09c602561c38501a3be0b8c7f0daf645db983a Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Thu, 18 Nov 2021 14:50:56 +0100 Subject: [PATCH 23/61] errors: rework error response naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Co-authored-by: Fredrik Adelöw Co-authored-by: blam Signed-off-by: Johan Haals --- .changeset/afraid-chairs-warn.md | 5 +++ packages/errors/api-report.md | 19 ++++++++--- packages/errors/src/errors/ResponseError.ts | 30 ++++++++++++----- packages/errors/src/serialization/index.ts | 4 +-- packages/errors/src/serialization/response.ts | 33 +++++++++++++++++-- 5 files changed, 73 insertions(+), 18 deletions(-) create mode 100644 .changeset/afraid-chairs-warn.md diff --git a/.changeset/afraid-chairs-warn.md b/.changeset/afraid-chairs-warn.md new file mode 100644 index 0000000000..d837744255 --- /dev/null +++ b/.changeset/afraid-chairs-warn.md @@ -0,0 +1,5 @@ +--- +'@backstage/errors': patch +--- + +Deprecate `parseErrorResponse` in favour of `parseErrorResponseBody`. Deprecate `data` field inside `ErrorResponse` in favour of `body`. diff --git a/packages/errors/api-report.md b/packages/errors/api-report.md index 4984919e6a..97b011bad6 100644 --- a/packages/errors/api-report.md +++ b/packages/errors/api-report.md @@ -33,8 +33,11 @@ export type ErrorLike = { [unknownKeys: string]: unknown; }; +// @public @deprecated +export type ErrorResponse = ErrorResponseBody; + // @public -export type ErrorResponse = { +export type ErrorResponseBody = { error: SerializedError; request?: { method: string; @@ -65,19 +68,27 @@ export class NotFoundError extends CustomErrorBase {} // @public export class NotModifiedError extends CustomErrorBase {} -// @public +// @public @deprecated export function parseErrorResponse(response: Response): Promise; +// @public +export function parseErrorResponseBody( + response: Response, +): Promise; + // @public export class ResponseError extends Error { + // @deprecated constructor(props: { message: string; response: Response; - data: ErrorResponse; + data: ErrorResponseBody; cause: Error; }); + readonly body: ErrorResponseBody; readonly cause: Error; - readonly data: ErrorResponse; + // @deprecated + get data(): ErrorResponseBody; static fromResponse(response: Response): Promise; readonly response: Response; } diff --git a/packages/errors/src/errors/ResponseError.ts b/packages/errors/src/errors/ResponseError.ts index f74ad2fa0c..a20035cd8c 100644 --- a/packages/errors/src/errors/ResponseError.ts +++ b/packages/errors/src/errors/ResponseError.ts @@ -14,16 +14,16 @@ * limitations under the License. */ +import { deserializeError } from '../serialization'; import { - parseErrorResponse, - ErrorResponse, - deserializeError, -} from '../serialization'; + ErrorResponseBody, + parseErrorResponseBody, +} from '../serialization/response'; /** * An error thrown as the result of a failed server request. * - * The server is expected to respond on the ErrorResponse format. + * The server is expected to respond on the ErrorResponseBody format. * * @public */ @@ -39,7 +39,7 @@ export class ResponseError extends Error { /** * The parsed JSON error body, as sent by the server. */ - readonly data: ErrorResponse; + readonly body: ErrorResponseBody; /** * The Error cause, as seen by the remote server. This is parsed out of the @@ -60,7 +60,7 @@ export class ResponseError extends Error { * been consumed before. */ static async fromResponse(response: Response): Promise { - const data = await parseErrorResponse(response); + const data = await parseErrorResponseBody(response); const status = data.response.statusCode || response.status; const statusText = data.error.name || response.statusText; @@ -75,16 +75,28 @@ export class ResponseError extends Error { }); } + /** + * @deprecated will be removed. + **/ constructor(props: { message: string; response: Response; - data: ErrorResponse; + data: ErrorResponseBody; cause: Error; }) { super(props.message); this.name = 'ResponseError'; this.response = props.response; - this.data = props.data; + this.body = props.data; this.cause = props.cause; } + /** + * The parsed JSON error body, as sent by the server. + * @deprecated use body instead. + */ + get data(): ErrorResponseBody { + // eslint-disable-next-line no-console + console.warn('ErrorResponse.data is deprecated, use .body instead.'); + return this.body; + } } diff --git a/packages/errors/src/serialization/index.ts b/packages/errors/src/serialization/index.ts index d37b04297a..b86661d496 100644 --- a/packages/errors/src/serialization/index.ts +++ b/packages/errors/src/serialization/index.ts @@ -16,5 +16,5 @@ export { deserializeError, serializeError, stringifyError } from './error'; export type { SerializedError } from './error'; -export { parseErrorResponse } from './response'; -export type { ErrorResponse } from './response'; +export { parseErrorResponse, parseErrorResponseBody } from './response'; +export type { ErrorResponse, ErrorResponseBody } from './response'; diff --git a/packages/errors/src/serialization/response.ts b/packages/errors/src/serialization/response.ts index 50bf8f7ab1..4a1731646d 100644 --- a/packages/errors/src/serialization/response.ts +++ b/packages/errors/src/serialization/response.ts @@ -20,8 +20,16 @@ import { SerializedError } from './error'; * A standard shape of JSON data returned as the body of backend errors. * * @public + * @deprecated - Use {@link ErrorResponseBody} instead. */ -export type ErrorResponse = { +export type ErrorResponse = ErrorResponseBody; + +/** + * A standard shape of JSON data returned as the body of backend errors. + * + * @public + */ +export type ErrorResponseBody = { /** Details of the error that was caught */ error: SerializedError; @@ -51,10 +59,29 @@ export type ErrorResponse = { * * @public * @param response - The response of a failed request + * @deprecated - Use {@link parseErrorResponseBody} instead. */ export async function parseErrorResponse( response: Response, ): Promise { + return parseErrorResponseBody(response); +} + +/** + * Attempts to construct an ErrorResponseBody out of a failed server request. + * Assumes that the response has already been checked to be not ok. This + * function consumes the body of the response, and assumes that it hasn't + * been consumed before. + * + * The code is forgiving, and constructs a useful synthetic body as best it can + * if the response body wasn't on the expected form. + * + * @public + * @param response - The response of a failed request + */ +export async function parseErrorResponseBody( + response: Response, +): Promise { try { const text = await response.text(); if (text) { @@ -73,7 +100,7 @@ export async function parseErrorResponse( return { error: { - name: 'Unknown', + name: 'Error', message: `Request failed with status ${response.status} ${response.statusText}, ${text}`, }, response: { @@ -87,7 +114,7 @@ export async function parseErrorResponse( return { error: { - name: 'Unknown', + name: 'Error', message: `Request failed with status ${response.status} ${response.statusText}`, }, response: { From 4d97ec07fa44540ea3a99f4e5ec73c279ad73626 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Thu, 18 Nov 2021 14:56:32 +0100 Subject: [PATCH 24/61] Update tests Signed-off-by: Johan Haals --- .changeset/afraid-chairs-warn.md | 1 + .../errors/src/serialization/response.test.ts | 62 ++++++++++--------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/.changeset/afraid-chairs-warn.md b/.changeset/afraid-chairs-warn.md index d837744255..1ae2a7513e 100644 --- a/.changeset/afraid-chairs-warn.md +++ b/.changeset/afraid-chairs-warn.md @@ -3,3 +3,4 @@ --- Deprecate `parseErrorResponse` in favour of `parseErrorResponseBody`. Deprecate `data` field inside `ErrorResponse` in favour of `body`. +Rename the error name for unknown errors from `unknown` to `error`. diff --git a/packages/errors/src/serialization/response.test.ts b/packages/errors/src/serialization/response.test.ts index 54a3641657..fe1cc1e9c4 100644 --- a/packages/errors/src/serialization/response.test.ts +++ b/packages/errors/src/serialization/response.test.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import { parseErrorResponse, ErrorResponse } from './response'; +import { parseErrorResponseBody, ErrorResponseBody } from './response'; -describe('parseErrorResponse', () => { +describe('parseErrorResponseBody', () => { it('handles the happy path', async () => { - const body: ErrorResponse = { + const body: ErrorResponseBody = { error: { name: 'Fours', message: 'Expected fives', stack: 'lines' }, request: { method: 'GET', url: '/' }, response: { statusCode: 444 }, @@ -31,13 +31,13 @@ describe('parseErrorResponse', () => { headers: new Headers({ 'Content-Type': 'application/json' }), }; - await expect(parseErrorResponse(response as Response)).resolves.toEqual( + await expect(parseErrorResponseBody(response as Response)).resolves.toEqual( body, ); }); it('uses request header and text body when wrong content type, even if parsable', async () => { - const body: ErrorResponse = { + const body: ErrorResponseBody = { error: { name: 'Threes', message: 'Expected twos' }, request: { method: 'GET', url: '/' }, response: { statusCode: 333 }, @@ -50,19 +50,21 @@ describe('parseErrorResponse', () => { headers: new Headers({ 'Content-Type': 'not-application/not-json' }), }; - await expect(parseErrorResponse(response as Response)).resolves.toEqual({ - error: { - name: 'Unknown', - message: `Request failed with status 444 Fours, ${JSON.stringify( - body, - )}`, + await expect(parseErrorResponseBody(response as Response)).resolves.toEqual( + { + error: { + name: 'Error', + message: `Request failed with status 444 Fours, ${JSON.stringify( + body, + )}`, + }, + response: { statusCode: 444 }, }, - response: { statusCode: 444 }, - }); + ); }); it('uses request header and text body when not parsable', async () => { - const body: ErrorResponse = { + const body: ErrorResponseBody = { error: { name: 'Threes', message: 'Expected twos' }, request: { method: 'GET', url: '/' }, response: { statusCode: 333 }, @@ -75,15 +77,17 @@ describe('parseErrorResponse', () => { headers: new Headers({ 'Content-Type': 'application/json' }), }; - await expect(parseErrorResponse(response as Response)).resolves.toEqual({ - error: { - name: 'Unknown', - message: `Request failed with status 444 Fours, ${JSON.stringify( - body, - ).substring(1)}`, + await expect(parseErrorResponseBody(response as Response)).resolves.toEqual( + { + error: { + name: 'Error', + message: `Request failed with status 444 Fours, ${JSON.stringify( + body, + ).substring(1)}`, + }, + response: { statusCode: 444 }, }, - response: { statusCode: 444 }, - }); + ); }); it('uses request header when failing to get body', async () => { @@ -96,12 +100,14 @@ describe('parseErrorResponse', () => { headers: new Headers({ 'Content-Type': 'application/json' }), }; - await expect(parseErrorResponse(response as Response)).resolves.toEqual({ - error: { - name: 'Unknown', - message: `Request failed with status 444 Fours`, + await expect(parseErrorResponseBody(response as Response)).resolves.toEqual( + { + error: { + name: 'Error', + message: `Request failed with status 444 Fours`, + }, + response: { statusCode: 444 }, }, - response: { statusCode: 444 }, - }); + ); }); }); From b23bc7f9c3437ff95641292e323950ae36c80ae2 Mon Sep 17 00:00:00 2001 From: Otto Sichert Date: Tue, 16 Nov 2021 14:58:56 +0100 Subject: [PATCH 25/61] Change default port of backend to 7007 due to MacOS Control Center update Signed-off-by: Otto Sichert --- .tugboat/config.yml | 4 ++-- app-config.yaml | 4 ++-- .../files/app-config.development.yaml.tpl | 2 +- contrib/chart/backstage/values.yaml | 4 ++-- contrib/docker/devops/makefile | 10 +++++----- .../backend.yaml | 2 +- .../backstage/values.yaml | 2 +- .../service.yaml | 2 +- cypress/cypress.json | 2 +- docs/auth/add-auth-provider.md | 2 +- docs/auth/atlassian/provider.md | 2 +- docs/auth/auth0/provider.md | 2 +- docs/auth/bitbucket/provider.md | 2 +- docs/auth/github/provider.md | 2 +- docs/auth/gitlab/provider.md | 2 +- docs/auth/google/provider.md | 2 +- docs/auth/microsoft/provider.md | 2 +- docs/auth/okta/provider.md | 4 ++-- docs/auth/onelogin/provider.md | 2 +- docs/conf/writing.md | 4 ++-- docs/deployment/docker.md | 8 ++++---- docs/deployment/k8s.md | 14 +++++++------- docs/features/techdocs/configuration.md | 4 ++-- docs/getting-started/contributors.md | 2 +- docs/getting-started/index.md | 2 +- .../getting-started/running-backstage-locally.md | 2 +- docs/openapi/definitions/auth.yaml | 2 +- docs/plugins/backend-plugin.md | 6 +++--- .../integration/components/search/SearchPage.js | 2 +- packages/app/src/App.test.tsx | 6 +++--- .../src/discovery/SingleHostDiscovery.ts | 2 +- .../src/service/lib/ServiceBuilderImpl.ts | 2 +- .../backend-common/src/service/lib/config.ts | 4 ++-- packages/backend-common/src/service/types.ts | 2 +- packages/backend/README.md | 2 +- .../default-backend-plugin/src/run.ts.hbs | 2 +- .../DiscoveryApi/UrlPatternDiscovery.test.ts | 4 ++-- .../DiscoveryApi/UrlPatternDiscovery.ts | 2 +- packages/create-app/CHANGELOG.md | 14 +++++++------- .../default-app/app-config.production.yaml | 6 +++--- .../templates/default-app/app-config.yaml.hbs | 4 ++-- .../default-app/packages/app/src/App.test.tsx | 4 ++-- .../default-app/packages/backend/README.md | 2 +- packages/e2e-test/src/commands/run.ts | 2 +- packages/storybook/.storybook/apis.js | 12 ++++++------ packages/techdocs-common/CHANGELOG.md | 2 +- .../src/stages/publish/awsS3.test.ts | 2 +- .../src/stages/publish/azureBlobStorage.test.ts | 2 +- .../src/stages/publish/googleStorage.test.ts | 2 +- .../src/stages/publish/local.test.ts | 2 +- .../src/stages/publish/openStackSwift.test.ts | 4 ++-- .../src/stages/publish/publish.test.ts | 16 ++++++++-------- plugins/auth-backend/README.md | 12 ++++++------ plugins/auth-backend/scripts/start-saml-idp.sh | 2 +- plugins/azure-devops-backend/README.md | 2 +- plugins/azure-devops-backend/src/run.ts | 2 +- plugins/badges-backend/src/run.ts | 2 +- .../badges-backend/src/service/router.test.ts | 2 +- plugins/bazaar-backend/src/run.ts | 2 +- plugins/catalog-backend/src/run.ts | 2 +- .../src/search/DefaultCatalogCollator.test.ts | 4 ++-- plugins/code-coverage-backend/README.md | 12 ++++++------ plugins/code-coverage-backend/src/run.ts | 2 +- .../src/service/router.test.ts | 2 +- plugins/github-actions/README.md | 2 +- plugins/jenkins-backend/src/run.ts | 2 +- plugins/proxy-backend/src/run.ts | 2 +- plugins/proxy-backend/src/service/router.test.ts | 4 ++-- plugins/rollbar-backend/src/run.ts | 2 +- plugins/search-backend/src/run.ts | 2 +- plugins/techdocs-backend/config.d.ts | 4 ++-- plugins/techdocs/config.d.ts | 2 +- scripts/migrate-location-types.js | 8 ++++---- 73 files changed, 137 insertions(+), 137 deletions(-) diff --git a/.tugboat/config.yml b/.tugboat/config.yml index b8c3c127c8..883708bef7 100644 --- a/.tugboat/config.yml +++ b/.tugboat/config.yml @@ -1,7 +1,7 @@ services: backstage: image: tugboatqa/node:lts - expose: 7000 + expose: 7007 default: true commands: init: @@ -14,4 +14,4 @@ services: - yarn workspace example-app build start: # wget the endpoint. Will retry every 2 seconds. 30 retries = 1m for service to come up. Plenty. - - wget -O /dev/null -o /dev/null --tries=30 --timeout=5 --retry-connrefused http://localhost:7000 + - wget -O /dev/null -o /dev/null --tries=30 --timeout=5 --retry-connrefused http://localhost:7007 diff --git a/app-config.yaml b/app-config.yaml index 8aa3bc569c..50ddb7ce89 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -23,9 +23,9 @@ app: title: '#backstage' backend: - baseUrl: http://localhost:7000 + baseUrl: http://localhost:7007 listen: - port: 7000 + port: 7007 database: client: sqlite3 connection: ':memory:' diff --git a/contrib/chart/backstage/files/app-config.development.yaml.tpl b/contrib/chart/backstage/files/app-config.development.yaml.tpl index 6d3ded16c1..105ba3b259 100644 --- a/contrib/chart/backstage/files/app-config.development.yaml.tpl +++ b/contrib/chart/backstage/files/app-config.development.yaml.tpl @@ -1,7 +1,7 @@ backend: lighthouseHostname: {{ include "lighthouse.serviceName" . | quote }} listen: - port: {{ .Values.appConfig.backend.listen.port | default 7000 }} + port: {{ .Values.appConfig.backend.listen.port | default 7007 }} database: client: {{ .Values.appConfig.backend.database.client | quote }} connection: diff --git a/contrib/chart/backstage/values.yaml b/contrib/chart/backstage/values.yaml index 9f70dac6dc..6ffe076e57 100644 --- a/contrib/chart/backstage/values.yaml +++ b/contrib/chart/backstage/values.yaml @@ -26,7 +26,7 @@ backend: repository: martinaif/backstage-k8s-demo-backend tag: 20210423T1550 pullPolicy: IfNotPresent - containerPort: 7000 + containerPort: 7007 serviceType: ClusterIP postgresCertMountEnabled: true resources: @@ -96,7 +96,7 @@ appConfig: backend: baseUrl: https://demo.example.com listen: - port: 7000 + port: 7007 cors: origin: https://demo.example.com database: diff --git a/contrib/docker/devops/makefile b/contrib/docker/devops/makefile index 3ae89a161b..048edc8886 100644 --- a/contrib/docker/devops/makefile +++ b/contrib/docker/devops/makefile @@ -9,8 +9,8 @@ docker_name_prefix := backstage-make # to the host computer frontend_port := 3000 frontend_host_port := 3000 -backend_port := 7000 -backend_host_port := 7000 +backend_port := 7007 +backend_host_port := 7007 # path to this "makefile" my_dir_path = $(dir $(CURDIR)/$(firstword $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) @@ -191,10 +191,10 @@ test: check-tests check: check-code check-docs check-type-dependencies check-styles # run development instance -# BUG: the frontend seems to run on "$(backend_port)" (7000 default). +# BUG: the frontend seems to run on "$(backend_port)" (7007 default). # The documentation states "This is going to start two things, -# the frontend (:3000) and the backend (:7000)." -# However, the frontend seems to end up running on 7000. +# the frontend (:3000) and the backend (:7007)." +# However, the frontend seems to end up running on 7007. .PHONY: dev dev: build @docker run --rm -it \ diff --git a/contrib/kubernetes/basic_kubernetes_example_with_helm/backend.yaml b/contrib/kubernetes/basic_kubernetes_example_with_helm/backend.yaml index f0695753fd..c8d60a9c1b 100644 --- a/contrib/kubernetes/basic_kubernetes_example_with_helm/backend.yaml +++ b/contrib/kubernetes/basic_kubernetes_example_with_helm/backend.yaml @@ -22,6 +22,6 @@ spec: image: spotify/backstage-backend:latest imagePullPolicy: IfNotPresent ports: - - containerPort: 7000 + - containerPort: 7007 name: backend protocol: TCP diff --git a/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/values.yaml b/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/values.yaml index d91808ed28..a293dc12fb 100644 --- a/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/values.yaml +++ b/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/values.yaml @@ -63,7 +63,7 @@ backend: pullPolicy: IfNotPresent service: type: ClusterIP - port: 7000 + port: 7007 ingress: enabled: false annotations: diff --git a/contrib/kubernetes/basic_kubernetes_example_with_helm/service.yaml b/contrib/kubernetes/basic_kubernetes_example_with_helm/service.yaml index 4d947b7afc..e1da35b598 100644 --- a/contrib/kubernetes/basic_kubernetes_example_with_helm/service.yaml +++ b/contrib/kubernetes/basic_kubernetes_example_with_helm/service.yaml @@ -30,6 +30,6 @@ spec: component: backend ports: - name: backend - port: 7000 + port: 7007 protocol: TCP targetPort: backend diff --git a/cypress/cypress.json b/cypress/cypress.json index 3ef3df8e65..7335d0f62a 100644 --- a/cypress/cypress.json +++ b/cypress/cypress.json @@ -1,5 +1,5 @@ { - "baseUrl": "http://localhost:7000", + "baseUrl": "http://localhost:7007", "integrationFolder": "./src/integration", "supportFile": "./src/support", "fixturesFolder": "./src/fixtures", diff --git a/docs/auth/add-auth-provider.md b/docs/auth/add-auth-provider.md index 472a6a0abc..07d6869fe3 100644 --- a/docs/auth/add-auth-provider.md +++ b/docs/auth/add-auth-provider.md @@ -229,7 +229,7 @@ name. ### Test the new provider -You can `curl -i localhost:7000/api/auth/providerA/start` and which should +You can `curl -i localhost:7007/api/auth/providerA/start` and which should provide a `302` redirect with a `Location` header. Paste the url from that header into a web browser and you should be able to trigger the authorization flow. diff --git a/docs/auth/atlassian/provider.md b/docs/auth/atlassian/provider.md index 38774ca3cc..cded6e73ca 100644 --- a/docs/auth/atlassian/provider.md +++ b/docs/auth/atlassian/provider.md @@ -28,7 +28,7 @@ Name your integration and click on the `Create` button. Settings for local development: -- Callback URL: `http://localhost:7000/api/auth/atlassian` +- Callback URL: `http://localhost:7007/api/auth/atlassian` - Use rotating refresh tokens - For permissions, you **must** enable `View user profile` for the currently logged-in user, under `User identity API` diff --git a/docs/auth/auth0/provider.md b/docs/auth/auth0/provider.md index 05553c3fd3..80106a73c9 100644 --- a/docs/auth/auth0/provider.md +++ b/docs/auth/auth0/provider.md @@ -17,7 +17,7 @@ provider that can authenticate users using OAuth. - Application type: Single Page Web Application 4. Click on the Settings tab 5. Add under `Application URIs` > `Allowed Callback URLs`: - `http://localhost:7000/api/auth/auth0/handler/frame` + `http://localhost:7007/api/auth/auth0/handler/frame` 6. Click `Save Changes` ## Configuration diff --git a/docs/auth/bitbucket/provider.md b/docs/auth/bitbucket/provider.md index ae09d5dbee..63dfb815e0 100644 --- a/docs/auth/bitbucket/provider.md +++ b/docs/auth/bitbucket/provider.md @@ -20,7 +20,7 @@ Click Add Consumer. Settings for local development: - Application name: Backstage (or your custom app name) -- Callback URL: `http://localhost:7000/api/auth/bitbucket` +- Callback URL: `http://localhost:7007/api/auth/bitbucket` - Other are optional - (IMPORTANT) **Permissions: Account - Read, Workspace membership - Read** diff --git a/docs/auth/github/provider.md b/docs/auth/github/provider.md index d8803e392d..14b99bfea5 100644 --- a/docs/auth/github/provider.md +++ b/docs/auth/github/provider.md @@ -24,7 +24,7 @@ Settings for local development: - Application name: Backstage (or your custom app name) - Homepage URL: `http://localhost:3000` -- Authorization callback URL: `http://localhost:7000/api/auth/github` +- Authorization callback URL: `http://localhost:7007/api/auth/github` ## Configuration diff --git a/docs/auth/gitlab/provider.md b/docs/auth/gitlab/provider.md index fd64ddac14..90939a1f03 100644 --- a/docs/auth/gitlab/provider.md +++ b/docs/auth/gitlab/provider.md @@ -17,7 +17,7 @@ should point to your Backstage backend auth handler. Settings for local development: - Name: Backstage (or your custom app name) -- Redirect URI: `http://localhost:7000/api/auth/gitlab/handler/frame` +- Redirect URI: `http://localhost:7007/api/auth/gitlab/handler/frame` - Scopes: read_user ## Configuration diff --git a/docs/auth/google/provider.md b/docs/auth/google/provider.md index 6216b21704..d3cd8f2dd2 100644 --- a/docs/auth/google/provider.md +++ b/docs/auth/google/provider.md @@ -26,7 +26,7 @@ To support Google authentication, you must create OAuth credentials: - `Name`: Backstage (or your custom app name) - `Authorized JavaScript origins`: http://localhost:3000 - `Authorized Redirect URIs`: - http://localhost:7000/api/auth/google/handler/frame + http://localhost:7007/api/auth/google/handler/frame 7. Click Create ## Configuration diff --git a/docs/auth/microsoft/provider.md b/docs/auth/microsoft/provider.md index 1b81ff76f1..1e24235f1a 100644 --- a/docs/auth/microsoft/provider.md +++ b/docs/auth/microsoft/provider.md @@ -21,7 +21,7 @@ To support Azure authentication, you must create an App Registration: 4. Register an application - Name: Backstage (or your custom app name) - Redirect URI: Web > - `http://localhost:7000/api/auth/microsoft/handler/frame` + `http://localhost:7007/api/auth/microsoft/handler/frame` 5. Navigate to **Certificates & secrets > New client secret** to create a secret ## Configuration diff --git a/docs/auth/okta/provider.md b/docs/auth/okta/provider.md index b5aaabe4f1..35394094f8 100644 --- a/docs/auth/okta/provider.md +++ b/docs/auth/okta/provider.md @@ -22,8 +22,8 @@ To add Okta authentication, you must create an Application from Okta: - `App integration name`: `Backstage` (or your custom app name) - `Grant type`: `Authorization Code` & `Refresh Token` - `Sign-in redirect URIs`: - `http://localhost:7000/api/auth/okta/handler/frame` - - `Sign-out redirect URIs`: `http://localhost:7000` + `http://localhost:7007/api/auth/okta/handler/frame` + - `Sign-out redirect URIs`: `http://localhost:7007` - `Controlled access`: (select as appropriate) - Click Save diff --git a/docs/auth/onelogin/provider.md b/docs/auth/onelogin/provider.md index a11304ae84..c3572367d2 100644 --- a/docs/auth/onelogin/provider.md +++ b/docs/auth/onelogin/provider.md @@ -18,7 +18,7 @@ To support OneLogin authentication, you must create an Application: 3. Click Save 4. Go to the Configuration tab for the Application and set: - `Login Url`: `http://localhost:3000` - - `Redirect URIs`: `http://localhost:7000/api/auth/onelogin/handler/frame` + - `Redirect URIs`: `http://localhost:7007/api/auth/onelogin/handler/frame` 5. Click Save 6. Go to the SSO tab for the Application and set: - `Token Endpoint` > `Authentication Method`: `POST` diff --git a/docs/conf/writing.md b/docs/conf/writing.md index a0e29820ed..7945d6c980 100644 --- a/docs/conf/writing.md +++ b/docs/conf/writing.md @@ -16,8 +16,8 @@ app: baseUrl: http://localhost:3000 backend: - listen: 0.0.0.0:7000 - baseUrl: http://localhost:7000 + listen: 0.0.0.0:7007 + baseUrl: http://localhost:7007 organization: name: CNCF diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md index 7230f5cf16..7cbd3cea89 100644 --- a/docs/deployment/docker.md +++ b/docs/deployment/docker.md @@ -105,11 +105,11 @@ docker image build . -f packages/backend/Dockerfile --tag backstage To try out the image locally you can run the following: ```sh -docker run -it -p 7000:7000 backstage +docker run -it -p 7007:7007 backstage ``` You should then start to get logs in your terminal, and then you can open your -browser at `http://localhost:7000` +browser at `http://localhost:7007` ## Multi-stage Build @@ -208,11 +208,11 @@ docker image build -t backstage . To try out the image locally you can run the following: ```sh -docker run -it -p 7000:7000 backstage +docker run -it -p 7007:7007 backstage ``` You should then start to get logs in your terminal, and then you can open your -browser at `http://localhost:7000` +browser at `http://localhost:7007` ## Separate Frontend diff --git a/docs/deployment/k8s.md b/docs/deployment/k8s.md index 2c52e0e308..a80ba1816e 100644 --- a/docs/deployment/k8s.md +++ b/docs/deployment/k8s.md @@ -351,7 +351,7 @@ spec: imagePullPolicy: IfNotPresent ports: - name: http - containerPort: 7000 + containerPort: 7007 envFrom: - secretRef: name: postgres-secrets @@ -361,11 +361,11 @@ spec: # https://backstage.io/docs/plugins/observability#health-checks # readinessProbe: # httpGet: -# port: 7000 +# port: 7007 # path: /healthcheck # livenessProbe: # httpGet: -# port: 7000 +# port: 7007 # path: /healthcheck ``` @@ -449,7 +449,7 @@ spec: ``` The `selector` here is telling the Service which pods to target, and the port -mapping translates normal HTTP port 80 to the backend http port (7000) on the +mapping translates normal HTTP port 80 to the backend http port (7007) on the pod. Apply this Service to the Kubernetes cluster: @@ -464,10 +464,10 @@ reveal**_, you can forward a local port to the service: ```shell $ sudo kubectl port-forward --namespace=backstage svc/backstage 80:80 -Forwarding from 127.0.0.1:80 -> 7000 +Forwarding from 127.0.0.1:80 -> 7007 ``` -This shows port 7000 since `port-forward` doesn't _really_ support services, so +This shows port 7007 since `port-forward` doesn't _really_ support services, so it cheats by looking up the first pod for a service and connecting to the mapped pod port. @@ -486,7 +486,7 @@ organization: backend: baseUrl: http://localhost listen: - port: 7000 + port: 7007 cors: origin: http://localhost ``` diff --git a/docs/features/techdocs/configuration.md b/docs/features/techdocs/configuration.md index 61d95f55c0..4148749a62 100644 --- a/docs/features/techdocs/configuration.md +++ b/docs/features/techdocs/configuration.md @@ -138,11 +138,11 @@ techdocs: # (Optional and Legacy) TechDocs makes API calls to techdocs-backend using this URL. e.g. get docs of an entity, get metadata, etc. # You don't have to specify this anymore. - requestUrl: http://localhost:7000/api/techdocs + requestUrl: http://localhost:7007/api/techdocs # (Optional and Legacy) Just another route in techdocs-backend where TechDocs requests the static files from. This URL uses an HTTP middleware # to serve files from either a local directory or an External storage provider. # You don't have to specify this anymore. - storageUrl: http://localhost:7000/api/techdocs/static/docs + storageUrl: http://localhost:7007/api/techdocs/static/docs ``` diff --git a/docs/getting-started/contributors.md b/docs/getting-started/contributors.md index 28b062b5ca..9154eae4d1 100644 --- a/docs/getting-started/contributors.md +++ b/docs/getting-started/contributors.md @@ -43,7 +43,7 @@ the project root. Make sure you have run the above mentioned commands first. $ yarn dev ``` -This is going to start two things, the frontend (:3000) and the backend (:7000). +This is going to start two things, the frontend (:3000) and the backend (:7007). This should open a local instance of Backstage in your browser, otherwise open one of the URLs printed in the terminal. diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 9632be71bf..5a970ef143 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -37,7 +37,7 @@ guide to do a repository-based installation. - `docker` [installation](https://docs.docker.com/engine/install/) - `git` [installation](https://github.com/git-guides/install-git) - If the system is not directly accessible over your network, the following - ports need to be opened: 3000, 7000 + ports need to be opened: 3000, 7007 ### Create your Backstage App diff --git a/docs/getting-started/running-backstage-locally.md b/docs/getting-started/running-backstage-locally.md index 873c26a099..daad7bf195 100644 --- a/docs/getting-started/running-backstage-locally.md +++ b/docs/getting-started/running-backstage-locally.md @@ -70,7 +70,7 @@ cd packages/backend yarn start ``` -That starts up a backend instance on port 7000. +That starts up a backend instance on port 7007. In the other window, we will then launch the frontend. This command is run from the project root, not inside the backend directory. diff --git a/docs/openapi/definitions/auth.yaml b/docs/openapi/definitions/auth.yaml index 411ce69253..032d89523d 100644 --- a/docs/openapi/definitions/auth.yaml +++ b/docs/openapi/definitions/auth.yaml @@ -21,7 +21,7 @@ externalDocs: description: Backstage official documentation url: https://github.com/backstage/backstage/blob/master/docs/README.md servers: - - url: http://localhost:7000/api/auth/ + - url: http://localhost:7007/api/auth/ tags: - name: provider description: List of endpoints per provider diff --git a/docs/plugins/backend-plugin.md b/docs/plugins/backend-plugin.md index 1d728b76aa..5ff0e5a62f 100644 --- a/docs/plugins/backend-plugin.md +++ b/docs/plugins/backend-plugin.md @@ -44,11 +44,11 @@ cd plugins/carmen-backend yarn start ``` -This will think for a bit, and then say `Listening on :7000`. In a different +This will think for a bit, and then say `Listening on :7007`. In a different terminal window, now run ```sh -curl localhost:7000/carmen/health +curl localhost:7007/carmen/health ``` This should return `{"status":"ok"}`. Success! Press `Ctrl + c` to kill it @@ -107,7 +107,7 @@ root), you should be able to fetch data from it. ```sh # Note the extra /api here -curl localhost:7000/api/carmen/health +curl localhost:7007/api/carmen/health ``` This should return `{"status":"ok"}` like before. Success! diff --git a/packages/app/cypress/integration/components/search/SearchPage.js b/packages/app/cypress/integration/components/search/SearchPage.js index 6a18d16198..11f31cfed3 100644 --- a/packages/app/cypress/integration/components/search/SearchPage.js +++ b/packages/app/cypress/integration/components/search/SearchPage.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const API_ENDPOINT = 'http://localhost:7000/api/search/query'; +const API_ENDPOINT = 'http://localhost:7007/api/search/query'; describe('SearchPage', () => { describe('Given a search context with a term, results, and filter values', () => { diff --git a/packages/app/src/App.test.tsx b/packages/app/src/App.test.tsx index aa6781ce61..8c7cefeb2c 100644 --- a/packages/app/src/App.test.tsx +++ b/packages/app/src/App.test.tsx @@ -27,14 +27,14 @@ describe('App', () => { data: { app: { title: 'Test', - support: { url: 'http://localhost:7000/support' }, + support: { url: 'http://localhost:7007/support' }, }, - backend: { baseUrl: 'http://localhost:7000' }, + backend: { baseUrl: 'http://localhost:7007' }, lighthouse: { baseUrl: 'http://localhost:3003', }, techdocs: { - storageUrl: 'http://localhost:7000/api/techdocs/static/docs', + storageUrl: 'http://localhost:7007/api/techdocs/static/docs', }, }, context: 'test', diff --git a/packages/backend-common/src/discovery/SingleHostDiscovery.ts b/packages/backend-common/src/discovery/SingleHostDiscovery.ts index c1e092706b..2f1e44b293 100644 --- a/packages/backend-common/src/discovery/SingleHostDiscovery.ts +++ b/packages/backend-common/src/discovery/SingleHostDiscovery.ts @@ -37,7 +37,7 @@ export class SingleHostDiscovery implements PluginEndpointDiscovery { * for the internal one. * * The basePath defaults to `/api`, meaning the default full internal - * path for the `catalog` plugin will be `http://localhost:7000/api/catalog`. + * path for the `catalog` plugin will be `http://localhost:7007/api/catalog`. */ static fromConfig(config: Config, options?: { basePath?: string }) { const basePath = options?.basePath ?? '/api'; diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index 885baba54b..b085cccfd6 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -40,7 +40,7 @@ import { } from './config'; import { createHttpServer, createHttpsServer } from './hostFactory'; -export const DEFAULT_PORT = 7000; +export const DEFAULT_PORT = 7007; // '' is express default, which listens to all interfaces const DEFAULT_HOST = ''; // taken from the helmet source code - don't seem to be exported diff --git a/packages/backend-common/src/service/lib/config.ts b/packages/backend-common/src/service/lib/config.ts index 57b814da63..d69b00f04c 100644 --- a/packages/backend-common/src/service/lib/config.ts +++ b/packages/backend-common/src/service/lib/config.ts @@ -63,8 +63,8 @@ type CustomOrigin = ( * @example * ```json * { - * baseUrl: "http://localhost:7000", - * listen: "0.0.0.0:7000" + * baseUrl: "http://localhost:7007", + * listen: "0.0.0.0:7007" * } * ``` */ diff --git a/packages/backend-common/src/service/types.ts b/packages/backend-common/src/service/types.ts index 3765cbcfdd..2ad379f31e 100644 --- a/packages/backend-common/src/service/types.ts +++ b/packages/backend-common/src/service/types.ts @@ -34,7 +34,7 @@ export type ServiceBuilder = { * * If no port is specified, the service will first look for an environment * variable named PORT and use that if present, otherwise it picks a default - * port (7000). + * port (7007). * * @param port - The port to listen on */ diff --git a/packages/backend/README.md b/packages/backend/README.md index e6f0c899ca..c2145705e0 100644 --- a/packages/backend/README.md +++ b/packages/backend/README.md @@ -37,7 +37,7 @@ Substitute `x` for actual values, or leave them as dummy values just to try out the backend without using the auth or sentry features. You can also, instead of using dummy values for a huge number of environment variables, remove those config directly from app-config.yaml file located in the root folder. -The backend starts up on port 7000 per default. +The backend starts up on port 7007 per default. ### Debugging diff --git a/packages/cli/templates/default-backend-plugin/src/run.ts.hbs b/packages/cli/templates/default-backend-plugin/src/run.ts.hbs index 54d2716290..0a3ed2b7f0 100644 --- a/packages/cli/templates/default-backend-plugin/src/run.ts.hbs +++ b/packages/cli/templates/default-backend-plugin/src/run.ts.hbs @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.test.ts b/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.test.ts index 7fcbde97df..5e404a35d7 100644 --- a/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.test.ts +++ b/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.test.ts @@ -26,10 +26,10 @@ describe('UrlPatternDiscovery', () => { it('should use a plain pattern', async () => { const discoveryApi = UrlPatternDiscovery.compile( - 'http://localhost:7000/{{ pluginId }}', + 'http://localhost:7007/{{ pluginId }}', ); await expect(discoveryApi.getBaseUrl('my-plugin')).resolves.toBe( - 'http://localhost:7000/my-plugin', + 'http://localhost:7007/my-plugin', ); }); diff --git a/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.ts b/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.ts index aa921c2595..cba8344977 100644 --- a/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.ts +++ b/packages/core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.ts @@ -30,7 +30,7 @@ export class UrlPatternDiscovery implements DiscoveryApi { * interpolation done for the template is to replace instances of `{{pluginId}}` * with the ID of the plugin being requested. * - * Example pattern: `http://localhost:7000/api/{{ pluginId }}` + * Example pattern: `http://localhost:7007/api/{{ pluginId }}` */ static compile(pattern: string): UrlPatternDiscovery { const parts = pattern.split(/\{\{\s*pluginId\s*\}\}/); diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index af1fd58ead..6ca70f1223 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1149,9 +1149,9 @@ // app-config.yaml backend: - baseUrl: http://localhost:7000 + baseUrl: http://localhost:7007 listen: - port: 7000 + port: 7007 database: client: sqlite3 connection: ':memory:' @@ -2238,9 +2238,9 @@ For more information and the background to this change, see the [composability s { data: { app: { title: 'Test' }, - backend: { baseUrl: 'http://localhost:7000' }, + backend: { baseUrl: 'http://localhost:7007' }, techdocs: { - storageUrl: 'http://localhost:7000/api/techdocs/static/docs', + storageUrl: 'http://localhost:7007/api/techdocs/static/docs', }, }, context: 'test', @@ -3444,12 +3444,12 @@ For more information and the background to this change, see the [composability s ```yaml app: # Should be the same as backend.baseUrl when using the `app-backend` plugin - baseUrl: http://localhost:7000 + baseUrl: http://localhost:7007 backend: - baseUrl: http://localhost:7000 + baseUrl: http://localhost:7007 listen: - port: 7000 + port: 7007 ``` In order to load in the new configuration at runtime, the command in the `Dockerfile` at the repo root was changed to the following: diff --git a/packages/create-app/templates/default-app/app-config.production.yaml b/packages/create-app/templates/default-app/app-config.production.yaml index 92f4574fd1..5e36c2319f 100644 --- a/packages/create-app/templates/default-app/app-config.production.yaml +++ b/packages/create-app/templates/default-app/app-config.production.yaml @@ -1,8 +1,8 @@ app: # Should be the same as backend.baseUrl when using the `app-backend` plugin - baseUrl: http://localhost:7000 + baseUrl: http://localhost:7007 backend: - baseUrl: http://localhost:7000 + baseUrl: http://localhost:7007 listen: - port: 7000 + port: 7007 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 9c35c58c33..55e2a80c27 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -6,9 +6,9 @@ organization: name: My Company backend: - baseUrl: http://localhost:7000 + baseUrl: http://localhost:7007 listen: - port: 7000 + port: 7007 csp: connect-src: ["'self'", 'http:', 'https:'] # Content-Security-Policy directives follow the Helmet format: https://helmetjs.github.io/#reference diff --git a/packages/create-app/templates/default-app/packages/app/src/App.test.tsx b/packages/create-app/templates/default-app/packages/app/src/App.test.tsx index 82bc479858..b94cac73b3 100644 --- a/packages/create-app/templates/default-app/packages/app/src/App.test.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/App.test.tsx @@ -10,9 +10,9 @@ describe('App', () => { { data: { app: { title: 'Test' }, - backend: { baseUrl: 'http://localhost:7000' }, + backend: { baseUrl: 'http://localhost:7007' }, techdocs: { - storageUrl: 'http://localhost:7000/api/techdocs/static/docs', + storageUrl: 'http://localhost:7007/api/techdocs/static/docs', }, }, context: 'test', diff --git a/packages/create-app/templates/default-app/packages/backend/README.md b/packages/create-app/templates/default-app/packages/backend/README.md index 81e0f80535..02426ef9b3 100644 --- a/packages/create-app/templates/default-app/packages/backend/README.md +++ b/packages/create-app/templates/default-app/packages/backend/README.md @@ -36,7 +36,7 @@ yarn start Substitute `x` for actual values, or leave them as dummy values just to try out the backend without using the auth or sentry features. -The backend starts up on port 7000 per default. +The backend starts up on port 7007 per default. ## Populating The Catalog diff --git a/packages/e2e-test/src/commands/run.ts b/packages/e2e-test/src/commands/run.ts index e1d8473121..a7456f91dd 100644 --- a/packages/e2e-test/src/commands/run.ts +++ b/packages/e2e-test/src/commands/run.ts @@ -471,7 +471,7 @@ async function testBackendStart(appDir: string, isPostgres: boolean) { print('Try to fetch entities from the backend'); // Try fetch entities, should be ok - await fetch('http://localhost:7000/api/catalog/entities').then(res => + await fetch('http://localhost:7007/api/catalog/entities').then(res => res.json(), ); print('Entities fetched successfully'); diff --git a/packages/storybook/.storybook/apis.js b/packages/storybook/.storybook/apis.js index 41b8433594..3b7f6119ef 100644 --- a/packages/storybook/.storybook/apis.js +++ b/packages/storybook/.storybook/apis.js @@ -50,7 +50,7 @@ const oauthRequestApi = builder.add( builder.add( googleAuthApiRef, GoogleAuth.create({ - apiOrigin: 'http://localhost:7000', + apiOrigin: 'http://localhost:7007', basePath: '/auth/', oauthRequestApi, }), @@ -59,7 +59,7 @@ builder.add( builder.add( githubAuthApiRef, GithubAuth.create({ - apiOrigin: 'http://localhost:7000', + apiOrigin: 'http://localhost:7007', basePath: '/auth/', oauthRequestApi, }), @@ -68,7 +68,7 @@ builder.add( builder.add( gitlabAuthApiRef, GitlabAuth.create({ - apiOrigin: 'http://localhost:7000', + apiOrigin: 'http://localhost:7007', basePath: '/auth/', oauthRequestApi, }), @@ -77,7 +77,7 @@ builder.add( builder.add( oktaAuthApiRef, OktaAuth.create({ - apiOrigin: 'http://localhost:7000', + apiOrigin: 'http://localhost:7007', basePath: '/auth/', oauthRequestApi, }), @@ -86,7 +86,7 @@ builder.add( builder.add( auth0AuthApiRef, Auth0Auth.create({ - apiOrigin: 'http://localhost:7000', + apiOrigin: 'http://localhost:7007', basePath: '/auth/', oauthRequestApi, }), @@ -95,7 +95,7 @@ builder.add( builder.add( oauth2ApiRef, OAuth2.create({ - apiOrigin: 'http://localhost:7000', + apiOrigin: 'http://localhost:7007', basePath: '/auth/', oauthRequestApi, }), diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md index 69bcbcdaeb..0207ea409d 100644 --- a/packages/techdocs-common/CHANGELOG.md +++ b/packages/techdocs-common/CHANGELOG.md @@ -865,7 +865,7 @@ Based on the config `techdocs.publisher.type`, the publisher could be either Local publisher or Google Cloud Storage publisher. - 4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7000/api/techdocs/static/docs` in most setups. + 4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7007/api/techdocs/static/docs` in most setups. 5. Parts of `@backstage/plugin-techdocs-backend` have been moved to a new package `@backstage/techdocs-common` to generate docs. Also to publish docs to-and-fro between TechDocs and a storage (either local or external). However, a Backstage app does NOT need to import the `techdocs-common` package - diff --git a/packages/techdocs-common/src/stages/publish/awsS3.test.ts b/packages/techdocs-common/src/stages/publish/awsS3.test.ts index ff88f12939..1f49668d35 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.test.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.test.ts @@ -54,7 +54,7 @@ const createPublisherFromConfig = ({ } = {}) => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'awsS3', awsS3: { diff --git a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts index 1bf3586266..a2503bd7b2 100644 --- a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts @@ -51,7 +51,7 @@ const createPublisherFromConfig = ({ } = {}) => { const config = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'azureBlobStorage', azureBlobStorage: { diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts index c085594325..a52fd0f0bd 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts @@ -52,7 +52,7 @@ const createPublisherFromConfig = ({ } = {}) => { const config = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'googleGcs', googleGcs: { diff --git a/packages/techdocs-common/src/stages/publish/local.test.ts b/packages/techdocs-common/src/stages/publish/local.test.ts index de56580e02..761de03c5a 100644 --- a/packages/techdocs-common/src/stages/publish/local.test.ts +++ b/packages/techdocs-common/src/stages/publish/local.test.ts @@ -39,7 +39,7 @@ const createMockEntity = (annotations = {}, lowerCase = false) => { }; const testDiscovery: jest.Mocked = { - getBaseUrl: jest.fn().mockResolvedValue('http://localhost:7000/api/techdocs'), + getBaseUrl: jest.fn().mockResolvedValue('http://localhost:7007/api/techdocs'), getExternalBaseUrl: jest.fn(), }; diff --git a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts index 8dde687997..c2236fb880 100644 --- a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts +++ b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts @@ -84,7 +84,7 @@ beforeEach(() => { mockFs.restore(); const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'openStackSwift', openStackSwift: { @@ -114,7 +114,7 @@ describe('OpenStackSwiftPublish', () => { it('should reject incorrect config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'openStackSwift', openStackSwift: { diff --git a/packages/techdocs-common/src/stages/publish/publish.test.ts b/packages/techdocs-common/src/stages/publish/publish.test.ts index 2671ef7b47..a47da828a7 100644 --- a/packages/techdocs-common/src/stages/publish/publish.test.ts +++ b/packages/techdocs-common/src/stages/publish/publish.test.ts @@ -27,7 +27,7 @@ import { OpenStackSwiftPublish } from './openStackSwift'; const logger = getVoidLogger(); const discovery: jest.Mocked = { - getBaseUrl: jest.fn().mockResolvedValueOnce('http://localhost:7000'), + getBaseUrl: jest.fn().mockResolvedValueOnce('http://localhost:7007'), getExternalBaseUrl: jest.fn(), }; @@ -39,7 +39,7 @@ describe('Publisher', () => { it('should create local publisher by default', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', }, }); @@ -53,7 +53,7 @@ describe('Publisher', () => { it('should create local publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'local', }, @@ -70,7 +70,7 @@ describe('Publisher', () => { it('should create google gcs publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'googleGcs', googleGcs: { @@ -91,7 +91,7 @@ describe('Publisher', () => { it('should create AWS S3 publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'awsS3', awsS3: { @@ -115,7 +115,7 @@ describe('Publisher', () => { it('should create Azure Blob Storage publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'azureBlobStorage', azureBlobStorage: { @@ -143,7 +143,7 @@ describe('Publisher', () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'azureBlobStorage', azureBlobStorage: { @@ -166,7 +166,7 @@ describe('Publisher', () => { it('should create Open Stack Swift publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7000', + requestUrl: 'http://localhost:7007', publisher: { type: 'openStackSwift', openStackSwift: { diff --git a/plugins/auth-backend/README.md b/plugins/auth-backend/README.md index 1fea3346a7..fe2cd05c22 100644 --- a/plugins/auth-backend/README.md +++ b/plugins/auth-backend/README.md @@ -34,7 +34,7 @@ Follow this link, [Create new OAuth App](https://github.com/settings/application 1. Set Application Name to `backstage-dev` or something along those lines. 1. You can set the Homepage URL to whatever you want to. 1. The Authorization Callback URL should match the redirect URI set in Backstage. - 1. Set this to `http://localhost:7000/api/auth/github` for local development. + 1. Set this to `http://localhost:7007/api/auth/github` for local development. 1. Set this to `http://{APP_FQDN}:{APP_BACKEND_PORT}/api/auth/github` for non-local deployments. ```bash @@ -58,7 +58,7 @@ Follow this link, [Add new application](https://gitlab.com/-/profile/application 1. Set Application Name to `backstage-dev` or something along those lines. 1. The Authorization Callback URL should match the redirect URI set in Backstage. - 1. Set this to `http://localhost:7000/api/auth/gitlab/handler/frame` for local development. + 1. Set this to `http://localhost:7007/api/auth/gitlab/handler/frame` for local development. 1. Set this to `http://{APP_FQDN}:{APP_BACKEND_PORT}/api/auth/gitlab/handler/frame` for non-local deployments. 1. Select the following scopes from the list: - [x] `read_user` Grants read-only access to the authenticated user's profile through the /user API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under /users. @@ -91,9 +91,9 @@ export AUTH_GITLAB_CLIENT_SECRET=x Add a new Okta application using the following URI conventions: -Login redirect URI's: `http://localhost:7000/api/auth/okta/handler/frame` -Logout redirect URI's: `http://localhost:7000/api/auth/okta/logout` -Initiate login URI's: `http://localhost:7000/api/auth/okta/start` +Login redirect URI's: `http://localhost:7007/api/auth/okta/handler/frame` +Logout redirect URI's: `http://localhost:7007/api/auth/okta/logout` +Initiate login URI's: `http://localhost:7007/api/auth/okta/start` Then configure the following environment variables to be used in the `app-config.yaml` file: @@ -122,7 +122,7 @@ Click [here](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMe - Give the app a name. e.g. `backstage-dev` - Select `Accounts in this organizational directory only` under supported account types. - Enter the callback URL for your backstage backend instance: - - For local development, this is likely `http://localhost:7000/api/auth/microsoft/handler/frame` + - For local development, this is likely `http://localhost:7007/api/auth/microsoft/handler/frame` - For non-local deployments, this will be `https://{APP_FQDN}:{APP_BACKEND_PORT}/auth/microsoft/handler/frame` - Click `Register`. diff --git a/plugins/auth-backend/scripts/start-saml-idp.sh b/plugins/auth-backend/scripts/start-saml-idp.sh index b312a4b85e..e12b725191 100755 --- a/plugins/auth-backend/scripts/start-saml-idp.sh +++ b/plugins/auth-backend/scripts/start-saml-idp.sh @@ -18,4 +18,4 @@ fi echo "Downloading and starting SAML-IdP" export NPM_CONFIG_REGISTRY=https://registry.npmjs.org -exec npx saml-idp --acsUrl "http://localhost:7000/api/auth/saml/handler/frame" --audience "http://localhost:7000" --port 7001 +exec npx saml-idp --acsUrl "http://localhost:7007/api/auth/saml/handler/frame" --audience "http://localhost:7007" --port 7001 diff --git a/plugins/azure-devops-backend/README.md b/plugins/azure-devops-backend/README.md index 6101794cd1..79db9f5ff1 100644 --- a/plugins/azure-devops-backend/README.md +++ b/plugins/azure-devops-backend/README.md @@ -63,7 +63,7 @@ Here's how to get the backend up and running: ``` 4. Now run `yarn start-backend` from the repo root -5. Finally open `http://localhost:7000/api/azure-devops/health` in a browser and it should return `{"status":"ok"}` +5. Finally open `http://localhost:7007/api/azure-devops/health` in a browser and it should return `{"status":"ok"}` ## Links diff --git a/plugins/azure-devops-backend/src/run.ts b/plugins/azure-devops-backend/src/run.ts index addfdfd6d7..53d4e4334a 100644 --- a/plugins/azure-devops-backend/src/run.ts +++ b/plugins/azure-devops-backend/src/run.ts @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/plugins/badges-backend/src/run.ts b/plugins/badges-backend/src/run.ts index addfdfd6d7..53d4e4334a 100644 --- a/plugins/badges-backend/src/run.ts +++ b/plugins/badges-backend/src/run.ts @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/plugins/badges-backend/src/service/router.test.ts b/plugins/badges-backend/src/service/router.test.ts index 51ad1e7e11..286a2335f1 100644 --- a/plugins/badges-backend/src/service/router.test.ts +++ b/plugins/badges-backend/src/service/router.test.ts @@ -73,7 +73,7 @@ describe('createRouter', () => { config = new ConfigReader({ backend: { baseUrl: 'http://127.0.0.1', - listen: { port: 7000 }, + listen: { port: 7007 }, }, }); discovery = SingleHostDiscovery.fromConfig(config); diff --git a/plugins/bazaar-backend/src/run.ts b/plugins/bazaar-backend/src/run.ts index 54d2716290..0a3ed2b7f0 100644 --- a/plugins/bazaar-backend/src/run.ts +++ b/plugins/bazaar-backend/src/run.ts @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/plugins/catalog-backend/src/run.ts b/plugins/catalog-backend/src/run.ts index 54d2716290..0a3ed2b7f0 100644 --- a/plugins/catalog-backend/src/run.ts +++ b/plugins/catalog-backend/src/run.ts @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts index 20e141b921..8f1af6f615 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts @@ -59,7 +59,7 @@ describe('DefaultCatalogCollator', () => { beforeAll(() => { mockDiscoveryApi = { - getBaseUrl: jest.fn().mockResolvedValue('http://localhost:7000'), + getBaseUrl: jest.fn().mockResolvedValue('http://localhost:7007'), getExternalBaseUrl: jest.fn(), }; collator = new DefaultCatalogCollator({ discovery: mockDiscoveryApi }); @@ -67,7 +67,7 @@ describe('DefaultCatalogCollator', () => { }); beforeEach(() => { server.use( - rest.get('http://localhost:7000/entities', (req, res, ctx) => { + rest.get('http://localhost:7007/entities', (req, res, ctx) => { if (req.url.searchParams.has('filter')) { const filter = req.url.searchParams.get('filter'); if (filter === 'kind=Foo,kind=Bar') { diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md index 101bee3e3f..4cfc187a3d 100644 --- a/plugins/code-coverage-backend/README.md +++ b/plugins/code-coverage-backend/README.md @@ -31,11 +31,11 @@ POST a Cobertura XML file to `/report` Example: ```json -// curl -X POST -H "Content-Type:text/xml" -d @cobertura.xml "localhost:7000/api/code-coverage/report?entity=component:default/entity-name&coverageType=cobertura" +// curl -X POST -H "Content-Type:text/xml" -d @cobertura.xml "localhost:7007/api/code-coverage/report?entity=component:default/entity-name&coverageType=cobertura" { "links": [ { - "href": "http://localhost:7000/api/code-coverage/report?entity=component:default/entity-name", + "href": "http://localhost:7007/api/code-coverage/report?entity=component:default/entity-name", "rel": "coverage" } ] @@ -49,11 +49,11 @@ POST a JaCoCo XML file to `/report` Example: ```json -// curl -X POST -H "Content-Type:text/xml" -d @jacoco.xml "localhost:7000/api/code-coverage/report?entity=component:default/entity-name&coverageType=jacoco" +// curl -X POST -H "Content-Type:text/xml" -d @jacoco.xml "localhost:7007/api/code-coverage/report?entity=component:default/entity-name&coverageType=jacoco" { "links": [ { - "href": "http://localhost:7000/api/code-coverage/report?entity=component:default/entity-name", + "href": "http://localhost:7007/api/code-coverage/report?entity=component:default/entity-name", "rel": "coverage" } ] @@ -67,7 +67,7 @@ GET `/report` Example: ```json -// curl localhost:7000/api/code-coverage/report?entity=component:default/entity-name +// curl localhost:7007/api/code-coverage/report?entity=component:default/entity-name { "aggregate": { "branch": { @@ -111,7 +111,7 @@ GET `/history` Example ```json -// curl localhost:7000/api/code-coverage/history?entity=component:default/entity-name +// curl localhost:7007/api/code-coverage/history?entity=component:default/entity-name { "entity": { "kind": "Component", diff --git a/plugins/code-coverage-backend/src/run.ts b/plugins/code-coverage-backend/src/run.ts index 54d2716290..0a3ed2b7f0 100644 --- a/plugins/code-coverage-backend/src/run.ts +++ b/plugins/code-coverage-backend/src/run.ts @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/plugins/code-coverage-backend/src/service/router.test.ts b/plugins/code-coverage-backend/src/service/router.test.ts index 462606bbab..4e6a66fdd8 100644 --- a/plugins/code-coverage-backend/src/service/router.test.ts +++ b/plugins/code-coverage-backend/src/service/router.test.ts @@ -42,7 +42,7 @@ function createDatabase(): PluginDatabaseManager { const testDiscovery: jest.Mocked = { getBaseUrl: jest .fn() - .mockResolvedValue('http://localhost:7000/api/code-coverage'), + .mockResolvedValue('http://localhost:7007/api/code-coverage'), getExternalBaseUrl: jest.fn(), }; const mockUrlReader = UrlReaders.default({ diff --git a/plugins/github-actions/README.md b/plugins/github-actions/README.md index d027368c8b..082267d424 100644 --- a/plugins/github-actions/README.md +++ b/plugins/github-actions/README.md @@ -11,7 +11,7 @@ TBD ### Generic Requirements 1. Provide OAuth credentials: - 1. [Create an OAuth App](https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app/) with the callback URL set to `http://localhost:7000/api/auth/github`. + 1. [Create an OAuth App](https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app/) with the callback URL set to `http://localhost:7007/api/auth/github`. 2. Take the Client ID and Client Secret from the newly created app's settings page and put them into `AUTH_GITHUB_CLIENT_ID` and `AUTH_GITHUB_CLIENT_SECRET` environment variables. 2. Annotate your component with a correct GitHub Actions repository and owner: diff --git a/plugins/jenkins-backend/src/run.ts b/plugins/jenkins-backend/src/run.ts index b96989e4b8..068a2b9d5f 100644 --- a/plugins/jenkins-backend/src/run.ts +++ b/plugins/jenkins-backend/src/run.ts @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/plugins/proxy-backend/src/run.ts b/plugins/proxy-backend/src/run.ts index 54d2716290..0a3ed2b7f0 100644 --- a/plugins/proxy-backend/src/run.ts +++ b/plugins/proxy-backend/src/run.ts @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/plugins/proxy-backend/src/service/router.test.ts b/plugins/proxy-backend/src/service/router.test.ts index df999dbe2a..ddb524d3aa 100644 --- a/plugins/proxy-backend/src/service/router.test.ts +++ b/plugins/proxy-backend/src/service/router.test.ts @@ -34,9 +34,9 @@ describe('createRouter', () => { const logger = getVoidLogger(); const config = new ConfigReader({ backend: { - baseUrl: 'https://example.com:7000', + baseUrl: 'https://example.com:7007', listen: { - port: 7000, + port: 7007, }, }, }); diff --git a/plugins/rollbar-backend/src/run.ts b/plugins/rollbar-backend/src/run.ts index 54d2716290..0a3ed2b7f0 100644 --- a/plugins/rollbar-backend/src/run.ts +++ b/plugins/rollbar-backend/src/run.ts @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/plugins/search-backend/src/run.ts b/plugins/search-backend/src/run.ts index addfdfd6d7..53d4e4334a 100644 --- a/plugins/search-backend/src/run.ts +++ b/plugins/search-backend/src/run.ts @@ -18,7 +18,7 @@ import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; import { startStandaloneServer } from './service/standaloneServer'; -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); const logger = getRootLogger(); diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index da3cd34830..9e563137bd 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -227,14 +227,14 @@ export interface Config { }; /** - * @example http://localhost:7000/api/techdocs + * @example http://localhost:7007/api/techdocs * @visibility frontend * @deprecated */ requestUrl?: string; /** - * @example http://localhost:7000/api/techdocs/static/docs + * @example http://localhost:7007/api/techdocs/static/docs * @deprecated */ storageUrl?: string; diff --git a/plugins/techdocs/config.d.ts b/plugins/techdocs/config.d.ts index d6bf21b10b..45fd524eff 100644 --- a/plugins/techdocs/config.d.ts +++ b/plugins/techdocs/config.d.ts @@ -34,7 +34,7 @@ export interface Config { legacyUseCaseSensitiveTripletPaths?: boolean; /** - * @example http://localhost:7000/api/techdocs + * @example http://localhost:7007/api/techdocs * @visibility frontend * @deprecated */ diff --git a/scripts/migrate-location-types.js b/scripts/migrate-location-types.js index d6ac5c6a2a..168a5e825c 100755 --- a/scripts/migrate-location-types.js +++ b/scripts/migrate-location-types.js @@ -20,7 +20,7 @@ // catalog API endpoint and execute the script. It will delete and add // back the locations with the correct type one by one. -const BASE_URL = 'http://localhost:7000/api/catalog'; // Change me +const BASE_URL = 'http://localhost:7007/api/catalog'; // Change me const deprecatedTypes = [ 'github', @@ -81,9 +81,9 @@ async function request(method, url, body) { return; } try { - const body = Buffer.concat(chunks).toString('utf8').trim(); - if (body) { - resolve(JSON.parse(body)); + const responseBody = Buffer.concat(chunks).toString('utf8').trim(); + if (responseBody) { + resolve(JSON.parse(responseBody)); } else { resolve(); } From bab752e2b3ed7c120143b715098d34195d8a8ebd Mon Sep 17 00:00:00 2001 From: Otto Sichert Date: Tue, 16 Nov 2021 15:11:40 +0100 Subject: [PATCH 26/61] Add changeset Signed-off-by: Otto Sichert --- .changeset/pretty-trains-appear.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .changeset/pretty-trains-appear.md diff --git a/.changeset/pretty-trains-appear.md b/.changeset/pretty-trains-appear.md new file mode 100644 index 0000000000..3e3c9e9a5e --- /dev/null +++ b/.changeset/pretty-trains-appear.md @@ -0,0 +1,26 @@ +--- +'example-app': patch +'example-backend': patch +'@backstage/backend-common': patch +'@backstage/cli': patch +'@backstage/core-app-api': patch +'@backstage/create-app': patch +'e2e-test': patch +'storybook': patch +'@backstage/techdocs-common': patch +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-azure-devops-backend': patch +'@backstage/plugin-badges-backend': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-code-coverage-backend': patch +'@backstage/plugin-github-actions': patch +'@backstage/plugin-jenkins-backend': patch +'@backstage/plugin-proxy-backend': patch +'@backstage/plugin-rollbar-backend': patch +'@backstage/plugin-search-backend': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-techdocs-backend': patch +--- + +Change default port of backend from 7000 to 7007 From 2017de90da1d5bf37d8834d93ee1d479ab9e85d0 Mon Sep 17 00:00:00 2001 From: goenning Date: Thu, 18 Nov 2021 15:53:50 +0000 Subject: [PATCH 27/61] add changeset Signed-off-by: goenning --- .changeset/curly-points-hide.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/curly-points-hide.md diff --git a/.changeset/curly-points-hide.md b/.changeset/curly-points-hide.md new file mode 100644 index 0000000000..ba513e5915 --- /dev/null +++ b/.changeset/curly-points-hide.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-tech-insights-backend': patch +'@backstage/plugin-tech-insights-backend-module-jsonfc': patch +--- + +Update README docs to use correct function/parameter names From ee055cf6db4d04c6fa090a37cf005cb25bad74f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 18 Nov 2021 16:59:38 +0100 Subject: [PATCH 28/61] use id instead of title in the default plugin routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/weak-berries-sing.md | 5 +++++ packages/cli/templates/default-plugin/src/routes.ts.hbs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/weak-berries-sing.md diff --git a/.changeset/weak-berries-sing.md b/.changeset/weak-berries-sing.md new file mode 100644 index 0000000000..1b0cb8d719 --- /dev/null +++ b/.changeset/weak-berries-sing.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Update the default routes to use id instead of title diff --git a/packages/cli/templates/default-plugin/src/routes.ts.hbs b/packages/cli/templates/default-plugin/src/routes.ts.hbs index a5a278e8a7..7e5d8f85f0 100644 --- a/packages/cli/templates/default-plugin/src/routes.ts.hbs +++ b/packages/cli/templates/default-plugin/src/routes.ts.hbs @@ -1,5 +1,5 @@ import { createRouteRef } from '@backstage/core-plugin-api'; export const rootRouteRef = createRouteRef({ - title: '{{ id }}', + id: '{{ id }}', }); From 97b8c8c8fc6a44bc19ad9850ae0ef8890f66c890 Mon Sep 17 00:00:00 2001 From: Otto Sichert Date: Thu, 18 Nov 2021 17:23:43 +0100 Subject: [PATCH 29/61] Ensure all relevant port references are updated and document changes Signed-off-by: Otto Sichert --- .changeset/pretty-trains-appear.md | 18 +++++++++++++----- packages/create-app/CHANGELOG.md | 14 +++++++------- .../embedded-techdocs-app/app-config.dev.yaml | 4 ++-- .../embedded-techdocs-app/src/App.test.tsx | 4 ++-- .../techdocs-cli/src/commands/serve/serve.ts | 2 +- .../techdocs-cli/src/lib/PublisherConfig.ts | 4 ++-- 6 files changed, 27 insertions(+), 19 deletions(-) diff --git a/.changeset/pretty-trains-appear.md b/.changeset/pretty-trains-appear.md index 3e3c9e9a5e..9a7b313524 100644 --- a/.changeset/pretty-trains-appear.md +++ b/.changeset/pretty-trains-appear.md @@ -1,12 +1,8 @@ --- -'example-app': patch -'example-backend': patch '@backstage/backend-common': patch '@backstage/cli': patch '@backstage/core-app-api': patch '@backstage/create-app': patch -'e2e-test': patch -'storybook': patch '@backstage/techdocs-common': patch '@backstage/plugin-auth-backend': patch '@backstage/plugin-azure-devops-backend': patch @@ -23,4 +19,16 @@ '@backstage/plugin-techdocs-backend': patch --- -Change default port of backend from 7000 to 7007 +Change default port of backend from 7000 to 7007. + +This is due to the AirPlay Receiver process occupying port 7000 and preventing local Backstage instances on MacOS to start. + +You can change the port back to 7000 or any other value by providing an `app-config.yaml` with the following values: + +``` +backend: + listen: 0.0.0.0:7123 + baseUrl: http://localhost:7123 +``` + +More information can be found here: https://backstage.io/docs/conf/writing diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 6ca70f1223..af1fd58ead 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1149,9 +1149,9 @@ // app-config.yaml backend: - baseUrl: http://localhost:7007 + baseUrl: http://localhost:7000 listen: - port: 7007 + port: 7000 database: client: sqlite3 connection: ':memory:' @@ -2238,9 +2238,9 @@ For more information and the background to this change, see the [composability s { data: { app: { title: 'Test' }, - backend: { baseUrl: 'http://localhost:7007' }, + backend: { baseUrl: 'http://localhost:7000' }, techdocs: { - storageUrl: 'http://localhost:7007/api/techdocs/static/docs', + storageUrl: 'http://localhost:7000/api/techdocs/static/docs', }, }, context: 'test', @@ -3444,12 +3444,12 @@ For more information and the background to this change, see the [composability s ```yaml app: # Should be the same as backend.baseUrl when using the `app-backend` plugin - baseUrl: http://localhost:7007 + baseUrl: http://localhost:7000 backend: - baseUrl: http://localhost:7007 + baseUrl: http://localhost:7000 listen: - port: 7007 + port: 7000 ``` In order to load in the new configuration at runtime, the command in the `Dockerfile` at the repo root was changed to the following: diff --git a/packages/embedded-techdocs-app/app-config.dev.yaml b/packages/embedded-techdocs-app/app-config.dev.yaml index 2d1bad2808..02d68c940e 100644 --- a/packages/embedded-techdocs-app/app-config.dev.yaml +++ b/packages/embedded-techdocs-app/app-config.dev.yaml @@ -5,8 +5,8 @@ app: baseUrl: http://localhost:3000 backend: - baseUrl: http://localhost:7000 + baseUrl: http://localhost:7007 techdocs: builder: 'external' - requestUrl: http://localhost:7000/api + requestUrl: http://localhost:7007/api diff --git a/packages/embedded-techdocs-app/src/App.test.tsx b/packages/embedded-techdocs-app/src/App.test.tsx index a5a4374976..f177433d95 100644 --- a/packages/embedded-techdocs-app/src/App.test.tsx +++ b/packages/embedded-techdocs-app/src/App.test.tsx @@ -26,9 +26,9 @@ describe('App', () => { { data: { app: { title: 'Test' }, - backend: { baseUrl: 'http://localhost:7000' }, + backend: { baseUrl: 'http://localhost:7007' }, techdocs: { - storageUrl: 'http://localhost:7000/api/techdocs/static/docs', + storageUrl: 'http://localhost:7007/api/techdocs/static/docs', }, }, context: 'test', diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index 1182c850b3..4d71de3e52 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -36,7 +36,7 @@ export default async function serve(cmd: Command) { // a backstage app, we define app.baseUrl in the app-config.yaml. // Hence, it is complicated to make this configurable. const backstagePort = 3000; - const backstageBackendPort = 7000; + const backstageBackendPort = 7007; const mkdocsDockerAddr = `http://0.0.0.0:${cmd.mkdocsPort}`; const mkdocsLocalAddr = `http://127.0.0.1:${cmd.mkdocsPort}`; diff --git a/packages/techdocs-cli/src/lib/PublisherConfig.ts b/packages/techdocs-cli/src/lib/PublisherConfig.ts index d4779995c0..c18b9ff588 100644 --- a/packages/techdocs-cli/src/lib/PublisherConfig.ts +++ b/packages/techdocs-cli/src/lib/PublisherConfig.ts @@ -55,9 +55,9 @@ export class PublisherConfig { return new ConfigReader({ // This backend config is not used at all. Just something needed a create a mock discovery instance. backend: { - baseUrl: 'http://localhost:7000', + baseUrl: 'http://localhost:7007', listen: { - port: 7000, + port: 7007, }, }, techdocs: { From bfa59576696f7d82bb8e6ea7485e261377eb3382 Mon Sep 17 00:00:00 2001 From: sblausten Date: Thu, 18 Nov 2021 18:25:43 +0100 Subject: [PATCH 30/61] Change sidebar to be pinned by default Signed-off-by: sblausten --- packages/core-components/src/layout/Sidebar/Page.tsx | 2 +- packages/core-components/src/layout/Sidebar/localStorage.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core-components/src/layout/Sidebar/Page.tsx b/packages/core-components/src/layout/Sidebar/Page.tsx index cc50c5af6b..6248c237b2 100644 --- a/packages/core-components/src/layout/Sidebar/Page.tsx +++ b/packages/core-components/src/layout/Sidebar/Page.tsx @@ -49,7 +49,7 @@ export type SidebarPinStateContextType = { export const SidebarPinStateContext = createContext( { - isPinned: false, + isPinned: true, toggleSidebarPinState: () => {}, }, ); diff --git a/packages/core-components/src/layout/Sidebar/localStorage.ts b/packages/core-components/src/layout/Sidebar/localStorage.ts index 0e904ee319..78ec355306 100644 --- a/packages/core-components/src/layout/Sidebar/localStorage.ts +++ b/packages/core-components/src/layout/Sidebar/localStorage.ts @@ -24,10 +24,10 @@ export const LocalStorage = { try { value = JSON.parse( window.localStorage.getItem(LocalStorageKeys.SIDEBAR_PIN_STATE) || - 'false', + 'true', ); } catch { - return false; + return true; } return !!value; }, From 157530187ac221beae04921619d063304e833abd Mon Sep 17 00:00:00 2001 From: sblausten Date: Thu, 18 Nov 2021 19:00:28 +0100 Subject: [PATCH 31/61] Add Changeset Signed-off-by: sblausten --- .changeset/yellow-pandas-draw.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/yellow-pandas-draw.md diff --git a/.changeset/yellow-pandas-draw.md b/.changeset/yellow-pandas-draw.md new file mode 100644 index 0000000000..6d4f8116b3 --- /dev/null +++ b/.changeset/yellow-pandas-draw.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Pin sidebar by default for easier navigation From 478c4e180abb5b4060b79eb3be656afcf70840c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Eugenio=20Rodrigues=20Gusm=C3=A3o?= Date: Thu, 18 Nov 2021 18:12:41 -0300 Subject: [PATCH 32/61] Add Globo as a Backstage Developer Portal adapter --- ADOPTERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ADOPTERS.md b/ADOPTERS.md index 4f1d7fbfe8..b59cf33b02 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -69,3 +69,4 @@ | [Unity](https://unity.com) | [Ted Cordery](https://github.com/TeddyBallGame) | A centralized service catalog with documentation for our service engineers. | | [PicPay](https://www.picpay.com) | [Luis Baroni](https://github.com/lcsbaroni), [Renata Poluceno](https://github.com/renatapoluceno), [PicPay](https://github.com/picpay) | Developer portal for building services throught templates, service catalog with ownership of services, documentation and metrics providing autonomy and visibility for all. | | [Epic Games](https://www.epicgames.com) | [Brian Jung](https://github.com/brian-at-epic), [Jeff Goldian](https://github.com/jeffgoldian-Epic) | Developer Portal: Service Catalog, Documentation, Software Templates and more making our internal teams' lives easier! | +| [Globo](https://globo.com) | [Carlos Gusmão](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. | From 0fae9f2c0b0e943b089e020661ed345765b50ad8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 18 Nov 2021 21:46:16 +0100 Subject: [PATCH 33/61] core-app-api: fix and release accidental createApp type breakage Signed-off-by: Patrik Oldsberg --- packages/core-app-api/CHANGELOG.md | 6 ++++++ packages/core-app-api/api-report.md | 6 ++++-- packages/core-app-api/package.json | 2 +- packages/core-app-api/src/app/createApp.tsx | 12 ++++++------ plugins/allure/package.json | 2 +- plugins/analytics-module-ga/package.json | 2 +- plugins/api-docs/package.json | 2 +- plugins/azure-devops/package.json | 2 +- plugins/badges/package.json | 2 +- plugins/bitrise/package.json | 2 +- plugins/catalog-graph/package.json | 2 +- plugins/catalog-import/package.json | 2 +- plugins/catalog/package.json | 2 +- plugins/circleci/package.json | 2 +- plugins/cloudbuild/package.json | 2 +- plugins/code-coverage/package.json | 2 +- plugins/config-schema/package.json | 2 +- plugins/cost-insights/package.json | 2 +- plugins/explore/package.json | 2 +- plugins/firehydrant/package.json | 2 +- plugins/fossa/package.json | 2 +- plugins/gcp-projects/package.json | 2 +- plugins/git-release-manager/package.json | 2 +- plugins/github-actions/package.json | 2 +- plugins/github-deployments/package.json | 2 +- plugins/gitops-profiles/package.json | 2 +- plugins/graphiql/package.json | 2 +- plugins/home/package.json | 2 +- plugins/ilert/package.json | 2 +- plugins/jenkins/package.json | 2 +- plugins/kafka/package.json | 2 +- plugins/kubernetes/package.json | 2 +- plugins/lighthouse/package.json | 2 +- plugins/newrelic/package.json | 2 +- plugins/org/package.json | 2 +- plugins/pagerduty/package.json | 2 +- plugins/rollbar/package.json | 2 +- plugins/scaffolder/package.json | 2 +- plugins/search/package.json | 2 +- plugins/sentry/package.json | 2 +- plugins/shortcuts/package.json | 2 +- plugins/sonarqube/package.json | 2 +- plugins/splunk-on-call/package.json | 2 +- plugins/tech-radar/package.json | 2 +- plugins/techdocs/package.json | 2 +- plugins/todo/package.json | 2 +- plugins/user-settings/package.json | 2 +- plugins/xcmetrics/package.json | 2 +- 48 files changed, 61 insertions(+), 53 deletions(-) diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 342d453eae..b1d590a7bd 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/core-app-api +## 0.1.22 + +### Patch Changes + +- Reverted the `createApp` TypeScript type to match the one before version `0.1.21`, as it was an accidental breaking change. + ## 0.1.21 ### Patch Changes diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index a67d2a2225..77eb6a85d5 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -27,6 +27,7 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { bitbucketAuthApiRef } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; import { ConfigReader } from '@backstage/config'; +import { createApp as createApp_2 } from '@backstage/app-defaults'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { ErrorApi } from '@backstage/core-plugin-api'; import { ErrorApiError } from '@backstage/core-plugin-api'; @@ -45,7 +46,6 @@ import { Observable } from '@backstage/types'; import { oktaAuthApiRef } from '@backstage/core-plugin-api'; import { oneloginAuthApiRef } from '@backstage/core-plugin-api'; import { OpenIdConnectApi } from '@backstage/core-plugin-api'; -import { OptionalAppOptions } from '@backstage/app-defaults'; import { PendingAuthRequest } from '@backstage/core-plugin-api'; import { PluginOutput } from '@backstage/core-plugin-api'; import { ProfileInfo } from '@backstage/core-plugin-api'; @@ -332,7 +332,9 @@ export type BootErrorPageProps = { export { ConfigReader }; // @public @deprecated -export function createApp(options?: OptionalAppOptions): BackstageApp; +export function createApp( + options?: Parameters[0], +): BackstageApp & AppContext; // @public export function createSpecializedApp(options: AppOptions): BackstageApp; diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 4c79f9eb3f..96c021b1ee 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "0.1.21", + "version": "0.1.22", "private": false, "publishConfig": { "access": "public", diff --git a/packages/core-app-api/src/app/createApp.tsx b/packages/core-app-api/src/app/createApp.tsx index e11076099b..b2a21634d3 100644 --- a/packages/core-app-api/src/app/createApp.tsx +++ b/packages/core-app-api/src/app/createApp.tsx @@ -14,10 +14,8 @@ * limitations under the License. */ -import { - createApp as createDefaultApp, - OptionalAppOptions, -} from '@backstage/app-defaults'; +import { createApp as createDefaultApp } from '@backstage/app-defaults'; +import { AppContext, BackstageApp } from './types'; /** * Creates a new Backstage App. @@ -26,7 +24,9 @@ import { * @param options - A set of options for creating the app * @public */ -export function createApp(options?: OptionalAppOptions) { +export function createApp( + options?: Parameters[0], +): BackstageApp & AppContext { // eslint-disable-next-line no-console console.warn( 'DEPRECATION WARNING: The createApp function from @backstage/core-app-api will soon be removed, ' + @@ -34,5 +34,5 @@ export function createApp(options?: OptionalAppOptions) { 'If you do not wish to use a standard app configuration but instead supply all options yourself ' + ' you can use createSpecializedApp from @backstage/core-app-api instead.', ); - return createDefaultApp(options); + return createDefaultApp(options) as BackstageApp & AppContext; } diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 6a9a55bceb..9efe6132e8 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -37,7 +37,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index b83aed37c0..e0a32960c5 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -35,7 +35,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 16f2d0d188..a4aa15c419 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -54,7 +54,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 0642a24cac..9d235b0641 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -46,7 +46,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/badges/package.json b/plugins/badges/package.json index dcc422ec19..4d02d64237 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -43,7 +43,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 28a3c88ad1..92cd9693e1 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -40,7 +40,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 53fde11c7b..13869cfd38 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -42,7 +42,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index bd7f99c884..933a84f13e 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -56,7 +56,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 254718bd3c..ddee20c488 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -52,7 +52,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index d7cd3b0fd2..7228044f4f 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -53,7 +53,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 32b860ec23..4125a8c82e 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -50,7 +50,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 0c32718e97..e5b51e90b4 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -43,7 +43,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 0385a64ec8..c9abbc7e4e 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -38,7 +38,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 04e4f41701..da9ba8b1f6 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -56,7 +56,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 5732e3fca6..d9945edc51 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -50,7 +50,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index dce261617d..f332efc150 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -36,7 +36,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 8090fdc1c7..cc0b486d60 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -50,7 +50,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 0e33130274..cd1c3ac4a1 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -44,7 +44,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 0c52381514..7f7ff6184d 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -40,7 +40,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 789385308e..ae7f32be1f 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -53,7 +53,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index a52bbfa95a..062113a8ef 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -40,7 +40,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 226a45332c..dfbd6297cf 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -45,7 +45,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index aeefce3340..5c72a4c728 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -45,7 +45,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/home/package.json b/plugins/home/package.json index 74336d80be..ef13ce3a00 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -36,7 +36,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index e0ccd3cd2d..6011dd4f46 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -40,7 +40,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index e8115c3800..4456b15284 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index bea4aadcba..a6fbe36e99 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -36,7 +36,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 8f4e3356c5..618f814c21 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -52,7 +52,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index b1e0290b4c..e53f6ee261 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -48,7 +48,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index c19bc9ed37..16029f1783 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -44,7 +44,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/org/package.json b/plugins/org/package.json index 035ae50c3b..db6cfe4d0b 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -38,7 +38,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 735b541451..7981b2c104 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index f3d32eed11..ee3fc9f5a6 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -50,7 +50,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 3d7bde77c9..a47cee2d75 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -67,7 +67,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/search/package.json b/plugins/search/package.json index 24984d10e7..aaddf130bf 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -52,7 +52,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index fd7cc34b1f..a04043c789 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 8fad41f0a8..f0139d5728 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -39,7 +39,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 07467ac1cf..f92c21ad7e 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -50,7 +50,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index dfb1c58aca..10eb807ba1 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -48,7 +48,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index d07b75c401..99fce10345 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -46,7 +46,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index d1c337754a..663c83118e 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -62,7 +62,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/todo/package.json b/plugins/todo/package.json index b11721695a..22a8e6b1e2 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -42,7 +42,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 6b7ef01538..def12ac1d2 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -44,7 +44,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index c23a5487db..f29f763666 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -37,7 +37,7 @@ }, "devDependencies": { "@backstage/cli": "^0.9.0", - "@backstage/core-app-api": "^0.1.21", + "@backstage/core-app-api": "^0.1.22", "@backstage/dev-utils": "^0.2.13", "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", From 0496f6497c5daf34d30c3a6474fd2db7c45ccb9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Nov 2021 04:07:58 +0000 Subject: [PATCH 34/61] chore(deps-dev): bump @types/diff from 5.0.0 to 5.0.1 Bumps [@types/diff](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/diff) from 5.0.0 to 5.0.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/diff) --- updated-dependencies: - dependency-name: "@types/diff" dependency-type: direct:development 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 9b934191d8..29145d1154 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7080,9 +7080,9 @@ "@types/ms" "*" "@types/diff@^5.0.0": - version "5.0.0" - resolved "https://registry.npmjs.org/@types/diff/-/diff-5.0.0.tgz#eb71e94feae62548282c4889308a3dfb57e36020" - integrity sha512-jrm2K65CokCCX4NmowtA+MfXyuprZC13jbRuwprs6/04z/EcFg/MCwYdsHn+zgV4CQBiATiI7AEq7y1sZCtWKA== + version "5.0.1" + resolved "https://registry.npmjs.org/@types/diff/-/diff-5.0.1.tgz#9c9b9a331d4e41ccccff553f5d7ef964c6cf4042" + integrity sha512-XIpxU6Qdvp1ZE6Kr3yrkv1qgUab0fyf4mHYvW8N3Bx3PCsbN6or1q9/q72cv5jIFWolaGH08U9XyYoLLIykyKQ== "@types/docker-modem@*": version "3.0.2" From 20900440a33dff1d9a1df11affa72db4fc34b865 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Fri, 19 Nov 2021 16:43:10 +0800 Subject: [PATCH 35/61] disable snyk workflow on forks Signed-off-by: Gauthier Roebroeck --- .github/workflows/snyk-github-issue-sync.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/snyk-github-issue-sync.yml b/.github/workflows/snyk-github-issue-sync.yml index 0c50b2c505..7b93374609 100644 --- a/.github/workflows/snyk-github-issue-sync.yml +++ b/.github/workflows/snyk-github-issue-sync.yml @@ -6,6 +6,8 @@ on: jobs: sync: + if: github.repository == 'backstage/backstage' # prevent running on forks + runs-on: ubuntu-latest strategy: From 430b3f7a8f88e965587b292971b7008ff8bc8a67 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 19 Nov 2021 09:35:09 +0000 Subject: [PATCH 36/61] permission-common: accept configApi in PermissionClient constructor Moving the responsibility of pulling the right configuration key inside the PermissionClient keeps it as the responsibility of permission-common, whereas putting it on the outside means anyone constructing a PermissionClient has to know which key to use. Signed-off-by: Mike Lewis --- plugins/permission-common/api-report.md | 4 +++- plugins/permission-common/package.json | 1 + plugins/permission-common/src/PermissionClient.test.ts | 8 ++++++-- plugins/permission-common/src/PermissionClient.ts | 5 +++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/plugins/permission-common/api-report.md b/plugins/permission-common/api-report.md index cbf1877c75..043b27554c 100644 --- a/plugins/permission-common/api-report.md +++ b/plugins/permission-common/api-report.md @@ -3,6 +3,8 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { Config } from '@backstage/config'; + // @public export type AuthorizeRequest = { permission: Permission; @@ -67,7 +69,7 @@ export type PermissionAttributes = { // @public export class PermissionClient { - constructor(options: { discoveryApi: DiscoveryApi; enabled?: boolean }); + constructor(options: { discoveryApi: DiscoveryApi; configApi: Config }); authorize( requests: AuthorizeRequest[], options?: AuthorizeRequestOptions, diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index 95a0d9d3c3..9e1d60f782 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -38,6 +38,7 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { + "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.2", "cross-fetch": "^3.0.6", "uuid": "^8.0.0", diff --git a/plugins/permission-common/src/PermissionClient.test.ts b/plugins/permission-common/src/PermissionClient.test.ts index 06e2ae0561..8d7933d967 100644 --- a/plugins/permission-common/src/PermissionClient.test.ts +++ b/plugins/permission-common/src/PermissionClient.test.ts @@ -16,6 +16,7 @@ import { RestContext, rest } from 'msw'; import { setupServer } from 'msw/node'; +import { ConfigReader } from '@backstage/config'; import { PermissionClient } from './PermissionClient'; import { AuthorizeRequest, AuthorizeResult, Identified } from './types/api'; import { DiscoveryApi } from './types/discovery'; @@ -32,7 +33,7 @@ const discoveryApi: DiscoveryApi = { }; const client: PermissionClient = new PermissionClient({ discoveryApi, - enabled: true, + configApi: new ConfigReader({ permission: { enabled: true } }), }); const mockPermission: Permission = { @@ -156,7 +157,10 @@ describe('PermissionClient', () => { return res(json(responses)); }, ); - const disabled = new PermissionClient({ discoveryApi, enabled: false }); + const disabled = new PermissionClient({ + discoveryApi, + configApi: new ConfigReader({ permission: { enabled: false } }), + }); const response = await disabled.authorize([mockAuthorizeRequest]); expect(response[0]).toEqual( expect.objectContaining({ result: AuthorizeResult.ALLOW }), diff --git a/plugins/permission-common/src/PermissionClient.ts b/plugins/permission-common/src/PermissionClient.ts index 5b17ccd333..aa1cde9ba1 100644 --- a/plugins/permission-common/src/PermissionClient.ts +++ b/plugins/permission-common/src/PermissionClient.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { Config } from '@backstage/config'; import { ResponseError } from '@backstage/errors'; import fetch from 'cross-fetch'; import * as uuid from 'uuid'; @@ -74,9 +75,9 @@ export class PermissionClient { private readonly enabled: boolean; private readonly discoveryApi: DiscoveryApi; - constructor(options: { discoveryApi: DiscoveryApi; enabled?: boolean }) { + constructor(options: { discoveryApi: DiscoveryApi; configApi: Config }) { this.discoveryApi = options.discoveryApi; - this.enabled = options.enabled ?? false; + this.enabled = options.configApi.getBoolean('permission.enabled'); } /** From d1dcd7e309486570627baaf4801d19d9b250ce77 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 19 Nov 2021 09:34:21 +0000 Subject: [PATCH 37/61] permission-common: make permission.enabled config optional Signed-off-by: Mike Lewis --- .../src/PermissionClient.test.ts | 24 ++++++++++++++++++- .../permission-common/src/PermissionClient.ts | 3 ++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/plugins/permission-common/src/PermissionClient.test.ts b/plugins/permission-common/src/PermissionClient.test.ts index 8d7933d967..b2e66986a1 100644 --- a/plugins/permission-common/src/PermissionClient.test.ts +++ b/plugins/permission-common/src/PermissionClient.test.ts @@ -146,7 +146,7 @@ describe('PermissionClient', () => { ).rejects.toThrowError(/invalid input/i); }); - it('should allow all when authorization is not enabled', async () => { + it('should allow all when permission.enabled is false', async () => { mockAuthorizeHandler.mockImplementationOnce( (req, res, { json }: RestContext) => { const responses = req.body.map((a: Identified) => ({ @@ -167,5 +167,27 @@ describe('PermissionClient', () => { ); expect(mockAuthorizeHandler).not.toBeCalled(); }); + + it('should allow all when permission.enabled is not configured', async () => { + mockAuthorizeHandler.mockImplementationOnce( + (req, res, { json }: RestContext) => { + const responses = req.body.map((a: Identified) => ({ + id: a.id, + outcome: AuthorizeResult.DENY, + })); + + return res(json(responses)); + }, + ); + const disabled = new PermissionClient({ + discoveryApi, + configApi: new ConfigReader({}), + }); + const response = await disabled.authorize([mockAuthorizeRequest]); + expect(response[0]).toEqual( + expect.objectContaining({ result: AuthorizeResult.ALLOW }), + ); + expect(mockAuthorizeHandler).not.toBeCalled(); + }); }); }); diff --git a/plugins/permission-common/src/PermissionClient.ts b/plugins/permission-common/src/PermissionClient.ts index aa1cde9ba1..f98d40a3c4 100644 --- a/plugins/permission-common/src/PermissionClient.ts +++ b/plugins/permission-common/src/PermissionClient.ts @@ -77,7 +77,8 @@ export class PermissionClient { constructor(options: { discoveryApi: DiscoveryApi; configApi: Config }) { this.discoveryApi = options.discoveryApi; - this.enabled = options.configApi.getBoolean('permission.enabled'); + this.enabled = + options.configApi.getOptionalBoolean('permission.enabled') ?? false; } /** From 92439056fbe089749f123d52b0de07bf150ff100 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 19 Nov 2021 09:35:47 +0000 Subject: [PATCH 38/61] add changeset for new PermissionClient constructor signature Signed-off-by: Mike Lewis --- .changeset/purple-grapes-attack.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/purple-grapes-attack.md diff --git a/.changeset/purple-grapes-attack.md b/.changeset/purple-grapes-attack.md new file mode 100644 index 0000000000..a2a99690e9 --- /dev/null +++ b/.changeset/purple-grapes-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-permission-common': minor +--- + +Accept configApi rather than enabled flag in PermissionClient constructor. From 8c4397730c13f3cdcba55abbb6faa82eaffd72c5 Mon Sep 17 00:00:00 2001 From: Pete Jespers Date: Fri, 19 Nov 2021 10:11:30 +0000 Subject: [PATCH 39/61] Add QBE as a Backstage adopter Signed-off-by: Pete Jespers --- ADOPTERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ADOPTERS.md b/ADOPTERS.md index b59cf33b02..e2585184b2 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -70,3 +70,4 @@ | [PicPay](https://www.picpay.com) | [Luis Baroni](https://github.com/lcsbaroni), [Renata Poluceno](https://github.com/renatapoluceno), [PicPay](https://github.com/picpay) | Developer portal for building services throught templates, service catalog with ownership of services, documentation and metrics providing autonomy and visibility for all. | | [Epic Games](https://www.epicgames.com) | [Brian Jung](https://github.com/brian-at-epic), [Jeff Goldian](https://github.com/jeffgoldian-Epic) | Developer Portal: Service Catalog, Documentation, Software Templates and more making our internal teams' lives easier! | | [Globo](https://globo.com) | [Carlos Gusmão](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. | +| [QBE Ltd](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly 🚀 | \ No newline at end of file From ab7f280cb491ce2dee52773e52d609978c2927ac Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Fri, 19 Nov 2021 07:31:10 -0600 Subject: [PATCH 40/61] Fixed missed naming and typos Signed-off-by: Andre Wanlin --- plugins/azure-devops/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/azure-devops/README.md b/plugins/azure-devops/README.md index f33bd3bdb6..1e7235b546 100644 --- a/plugins/azure-devops/README.md +++ b/plugins/azure-devops/README.md @@ -84,7 +84,7 @@ To get the Azure Pipelines component working you'll need to do the following two **Notes:** - The `if` prop is optional on the `EntitySwitch.Case`, you can remove it if you always want to see the tab even if the entity being viewed does not have the needed annotation -- The `defaultLimit` proper on the `EntityAzurePipelinesContent` will set the max number of Builds you would like to see, if not set this will default to 10 +- The `defaultLimit` property on the `EntityAzurePipelinesContent` will set the max number of Builds you would like to see, if not set this will default to 10 ### Azure Repos Component @@ -98,12 +98,12 @@ To get the Azure Repos component working you'll need to do the following two ste yarn add @backstage/plugin-azure-devops ``` -2. Second we need to add the `EntityAzureReposContent` extension to the entity page in your app: +2. Second we need to add the `EntityAzurePipelinesContent` extension to the entity page in your app: ```tsx // In packages/app/src/components/catalog/EntityPage.tsx import { - EntityAzureReposContent, + EntityAzurePipelinesContent, isAzureDevOpsAvailable, } from '@backstage/plugin-azure-devops'; @@ -112,7 +112,7 @@ To get the Azure Repos component working you'll need to do the following two ste // ... - + // ... @@ -122,7 +122,7 @@ To get the Azure Repos component working you'll need to do the following two ste - You'll need to add the `EntityLayout.Route` above from step 2 to all the entity sections you want to see Pull Requests in. For example if you wanted to see Pull Requests when looking at Website entities then you would need to add this to the `websiteEntityPage` section. - The `if` prop is optional on the `EntityLayout.Route`, you can remove it if you always want to see the tab even if the entity being viewed does not have the needed annotation -- The `defaultLimit` proper on the `EntityAzureReposContent` will set the max number of Pull Requests you would like to see, if not set this will default to 10 +- The `defaultLimit` property on the `EntityAzurePipelinesContent` will set the max number of Pull Requests you would like to see, if not set this will default to 10 ## Limitations From a519640e6742e78d2f0d6da811c71002c1ef455b Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Fri, 19 Nov 2021 07:34:56 -0600 Subject: [PATCH 41/61] Rushing, this is the correct change Signed-off-by: Andre Wanlin --- plugins/azure-devops/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/azure-devops/README.md b/plugins/azure-devops/README.md index 1e7235b546..7b39dae443 100644 --- a/plugins/azure-devops/README.md +++ b/plugins/azure-devops/README.md @@ -98,12 +98,12 @@ To get the Azure Repos component working you'll need to do the following two ste yarn add @backstage/plugin-azure-devops ``` -2. Second we need to add the `EntityAzurePipelinesContent` extension to the entity page in your app: +2. Second we need to add the `EntityAzurePullRequestsContent` extension to the entity page in your app: ```tsx // In packages/app/src/components/catalog/EntityPage.tsx import { - EntityAzurePipelinesContent, + EntityAzurePullRequestsContent, isAzureDevOpsAvailable, } from '@backstage/plugin-azure-devops'; @@ -112,7 +112,7 @@ To get the Azure Repos component working you'll need to do the following two ste // ... - + // ... @@ -122,7 +122,7 @@ To get the Azure Repos component working you'll need to do the following two ste - You'll need to add the `EntityLayout.Route` above from step 2 to all the entity sections you want to see Pull Requests in. For example if you wanted to see Pull Requests when looking at Website entities then you would need to add this to the `websiteEntityPage` section. - The `if` prop is optional on the `EntityLayout.Route`, you can remove it if you always want to see the tab even if the entity being viewed does not have the needed annotation -- The `defaultLimit` property on the `EntityAzurePipelinesContent` will set the max number of Pull Requests you would like to see, if not set this will default to 10 +- The `defaultLimit` property on the `EntityAzurePullRequestsContent` will set the max number of Pull Requests you would like to see, if not set this will default to 10 ## Limitations From 719cc87d2f2183a6595c60fe8d14b30a50e44188 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 20 Nov 2021 11:24:08 +0100 Subject: [PATCH 42/61] cli: disable ES transform in tests Signed-off-by: Patrik Oldsberg --- .changeset/large-mugs-repair.md | 5 +++++ packages/cli/config/jestSucraseTransform.js | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .changeset/large-mugs-repair.md diff --git a/.changeset/large-mugs-repair.md b/.changeset/large-mugs-repair.md new file mode 100644 index 0000000000..5043fb80e1 --- /dev/null +++ b/.changeset/large-mugs-repair.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Disable ES transforms in tests transformed by the `jestSucraseTransform.js`. This is not considered a breaking change since all code is already transpiled this way in the development setup. diff --git a/packages/cli/config/jestSucraseTransform.js b/packages/cli/config/jestSucraseTransform.js index 01acfee38d..c88909d21f 100644 --- a/packages/cli/config/jestSucraseTransform.js +++ b/packages/cli/config/jestSucraseTransform.js @@ -46,7 +46,11 @@ function process(source, filePath) { } if (transforms) { - return transform(source, { transforms, filePath }).code; + return transform(source, { + transforms, + filePath, + disableESTransforms: true, + }).code; } return source; From dde216acf4317c13f3a21fbed5483d068391d565 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 20 Nov 2021 11:32:22 +0100 Subject: [PATCH 43/61] cli: switch to v8 coverage provider Signed-off-by: Patrik Oldsberg --- .changeset/giant-bees-applaud.md | 5 +++++ packages/cli/config/jest.js | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/giant-bees-applaud.md diff --git a/.changeset/giant-bees-applaud.md b/.changeset/giant-bees-applaud.md new file mode 100644 index 0000000000..c4591dbc64 --- /dev/null +++ b/.changeset/giant-bees-applaud.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Switch the default test coverage provider from the jest default one to `'v8'`, which provides much better coverage information when using the default Backstage test setup. This is considered a bug fix as the current coverage information is often very inaccurate. diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js index e889d23c3a..1d33372c60 100644 --- a/packages/cli/config/jest.js +++ b/packages/cli/config/jest.js @@ -95,6 +95,7 @@ async function getProjectConfig(targetPath, displayName) { ...(displayName && { displayName }), rootDir: path.resolve(targetPath, 'src'), coverageDirectory: path.resolve(targetPath, 'coverage'), + coverageProvider: 'v8', collectCoverageFrom: ['**/*.{js,jsx,ts,tsx}', '!**/*.d.ts'], moduleNameMapper: { '\\.(css|less|scss|sss|styl)$': require.resolve('jest-css-modules'), From ab31a2c2869dcaafc8e1bb61cf1e6419f6334704 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 20 Nov 2021 14:50:10 +0100 Subject: [PATCH 44/61] updated release process to not release new packages immediately Signed-off-by: Patrik Oldsberg --- CONTRIBUTING.md | 4 +++- scripts/check-if-release.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 99d63cf0b4..31f912f43e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,7 +122,9 @@ We use [changesets](https://github.com/atlassian/changesets) to help us prepare Any time a patch, minor, or major change aligning to [Semantic Versioning](https://semver.org) is made to any published package in `packages/` or `plugins/`, a changeset should be used. It helps to align your change to the [Backstage stability index](https://backstage.io/docs/overview/stability-index) for the package you are changing, for example, when to provide additional clarity on deprecation or impacting changes which will then be included into CHANGELOGs. -In general, changesets are not needed for the documentation, build utilities, contributed samples in `contrib/`, or the [example `packages/app`](packages/app). +In general, changesets are only needed for changes to packages within `packages/` or `plugins/` directories, and only for the packages that are not marked as `private`. Changesets are also not needed for changes that do not affect the published version of each package, for example changes to tests or in-line source code comments. + +Changesets **are** needed for new packages, as that is what triggers the package to be part of the next release. ### How to create a changeset diff --git a/scripts/check-if-release.js b/scripts/check-if-release.js index 4475ed6207..b61b0e2eb7 100755 --- a/scripts/check-if-release.js +++ b/scripts/check-if-release.js @@ -96,7 +96,9 @@ async function main() { const newVersions = packageVersions.filter( ({ oldVersion, newVersion }) => - oldVersion !== newVersion && newVersion !== '', + oldVersion !== newVersion && + oldVersion !== '' && + newVersion !== '', ); if (newVersions.length === 0) { From 7673d7b2b3c955a9d5b7e4f7f4bffaec5e9828a8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 20 Nov 2021 14:54:49 +0100 Subject: [PATCH 45/61] set initial version of packages to 0.0.0 Signed-off-by: Patrik Oldsberg --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 322929db1d..4621689664 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "packages": ["packages/*", "plugins/*"], "npmClient": "yarn", "useWorkspaces": true, - "version": "0.1.0" + "version": "0.0.0" } From 2cd2bab86af08901a9b9193da6a2fa6f788709f2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 20 Nov 2021 13:54:34 +0100 Subject: [PATCH 46/61] scripts: add script for listing deprecations Signed-off-by: Patrik Oldsberg --- scripts/list-deprecations.js | 172 +++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100755 scripts/list-deprecations.js diff --git a/scripts/list-deprecations.js b/scripts/list-deprecations.js new file mode 100755 index 0000000000..c5d6e02f9e --- /dev/null +++ b/scripts/list-deprecations.js @@ -0,0 +1,172 @@ +#!/usr/bin/env node +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable import/no-extraneous-dependencies */ + +const _ = require('lodash'); +const fs = require('fs-extra'); +const globby = require('globby'); +const { resolve: resolvePath, relative: relativePath } = require('path'); +const { execFile: execFileCb } = require('child_process'); +const { promisify } = require('util'); + +const execFile = promisify(execFileCb); + +const WORKER_COUNT = 16; + +const deprecatedPattern = /@deprecated|DEPRECATION/; + +class ReleaseProvider { + cache = new Map(); + + async lookup(commitSha) { + if (this.cache.has(commitSha)) { + return this.cache.get(commitSha); + } + + const { stdout: tagOutput } = await execFile( + 'git', + ['tag', '--contains', commitSha], + { shell: true }, + ); + + const [release] = tagOutput + .split('\n') + .filter(l => l.startsWith('release-')); + + this.cache.set(commitSha, release); + return release; + } +} + +async function main() { + const rootPath = resolvePath(__dirname, '..'); + const packageDirQueue = await Promise.all([ + fs.readdir(resolvePath(rootPath, 'packages')), + fs.readdir(resolvePath(rootPath, 'plugins')), + ]).then(([packages, plugins]) => [ + ...packages.map(dir => `packages/${dir}`), + ...plugins.map(dir => `plugins/${dir}`), + ]); + + const fileQueue = []; + const deprecationQueue = []; + const releaseProvider = new ReleaseProvider(); + const deprecations = []; + + await Promise.all( + Array(WORKER_COUNT) + .fill() + .map(async () => { + // Find all files we want to scan + while (packageDirQueue.length) { + const packageDir = packageDirQueue.pop(); + const srcDir = resolvePath(rootPath, packageDir, 'src'); + + if (await fs.pathExists(srcDir)) { + const files = await globby(['**/*.{js,jsx,ts,tsx}'], { + cwd: srcDir, + }); + fileQueue.push(...files.map(file => resolvePath(srcDir, file))); + } + } + + // Parse files and search for deprecations + while (fileQueue.length) { + const file = fileQueue.pop(); + const content = await fs.readFile(file, 'utf8'); + if (!deprecatedPattern.test(content)) { + continue; + } + + const lines = content.split('\n'); + for (const [index, line] of lines.entries()) { + if (deprecatedPattern.test(line)) { + deprecationQueue.push({ + file, + lineNumber: index + 1, + lineContent: line, + }); + } + } + } + + // Lookup git information for each deprecation + while (deprecationQueue.length) { + const deprecation = deprecationQueue.pop(); + + const { file, lineNumber: n, lineContent } = deprecation; + const { stdout: blameOutput } = await execFile( + 'git', + ['blame', '--porcelain', `-L ${n},${n}`, file], + { shell: true }, + ); + + const blameInfo = Object.fromEntries( + blameOutput + .split('\n') + .slice(1, -2) + .map(line => { + const [key] = line.split(' ', 1); + return [key, line.slice(key.length + 1)]; + }), + ); + const [commit] = blameOutput.split(' ', 1); + const { author, ['author-time']: authorTime } = blameInfo; + + const release = await releaseProvider.lookup(commit); + + deprecations.push({ + file: relativePath(rootPath, file), + release, + commit, + author, + authorTime: new Date(authorTime * 1000), + lineContent, + lineNumber: n, + }); + } + }), + ); + + const maxAuthor = Math.max(...deprecations.map(d => d.author.length)) + 1; + + // Group and sort by release + const sortedByRelease = _.sortBy( + Object.entries(_.groupBy(deprecations, 'release')), + ([release]) => release, + ); + + for (const [release, ds] of sortedByRelease) { + console.log(`\n### ${release === 'undefined' ? 'Not released' : release}`); + for (const d of _.sortBy(ds, 'authorTime', 'file', 'lineNumber')) { + console.log( + [ + d.commit.slice(0, 8), + d.authorTime.toLocaleDateString().padEnd('00/00/0000'.length + 1), + d.author.padEnd(maxAuthor + 1), + `${d.file}:${d.lineNumber}`, + ].join(' '), + ); + } + } +} + +main().catch(err => { + console.error(err.stack); + process.exit(1); +}); From 910c2674b501f3070cb3c817fad7d855021dd60b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 20 Nov 2021 15:52:01 +0100 Subject: [PATCH 47/61] test-utils: review fixes Signed-off-by: Patrik Oldsberg --- .changeset/wet-seas-deliver.md | 2 +- packages/test-utils/src/testUtils/TestApiProvider.test.tsx | 3 +-- packages/test-utils/src/testUtils/TestApiProvider.tsx | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.changeset/wet-seas-deliver.md b/.changeset/wet-seas-deliver.md index f625e093f5..da5679eb8e 100644 --- a/.changeset/wet-seas-deliver.md +++ b/.changeset/wet-seas-deliver.md @@ -31,7 +31,7 @@ render( ) ``` -In cases where the `ApiProvider` is used in a more standalone way, for example to reuse a set of APIs across multiple tests, the `TestApiRegistry` can be used instead. Note that the `TestApiRegistry` only has a single static factory method, `.with()`, and it is slightly different from the existing `.with()` method on `ApiRegistry`. +In cases where the `ApiProvider` is used in a more standalone way, for example to reuse a set of APIs across multiple tests, the `TestApiRegistry` can be used instead. Note that the `TestApiRegistry` only has a single static factory method, `.from()`, and it is slightly different from the existing `.from()` method on `ApiRegistry` in that it doesn't require the API pairs to be wrapped in an outer array. Usage that looks like this: diff --git a/packages/test-utils/src/testUtils/TestApiProvider.test.tsx b/packages/test-utils/src/testUtils/TestApiProvider.test.tsx index d3f84f854a..1b981b15ec 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.test.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.test.tsx @@ -16,9 +16,8 @@ import React from 'react'; import { createApiRef, useApiHolder } from '@backstage/core-plugin-api'; -import { TestApiProvider } from './TestApiProvider'; +import { TestApiProvider, TestApiRegistry } from './TestApiProvider'; import { render, screen } from '@testing-library/react'; -import { TestApiRegistry } from '.'; const xApiRef = createApiRef<{ a: string; b: number }>({ id: 'x', diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index 4408fc5b36..b1499b0cde 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -54,7 +54,7 @@ export class TestApiRegistry implements ApiHolder { * * @example * ```ts - * const apis = TestApiRegistry.with( + * const apis = TestApiRegistry.from( * [configApiRef, new ConfigReader({})], * [identityApiRef, { getUserId: () => 'tester' }], * ); From 05ccc8276c4db381bd0390b646fc4213863ea73f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 21 Nov 2021 13:53:33 +0100 Subject: [PATCH 48/61] scripts/list-deprecations: improve release lookup to check for actual release Signed-off-by: Patrik Oldsberg --- scripts/list-deprecations.js | 86 +++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 17 deletions(-) diff --git a/scripts/list-deprecations.js b/scripts/list-deprecations.js index c5d6e02f9e..4056ee8402 100755 --- a/scripts/list-deprecations.js +++ b/scripts/list-deprecations.js @@ -33,23 +33,69 @@ const deprecatedPattern = /@deprecated|DEPRECATION/; class ReleaseProvider { cache = new Map(); - async lookup(commitSha) { - if (this.cache.has(commitSha)) { - return this.cache.get(commitSha); + constructor(rootPath) { + this.rootPath = rootPath; + } + + async lookup(commitSha, packageDir) { + const key = commitSha + packageDir; + + if (this.cache.has(key)) { + return this.cache.get(key); } - const { stdout: tagOutput } = await execFile( - 'git', - ['tag', '--contains', commitSha], - { shell: true }, + const pkgJsonPath = relativePath( + this.rootPath, + resolvePath(this.rootPath, packageDir, 'package.json'), ); + const releasePromise = Promise.resolve().then(async () => { + // Find all tags that contain the commit + const { stdout: tagOutput } = await execFile( + 'git', + ['tag', '--contains', commitSha], + { shell: true }, + ); - const [release] = tagOutput - .split('\n') - .filter(l => l.startsWith('release-')); + // Filter out just the releases + const releases = tagOutput + .split('\n') + .filter(l => l.startsWith('release-')); - this.cache.set(commitSha, release); - return release; + // Then find the earliest release that affected our package + for (const release of releases) { + let oldVersion; + let newVersion; + + try { + const { stdout: content } = await execFile( + 'git', + ['show', `${release}^:${pkgJsonPath}`], + { shell: true }, + ); + oldVersion = JSON.parse(content).version; + } catch { + /* */ + } + try { + const { stdout: content } = await execFile( + 'git', + ['show', `${release}:${pkgJsonPath}`], + { shell: true }, + ); + newVersion = JSON.parse(content).version; + } catch { + /* */ + } + + if (oldVersion !== newVersion) { + return release; + } + } + return undefined; + }); + + this.cache.set(key, releasePromise); + return releasePromise; } } @@ -65,7 +111,7 @@ async function main() { const fileQueue = []; const deprecationQueue = []; - const releaseProvider = new ReleaseProvider(); + const releaseProvider = new ReleaseProvider(rootPath); const deprecations = []; await Promise.all( @@ -81,13 +127,18 @@ async function main() { const files = await globby(['**/*.{js,jsx,ts,tsx}'], { cwd: srcDir, }); - fileQueue.push(...files.map(file => resolvePath(srcDir, file))); + fileQueue.push( + ...files.map(file => ({ + packageDir, + file: resolvePath(srcDir, file), + })), + ); } } // Parse files and search for deprecations while (fileQueue.length) { - const file = fileQueue.pop(); + const { packageDir, file } = fileQueue.pop(); const content = await fs.readFile(file, 'utf8'); if (!deprecatedPattern.test(content)) { continue; @@ -97,6 +148,7 @@ async function main() { for (const [index, line] of lines.entries()) { if (deprecatedPattern.test(line)) { deprecationQueue.push({ + packageDir, file, lineNumber: index + 1, lineContent: line, @@ -109,7 +161,7 @@ async function main() { while (deprecationQueue.length) { const deprecation = deprecationQueue.pop(); - const { file, lineNumber: n, lineContent } = deprecation; + const { file, packageDir, lineNumber: n, lineContent } = deprecation; const { stdout: blameOutput } = await execFile( 'git', ['blame', '--porcelain', `-L ${n},${n}`, file], @@ -128,7 +180,7 @@ async function main() { const [commit] = blameOutput.split(' ', 1); const { author, ['author-time']: authorTime } = blameInfo; - const release = await releaseProvider.lookup(commit); + const release = await releaseProvider.lookup(commit, packageDir); deprecations.push({ file: relativePath(rootPath, file), From 08dc0d6788472521fa6863032d36cf99b101cb76 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 21 Nov 2021 15:09:42 +0100 Subject: [PATCH 49/61] scripts/list-deprecations: allow args to be passed to filter packages Signed-off-by: Patrik Oldsberg --- scripts/list-deprecations.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/scripts/list-deprecations.js b/scripts/list-deprecations.js index 4056ee8402..920b01c7b5 100755 --- a/scripts/list-deprecations.js +++ b/scripts/list-deprecations.js @@ -100,14 +100,19 @@ class ReleaseProvider { } async function main() { + let packageDirQueue = process.argv.slice(2); + const rootPath = resolvePath(__dirname, '..'); - const packageDirQueue = await Promise.all([ - fs.readdir(resolvePath(rootPath, 'packages')), - fs.readdir(resolvePath(rootPath, 'plugins')), - ]).then(([packages, plugins]) => [ - ...packages.map(dir => `packages/${dir}`), - ...plugins.map(dir => `plugins/${dir}`), - ]); + + if (packageDirQueue.length === 0) { + packageDirQueue = await Promise.all([ + fs.readdir(resolvePath(rootPath, 'packages')), + fs.readdir(resolvePath(rootPath, 'plugins')), + ]).then(([packages, plugins]) => [ + ...packages.map(dir => `packages/${dir}`), + ...plugins.map(dir => `plugins/${dir}`), + ]); + } const fileQueue = []; const deprecationQueue = []; From 07699d303fc2b7b3e10b5c4d4d769393b7c451a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Sun, 21 Nov 2021 21:15:01 +0100 Subject: [PATCH 50/61] Fix broken frontmatter on blog entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- microsite/blog/2020-05-22-phase-2-service-catalog.md | 2 +- microsite/blog/2020-09-08-announcing-tech-docs.md | 2 +- microsite/blog/2020-10-22-cost-insights-plugin.md | 2 +- ...01-12-new-backstage-feature-kubernetes-for-service-owners.md | 2 +- .../blog/2021-06-24-announcing-backstage-search-platform.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/microsite/blog/2020-05-22-phase-2-service-catalog.md b/microsite/blog/2020-05-22-phase-2-service-catalog.md index 520a2a5f10..2df8ce84f3 100644 --- a/microsite/blog/2020-05-22-phase-2-service-catalog.md +++ b/microsite/blog/2020-05-22-phase-2-service-catalog.md @@ -1,5 +1,5 @@ --- -title: Starting Phase 2: The Service Catalog +title: 'Starting Phase 2: The Service Catalog' author: Stefan Ålund, Spotify authorURL: http://twitter.com/stalund authorImageURL: https://pbs.twimg.com/profile_images/121166861/6919c047c0d0edaace78c3009b28e917-user-full-200-130.generated_400x400.jpg diff --git a/microsite/blog/2020-09-08-announcing-tech-docs.md b/microsite/blog/2020-09-08-announcing-tech-docs.md index 98fbad57c5..f9d7359526 100644 --- a/microsite/blog/2020-09-08-announcing-tech-docs.md +++ b/microsite/blog/2020-09-08-announcing-tech-docs.md @@ -1,5 +1,5 @@ --- -title: Announcing TechDocs: Spotify’s docs-like-code plugin for Backstage +title: 'Announcing TechDocs: Spotify’s docs-like-code plugin for Backstage' author: Gary Niemen, Spotify authorURL: https://github.com/garyniemen --- diff --git a/microsite/blog/2020-10-22-cost-insights-plugin.md b/microsite/blog/2020-10-22-cost-insights-plugin.md index d265698694..139e9a7ce9 100644 --- a/microsite/blog/2020-10-22-cost-insights-plugin.md +++ b/microsite/blog/2020-10-22-cost-insights-plugin.md @@ -1,5 +1,5 @@ --- -title: New Cost Insights plugin: The engineer’s solution to taming cloud costs +title: 'New Cost Insights plugin: The engineer’s solution to taming cloud costs' author: Janisa Anandamohan, Spotify authorURL: https://twitter.com/janisa_a --- diff --git a/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.md b/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.md index a0d11a580f..9b8c4637bd 100644 --- a/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.md +++ b/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.md @@ -1,5 +1,5 @@ --- -title: New Backstage feature: Kubernetes for Service owners +title: 'New Backstage feature: Kubernetes for Service owners' author: Matthew Clarke, Spotify authorURL: https://github.com/mclarke47 --- diff --git a/microsite/blog/2021-06-24-announcing-backstage-search-platform.md b/microsite/blog/2021-06-24-announcing-backstage-search-platform.md index 0a4ae572c2..6e6c9b7819 100644 --- a/microsite/blog/2021-06-24-announcing-backstage-search-platform.md +++ b/microsite/blog/2021-06-24-announcing-backstage-search-platform.md @@ -1,5 +1,5 @@ --- -title: Announcing the Backstage Search platform: a customizable search tool built just for you +title: 'Announcing the Backstage Search platform: a customizable search tool built just for you' author: Emma Indal, Spotify authorURL: https://www.linkedin.com/in/emma-indal --- From 58aaad546e6c2f081aa79c33af2f4e07a29ec2cc Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Sun, 21 Nov 2021 22:01:33 -0500 Subject: [PATCH 51/61] Refactor script var typo Signed-off-by: Adam Harvey --- .changeset/backstage-changelog.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/backstage-changelog.js b/.changeset/backstage-changelog.js index ea8ca2300b..22038b348b 100644 --- a/.changeset/backstage-changelog.js +++ b/.changeset/backstage-changelog.js @@ -23,13 +23,13 @@ const { async function getDependencyReleaseLine(changesets, dependenciesUpdated) { if (dependenciesUpdated.length === 0) return ''; - const updatedDepenenciesList = dependenciesUpdated.map( + const updatedDependenciesList = dependenciesUpdated.map( dependency => ` - ${dependency.name}@${dependency.newVersion}`, ); // Return one `Updated dependencies` bullet instead of repeating for each changeset; this // sacrifices the commit shas for brevity. - return ['- Updated dependencies', ...updatedDepenenciesList].join('\n'); + return ['- Updated dependencies', ...updatedDependenciesList].join('\n'); } module.exports = { From 3c15ad9a55bd83d2bd135081fa91e48b7c6568b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Nov 2021 04:13:50 +0000 Subject: [PATCH 52/61] chore(deps): bump @octokit/webhooks from 9.17.0 to 9.18.0 Bumps [@octokit/webhooks](https://github.com/octokit/webhooks.js) from 9.17.0 to 9.18.0. - [Release notes](https://github.com/octokit/webhooks.js/releases) - [Commits](https://github.com/octokit/webhooks.js/compare/v9.17.0...v9.18.0) --- updated-dependencies: - dependency-name: "@octokit/webhooks" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 29145d1154..27da8beb90 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5072,19 +5072,19 @@ resolved "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz#1108b9ea661ca6c81e4a8bfa63a09eb27d5bc2db" integrity sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig== -"@octokit/webhooks-types@4.12.0": - version "4.12.0" - resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-4.12.0.tgz#add8b98d60ab42e965c4ba31040097f810e222de" - integrity sha512-G0k7CoS9bK+OI7kPHgqi1KqK4WhrjDQSjy0wJI+0OTx/xvbHUIZDeqatY60ceeRINP/1ExEk6kTARboP0xavEw== +"@octokit/webhooks-types@4.15.0": + version "4.15.0" + resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-4.15.0.tgz#1158cba6578237d60957a37963a4a05654f5668b" + integrity sha512-s9LgKsUzq/JH3PWDjaD/m1DIlC/QWgBWbmXVqjdxJXJQBA67KZrLWjStVlYPf0mWlVZ1MOKphDyHiOGCbs0+Kg== "@octokit/webhooks@^9.14.1": - version "9.17.0" - resolved "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.17.0.tgz#81140b2e127157aa9817d085cd8758545e4a72e4" - integrity sha512-/+9WSLuDuoqNWnMY4w6ePioILBqsUOiUt0ygQzugYzd112WB+yPIjmUQjAbNXImDsAa1myLpBICAMQDZlULyAA== + version "9.18.0" + resolved "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.18.0.tgz#19cc70e1ef281e33d830ea23e8011d25d8051f7f" + integrity sha512-N2hP7vCouKk9UWZxvqgWTPbp34i6g9Om/jk+TZeZ5Z+VsKjXvGtONlEd9H8DM1yOeEC+ARDpfhraX6UsK5tesQ== dependencies: "@octokit/request-error" "^2.0.2" "@octokit/webhooks-methods" "^2.0.0" - "@octokit/webhooks-types" "4.12.0" + "@octokit/webhooks-types" "4.15.0" aggregate-error "^3.1.0" "@open-draft/until@^1.0.3": From 73438d1ff10b751701e948d5be01b800916cd7fc Mon Sep 17 00:00:00 2001 From: Ainhoa Larumbe Date: Mon, 22 Nov 2021 09:41:00 +0000 Subject: [PATCH 53/61] change methods to private Signed-off-by: Ainhoa Larumbe --- plugins/catalog-backend/api-report.md | 5 ----- .../catalog-backend/src/search/DefaultCatalogCollator.ts | 9 +++++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 6c8c9a8f82..6660912dda 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -32,7 +32,6 @@ import { Router } from 'express'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { ScmIntegrations } from '@backstage/integration'; import { UrlReader } from '@backstage/backend-common'; -import { UserEntity } from '@backstage/catalog-model'; import { Validators } from '@backstage/catalog-model'; // Warning: (ae-missing-release-tag) "AddLocationResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -765,10 +764,6 @@ export class DefaultCatalogCollator implements DocumentCollator { }, ): DefaultCatalogCollator; // (undocumented) - protected getDocumentText(entity: Entity): string; - // (undocumented) - protected isUserEntity(entity: Entity): entity is UserEntity; - // (undocumented) protected locationTemplate: string; // (undocumented) readonly type: string; diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index 5458b9054a..751ea30832 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -81,16 +81,17 @@ export class DefaultCatalogCollator implements DocumentCollator { return formatted.toLowerCase(); } - protected isUserEntity(entity: Entity): entity is UserEntity { + private isUserEntity(entity: Entity): entity is UserEntity { return entity.kind === 'User'; } - protected getDocumentText(entity: Entity): string { + private getDocumentText(entity: Entity): string { let documentText = entity.metadata.description || ''; if (this.isUserEntity(entity)) { - if (entity.spec?.profile?.displayName && entity.metadata.description) { + if (entity.spec?.profile?.displayName && documentText) { // combine displayName and description - documentText = `${entity.spec?.profile?.displayName} : ${entity.metadata.description}`; + const displayName = entity.spec?.profile?.displayName; + documentText = displayName.concat(' : ', documentText); } else { documentText = entity.spec?.profile?.displayName || documentText; } From 4f3f55f15feddead13e29e940192bdb6ea48fa54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 22 Nov 2021 10:57:56 +0100 Subject: [PATCH 54/61] bump terser-webpack-plugin and therefore serialize-javascript MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- yarn.lock | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 27da8beb90..730d4533de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25628,10 +25628,12 @@ serialize-error@^8.0.1, serialize-error@^8.1.0: dependencies: type-fest "^0.20.2" -serialize-javascript@^2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" - integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" serialize-javascript@^5.0.1: version "5.0.1" @@ -27209,15 +27211,15 @@ terser-webpack-plugin@*, terser-webpack-plugin@^5.1.3: terser "^5.7.2" terser-webpack-plugin@^1.4.3: - version "1.4.3" - resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" - integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== + version "1.4.5" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^2.1.2" + serialize-javascript "^4.0.0" source-map "^0.6.1" terser "^4.1.2" webpack-sources "^1.4.0" From 84ea8bf56676b25adca67e5489b1cd11857d4221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 22 Nov 2021 11:09:46 +0100 Subject: [PATCH 55/61] make sure to get rid of is-svg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- yarn.lock | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/yarn.lock b/yarn.lock index 27da8beb90..b8642e26d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16266,11 +16266,6 @@ hsla-regex@^1.0.0: resolved "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= -html-comment-regex@^1.1.0: - version "1.1.2" - resolved "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== - html-encoding-sniffer@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" @@ -17484,13 +17479,6 @@ is-subdir@^1.1.1: dependencies: better-path-resolve "1.0.0" -is-svg@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== - dependencies: - html-comment-regex "^1.1.0" - is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" @@ -23181,11 +23169,10 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector util-deprecate "^1.0.2" postcss-svgo@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" - integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== + version "4.0.3" + resolved "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz#343a2cdbac9505d416243d496f724f38894c941e" + integrity sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw== dependencies: - is-svg "^3.0.0" postcss "^7.0.0" postcss-value-parser "^3.0.0" svgo "^1.0.0" From 45dbf26094e0fdc721b1f977cc643225f899005c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 22 Nov 2021 11:15:18 +0100 Subject: [PATCH 56/61] bump mixme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 27da8beb90..788549ca7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20755,10 +20755,10 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mixme@^0.3.1: - version "0.3.5" - resolved "https://registry.npmjs.org/mixme/-/mixme-0.3.5.tgz#304652cdaf24a3df0487205e61ac6162c6906ddd" - integrity sha512-SyV9uPETRig5ZmYev0ANfiGeB+g6N2EnqqEfBbCGmmJ6MgZ3E4qv5aPbnHVdZ60KAHHXV+T3sXopdrnIXQdmjQ== +mixme@^0.5.1: + version "0.5.4" + resolved "https://registry.npmjs.org/mixme/-/mixme-0.5.4.tgz#8cb3bd0cd32a513c161bf1ca99d143f0bcf2eff3" + integrity sha512-3KYa4m4Vlqx98GPdOHghxSdNtTvcP8E0kkaJ5Dlh+h2DRzF7zpuVVcA8B0QpKd11YJeP9QQ7ASkKzOeu195Wzw== mkdirp-classic@^0.5.2: version "0.5.2" @@ -26469,11 +26469,11 @@ stream-shift@^1.0.0: integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== stream-transform@^2.0.1: - version "2.0.2" - resolved "https://registry.npmjs.org/stream-transform/-/stream-transform-2.0.2.tgz#3cb7a14c802eb39bc40caaab0535e584f3a65caf" - integrity sha512-J+D5jWPF/1oX+r9ZaZvEXFbu7znjxSkbNAHJ9L44bt/tCVuOEWZlDqU9qJk7N2xBU1S+K2DPpSKeR/MucmCA1Q== + version "2.1.3" + resolved "https://registry.npmjs.org/stream-transform/-/stream-transform-2.1.3.tgz#a1c3ecd72ddbf500aa8d342b0b9df38f5aa598e3" + integrity sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ== dependencies: - mixme "^0.3.1" + mixme "^0.5.1" streamsearch@0.1.2: version "0.1.2" From 776cb9c1c592c7ddbaf0bd7336899a145405b50c Mon Sep 17 00:00:00 2001 From: Pete Jespers Date: Mon, 22 Nov 2021 11:04:11 +0000 Subject: [PATCH 57/61] Fix QBE name in adopters list --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index e2585184b2..67aa8ec709 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -70,4 +70,4 @@ | [PicPay](https://www.picpay.com) | [Luis Baroni](https://github.com/lcsbaroni), [Renata Poluceno](https://github.com/renatapoluceno), [PicPay](https://github.com/picpay) | Developer portal for building services throught templates, service catalog with ownership of services, documentation and metrics providing autonomy and visibility for all. | | [Epic Games](https://www.epicgames.com) | [Brian Jung](https://github.com/brian-at-epic), [Jeff Goldian](https://github.com/jeffgoldian-Epic) | Developer Portal: Service Catalog, Documentation, Software Templates and more making our internal teams' lives easier! | | [Globo](https://globo.com) | [Carlos Gusmão](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. | -| [QBE Ltd](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly 🚀 | \ No newline at end of file +| [QBE](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly 🚀 | \ No newline at end of file From e5bff80f786841550d024968d7182d14d8bbdfdd Mon Sep 17 00:00:00 2001 From: Ainhoa Larumbe Date: Mon, 22 Nov 2021 11:44:54 +0000 Subject: [PATCH 58/61] uppercase kind Signed-off-by: Ainhoa Larumbe --- plugins/catalog-backend/src/search/DefaultCatalogCollator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index 751ea30832..0f7cdb62b4 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -82,7 +82,7 @@ export class DefaultCatalogCollator implements DocumentCollator { } private isUserEntity(entity: Entity): entity is UserEntity { - return entity.kind === 'User'; + return entity.kind.toUpperCase() === 'USER'; } private getDocumentText(entity: Entity): string { From 9312572360b69d65bcc2165a1f3c157a60c1eb54 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 22 Nov 2021 13:17:26 +0100 Subject: [PATCH 59/61] auth-backend: use more standardized error responses Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .changeset/forty-teachers-argue.md | 5 +++ .../src/lib/oauth/OAuthAdapter.test.ts | 20 ++++------- .../src/lib/oauth/OAuthAdapter.ts | 28 +++++++-------- .../src/lib/oauth/OAuthEnvironmentHandler.ts | 36 ++++++++----------- 4 files changed, 41 insertions(+), 48 deletions(-) create mode 100644 .changeset/forty-teachers-argue.md diff --git a/.changeset/forty-teachers-argue.md b/.changeset/forty-teachers-argue.md new file mode 100644 index 0000000000..2e32719037 --- /dev/null +++ b/.changeset/forty-teachers-argue.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Switched to using the standardized JSON error responses for all provider endpoints. diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts index dfb3a0a79a..fa61d69d80 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts @@ -176,7 +176,7 @@ describe('OAuthAdapter', () => { const mockResponse = { cookie: jest.fn().mockReturnThis(), - send: jest.fn().mockReturnThis(), + end: jest.fn().mockReturnThis(), status: jest.fn().mockReturnThis(), } as unknown as express.Response; @@ -187,6 +187,7 @@ describe('OAuthAdapter', () => { '', expect.objectContaining({ path: '/auth/test-provider' }), ); + expect(mockResponse.end).toHaveBeenCalledTimes(1); }); it('gets new access-token when refreshing', async () => { @@ -230,21 +231,14 @@ describe('OAuthAdapter', () => { const mockRequest = { header: () => 'XMLHttpRequest', - cookies: { - 'test-provider-refresh-token': 'token', - }, - query: {}, } as unknown as express.Request; - const mockResponse = { - send: jest.fn().mockReturnThis(), - status: jest.fn().mockReturnThis(), - } as unknown as express.Response; + const mockResponse = {} as unknown as express.Response; - await oauthProvider.refresh(mockRequest, mockResponse); - expect(mockResponse.send).toHaveBeenCalledTimes(1); - expect(mockResponse.send).toHaveBeenCalledWith( - 'Refresh token not supported for provider: test-provider', + await expect( + oauthProvider.refresh(mockRequest, mockResponse), + ).rejects.toThrow( + 'Refresh token is not supported for provider test-provider', ); }); }); diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts index 24b9a0f210..e1a6fdf2f9 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts @@ -22,7 +22,12 @@ import { BackstageIdentity, AuthProviderConfig, } from '../../providers/types'; -import { InputError, isError, NotAllowedError } from '@backstage/errors'; +import { + AuthenticationError, + InputError, + isError, + NotAllowedError, +} from '@backstage/errors'; import { TokenIssuer } from '../../identity/types'; import { readState, verifyNonce } from './helpers'; import { postMessageResponse, ensuresXRequestedWith } from '../flow'; @@ -166,29 +171,24 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { async logout(req: express.Request, res: express.Response): Promise { if (!ensuresXRequestedWith(req)) { - res.status(401).send('Invalid X-Requested-With header'); - return; + throw new AuthenticationError('Invalid X-Requested-With header'); } // remove refresh token cookie if it is set this.removeRefreshTokenCookie(res); - res.status(200).send('logout!'); + res.status(200).end(); } async refresh(req: express.Request, res: express.Response): Promise { if (!ensuresXRequestedWith(req)) { - res.status(401).send('Invalid X-Requested-With header'); - return; + throw new AuthenticationError('Invalid X-Requested-With header'); } if (!this.handlers.refresh || this.options.disableRefresh) { - res - .status(400) - .send( - `Refresh token not supported for provider: ${this.options.providerId}`, - ); - return; + throw new InputError( + `Refresh token is not supported for provider ${this.options.providerId}`, + ); } try { @@ -197,7 +197,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { // throw error if refresh token is missing in the request if (!refreshToken) { - throw new Error('Missing session cookie'); + throw new InputError('Missing session cookie'); } const scope = req.query.scope?.toString() ?? ''; @@ -220,7 +220,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { res.status(200).json(response); } catch (error) { - res.status(401).send(String(error)); + throw new AuthenticationError('Refresh failed', error); } } diff --git a/plugins/auth-backend/src/lib/oauth/OAuthEnvironmentHandler.ts b/plugins/auth-backend/src/lib/oauth/OAuthEnvironmentHandler.ts index a2f427e741..95a0547a5e 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthEnvironmentHandler.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthEnvironmentHandler.ts @@ -16,7 +16,7 @@ import express from 'express'; import { Config } from '@backstage/config'; -import { InputError } from '@backstage/errors'; +import { InputError, NotFoundError } from '@backstage/errors'; import { readState } from './helpers'; import { AuthProviderRouteHandlers } from '../../providers/types'; @@ -42,26 +42,26 @@ export class OAuthEnvironmentHandler implements AuthProviderRouteHandlers { ) {} async start(req: express.Request, res: express.Response): Promise { - const provider = this.getProviderForEnv(req, res); - await provider?.start(req, res); + const provider = this.getProviderForEnv(req); + await provider.start(req, res); } async frameHandler( req: express.Request, res: express.Response, ): Promise { - const provider = this.getProviderForEnv(req, res); - await provider?.frameHandler(req, res); + const provider = this.getProviderForEnv(req); + await provider.frameHandler(req, res); } async refresh(req: express.Request, res: express.Response): Promise { - const provider = this.getProviderForEnv(req, res); - await provider?.refresh?.(req, res); + const provider = this.getProviderForEnv(req); + await provider.refresh?.(req, res); } async logout(req: express.Request, res: express.Response): Promise { - const provider = this.getProviderForEnv(req, res); - await provider?.logout?.(req, res); + const provider = this.getProviderForEnv(req); + await provider.logout?.(req, res); } private getRequestFromEnv(req: express.Request): string | undefined { @@ -77,26 +77,20 @@ export class OAuthEnvironmentHandler implements AuthProviderRouteHandlers { return env; } - private getProviderForEnv( - req: express.Request, - res: express.Response, - ): AuthProviderRouteHandlers | undefined { + private getProviderForEnv(req: express.Request): AuthProviderRouteHandlers { const env: string | undefined = this.getRequestFromEnv(req); if (!env) { throw new InputError(`Must specify 'env' query to select environment`); } - if (!this.handlers.has(env)) { - res.status(404).send( - `Missing configuration. -
-
- For this flow to work you need to supply a valid configuration for the "${env}" environment of provider.`, + const handler = this.handlers.get(env); + if (!handler) { + throw new NotFoundError( + `No configuration available for the '${env}' environment of this provider.`, ); - return undefined; } - return this.handlers.get(env); + return handler; } } From 4167f6ed7ec80e0b34da2aee78aa537e5a4b4232 Mon Sep 17 00:00:00 2001 From: Ainhoa Larumbe Date: Mon, 22 Nov 2021 12:42:22 +0000 Subject: [PATCH 60/61] change uppercase method Signed-off-by: Ainhoa Larumbe --- plugins/catalog-backend/src/search/DefaultCatalogCollator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index 0f7cdb62b4..3e19b38ea6 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -82,7 +82,7 @@ export class DefaultCatalogCollator implements DocumentCollator { } private isUserEntity(entity: Entity): entity is UserEntity { - return entity.kind.toUpperCase() === 'USER'; + return entity.kind.toLocaleUpperCase('en-US') === 'USER'; } private getDocumentText(entity: Entity): string { From 7b4db0d1aa2d6e7d102a85c5c956241e33add840 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 22 Nov 2021 09:17:19 -0500 Subject: [PATCH 61/61] Fix missing ADR number in title Signed-off-by: Adam Harvey --- .../adr012-use-luxon-locale-and-date-presets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture-decisions/adr012-use-luxon-locale-and-date-presets.md b/docs/architecture-decisions/adr012-use-luxon-locale-and-date-presets.md index a9a5ef5849..0893c105f4 100644 --- a/docs/architecture-decisions/adr012-use-luxon-locale-and-date-presets.md +++ b/docs/architecture-decisions/adr012-use-luxon-locale-and-date-presets.md @@ -1,6 +1,6 @@ --- id: adrs-adr012 -title: ADR000: Use Luxon.toLocaleString and date/time presets +title: ADR012: Use Luxon.toLocaleString and date/time presets description: Architecture Decision Record (ADR) for using Luxon's toLocaleString method and date/time presets for displaying dates and times ---