From d0c47ec505bbfa4e77ec546fffd4b201d0463cb3 Mon Sep 17 00:00:00 2001 From: Guilherme Oenning Date: Tue, 16 Nov 2021 11:34:52 +0000 Subject: [PATCH 001/138] 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 002/138] 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 003/138] 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 004/138] 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 005/138] 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 006/138] 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 007/138] 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 008/138] 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 009/138] 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 010/138] 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 011/138] 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 012/138] 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 013/138] 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 014/138] 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 015/138] 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 c4ed75622bf01d08d0b67a7d03a0e43d74fbedaa Mon Sep 17 00:00:00 2001 From: Chad Jensen Date: Wed, 17 Nov 2021 11:29:21 -0600 Subject: [PATCH 016/138] Letting GraphiQL use headers Letting GraphiQL use headers in browser Signed-off-by: Chad Jensen Signed-off-by: Chad Jensen --- .../graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx index b4321343a1..3a75b9a6cc 100644 --- a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx +++ b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx @@ -73,7 +73,7 @@ export const GraphiQLBrowser = ({ endpoints }: GraphiQLBrowserProps) => {
- +
From cd398cd4ab0b3599118923a49103a5bd186bb54e Mon Sep 17 00:00:00 2001 From: Chad Jensen Date: Wed, 17 Nov 2021 11:31:05 -0600 Subject: [PATCH 017/138] Create young-sheep-impress.md Signed-off-by: Chad Jensen --- .changeset/young-sheep-impress.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/young-sheep-impress.md diff --git a/.changeset/young-sheep-impress.md b/.changeset/young-sheep-impress.md new file mode 100644 index 0000000000..ac185bbfb4 --- /dev/null +++ b/.changeset/young-sheep-impress.md @@ -0,0 +1,5 @@ +--- +"@backstage/plugin-graphiql": patch +--- + +Letting GraphiQL use headers From 2dc6eb8fdd671b68298279672dc260bdb2177442 Mon Sep 17 00:00:00 2001 From: goenning Date: Wed, 17 Nov 2021 18:52:57 +0000 Subject: [PATCH 018/138] 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 e9ad91717e21dde1614fac74c161ede54601a9ce Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 17 Nov 2021 21:28:40 +0100 Subject: [PATCH 019/138] chore: bumping dockerode and testcontainers dependency to fix ssh2 Signed-off-by: blam --- yarn.lock | 138 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 60 deletions(-) diff --git a/yarn.lock b/yarn.lock index debcf79d8e..3188052baf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6763,6 +6763,13 @@ dependencies: "@types/glob" "*" +"@types/archiver@^5.1.1": + version "5.1.1" + resolved "https://registry.npmjs.org/@types/archiver/-/archiver-5.1.1.tgz#d6d7610de4386b293abd5c1cb1875e0a4f4e1c30" + integrity sha512-heuaCk0YH5m274NOLSi66H1zX6GtZoMsdE6TYFcpFFjBjg0FoU4i4/M/a/kNlgNg26Xk3g364mNOYe1JaiEPOQ== + dependencies: + "@types/glob" "*" + "@types/argparse@1.0.38": version "1.0.38" resolved "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" @@ -7060,14 +7067,14 @@ integrity sha512-jrm2K65CokCCX4NmowtA+MfXyuprZC13jbRuwprs6/04z/EcFg/MCwYdsHn+zgV4CQBiATiI7AEq7y1sZCtWKA== "@types/docker-modem@*": - version "3.0.1" - resolved "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.1.tgz#2a29c914dd64c4c9213510d2ce75fa85232934df" - integrity sha512-ZUXPF0WNnvs7AxoQRijt+DW2jsXnWCk8ac28tTYzTpBNnOEIAw83A+pYkCXjTFdJHMTc+wUmwNr71Zy2TRjlWg== + version "3.0.2" + resolved "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.2.tgz#c49c902e17364fc724e050db5c1d2b298c6379d4" + integrity sha512-qC7prjoEYR2QEe6SmCVfB1x3rfcQtUr1n4x89+3e0wSTMQ/KYCyf+/RAA9n2tllkkNc6//JMUZePdFRiGIWfaQ== dependencies: "@types/node" "*" "@types/ssh2" "*" -"@types/dockerode@^3.2.1": +"@types/dockerode@^3.2.1", "@types/dockerode@^3.2.5": version "3.3.0" resolved "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.0.tgz#d6afcc1de31e211ee900da3a48ef4f1a496cf05a" integrity sha512-3Mc0b2gnypJB8Gwmr+8UVPkwjpf4kg1gVxw8lAI4Y/EzpK50LixU1wBSPN9D+xqiw2Ubb02JO8oM0xpwzvi2mg== @@ -8010,10 +8017,10 @@ "@types/node" "*" "@types/ssh2-streams" "*" -"@types/ssh2@^0.5.45": - version "0.5.46" - resolved "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.46.tgz#e12341a242aea0e98ac2dec89e039bf421fd3584" - integrity sha512-1pC8FHrMPYdkLoUOwTYYifnSEPzAFZRsp3JFC/vokQ+dRrVI+hDBwz0SNmQ3pL6h39OSZlPs0uCG7wKJkftnaA== +"@types/ssh2@^0.5.48": + version "0.5.48" + resolved "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.48.tgz#0d9e8654a76eaaf4cfeaeb88d74c4489cfcf7aea" + integrity sha512-cmQu0gp/6RtDXe1r2xXGgi0V0TeCdueDSRMEvBX8cTRT/sSREkUpgCYZLyh+iI8Ql+VNV8Az9toQoYa/IdgHbQ== dependencies: "@types/node" "*" "@types/ssh2-streams" "*" @@ -9028,7 +9035,7 @@ any-observable@^0.3.0: resolved "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== -any-promise@^1.0.0, any-promise@^1.1.0: +any-promise@^1.0.0: version "1.3.0" resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= @@ -9467,7 +9474,7 @@ asn1.js@^4.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -asn1@^0.2.4, asn1@~0.2.0, asn1@~0.2.3: +asn1@^0.2.4, asn1@~0.2.3: version "0.2.4" resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== @@ -11884,6 +11891,13 @@ cp-file@^7.0.0: nested-error-stacks "^2.0.0" p-event "^4.1.0" +cpu-features@0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.2.tgz#9f636156f1155fd04bdbaa028bb3c2fbef3cea7a" + integrity sha512-/2yieBqvMcRj8McNzkycjW2v3OIUOibBfd2dLEJ0nWts8NobAxwiyw9phVNS6oDL8x8tz9F7uNVFEVpJncQpeA== + dependencies: + nan "^2.14.1" + cpy@^8.1.1: version "8.1.1" resolved "https://registry.npmjs.org/cpy/-/cpy-8.1.1.tgz#066ed4c6eaeed9577df96dae4db9438c1a90df62" @@ -13078,27 +13092,27 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" -docker-compose@^0.23.10: - version "0.23.12" - resolved "https://registry.npmjs.org/docker-compose/-/docker-compose-0.23.12.tgz#fa883b98be08f6926143d06bf9e522ef7ed3210c" - integrity sha512-KFbSMqQBuHjTGZGmYDOCO0L4SaML3BsWTId5oSUyaBa22vALuFHNv+UdDWs3HcMylHWKsxCbLB7hnM/nCosWZw== +docker-compose@^0.23.13: + version "0.23.13" + resolved "https://registry.npmjs.org/docker-compose/-/docker-compose-0.23.13.tgz#77d37bd05b6a966345f631e6d05e961c79514f06" + integrity sha512-/9fYC4g3AO+qsqxIZhmbVnFvJJPcYEV2yJbAPPXH+6AytU3urIY8lUAXOlvY8sl4u25pdKu1JrOfAmWC7lJDJg== dependencies: yaml "^1.10.2" docker-modem@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.0.tgz#cb912ad8daed42f858269fb3be6944df281ec12d" - integrity sha512-WwFajJ8I5geZ/dDZ5FDMDA6TBkWa76xWwGIGw8uzUjNUGCN0to83wJ8Oi1AxrJTC0JBn+7fvIxUctnawtlwXeg== + version "3.0.3" + resolved "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.3.tgz#ac4bb1f32f81ac2e7120c5e99a068fab2458a32f" + integrity sha512-Tgkn2a+yiNP9FoZgMa/D9Wk+D2Db///0KOyKSYZRJa8w4+DzKyzQMkczKSdR/adQ0x46BOpeNkoyEOKjPhCzjw== dependencies: debug "^4.1.1" readable-stream "^3.5.0" split-ca "^1.0.1" - ssh2 "^0.8.7" + ssh2 "^1.4.0" -dockerode@^3.2.1: - version "3.3.0" - resolved "https://registry.npmjs.org/dockerode/-/dockerode-3.3.0.tgz#bedaf48ef9fa9124275a54a9881a92374c51008e" - integrity sha512-St08lfOjpYCOXEM8XA0VLu3B3hRjtddODphNW5GFoA0AS3JHgoPQKOz0Qmdzg3P+hUPxhb02g1o1Cu1G+U3lRg== +dockerode@^3.2.1, dockerode@^3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/dockerode/-/dockerode-3.3.1.tgz#74f66e239e092e7910e2beae6322d35c44b08cdc" + integrity sha512-AS2mr8Lp122aa5n6d99HkuTNdRV1wkkhHwBdcnY6V0+28D3DSYwhxAk85/mM9XwD3RMliTxyr63iuvn5ZblFYQ== dependencies: docker-modem "^3.0.0" tar-fs "~2.0.1" @@ -15430,6 +15444,18 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, gl once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.2.0: + version "7.2.0" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-dirs@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201" @@ -20928,6 +20954,11 @@ nan@^2.12.1, nan@^2.14.0: resolved "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== +nan@^2.14.1, nan@^2.15.0: + version "2.15.0" + resolved "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + nano-css@^5.1.0, nano-css@^5.3.1: version "5.3.1" resolved "https://registry.npmjs.org/nano-css/-/nano-css-5.3.1.tgz#b709383e07ad3be61f64edffacb9d98250b87a1f" @@ -26208,29 +26239,24 @@ sqlstring@^2.3.2: resolved "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz#cdae7169389a1375b18e885f2e60b3e460809514" integrity sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg== -ssh-remote-port-forward@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.3.tgz#074cebed6d54a42ce4659d6aa24987e433ff5fef" - integrity sha512-PJ6qGFmB6n0iMCQIp+qzx8qVUE5cgacopvEh63t3NJjEQHOaza/JT9zywmmVlaol/eGtCmpvBXx2A03ih1Y+xg== +ssh-remote-port-forward@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz#72b0c5df8ec27ca300c75805cc6b266dee07e298" + integrity sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ== dependencies: - "@types/ssh2" "^0.5.45" - ssh2 "^0.8.9" + "@types/ssh2" "^0.5.48" + ssh2 "^1.4.0" -ssh2-streams@~0.4.10: - version "0.4.10" - resolved "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.4.10.tgz#48ef7e8a0e39d8f2921c30521d56dacb31d23a34" - integrity sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ== +ssh2@^1.4.0: + version "1.5.0" + resolved "https://registry.npmjs.org/ssh2/-/ssh2-1.5.0.tgz#4dc559ba98a1cbb420e8d42998dfe35d0eda92bc" + integrity sha512-iUmRkhH9KGeszQwDW7YyyqjsMTf4z+0o48Cp4xOwlY5LjtbIAvyd3fwnsoUZW/hXmTCRA3yt7S/Jb9uVjErVlA== dependencies: - asn1 "~0.2.0" + asn1 "^0.2.4" bcrypt-pbkdf "^1.0.2" - streamsearch "~0.1.2" - -ssh2@^0.8.7, ssh2@^0.8.9: - version "0.8.9" - resolved "https://registry.npmjs.org/ssh2/-/ssh2-0.8.9.tgz#54da3a6c4ba3daf0d8477a538a481326091815f3" - integrity sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw== - dependencies: - ssh2-streams "~0.4.10" + optionalDependencies: + cpu-features "0.0.2" + nan "^2.15.0" sshpk@^1.7.0: version "1.16.1" @@ -26424,13 +26450,6 @@ stream-shift@^1.0.0: resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== -stream-to-array@^2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" - integrity sha1-u/azn19D7DC8cbq8s3VXrOzzQ1M= - dependencies: - any-promise "^1.1.0" - stream-transform@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/stream-transform/-/stream-transform-2.0.2.tgz#3cb7a14c802eb39bc40caaab0535e584f3a65caf" @@ -26438,7 +26457,7 @@ stream-transform@^2.0.1: dependencies: mixme "^0.3.1" -streamsearch@0.1.2, streamsearch@~0.1.2: +streamsearch@0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= @@ -27238,22 +27257,21 @@ test-exclude@^6.0.0: minimatch "^3.0.4" testcontainers@^7.10.0: - version "7.11.1" - resolved "https://registry.npmjs.org/testcontainers/-/testcontainers-7.11.1.tgz#b3810badf79433ba02f210683eec1a1c488c107d" - integrity sha512-lfZeys5bLkADjOaoXfQy0V0+G8sGKr8ESANz7MhSVBwC+OTTxkP3+FVwP48bW4mwRcQ4Hojwbfw10OYT80QZmQ== + version "7.23.0" + resolved "https://registry.npmjs.org/testcontainers/-/testcontainers-7.23.0.tgz#7d73a5e219a970fb75ff6a23a28dace8b7f3f232" + integrity sha512-90H1iijeIjOLp7WVNYKTNkM1sd+dlW5019ns45hSPcOET43WebEZQVJl8/Ag9vwSZD2mjomMum9a/EXk/st4sQ== dependencies: - "@types/archiver" "^5.1.0" - "@types/dockerode" "^3.2.1" + "@types/archiver" "^5.1.1" + "@types/dockerode" "^3.2.5" archiver "^5.3.0" byline "^5.0.0" - debug "^4.3.1" - docker-compose "^0.23.10" - dockerode "^3.2.1" + debug "^4.3.2" + docker-compose "^0.23.13" + dockerode "^3.3.1" get-port "^5.1.1" - glob "^7.1.7" + glob "^7.2.0" slash "^3.0.0" - ssh-remote-port-forward "^1.0.3" - stream-to-array "^2.3.0" + ssh-remote-port-forward "^1.0.4" tar-fs "^2.1.1" text-encoding-utf-8@^1.0.1: From fb4377ac53c8abc829f86cb680c877efd27564a9 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 17 Nov 2021 21:32:43 +0100 Subject: [PATCH 020/138] chore: updating the bump in package.jsons too as it a security risk for the ssh2 packages Signed-off-by: blam --- packages/backend-common/package.json | 4 ++-- packages/backend-test-utils/package.json | 2 +- packages/backend/package.json | 4 ++-- .../templates/default-app/packages/backend/package.json.hbs | 4 ++-- packages/techdocs-cli/package.json | 4 ++-- plugins/techdocs-backend/package.json | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 16ce62c7d7..c46545c4d3 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -39,7 +39,7 @@ "@lerna/project": "^4.0.0", "@octokit/rest": "^18.5.3", "@types/cors": "^2.8.6", - "@types/dockerode": "^3.2.1", + "@types/dockerode": "^3.3.1", "@types/express": "^4.17.6", "archiver": "^5.0.2", "aws-sdk": "^2.840.0", @@ -47,7 +47,7 @@ "concat-stream": "^2.0.0", "cors": "^2.8.5", "cross-fetch": "^3.0.6", - "dockerode": "^3.2.1", + "dockerode": "^3.3.1", "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "9.1.0", diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 2f29c2412b..299b5588a2 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -37,7 +37,7 @@ "mysql2": "^2.2.5", "pg": "^8.3.0", "sqlite3": "^5.0.1", - "testcontainers": "^7.10.0", + "testcontainers": "^7.23.0", "uuid": "^8.0.0" }, "devDependencies": { diff --git a/packages/backend/package.json b/packages/backend/package.json index 4c854241d4..a05bdae692 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -55,7 +55,7 @@ "@gitbeaker/node": "^30.2.0", "@octokit/rest": "^18.5.3", "azure-devops-node-api": "^11.0.1", - "dockerode": "^3.2.1", + "dockerode": "^3.3.1", "example-app": "^0.2.51", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -69,7 +69,7 @@ }, "devDependencies": { "@backstage/cli": "^0.8.2", - "@types/dockerode": "^3.2.1", + "@types/dockerode": "^3.3.1", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5" }, diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs index 194892d40f..8fc193c911 100644 --- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs @@ -29,7 +29,7 @@ "@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}", "@gitbeaker/node": "^30.2.0", "@octokit/rest": "^18.5.3", - "dockerode": "^3.2.1", + "dockerode": "^3.3.1", "express": "^4.17.1", "express-promise-router": "^4.1.0", "knex": "^0.21.6", @@ -43,7 +43,7 @@ }, "devDependencies": { "@backstage/cli": "^{{version '@backstage/cli'}}", - "@types/dockerode": "^3.2.1", + "@types/dockerode": "^3.3.1", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5" }, diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index a24a1be0f8..ecdf488571 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -60,9 +60,9 @@ "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", "@backstage/techdocs-common": "^0.10.4", - "@types/dockerode": "^3.2.1", + "@types/dockerode": "^3.3.1", "commander": "^6.1.0", - "dockerode": "^3.2.1", + "dockerode": "^3.3.1", "fs-extra": "^9.0.1", "http-proxy": "^1.18.1", "react-dev-utils": "^11.0.4", diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index c71833948b..1524a8300e 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -41,7 +41,7 @@ "@backstage/techdocs-common": "^0.10.5", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", - "dockerode": "^3.2.1", + "dockerode": "^3.3.1", "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "9.1.0", @@ -53,7 +53,7 @@ "devDependencies": { "@backstage/cli": "^0.8.1", "@backstage/test-utils": "^0.1.20", - "@types/dockerode": "^3.2.1", + "@types/dockerode": "^3.3.1", "msw": "^0.35.0", "supertest": "^6.1.3" }, From e21e3c6102c620205b37e11dff0b217caa101fc5 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 17 Nov 2021 21:33:55 +0100 Subject: [PATCH 021/138] chore: add changeset Signed-off-by: blam --- .changeset/honest-shrimps-dance.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/honest-shrimps-dance.md diff --git a/.changeset/honest-shrimps-dance.md b/.changeset/honest-shrimps-dance.md new file mode 100644 index 0000000000..8c7852b96b --- /dev/null +++ b/.changeset/honest-shrimps-dance.md @@ -0,0 +1,9 @@ +--- +'@backstage/backend-common': patch +'@backstage/backend-test-utils': patch +'@backstage/create-app': patch +'@techdocs/cli': patch +'@backstage/plugin-techdocs-backend': patch +--- + +Bumping minimum requirements for `dockerode` and `testcontainers` From 0c92f73a111b3c3d40ddbc3d1a0e28fca0324f4a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 18 Nov 2021 10:37:12 +0100 Subject: [PATCH 022/138] 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 023/138] 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 92f87a9a16acd865097677c2c203c8cd5fab8d0c Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 18 Nov 2021 10:52:37 +0100 Subject: [PATCH 024/138] chore: fixing dockerode Signed-off-by: blam --- packages/backend-common/package.json | 2 +- packages/backend/package.json | 2 +- .../templates/default-app/packages/backend/package.json.hbs | 2 +- packages/techdocs-cli/package.json | 2 +- plugins/techdocs-backend/package.json | 2 +- yarn.lock | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index c46545c4d3..ce392a782b 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -39,7 +39,7 @@ "@lerna/project": "^4.0.0", "@octokit/rest": "^18.5.3", "@types/cors": "^2.8.6", - "@types/dockerode": "^3.3.1", + "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "archiver": "^5.0.2", "aws-sdk": "^2.840.0", diff --git a/packages/backend/package.json b/packages/backend/package.json index a05bdae692..7fdffc087f 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -69,7 +69,7 @@ }, "devDependencies": { "@backstage/cli": "^0.8.2", - "@types/dockerode": "^3.3.1", + "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5" }, diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs index 8fc193c911..8f2de6a8ae 100644 --- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs @@ -43,7 +43,7 @@ }, "devDependencies": { "@backstage/cli": "^{{version '@backstage/cli'}}", - "@types/dockerode": "^3.3.1", + "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5" }, diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index ecdf488571..28903ccb9a 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -60,7 +60,7 @@ "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", "@backstage/techdocs-common": "^0.10.4", - "@types/dockerode": "^3.3.1", + "@types/dockerode": "^3.3.0", "commander": "^6.1.0", "dockerode": "^3.3.1", "fs-extra": "^9.0.1", diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 1524a8300e..30be9c9063 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -53,7 +53,7 @@ "devDependencies": { "@backstage/cli": "^0.8.1", "@backstage/test-utils": "^0.1.20", - "@types/dockerode": "^3.3.1", + "@types/dockerode": "^3.3.0", "msw": "^0.35.0", "supertest": "^6.1.3" }, diff --git a/yarn.lock b/yarn.lock index 3188052baf..597ae5e487 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7074,7 +7074,7 @@ "@types/node" "*" "@types/ssh2" "*" -"@types/dockerode@^3.2.1", "@types/dockerode@^3.2.5": +"@types/dockerode@^3.2.5", "@types/dockerode@^3.3.0": version "3.3.0" resolved "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.0.tgz#d6afcc1de31e211ee900da3a48ef4f1a496cf05a" integrity sha512-3Mc0b2gnypJB8Gwmr+8UVPkwjpf4kg1gVxw8lAI4Y/EzpK50LixU1wBSPN9D+xqiw2Ubb02JO8oM0xpwzvi2mg== @@ -13109,7 +13109,7 @@ docker-modem@^3.0.0: split-ca "^1.0.1" ssh2 "^1.4.0" -dockerode@^3.2.1, dockerode@^3.3.1: +dockerode@^3.3.1: version "3.3.1" resolved "https://registry.npmjs.org/dockerode/-/dockerode-3.3.1.tgz#74f66e239e092e7910e2beae6322d35c44b08cdc" integrity sha512-AS2mr8Lp122aa5n6d99HkuTNdRV1wkkhHwBdcnY6V0+28D3DSYwhxAk85/mM9XwD3RMliTxyr63iuvn5ZblFYQ== @@ -27256,7 +27256,7 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -testcontainers@^7.10.0: +testcontainers@^7.23.0: version "7.23.0" resolved "https://registry.npmjs.org/testcontainers/-/testcontainers-7.23.0.tgz#7d73a5e219a970fb75ff6a23a28dace8b7f3f232" integrity sha512-90H1iijeIjOLp7WVNYKTNkM1sd+dlW5019ns45hSPcOET43WebEZQVJl8/Ag9vwSZD2mjomMum9a/EXk/st4sQ== From 475edb5bc593f609d94587ffc4f448c2ef989020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 18 Nov 2021 10:58:42 +0100 Subject: [PATCH 025/138] move the BehaviorSubject init into the constructor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/unlucky-chefs-arrive.md | 5 +++ packages/core-app-api/src/lib/subjects.ts | 39 ++++++++++++----------- 2 files changed, 26 insertions(+), 18 deletions(-) create mode 100644 .changeset/unlucky-chefs-arrive.md diff --git a/.changeset/unlucky-chefs-arrive.md b/.changeset/unlucky-chefs-arrive.md new file mode 100644 index 0000000000..4b1450b281 --- /dev/null +++ b/.changeset/unlucky-chefs-arrive.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-app-api': patch +--- + +move the BehaviorSubject init into the constructor diff --git a/packages/core-app-api/src/lib/subjects.ts b/packages/core-app-api/src/lib/subjects.ts index 79c2c25675..e0789da92c 100644 --- a/packages/core-app-api/src/lib/subjects.ts +++ b/packages/core-app-api/src/lib/subjects.ts @@ -121,34 +121,37 @@ export class PublishSubject * * See http://reactivex.io/documentation/subject.html */ + export class BehaviorSubject implements Observable, ZenObservable.SubscriptionObserver { - private isClosed = false; + private isClosed: boolean; private currentValue: T; - private terminatingError?: Error; + private terminatingError: Error | undefined; + private readonly observable: Observable; constructor(value: T) { + this.isClosed = false; this.currentValue = value; - } - - private readonly observable = new ObservableImpl(subscriber => { - if (this.isClosed) { - if (this.terminatingError) { - subscriber.error(this.terminatingError); - } else { - subscriber.complete(); + this.terminatingError = undefined; + this.observable = new ObservableImpl(subscriber => { + if (this.isClosed) { + if (this.terminatingError) { + subscriber.error(this.terminatingError); + } else { + subscriber.complete(); + } + return () => {}; } - return () => {}; - } - subscriber.next(this.currentValue); + subscriber.next(this.currentValue); - this.subscribers.add(subscriber); - return () => { - this.subscribers.delete(subscriber); - }; - }); + this.subscribers.add(subscriber); + return () => { + this.subscribers.delete(subscriber); + }; + }); + } private readonly subscribers = new Set< ZenObservable.SubscriptionObserver From 7ff56c23309ae0da66f3561aa425615ba27e3dee Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 18 Nov 2021 11:28:26 +0100 Subject: [PATCH 026/138] 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 29ef695410e42a7ffc7af79369a0f9717a27a8ec Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 17 Nov 2021 18:56:22 +0100 Subject: [PATCH 027/138] packages,plugins: migrate to using TestApiProvider and Registry Signed-off-by: Patrik Oldsberg --- docs/plugins/analytics.md | 13 +- .../components/catalog/EntityPage.test.tsx | 33 ++- .../src/devApp/SidebarThemeSwitcher.test.tsx | 15 +- packages/storybook/.storybook/apis.js | 118 ++++---- packages/storybook/.storybook/preview.js | 6 +- .../src/testUtils/TestApiProvider.tsx | 2 +- .../src/testUtils/appWrappers.test.tsx | 6 +- .../ApiDefinitionCard.test.tsx | 9 +- .../ApiDefinitionCard/ApiTypeTitle.test.tsx | 9 +- .../ApiExplorerPage/ApiExplorerPage.test.tsx | 20 +- .../ApisCards/ConsumedApisCard.test.tsx | 17 +- .../components/ApisCards/HasApisCard.test.tsx | 17 +- .../ApisCards/ProvidedApisCard.test.tsx | 17 +- .../ConsumingComponentsCard.test.tsx | 9 +- .../ProvidingComponentsCard.test.tsx | 9 +- .../components/EntityBadgesDialog.test.tsx | 15 +- .../BitriseBuildsTableComponent.test.tsx | 14 +- .../CatalogGraphCard.test.tsx | 17 +- .../CatalogGraphPage.test.tsx | 20 +- .../EntityRelationsGraph.test.tsx | 8 +- .../DefaultImportPage.test.tsx | 23 +- .../ImportInfoCard/ImportInfoCard.test.tsx | 47 +-- .../components/ImportPage/ImportPage.test.tsx | 23 +- .../StepInitAnalyzeUrl.test.tsx | 14 +- .../StepPrepareCreatePullRequest.test.tsx | 14 +- .../EntityTypePicker.test.tsx | 26 +- .../UnregisterEntityDialog.test.tsx | 17 +- .../useUnregisterEntityDialogState.test.tsx | 6 +- .../UserListPicker/UserListPicker.test.tsx | 8 +- .../src/hooks/useEntityKinds.test.tsx | 6 +- .../src/hooks/useEntityListProvider.test.tsx | 30 +- .../src/hooks/useEntityOwnership.test.tsx | 14 +- .../src/hooks/useStarredEntities.test.tsx | 17 +- .../src/hooks/useStarredEntity.test.tsx | 8 +- .../components/AboutCard/AboutCard.test.tsx | 270 ++++++++++-------- .../CatalogKindHeader.test.tsx | 14 +- .../CatalogPage/CatalogPage.test.tsx | 10 +- .../CatalogTable/CatalogTable.test.tsx | 12 +- .../DependencyOfComponentsCard.test.tsx | 20 +- .../DependsOnComponentsCard.test.tsx | 20 +- .../DependsOnResourcesCard.test.tsx | 20 +- .../EntityLayout/EntityLayout.test.tsx | 18 +- .../DeleteEntityDialog.test.tsx | 16 +- .../EntityOrphanWarning.test.tsx | 22 +- .../EntityProcessingErrorsPanel.test.tsx | 16 +- .../EntitySwitch/EntitySwitch.test.tsx | 11 +- .../HasComponentsCard.test.tsx | 20 +- .../HasResourcesCard.test.tsx | 20 +- .../HasSubcomponentsCard.test.tsx | 20 +- .../HasSystemsCard/HasSystemsCard.test.tsx | 20 +- .../SystemDiagramCard.test.tsx | 15 +- .../CostInsightsHeader.test.tsx | 6 +- .../cost-insights/src/testUtils/providers.tsx | 28 +- .../DefaultExplorePage.test.tsx | 7 +- .../DomainExplorerContent.test.tsx | 7 +- .../ExploreLayout/ExploreLayout.test.tsx | 14 +- .../GroupsDiagram.test.tsx | 7 +- .../GroupsExplorerContent.test.tsx | 7 +- .../ToolExplorerContent.test.tsx | 9 +- .../ServiceDetailsCard.test.tsx | 10 +- .../components/FossaCard/FossaCard.test.tsx | 9 +- .../components/FossaPage/FossaPage.test.tsx | 17 +- .../Cards/RecentWorkflowRunsCard.test.tsx | 19 +- .../components/GithubDeploymentsCard.test.tsx | 11 +- .../ProfileCatalog/ProfileCatalog.test.tsx | 7 +- .../GraphiQLPage/GraphiQLPage.test.tsx | 32 +-- .../src/components/Cards/Cards.test.tsx | 21 +- ...useConsumerGroupsOffsetsForEntity.test.tsx | 14 +- plugins/kubernetes/dev/index.tsx | 20 +- .../AuditList/AuditListForEntity.test.tsx | 9 +- .../AuditList/AuditListTable.test.tsx | 15 +- .../src/components/AuditList/index.test.tsx | 15 +- .../src/components/AuditView/index.test.tsx | 15 +- .../src/components/CreateAudit/index.test.tsx | 14 +- .../src/hooks/useWebsiteForEntity.test.tsx | 14 +- .../MembersList/MembersListCard.stories.tsx | 13 +- .../MembersList/MembersListCard.test.tsx | 13 +- .../OwnershipCard/OwnershipCard.stories.tsx | 10 +- .../OwnershipCard/OwnershipCard.test.tsx | 15 +- .../ChangeEvents/ChangeEvents.test.tsx | 8 +- .../components/Escalation/Escalation.test.tsx | 8 +- .../components/Incident/Incidents.test.tsx | 8 +- .../components/PagerDutyCard/index.test.tsx | 18 +- .../components/TriggerButton/index.test.tsx | 17 +- .../TriggerDialog/TriggerDialog.test.tsx | 17 +- .../ActionsPage/ActionsPage.test.tsx | 6 +- .../TemplatePage/TemplatePage.test.tsx | 12 +- .../TemplateTypePicker.test.tsx | 8 +- .../fields/EntityPicker/EntityPicker.test.tsx | 8 +- .../fields/OwnerPicker/OwnerPicker.test.tsx | 8 +- .../components/SearchBar/SearchBar.test.tsx | 11 +- .../SearchModal/SearchModal.test.tsx | 12 +- plugins/shortcuts/src/Shortcuts.test.tsx | 22 +- .../EntitySplunkOnCallCard.test.tsx | 21 +- .../components/Escalation/Escalation.test.tsx | 8 +- .../components/Incident/Incidents.test.tsx | 45 ++- .../TriggerDialog/TriggerDialog.test.tsx | 18 +- .../src/components/RadarComponent.test.tsx | 23 +- .../src/components/RadarPage.test.tsx | 22 +- .../components/DefaultTechDocsHome.test.tsx | 16 +- .../components/LegacyTechDocsHome.test.tsx | 12 +- .../components/TechDocsCustomHome.test.tsx | 6 +- .../src/reader/components/Reader.test.tsx | 8 +- .../reader/components/TechDocsPage.test.tsx | 12 +- .../reader/components/TechDocsSearch.test.tsx | 8 +- .../reader/components/useReaderState.test.tsx | 8 +- plugins/todo/dev/index.tsx | 6 +- .../src/components/TodoList/TodoList.test.tsx | 7 +- .../UserSettingsAuthProviders.test.tsx | 18 +- .../General/UserSettingsThemeToggle.test.tsx | 17 +- .../BuildDetails/BuildDetails.test.tsx | 27 +- .../components/BuildList/BuildList.test.tsx | 21 +- .../BuildListFilter/BuildListFilter.test.tsx | 15 +- .../src/components/Overview/Overview.test.tsx | 17 +- .../OverviewTrends/OverviewTrends.test.tsx | 23 +- .../components/StatusCell/StatusCell.test.tsx | 9 +- .../StatusMatrix/StatusMatrix.test.tsx | 9 +- .../XcmetricsLayout/XcmetricsLayout.test.tsx | 15 +- 118 files changed, 991 insertions(+), 1112 deletions(-) diff --git a/docs/plugins/analytics.md b/docs/plugins/analytics.md index 7adf2650df..ace9a89968 100644 --- a/docs/plugins/analytics.md +++ b/docs/plugins/analytics.md @@ -261,10 +261,13 @@ analytics events captured. Use it like this: ```tsx -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; -import { analyticsApiRef } from '@backstage/core-plugin-api'; -import { MockAnalyticsApi, wrapInTestApp } from '@backstage/test-utils'; import { render, fireEvent, waitFor } from '@testing-library/react'; +import { analyticsApiRef } from '@backstage/core-plugin-api'; +import { + MockAnalyticsApi, + TestApiProvider, + wrapInTestApp, +} from '@backstage/test-utils'; describe('SomeComponent', () => { it('should capture event on click', () => { @@ -274,9 +277,9 @@ describe('SomeComponent', () => { // Render the component being tested const { getByText } = render( wrapInTestApp( - + - , + , ), ); diff --git a/packages/app/src/components/catalog/EntityPage.test.tsx b/packages/app/src/components/catalog/EntityPage.test.tsx index 089cb9c7cf..a6878cd28b 100644 --- a/packages/app/src/components/catalog/EntityPage.test.tsx +++ b/packages/app/src/components/catalog/EntityPage.test.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { EntityLayout } from '@backstage/plugin-catalog'; import { DefaultStarredEntitiesApi, @@ -22,7 +21,11 @@ import { starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; import { githubActionsApiRef } from '@backstage/plugin-github-actions'; -import { MockStorageApi, renderInTestApp } from '@backstage/test-utils'; +import { + MockStorageApi, + renderInTestApp, + TestApiProvider, +} from '@backstage/test-utils'; import React from 'react'; import { cicdContent } from './EntityPage'; @@ -45,22 +48,22 @@ describe('EntityPage Test', () => { const mockedApi = { listWorkflowRuns: jest.fn().mockResolvedValue([]), - getWorkflow: jest.fn(), - getWorkflowRun: jest.fn(), - reRunWorkflow: jest.fn(), - listJobsForWorkflowRun: jest.fn(), - downloadJobLogsForWorkflowRun: jest.fn(), - } as jest.Mocked; - - const apis = ApiRegistry.with(githubActionsApiRef, mockedApi).with( - starredEntitiesApiRef, - new DefaultStarredEntitiesApi({ storageApi: MockStorageApi.create() }), - ); + }; describe('cicdContent', () => { it('Should render GitHub Actions View', async () => { const rendered = await renderInTestApp( - + @@ -68,7 +71,7 @@ describe('EntityPage Test', () => { - , + , ); expect(rendered.getByText('ExampleComponent')).toBeInTheDocument(); diff --git a/packages/dev-utils/src/devApp/SidebarThemeSwitcher.test.tsx b/packages/dev-utils/src/devApp/SidebarThemeSwitcher.test.tsx index 3907dc1007..43eaa6218c 100644 --- a/packages/dev-utils/src/devApp/SidebarThemeSwitcher.test.tsx +++ b/packages/dev-utils/src/devApp/SidebarThemeSwitcher.test.tsx @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; + import { AppThemeApi, appThemeApiRef } from '@backstage/core-plugin-api'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { BackstageTheme } from '@backstage/theme'; import userEvent from '@testing-library/user-event'; import React from 'react'; @@ -24,7 +24,6 @@ import { SidebarThemeSwitcher } from './SidebarThemeSwitcher'; describe('SidebarThemeSwitcher', () => { let appThemeApi: jest.Mocked; - let apiRegistry: ApiRegistry; beforeEach(() => { appThemeApi = { @@ -51,15 +50,13 @@ describe('SidebarThemeSwitcher', () => { theme: {} as unknown as BackstageTheme, }, ]); - - apiRegistry = ApiRegistry.with(appThemeApiRef, appThemeApi); }); it('should display current theme', async () => { const { getByLabelText, getByRole, getByText } = await renderInTestApp( - + - , + , ); const button = getByLabelText('Switch Theme'); @@ -76,9 +73,9 @@ describe('SidebarThemeSwitcher', () => { it('should select different theme', async () => { const { getByLabelText, getByRole, getByText } = await renderInTestApp( - + - , + , ); const button = getByLabelText('Switch Theme'); diff --git a/packages/storybook/.storybook/apis.js b/packages/storybook/.storybook/apis.js index 41b8433594..ca3914dd0c 100644 --- a/packages/storybook/.storybook/apis.js +++ b/packages/storybook/.storybook/apis.js @@ -1,6 +1,5 @@ import { AlertApiForwarder, - ApiRegistry, ErrorAlerter, ErrorApiForwarder, GithubAuth, @@ -27,78 +26,57 @@ import { configApiRef, } from '@backstage/core-plugin-api'; -const builder = ApiRegistry.builder(); - -builder.add(configApiRef, new ConfigReader({})); - -const alertApi = builder.add(alertApiRef, new AlertApiForwarder()); - -builder.add(errorApiRef, new ErrorAlerter(alertApi, new ErrorApiForwarder())); - -builder.add(identityApiRef, { +const configApi = new ConfigReader({}); +const alertApi = new AlertApiForwarder(); +const errorApi = new ErrorAlerter(alertApi, new ErrorApiForwarder()); +const identityApi = { getUserId: () => 'guest', getProfile: () => ({ email: 'guest@example.com' }), getIdToken: () => undefined, signOut: async () => {}, +}; +const oauthRequestApi = new OAuthRequestManager(); +const googleAuthApi = GoogleAuth.create({ + apiOrigin: 'http://localhost:7000', + basePath: '/auth/', + oauthRequestApi, +}); +const githubAuthApi = GithubAuth.create({ + apiOrigin: 'http://localhost:7000', + basePath: '/auth/', + oauthRequestApi, +}); +const gitlabAuthApi = GitlabAuth.create({ + apiOrigin: 'http://localhost:7000', + basePath: '/auth/', + oauthRequestApi, +}); +const oktaAuthApi = OktaAuth.create({ + apiOrigin: 'http://localhost:7000', + basePath: '/auth/', + oauthRequestApi, +}); +const auth0AuthApi = Auth0Auth.create({ + apiOrigin: 'http://localhost:7000', + basePath: '/auth/', + oauthRequestApi, +}); +const oauth2Api = OAuth2.create({ + apiOrigin: 'http://localhost:7000', + basePath: '/auth/', + oauthRequestApi, }); -const oauthRequestApi = builder.add( - oauthRequestApiRef, - new OAuthRequestManager(), -); - -builder.add( - googleAuthApiRef, - GoogleAuth.create({ - apiOrigin: 'http://localhost:7000', - basePath: '/auth/', - oauthRequestApi, - }), -); - -builder.add( - githubAuthApiRef, - GithubAuth.create({ - apiOrigin: 'http://localhost:7000', - basePath: '/auth/', - oauthRequestApi, - }), -); - -builder.add( - gitlabAuthApiRef, - GitlabAuth.create({ - apiOrigin: 'http://localhost:7000', - basePath: '/auth/', - oauthRequestApi, - }), -); - -builder.add( - oktaAuthApiRef, - OktaAuth.create({ - apiOrigin: 'http://localhost:7000', - basePath: '/auth/', - oauthRequestApi, - }), -); - -builder.add( - auth0AuthApiRef, - Auth0Auth.create({ - apiOrigin: 'http://localhost:7000', - basePath: '/auth/', - oauthRequestApi, - }), -); - -builder.add( - oauth2ApiRef, - OAuth2.create({ - apiOrigin: 'http://localhost:7000', - basePath: '/auth/', - oauthRequestApi, - }), -); - -export const apis = builder.build(); +export const apis = [ + [configApiRef, configApi], + [alertApiRef, alertApi], + [errorApiRef, errorApi], + [identityApiRef, identityApi], + [oauthRequestApiRef, oauthRequestApi], + [googleAuthApiRef, googleAuthApi], + [githubAuthApiRef, githubAuthApi], + [gitlabAuthApiRef, gitlabAuthApi], + [oktaAuthApiRef, oktaAuthApi], + [auth0AuthApiRef, auth0AuthApi], + [oauth2ApiRef, oauth2Api], +]; diff --git a/packages/storybook/.storybook/preview.js b/packages/storybook/.storybook/preview.js index 6186b82ca5..2b1a4af329 100644 --- a/packages/storybook/.storybook/preview.js +++ b/packages/storybook/.storybook/preview.js @@ -6,17 +6,17 @@ import { useDarkMode } from 'storybook-dark-mode'; import { apis } from './apis'; import { Content, AlertDisplay } from '@backstage/core-components'; -import { ApiProvider } from '@backstage/core-app-api'; +import { TestApiProvider } from '@backstage/test-utils'; addDecorator(story => ( - + {story()} - + )); addParameters({ 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' }], * ); diff --git a/packages/test-utils/src/testUtils/appWrappers.test.tsx b/packages/test-utils/src/testUtils/appWrappers.test.tsx index 25809912ec..39e5da3df2 100644 --- a/packages/test-utils/src/testUtils/appWrappers.test.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.test.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { createExternalRouteRef, createRouteRef, @@ -29,6 +28,7 @@ import React, { useEffect } from 'react'; import { Route, Routes } from 'react-router'; import { MockErrorApi } from './apis'; import { renderInTestApp, wrapInTestApp } from './appWrappers'; +import { TestApiProvider } from './TestApiProvider'; describe('wrapInTestApp', () => { it('should provide routing and warn about missing act()', async () => { @@ -111,9 +111,9 @@ describe('wrapInTestApp', () => { }; const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText('foo')).toBeInTheDocument(); diff --git a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.test.tsx b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.test.tsx index 7b0ffac58e..32a6ec0f77 100644 --- a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.test.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.test.tsx @@ -16,13 +16,12 @@ import { ApiEntity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { ApiDocsConfig, apiDocsConfigRef } from '../../config'; import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget'; import { ApiDefinitionCard } from './ApiDefinitionCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const apiDocsConfig: jest.Mocked = { @@ -31,10 +30,10 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(apiDocsConfigRef, apiDocsConfig); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/api-docs/src/components/ApiDefinitionCard/ApiTypeTitle.test.tsx b/plugins/api-docs/src/components/ApiDefinitionCard/ApiTypeTitle.test.tsx index 450e9e57ac..5476857a06 100644 --- a/plugins/api-docs/src/components/ApiDefinitionCard/ApiTypeTitle.test.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionCard/ApiTypeTitle.test.tsx @@ -15,11 +15,10 @@ */ import { ApiEntity } from '@backstage/catalog-model'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { ApiDocsConfig, apiDocsConfigRef } from '../../config'; import { ApiTypeTitle } from './ApiTypeTitle'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const apiDocsConfig: jest.Mocked = { @@ -28,10 +27,10 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(apiDocsConfigRef, apiDocsConfig); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.test.tsx b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.test.tsx index cf40e5160c..3629110d47 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.test.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.test.tsx @@ -15,11 +15,7 @@ */ import { Entity, RELATION_MEMBER_OF } from '@backstage/catalog-model'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ConfigReader } from '@backstage/core-app-api'; import { TableColumn, TableProps } from '@backstage/core-components'; import { ConfigApi, @@ -34,7 +30,11 @@ import { entityRouteRef, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; -import { MockStorageApi, wrapInTestApp } from '@backstage/test-utils'; +import { + MockStorageApi, + TestApiProvider, + wrapInTestApp, +} from '@backstage/test-utils'; import DashboardIcon from '@material-ui/icons/Dashboard'; import { render } from '@testing-library/react'; import React from 'react'; @@ -88,8 +88,8 @@ describe('ApiCatalogPage', () => { const renderWrapped = (children: React.ReactNode) => render( wrapInTestApp( - { new DefaultStarredEntitiesApi({ storageApi }), ], [apiDocsConfigRef, apiDocsConfig], - ])} + ]} > {children} - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, diff --git a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx index ac09b717f7..5e7b22524a 100644 --- a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx +++ b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx @@ -21,12 +21,11 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { ApiDocsConfig, apiDocsConfigRef } from '../../config'; import { ConsumedApisCard } from './ConsumedApisCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const apiDocsConfig: jest.Mocked = { @@ -43,13 +42,15 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi).with( - apiDocsConfigRef, - apiDocsConfig, - ); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx index ac833251e3..4102bebf0e 100644 --- a/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx +++ b/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx @@ -21,12 +21,11 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { ApiDocsConfig, apiDocsConfigRef } from '../../config'; import { HasApisCard } from './HasApisCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const apiDocsConfig: jest.Mocked = { @@ -43,13 +42,15 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi).with( - apiDocsConfigRef, - apiDocsConfig, - ); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx index f2719d0f4b..b29075aee9 100644 --- a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx +++ b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx @@ -21,12 +21,11 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { ApiDocsConfig, apiDocsConfigRef } from '../../config'; import { ProvidedApisCard } from './ProvidedApisCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const apiDocsConfig: jest.Mocked = { @@ -43,13 +42,15 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi).with( - apiDocsConfigRef, - apiDocsConfig, - ); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx index 274962c346..06022eec69 100644 --- a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx +++ b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx @@ -21,11 +21,10 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { ConsumingComponentsCard } from './ConsumingComponentsCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const catalogApi: jest.Mocked = { @@ -39,10 +38,10 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx index 879944749a..275338d2f9 100644 --- a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx +++ b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx @@ -21,11 +21,10 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { ProvidingComponentsCard } from './ProvidingComponentsCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const catalogApi: jest.Mocked = { @@ -39,10 +38,10 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/badges/src/components/EntityBadgesDialog.test.tsx b/plugins/badges/src/components/EntityBadgesDialog.test.tsx index 1f5ee94e04..ea44eb20fc 100644 --- a/plugins/badges/src/components/EntityBadgesDialog.test.tsx +++ b/plugins/badges/src/components/EntityBadgesDialog.test.tsx @@ -16,12 +16,11 @@ import React from 'react'; import { Entity } from '@backstage/catalog-model'; -import { renderWithEffects } from '@backstage/test-utils'; +import { renderWithEffects, TestApiProvider } from '@backstage/test-utils'; import { BadgesApi, badgesApiRef } from '../api'; import { EntityBadgesDialog } from './EntityBadgesDialog'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { ErrorApi, errorApiRef } from '@backstage/core-plugin-api'; describe('EntityBadgesDialog', () => { @@ -42,16 +41,16 @@ describe('EntityBadgesDialog', () => { const mockEntity = { metadata: { name: 'mock' } } as Entity; const rendered = await renderWithEffects( - - , + , ); await expect( diff --git a/plugins/bitrise/src/components/BitriseBuildsTableComponent/BitriseBuildsTableComponent.test.tsx b/plugins/bitrise/src/components/BitriseBuildsTableComponent/BitriseBuildsTableComponent.test.tsx index a206e28de6..82faa3e39c 100644 --- a/plugins/bitrise/src/components/BitriseBuildsTableComponent/BitriseBuildsTableComponent.test.tsx +++ b/plugins/bitrise/src/components/BitriseBuildsTableComponent/BitriseBuildsTableComponent.test.tsx @@ -21,14 +21,11 @@ import { setupServer } from 'msw/node'; import { setupRequestMockHandlers, renderInTestApp, + TestApiRegistry, } from '@backstage/test-utils'; import { useBitriseBuilds } from '../../hooks/useBitriseBuilds'; import { BitriseBuildsTable } from './BitriseBuildsTableComponent'; -import { - ApiProvider, - ApiRegistry, - UrlPatternDiscovery, -} from '@backstage/core-app-api'; +import { ApiProvider, UrlPatternDiscovery } from '@backstage/core-app-api'; jest.mock('../../hooks/useBitriseBuilds', () => ({ useBitriseBuilds: jest.fn(), @@ -40,10 +37,13 @@ describe('BitriseBuildsFetchComponent', () => { setupRequestMockHandlers(server); const mockBaseUrl = 'http://backstage:9191'; const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); - let apis: ApiRegistry; + let apis: TestApiRegistry; beforeEach(() => { - apis = ApiRegistry.with(bitriseApiRef, new BitriseClientApi(discoveryApi)); + apis = TestApiRegistry.from([ + bitriseApiRef, + new BitriseClientApi(discoveryApi), + ]); }); it('should display `no records` message if there are no builds', async () => { diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx index 9fe482a30b..3c167946d4 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx @@ -14,14 +14,19 @@ * limitations under the License. */ import { Entity } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { analyticsApiRef } from '@backstage/core-plugin-api'; import { CatalogApi, catalogApiRef, EntityProvider, } from '@backstage/plugin-catalog-react'; -import { MockAnalyticsApi, renderInTestApp } from '@backstage/test-utils'; +import { + MockAnalyticsApi, + renderInTestApp, + TestApiProvider, + TestApiRegistry, +} from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { catalogEntityRouteRef, catalogGraphRouteRef } from '../../routes'; @@ -31,7 +36,7 @@ describe('', () => { let entity: Entity; let wrapper: JSX.Element; let catalog: jest.Mocked; - let apis: ApiRegistry; + let apis: TestApiRegistry; beforeAll(() => { Object.defineProperty(window.SVGElement.prototype, 'getBBox', { @@ -61,7 +66,7 @@ describe('', () => { refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), }; - apis = ApiRegistry.with(catalogApiRef, catalog); + apis = TestApiRegistry.from([catalogApiRef, catalog]); wrapper = ( @@ -123,9 +128,9 @@ describe('', () => { test('captures analytics event on click', async () => { const analyticsSpy = new MockAnalyticsApi(); const { findByText } = await renderInTestApp( - + {wrapper} - , + , { mountedRoutes: { '/entity/{kind}/{namespace}/{name}': catalogEntityRouteRef, diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx index b992d0c976..7bd1045fff 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx @@ -14,10 +14,13 @@ * limitations under the License. */ import { RELATION_HAS_PART, RELATION_PART_OF } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { analyticsApiRef } from '@backstage/core-plugin-api'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; -import { MockAnalyticsApi, renderInTestApp } from '@backstage/test-utils'; +import { + MockAnalyticsApi, + renderInTestApp, + TestApiProvider, +} from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { catalogEntityRouteRef } from '../../routes'; @@ -90,10 +93,9 @@ describe('', () => { refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), }; - const apis = ApiRegistry.with(catalogApiRef, catalog); wrapper = ( - + ', () => { selectedKinds: ['b'], }} /> - + ); }); @@ -172,9 +174,9 @@ describe('', () => { test('should capture analytics event when selecting other entity', async () => { const analyticsSpy = new MockAnalyticsApi(); const { getByText, findAllByTestId } = await renderInTestApp( - + {wrapper} - , + , { mountedRoutes: { '/entity/{kind}/{namespace}/{name}': catalogEntityRouteRef, @@ -195,9 +197,9 @@ describe('', () => { test('should capture analytics event when navigating to entity', async () => { const analyticsSpy = new MockAnalyticsApi(); const { getByText, findAllByTestId } = await renderInTestApp( - + {wrapper} - , + , { mountedRoutes: { '/entity/{kind}/{namespace}/{name}': catalogEntityRouteRef, diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx index 2d6c5cc93d..be0c4dc5e5 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx @@ -21,9 +21,8 @@ import { RELATION_PART_OF, stringifyEntityRef, } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import React, { FunctionComponent } from 'react'; import { EntityRelationsGraph } from './EntityRelationsGraph'; @@ -158,10 +157,11 @@ describe('', () => { refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), }; - const apis = ApiRegistry.with(catalogApiRef, catalog); Wrapper = ({ children }) => ( - {children} + + {children} + ); }); diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx index 69ae38207d..784cbfbe9e 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx @@ -15,14 +15,10 @@ */ import { CatalogClient } from '@backstage/catalog-client'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import React from 'react'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; import { DefaultImportPage } from './DefaultImportPage'; @@ -43,15 +39,13 @@ describe('', () => { }, }; - let apis: ApiRegistry; + let apis: TestApiRegistry; beforeEach(() => { - apis = ApiRegistry.with( - configApiRef, - new ConfigReader({ integrations: {} }), - ) - .with(catalogApiRef, new CatalogClient({ discoveryApi: {} as any })) - .with( + apis = TestApiRegistry.from( + [configApiRef, new ConfigReader({ integrations: {} })], + [catalogApiRef, new CatalogClient({ discoveryApi: {} as any })], + [ catalogImportApiRef, new CatalogImportClient({ discoveryApi: {} as any, @@ -63,7 +57,8 @@ describe('', () => { catalogApi: {} as any, configApi: {} as any, }), - ); + ], + ); }); it('renders without exploding', async () => { diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx index 4e0c3694cd..9a27532c57 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -14,19 +14,19 @@ * limitations under the License. */ -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; -import { renderInTestApp } from '@backstage/test-utils'; +import { + renderInTestApp, + TestApiProvider, + TestApiRegistry, +} from '@backstage/test-utils'; import React from 'react'; import { CatalogImportApi, catalogImportApiRef } from '../../api'; import { ImportInfoCard } from './ImportInfoCard'; describe('', () => { - let apis: ApiRegistry; + let apis: TestApiRegistry; let catalogImportApi: jest.Mocked; beforeEach(() => { @@ -35,26 +35,29 @@ describe('', () => { submitPullRequest: jest.fn(), }; - apis = ApiRegistry.with( - configApiRef, - new ConfigReader({ - integrations: { - github: [{ token: 'my-token' }], - }, - }), - ).with(catalogImportApiRef, catalogImportApi); + apis = TestApiRegistry.from( + [ + configApiRef, + new ConfigReader({ + integrations: { + github: [{ token: 'my-token' }], + }, + }), + ], + [catalogImportApiRef, catalogImportApi], + ); }); it('renders without exploding', async () => { - apis = ApiRegistry.with( - configApiRef, - new ConfigReader({ integrations: {} }), - ).with(catalogImportApiRef, catalogImportApi); - const { getByText } = await renderInTestApp( - + - , + , ); expect(getByText('Register an existing component')).toBeInTheDocument(); diff --git a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx index 92a6077792..1778af73dc 100644 --- a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx @@ -15,14 +15,10 @@ */ import { CatalogClient } from '@backstage/catalog-client'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import React from 'react'; import { useOutlet } from 'react-router'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; @@ -49,15 +45,13 @@ describe('', () => { }, }; - let apis: ApiRegistry; + let apis: TestApiRegistry; beforeEach(() => { - apis = ApiRegistry.with( - configApiRef, - new ConfigReader({ integrations: {} }), - ) - .with(catalogApiRef, new CatalogClient({ discoveryApi: {} as any })) - .with( + apis = TestApiRegistry.from( + [configApiRef, new ConfigReader({ integrations: {} })], + [catalogApiRef, new CatalogClient({ discoveryApi: {} as any })], + [ catalogImportApiRef, new CatalogImportClient({ discoveryApi: {} as any, @@ -67,7 +61,8 @@ describe('', () => { catalogApi: {} as any, configApi: new ConfigReader({}), }), - ); + ], + ); }); afterEach(() => jest.resetAllMocks()); diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx index 4a72a653ea..8d28fb8604 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; +import { TestApiProvider } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; @@ -34,14 +34,14 @@ describe('', () => { }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} - + ); const location = { diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index 0a55d6337b..3b6f353155 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -14,9 +14,9 @@ * limitations under the License. */ -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { TestApiProvider } from '@backstage/test-utils'; import { TextField } from '@material-ui/core'; import { act, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -54,13 +54,15 @@ describe('', () => { }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} - + ); const onPrepareFn = jest.fn(); diff --git a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx index 8eba11aeca..f6e9d296df 100644 --- a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx @@ -17,16 +17,15 @@ import React from 'react'; import { fireEvent, waitFor } from '@testing-library/react'; import { capitalize } from 'lodash'; -import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { EntityTypePicker } from './EntityTypePicker'; import { MockEntityListContextProvider } from '../../testUtils/providers'; import { catalogApiRef } from '../../api'; import { EntityKindFilter, EntityTypeFilter } from '../../filters'; -import { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; -import { renderWithEffects } from '@backstage/test-utils'; +import { alertApiRef } from '@backstage/core-plugin-api'; +import { ApiProvider } from '@backstage/core-app-api'; +import { renderWithEffects, TestApiRegistry } from '@backstage/test-utils'; const entities: Entity[] = [ { @@ -61,11 +60,20 @@ const entities: Entity[] = [ }, ]; -const apis = ApiRegistry.with(catalogApiRef, { - getEntities: jest.fn().mockResolvedValue({ items: entities }), -} as unknown as CatalogApi).with(alertApiRef, { - post: jest.fn(), -} as unknown as AlertApi); +const apis = TestApiRegistry.from( + [ + catalogApiRef, + { + getEntities: jest.fn().mockResolvedValue({ items: entities }), + }, + ], + [ + alertApiRef, + { + post: jest.fn(), + }, + ], +); describe('', () => { it('renders available entity types', async () => { diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx index eccf824c2e..2b29bba4fd 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx @@ -24,7 +24,7 @@ import { CatalogClient } from '@backstage/catalog-client'; import { catalogApiRef } from '../../api'; import { entityRouteRef } from '../../routes'; import { screen, waitFor } from '@testing-library/react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import * as state from './useUnregisterEntityDialogState'; import { @@ -32,7 +32,6 @@ import { alertApiRef, DiscoveryApi, } from '@backstage/core-plugin-api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('UnregisterEntityDialog', () => { const discoveryApi: DiscoveryApi = { @@ -49,11 +48,6 @@ describe('UnregisterEntityDialog', () => { }, }; - const apis = ApiRegistry.with( - catalogApiRef, - new CatalogClient({ discoveryApi }), - ).with(alertApiRef, alertApi); - const entity = { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', @@ -68,7 +62,14 @@ describe('UnregisterEntityDialog', () => { }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); const stateSpy = jest.spyOn(state, 'useUnregisterEntityDialogState'); diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx index 8b4f436aed..8d6083f111 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx @@ -31,7 +31,7 @@ import { UseUnregisterEntityDialogState, useUnregisterEntityDialogState, } from './useUnregisterEntityDialogState'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { TestApiProvider } from '@backstage/test-utils'; function defer(): { promise: Promise; resolve: (value: T) => void } { let resolve: (value: T) => void = () => {}; @@ -51,9 +51,9 @@ describe('useUnregisterEntityDialogState', () => { const catalogApi = catalogApiMock as Partial as CatalogApi; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - + {children} - + ); let entity: Entity; diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index 4662e58dd2..f6a4c59374 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -26,9 +26,9 @@ import { MockEntityListContextProvider } from '../../testUtils/providers'; import { EntityTagFilter, UserListFilter } from '../../filters'; import { CatalogApi } from '@backstage/catalog-client'; import { catalogApiRef } from '../../api'; -import { MockStorageApi } from '@backstage/test-utils'; +import { MockStorageApi, TestApiRegistry } from '@backstage/test-utils'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { ConfigApi, configApiRef, @@ -62,12 +62,12 @@ const mockIdentityApi = { getIdToken: async () => undefined, } as Partial; -const apis = ApiRegistry.from([ +const apis = TestApiRegistry.from( [configApiRef, mockConfigApi], [catalogApiRef, mockCatalogApi], [identityApiRef, mockIdentityApi], [storageApiRef, MockStorageApi.create()], -]); +); const mockIsOwnedEntity = (entity: Entity) => entity.metadata.name === 'component-1'; diff --git a/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx b/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx index d801e508a6..cdcac8c194 100644 --- a/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx @@ -15,12 +15,12 @@ */ import React, { PropsWithChildren } from 'react'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { catalogApiRef } from '../api'; import { renderHook } from '@testing-library/react-hooks'; import { useEntityKinds } from './useEntityKinds'; +import { TestApiProvider } from '@backstage/test-utils'; const entities: Entity[] = [ { @@ -59,9 +59,9 @@ const mockCatalogApi: Partial = { const wrapper = ({ children }: PropsWithChildren<{}>) => { return ( - + {children} - + ); }; diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index e448ee73f1..b96f63304a 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -16,7 +16,6 @@ import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { ConfigApi, configApiRef, @@ -24,7 +23,7 @@ import { identityApiRef, storageApiRef, } from '@backstage/core-plugin-api'; -import { MockStorageApi } from '@backstage/test-utils'; +import { MockStorageApi, TestApiProvider } from '@backstage/test-utils'; import { act, renderHook } from '@testing-library/react-hooks'; import qs from 'qs'; import React, { PropsWithChildren } from 'react'; @@ -76,16 +75,6 @@ const mockCatalogApi: Partial = { getEntities: jest.fn().mockImplementation(async () => ({ items: entities })), getEntityByName: async () => undefined, }; -const apis = ApiRegistry.from([ - [configApiRef, mockConfigApi], - [catalogApiRef, mockCatalogApi], - [identityApiRef, mockIdentityApi], - [storageApiRef, MockStorageApi.create()], - [ - starredEntitiesApiRef, - new DefaultStarredEntitiesApi({ storageApi: MockStorageApi.create() }), - ], -]); const wrapper = ({ userFilter, @@ -94,13 +83,26 @@ const wrapper = ({ userFilter?: UserListFilterKind; }>) => { return ( - + - + ); }; diff --git a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx index 4edad98c12..f01c13839d 100644 --- a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx @@ -21,8 +21,8 @@ import { RELATION_OWNED_BY, UserEntity, } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { IdentityApi, identityApiRef } from '@backstage/core-plugin-api'; +import { TestApiProvider } from '@backstage/test-utils'; import { renderHook } from '@testing-library/react-hooks'; import React from 'react'; import { catalogApiRef } from '../api'; @@ -50,14 +50,14 @@ describe('useEntityOwnership', () => { const catalogApi = mockCatalogApi as unknown as CatalogApi; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} - + ); const ownedEntity: ComponentEntity = { diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx index 4f41ef090f..aef876a1b2 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx @@ -15,9 +15,8 @@ */ import { Entity } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { StorageApi } from '@backstage/core-plugin-api'; -import { MockStorageApi } from '@backstage/test-utils'; +import { MockStorageApi, TestApiProvider } from '@backstage/test-utils'; import { act, renderHook } from '@testing-library/react-hooks'; import React, { PropsWithChildren } from 'react'; import { DefaultStarredEntitiesApi, starredEntitiesApiRef } from '../apis'; @@ -47,14 +46,16 @@ describe('useStarredEntities', () => { beforeEach(() => { mockStorage = MockStorageApi.create(); wrapper = ({ children }: PropsWithChildren<{}>) => ( - {children} - + ); }); diff --git a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx index b8577aec0c..8ffc891092 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx @@ -15,7 +15,7 @@ */ import { Entity, EntityName } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { TestApiProvider } from '@backstage/test-utils'; import { renderHook } from '@testing-library/react-hooks'; import React, { PropsWithChildren } from 'react'; import Observable from 'zen-observable'; @@ -31,11 +31,9 @@ describe('useStarredEntity', () => { beforeEach(() => { wrapper = ({ children }: PropsWithChildren<{}>) => ( - + {children} - + ); }); diff --git a/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx b/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx index d6f13ed22d..afbed3bdc7 100644 --- a/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx +++ b/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx @@ -15,11 +15,7 @@ */ import { RELATION_OWNED_BY } from '@backstage/catalog-model'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ConfigReader } from '@backstage/core-app-api'; import { ScmIntegrationsApi, scmIntegrationsApiRef, @@ -30,7 +26,7 @@ import { CatalogApi, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { viewTechDocRouteRef } from '../../routes'; @@ -71,21 +67,25 @@ describe('', () => { }, ], }; - const apis = ApiRegistry.with( - scmIntegrationsApiRef, - ScmIntegrationsApi.fromConfig( - new ConfigReader({ - integrations: {}, - }), - ), - ).with(catalogApiRef, catalogApi); const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, @@ -116,28 +116,32 @@ describe('', () => { lifecycle: 'production', }, }; - const apis = ApiRegistry.with( - scmIntegrationsApiRef, - ScmIntegrationsApi.fromConfig( - new ConfigReader({ - integrations: { - github: [ - { - host: 'github.com', - token: '...', - }, - ], - }, - }), - ), - ).with(catalogApiRef, catalogApi); const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, @@ -167,28 +171,32 @@ describe('', () => { lifecycle: 'production', }, }; - const apis = ApiRegistry.with( - scmIntegrationsApiRef, - ScmIntegrationsApi.fromConfig( - new ConfigReader({ - integrations: { - github: [ - { - host: 'github.com', - token: '...', - }, - ], - }, - }), - ), - ).with(catalogApiRef, catalogApi); const { getByTitle } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, @@ -216,17 +224,21 @@ describe('', () => { lifecycle: 'production', }, }; - const apis = ApiRegistry.with( - scmIntegrationsApiRef, - ScmIntegrationsApi.fromConfig(new ConfigReader({})), - ).with(catalogApiRef, catalogApi); const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, @@ -253,17 +265,21 @@ describe('', () => { lifecycle: 'production', }, }; - const apis = ApiRegistry.with( - scmIntegrationsApiRef, - ScmIntegrationsApi.fromConfig(new ConfigReader({})), - ).with(catalogApiRef, catalogApi); const { getByTitle } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, @@ -295,17 +311,21 @@ describe('', () => { lifecycle: 'production', }, }; - const apis = ApiRegistry.with( - scmIntegrationsApiRef, - ScmIntegrationsApi.fromConfig(new ConfigReader({})), - ).with(catalogApiRef, catalogApi); const { queryByTitle } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, @@ -332,28 +352,32 @@ describe('', () => { lifecycle: 'production', }, }; - const apis = ApiRegistry.with( - scmIntegrationsApiRef, - ScmIntegrationsApi.fromConfig( - new ConfigReader({ - integrations: { - github: [ - { - host: 'github.com', - token: '...', - }, - ], - }, - }), - ), - ).with(catalogApiRef, catalogApi); const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/docs/:namespace/:kind/:name': viewTechDocRouteRef, @@ -381,28 +405,32 @@ describe('', () => { lifecycle: 'production', }, }; - const apis = ApiRegistry.with( - scmIntegrationsApiRef, - ScmIntegrationsApi.fromConfig( - new ConfigReader({ - integrations: { - github: [ - { - host: 'github.com', - token: '...', - }, - ], - }, - }), - ), - ).with(catalogApiRef, catalogApi); const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, @@ -429,28 +457,32 @@ describe('', () => { lifecycle: 'production', }, }; - const apis = ApiRegistry.with( - scmIntegrationsApiRef, - ScmIntegrationsApi.fromConfig( - new ConfigReader({ - integrations: { - github: [ - { - host: 'github.com', - token: '...', - }, - ], - }, - }), - ), - ).with(catalogApiRef, catalogApi); const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx index 2730665fb6..b320d6d220 100644 --- a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx +++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx @@ -18,13 +18,12 @@ import React from 'react'; import { fireEvent } from '@testing-library/react'; import { Entity } from '@backstage/catalog-model'; import { - CatalogApi, catalogApiRef, EntityKindFilter, MockEntityListContextProvider, } from '@backstage/plugin-catalog-react'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; -import { renderWithEffects } from '@backstage/test-utils'; +import { ApiProvider } from '@backstage/core-app-api'; +import { renderWithEffects, TestApiRegistry } from '@backstage/test-utils'; import { CatalogKindHeader } from './CatalogKindHeader'; const entities: Entity[] = [ @@ -58,9 +57,12 @@ const entities: Entity[] = [ }, ]; -const apis = ApiRegistry.with(catalogApiRef, { - getEntities: jest.fn().mockResolvedValue({ items: entities }), -} as Partial); +const apis = TestApiRegistry.from([ + catalogApiRef, + { + getEntities: jest.fn().mockResolvedValue({ items: entities }), + }, +]); describe('', () => { it('renders available kinds', async () => { diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx index 6b33b33b08..0a46580c12 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx @@ -20,7 +20,6 @@ import { RELATION_MEMBER_OF, RELATION_OWNED_BY, } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { TableColumn, TableProps } from '@backstage/core-components'; import { IdentityApi, @@ -38,6 +37,7 @@ import { mockBreakpoint, MockStorageApi, renderWithEffects, + TestApiProvider, wrapInTestApp, } from '@backstage/test-utils'; import DashboardIcon from '@material-ui/icons/Dashboard'; @@ -129,8 +129,8 @@ describe('CatalogPage', () => { const renderWrapped = (children: React.ReactNode) => renderWithEffects( wrapInTestApp( - { starredEntitiesApiRef, new DefaultStarredEntitiesApi({ storageApi }), ], - ])} + ]} > {children} - , + , { mountedRoutes: { '/create': createComponentRouteRef, diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx index 822913a385..4c6adcf400 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx @@ -19,7 +19,7 @@ import { Entity, VIEW_URL_ANNOTATION, } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { entityRouteRef, DefaultStarredEntitiesApi, @@ -27,7 +27,11 @@ import { starredEntitiesApiRef, UserListFilter, } from '@backstage/plugin-catalog-react'; -import { MockStorageApi, renderInTestApp } from '@backstage/test-utils'; +import { + MockStorageApi, + renderInTestApp, + TestApiRegistry, +} from '@backstage/test-utils'; import { act, fireEvent } from '@testing-library/react'; import * as React from 'react'; import { CatalogTable } from './CatalogTable'; @@ -51,10 +55,10 @@ const entities: Entity[] = [ ]; describe('CatalogTable component', () => { - const mockApis = ApiRegistry.with( + const mockApis = TestApiRegistry.from([ starredEntitiesApiRef, new DefaultStarredEntitiesApi({ storageApi: MockStorageApi.create() }), - ); + ]); beforeEach(() => { window.open = jest.fn(); diff --git a/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.test.tsx b/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.test.tsx index 7dd823a8f0..e43104b67d 100644 --- a/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.test.tsx +++ b/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.test.tsx @@ -21,28 +21,20 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { DependencyOfComponentsCard } from './DependencyOfComponentsCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { - const catalogApi: jest.Mocked = { - getLocationById: jest.fn(), - getEntityByName: jest.fn(), - getEntities: jest.fn(), - addLocation: jest.fn(), - getLocationByEntity: jest.fn(), - removeEntityByUid: jest.fn(), - } as any; + const getEntities: jest.MockedFunction = jest.fn(); let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); @@ -97,7 +89,7 @@ describe('', () => { }, ], }; - catalogApi.getEntities.mockResolvedValue({ + getEntities.mockResolvedValue({ items: [ { apiVersion: 'v1', diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx index b9fd75def9..b654136d18 100644 --- a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx +++ b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx @@ -21,28 +21,20 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { DependsOnComponentsCard } from './DependsOnComponentsCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { - const catalogApi: jest.Mocked = { - getLocationById: jest.fn(), - getEntityByName: jest.fn(), - getEntities: jest.fn(), - addLocation: jest.fn(), - getLocationByEntity: jest.fn(), - removeEntityByUid: jest.fn(), - } as any; + const getEntities: jest.MockedFunction = jest.fn(); let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); @@ -97,7 +89,7 @@ describe('', () => { }, ], }; - catalogApi.getEntities.mockResolvedValue({ + getEntities.mockResolvedValue({ items: [ { apiVersion: 'v1', diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx index bee759254c..40685705aa 100644 --- a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx +++ b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx @@ -21,28 +21,20 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { DependsOnResourcesCard } from './DependsOnResourcesCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { - const catalogApi: jest.Mocked = { - getLocationById: jest.fn(), - getEntityByName: jest.fn(), - getEntities: jest.fn(), - addLocation: jest.fn(), - getLocationByEntity: jest.fn(), - removeEntityByUid: jest.fn(), - } as any; + const getEntities: jest.MockedFunction = jest.fn(); let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); @@ -97,7 +89,7 @@ describe('', () => { }, ], }; - catalogApi.getEntities.mockResolvedValue({ + getEntities.mockResolvedValue({ items: [ { apiVersion: 'v1', diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx index 2216070984..3f3fc804e1 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx @@ -16,7 +16,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; import { AsyncEntityProvider, @@ -26,7 +26,11 @@ import { entityRouteRef, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; -import { MockStorageApi, renderInTestApp } from '@backstage/test-utils'; +import { + MockStorageApi, + renderInTestApp, + TestApiRegistry, +} from '@backstage/test-utils'; import { fireEvent } from '@testing-library/react'; import React from 'react'; import { act } from 'react-dom/test-utils'; @@ -40,12 +44,14 @@ const mockEntity = { }, } as Entity; -const mockApis = ApiRegistry.with(catalogApiRef, {} as CatalogApi) - .with(alertApiRef, {} as AlertApi) - .with( +const mockApis = TestApiRegistry.from( + [catalogApiRef, {} as CatalogApi], + [alertApiRef, {} as AlertApi], + [ starredEntitiesApiRef, new DefaultStarredEntitiesApi({ storageApi: MockStorageApi.create() }), - ); + ], +); describe('EntityLayout', () => { it('renders simplest case', async () => { diff --git a/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.test.tsx b/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.test.tsx index 862ef9504b..f58e6b9b66 100644 --- a/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.test.tsx +++ b/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.test.tsx @@ -20,10 +20,9 @@ import { ORIGIN_LOCATION_ANNOTATION } from '@backstage/catalog-model'; import { CatalogApi } from '@backstage/catalog-client'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { screen, waitFor } from '@testing-library/react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('DeleteEntityDialog', () => { const alertApi: jest.Mocked = { @@ -34,10 +33,6 @@ describe('DeleteEntityDialog', () => { const catalogClient: jest.Mocked = { removeEntityByUid: jest.fn(), } as any; - const apis = ApiRegistry.with(catalogApiRef, catalogClient).with( - alertApiRef, - alertApi, - ); const entity = { apiVersion: 'backstage.io/v1alpha1', @@ -54,7 +49,14 @@ describe('DeleteEntityDialog', () => { }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); afterEach(() => { diff --git a/plugins/catalog/src/components/EntityOrphanWarning/EntityOrphanWarning.test.tsx b/plugins/catalog/src/components/EntityOrphanWarning/EntityOrphanWarning.test.tsx index 9e26184a8d..a8aac405fe 100644 --- a/plugins/catalog/src/components/EntityOrphanWarning/EntityOrphanWarning.test.tsx +++ b/plugins/catalog/src/components/EntityOrphanWarning/EntityOrphanWarning.test.tsx @@ -15,23 +15,16 @@ */ import { - CatalogApi, catalogApiRef, catalogRouteRef, EntityProvider, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { EntityOrphanWarning } from './EntityOrphanWarning'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { - const catalogClient: jest.Mocked = { - removeEntityByUid: jest.fn(), - } as any; - const apis = ApiRegistry.with(catalogApiRef, catalogClient); - it('renders EntityOrphanWarning if the entity is orphan', async () => { const entity = { apiVersion: 'v1', @@ -50,11 +43,20 @@ describe('', () => { }; const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/create': catalogRouteRef, diff --git a/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.test.tsx b/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.test.tsx index c406d0ed3c..fcc4475f6a 100644 --- a/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.test.tsx +++ b/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.test.tsx @@ -21,17 +21,17 @@ import { entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import React from 'react'; import { EntityProcessingErrorsPanel } from './EntityProcessingErrorsPanel'; import { Entity, getEntityName } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; describe('', () => { - const catalogClient: jest.Mocked = { - getEntityAncestors: jest.fn(), - } as any; - const apis = ApiRegistry.with(catalogApiRef, catalogClient); + const getEntityAncestors: jest.MockedFunction< + CatalogApi['getEntityAncestors'] + > = jest.fn(); + const apis = TestApiRegistry.from([catalogApiRef, { getEntityAncestors }]); it('renders EntityProcessErrors if the entity has errors', async () => { const entity: Entity = { @@ -97,7 +97,7 @@ describe('', () => { }, }; - catalogClient.getEntityAncestors.mockResolvedValue({ + getEntityAncestors.mockResolvedValue({ root: getEntityName(entity), items: [{ entity, parents: [] }], }); @@ -198,7 +198,7 @@ describe('', () => { ], }, }; - catalogClient.getEntityAncestors.mockResolvedValue({ + getEntityAncestors.mockResolvedValue({ root: getEntityName(entity), items: [ { entity, parents: [getEntityName(parent)] }, diff --git a/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx b/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx index 7f8bf35b74..8768e9728e 100644 --- a/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx +++ b/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx @@ -21,17 +21,14 @@ import React from 'react'; import { isKind } from './conditions'; import { EntitySwitch } from './EntitySwitch'; import { featureFlagsApiRef } from '@backstage/core-plugin-api'; -import { - LocalStorageFeatureFlags, - ApiProvider, - ApiRegistry, -} from '@backstage/core-app-api'; +import { LocalStorageFeatureFlags } from '@backstage/core-app-api'; +import { TestApiProvider } from '@backstage/test-utils'; const mockFeatureFlagsApi = new LocalStorageFeatureFlags(); const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - + {children} - + ); describe('EntitySwitch', () => { diff --git a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.test.tsx b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.test.tsx index d484ab026a..45f7561d6e 100644 --- a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.test.tsx +++ b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.test.tsx @@ -21,28 +21,20 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { HasComponentsCard } from './HasComponentsCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { - const catalogApi: jest.Mocked = { - getLocationById: jest.fn(), - getEntityByName: jest.fn(), - getEntities: jest.fn(), - addLocation: jest.fn(), - getLocationByEntity: jest.fn(), - removeEntityByUid: jest.fn(), - } as any; + const getEntities: jest.MockedFunction = jest.fn(); let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); @@ -97,7 +89,7 @@ describe('', () => { }, ], }; - catalogApi.getEntities.mockResolvedValue({ + getEntities.mockResolvedValue({ items: [ { apiVersion: 'v1', diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx index 45604ceb56..a01922d988 100644 --- a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx +++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx @@ -21,28 +21,20 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { HasResourcesCard } from './HasResourcesCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { - const catalogApi: jest.Mocked = { - getLocationById: jest.fn(), - getEntityByName: jest.fn(), - getEntities: jest.fn(), - addLocation: jest.fn(), - getLocationByEntity: jest.fn(), - removeEntityByUid: jest.fn(), - } as any; + const getEntities: jest.MockedFunction = jest.fn(); let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); @@ -92,7 +84,7 @@ describe('', () => { }, ], }; - catalogApi.getEntities.mockResolvedValue({ + getEntities.mockResolvedValue({ items: [ { apiVersion: 'v1', diff --git a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.test.tsx b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.test.tsx index 431e757656..e517bd38ae 100644 --- a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.test.tsx +++ b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.test.tsx @@ -21,28 +21,20 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { HasSubcomponentsCard } from './HasSubcomponentsCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { - const catalogApi: jest.Mocked = { - getLocationById: jest.fn(), - getEntityByName: jest.fn(), - getEntities: jest.fn(), - addLocation: jest.fn(), - getLocationByEntity: jest.fn(), - removeEntityByUid: jest.fn(), - } as any; + const getEntities: jest.MockedFunction = jest.fn(); let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); @@ -97,7 +89,7 @@ describe('', () => { }, ], }; - catalogApi.getEntities.mockResolvedValue({ + getEntities.mockResolvedValue({ items: [ { apiVersion: 'v1', diff --git a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.test.tsx b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.test.tsx index 3fcfed6099..050550101f 100644 --- a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.test.tsx +++ b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.test.tsx @@ -21,28 +21,20 @@ import { EntityProvider, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { HasSystemsCard } from './HasSystemsCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { - const catalogApi: jest.Mocked = { - getLocationById: jest.fn(), - getEntityByName: jest.fn(), - getEntities: jest.fn(), - addLocation: jest.fn(), - getLocationByEntity: jest.fn(), - removeEntityByUid: jest.fn(), - } as any; + const getEntities: jest.MockedFunction = jest.fn(); let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); @@ -95,7 +87,7 @@ describe('', () => { }, ], }; - catalogApi.getEntities.mockResolvedValue({ + getEntities.mockResolvedValue({ items: [ { apiVersion: 'v1', diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx index 2b35d0f3b6..e0ec48fbed 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx @@ -21,10 +21,9 @@ import { entityRouteRef, } from '@backstage/plugin-catalog-react'; import { Entity, RELATION_PART_OF } from '@backstage/catalog-model'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { SystemDiagramCard } from './SystemDiagramCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { beforeAll(() => { @@ -55,11 +54,11 @@ describe('', () => { }; const { queryByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, @@ -114,11 +113,11 @@ describe('', () => { }; const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, @@ -173,11 +172,11 @@ describe('', () => { }; const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, diff --git a/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.test.tsx b/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.test.tsx index 4a38af3dbc..e29bb78f2f 100644 --- a/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.test.tsx +++ b/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.test.tsx @@ -15,10 +15,10 @@ */ import { CostInsightsHeader } from './CostInsightsHeader'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import React from 'react'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { IdentityApi, identityApiRef } from '@backstage/core-plugin-api'; describe('', () => { @@ -29,7 +29,7 @@ describe('', () => { }), }; - const apis = ApiRegistry.from([[identityApiRef, identityApi]]); + const apis = TestApiRegistry.from([identityApiRef, identityApi]); it('Shows nothing to do when no alerts exist', async () => { const rendered = await renderInTestApp( diff --git a/plugins/cost-insights/src/testUtils/providers.tsx b/plugins/cost-insights/src/testUtils/providers.tsx index 75450c0bb7..09d2feb71b 100644 --- a/plugins/cost-insights/src/testUtils/providers.tsx +++ b/plugins/cost-insights/src/testUtils/providers.tsx @@ -30,8 +30,9 @@ import { Group, Duration } from '../types'; // TODO(Rugvip): Could be good to have a clear place to put test utils that is linted accordingly // eslint-disable-next-line import/no-extraneous-dependencies -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { IdentityApi, identityApiRef } from '@backstage/core-plugin-api'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { TestApiProvider } from '@backstage/test-utils'; type PartialPropsWithChildren = PropsWithChildren>; @@ -199,16 +200,17 @@ export const MockCostInsightsApiProvider = ({ getUserGroups: jest.fn(), }; - // TODO: defaultConfigApiRef: ConfigApiRef - - const defaultContext = ApiRegistry.from([ - [identityApiRef, { ...defaultIdentityApi, ...context.identityApi }], - [ - costInsightsApiRef, - { ...defaultCostInsightsApi, ...context.costInsightsApi }, - ], - // [configApiRef, { ...defaultConfigApiRef, ...context.configApiRef }] - ]); - - return {children}; + return ( + + {children} + + ); }; diff --git a/plugins/explore/src/components/DefaultExplorePage/DefaultExplorePage.test.tsx b/plugins/explore/src/components/DefaultExplorePage/DefaultExplorePage.test.tsx index 8927cf088b..d10c262357 100644 --- a/plugins/explore/src/components/DefaultExplorePage/DefaultExplorePage.test.tsx +++ b/plugins/explore/src/components/DefaultExplorePage/DefaultExplorePage.test.tsx @@ -15,11 +15,10 @@ */ import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor, getByText } from '@testing-library/react'; import React from 'react'; import { DefaultExplorePage } from './DefaultExplorePage'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const catalogApi: jest.Mocked = { @@ -36,9 +35,9 @@ describe('', () => { }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - + {children} - + ); beforeEach(() => { diff --git a/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.test.tsx b/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.test.tsx index d78fc0428d..46a8f1adf2 100644 --- a/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.test.tsx +++ b/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.test.tsx @@ -16,12 +16,11 @@ import { DomainEntity } from '@backstage/catalog-model'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { catalogEntityRouteRef } from '../../routes'; import { DomainExplorerContent } from './DomainExplorerContent'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const catalogApi: jest.Mocked = { @@ -38,9 +37,9 @@ describe('', () => { }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - + {children} - + ); const mountedRoutes = { diff --git a/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx b/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx index 80944628da..7574c685a4 100644 --- a/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx +++ b/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx @@ -14,16 +14,12 @@ * limitations under the License. */ -import { - ApiProvider, - ApiRegistry, - FeatureFlagged, -} from '@backstage/core-app-api'; +import { FeatureFlagged } from '@backstage/core-app-api'; import { FeatureFlagsApi, featureFlagsApiRef, } from '@backstage/core-plugin-api'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { ExploreLayout } from './ExploreLayout'; @@ -35,11 +31,11 @@ const featureFlagsApi: jest.Mocked = { registerFlag: jest.fn(), }; -const mockApis = ApiRegistry.with(featureFlagsApiRef, featureFlagsApi); - describe('', () => { const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); afterEach(() => { diff --git a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.test.tsx b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.test.tsx index 66f54900c9..7c57de84bc 100644 --- a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.test.tsx +++ b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.test.tsx @@ -20,10 +20,9 @@ import { entityRouteRef, } from '@backstage/plugin-catalog-react'; import { Entity } from '@backstage/catalog-model'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { GroupsDiagram } from './GroupsDiagram'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { beforeAll(() => { @@ -57,9 +56,9 @@ describe('', () => { }; const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, diff --git a/plugins/explore/src/components/GroupsExplorerContent/GroupsExplorerContent.test.tsx b/plugins/explore/src/components/GroupsExplorerContent/GroupsExplorerContent.test.tsx index f0815e0116..5d3f7c358b 100644 --- a/plugins/explore/src/components/GroupsExplorerContent/GroupsExplorerContent.test.tsx +++ b/plugins/explore/src/components/GroupsExplorerContent/GroupsExplorerContent.test.tsx @@ -16,11 +16,10 @@ import { Entity } from '@backstage/catalog-model'; import { catalogApiRef, entityRouteRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { GroupsExplorerContent } from '../GroupsExplorerContent'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const catalogApi: jest.Mocked = { @@ -37,9 +36,9 @@ describe('', () => { }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - + {children} - + ); const mountedRoutes = { diff --git a/plugins/explore/src/components/ToolExplorerContent/ToolExplorerContent.test.tsx b/plugins/explore/src/components/ToolExplorerContent/ToolExplorerContent.test.tsx index 8accf8fd30..da35c9fa39 100644 --- a/plugins/explore/src/components/ToolExplorerContent/ToolExplorerContent.test.tsx +++ b/plugins/explore/src/components/ToolExplorerContent/ToolExplorerContent.test.tsx @@ -18,13 +18,12 @@ import { ExploreTool, exploreToolsConfigRef, } from '@backstage/plugin-explore-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { lightTheme } from '@backstage/theme'; import { ThemeProvider } from '@material-ui/core'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { ToolExplorerContent } from './ToolExplorerContent'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const exploreToolsConfigApi: jest.Mocked = { @@ -33,11 +32,9 @@ describe('', () => { const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - + {children} - + ); diff --git a/plugins/firehydrant/src/components/ServiceDetailsCard/ServiceDetailsCard.test.tsx b/plugins/firehydrant/src/components/ServiceDetailsCard/ServiceDetailsCard.test.tsx index 1123f014da..20dbb77e86 100644 --- a/plugins/firehydrant/src/components/ServiceDetailsCard/ServiceDetailsCard.test.tsx +++ b/plugins/firehydrant/src/components/ServiceDetailsCard/ServiceDetailsCard.test.tsx @@ -14,19 +14,19 @@ * limitations under the License. */ import React from 'react'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { fireHydrantApiRef } from '../../api'; import { screen } from '@testing-library/react'; import { ServiceDetailsCard } from './ServiceDetailsCard'; import { Service, Incident } from '../types'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; const mockFireHydrantApi = { - getServiceDetails: () => {}, - getServiceAnalytics: () => {}, + getServiceDetails: jest.fn(), + getServiceAnalytics: jest.fn(), }; -const apis = ApiRegistry.from([[fireHydrantApiRef, mockFireHydrantApi]]); +const apis = TestApiRegistry.from([fireHydrantApiRef, mockFireHydrantApi]); jest.mock('@backstage/plugin-catalog-react', () => ({ useEntity: () => { diff --git a/plugins/fossa/src/components/FossaCard/FossaCard.test.tsx b/plugins/fossa/src/components/FossaCard/FossaCard.test.tsx index 79b401e4a8..046e3e9860 100644 --- a/plugins/fossa/src/components/FossaCard/FossaCard.test.tsx +++ b/plugins/fossa/src/components/FossaCard/FossaCard.test.tsx @@ -16,11 +16,10 @@ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { FossaApi, fossaApiRef } from '../../api'; import { FossaCard } from './FossaCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const fossaApi: jest.Mocked = { @@ -30,10 +29,10 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(fossaApiRef, fossaApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx b/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx index 778f5ee9c6..421ff4431f 100644 --- a/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx +++ b/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx @@ -20,11 +20,10 @@ import { catalogApiRef, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { FossaApi, fossaApiRef } from '../../api'; import { FossaPage } from './FossaPage'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const catalogApi: jest.Mocked = { @@ -46,13 +45,15 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(fossaApiRef, fossaApi).with( - catalogApiRef, - catalogApi, - ); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx index 4a4452be5c..0f9573e051 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx @@ -24,16 +24,13 @@ import { useWorkflowRuns } from '../useWorkflowRuns'; import type { Props as RecentWorkflowRunsCardProps } from './RecentWorkflowRunsCard'; import { RecentWorkflowRunsCard } from './RecentWorkflowRunsCard'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ConfigReader } from '@backstage/core-app-api'; import { errorApiRef, configApiRef, ConfigApi, } from '@backstage/core-plugin-api'; +import { TestApiProvider } from '@backstage/test-utils'; jest.mock('../useWorkflowRuns', () => ({ useWorkflowRuns: jest.fn(), @@ -82,16 +79,16 @@ describe('', () => { render( - - + , ); diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx index 08eeb4a3ce..dba5bbfe1c 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx @@ -19,6 +19,7 @@ import { fireEvent } from '@testing-library/react'; import { setupRequestMockHandlers, renderInTestApp, + TestApiRegistry, } from '@backstage/test-utils'; import { GithubDeployment, @@ -42,11 +43,7 @@ import { Entity } from '@backstage/catalog-model'; import { GithubDeploymentsTable } from './GithubDeploymentsTable'; import { Box } from '@material-ui/core'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { errorApiRef, configApiRef, @@ -95,14 +92,14 @@ const githubAuthApi: OAuthApi = { getAccessToken: async _ => 'access_token', }; -const apis = ApiRegistry.from([ +const apis = TestApiRegistry.from( [configApiRef, configApi], [errorApiRef, errorApiMock], [ githubDeploymentsApiRef, new GithubDeploymentsApiClient({ scmIntegrationsApi, githubAuthApi }), ], -]); +); const assertFetchedData = async () => { const rendered = await renderInTestApp( diff --git a/plugins/gitops-profiles/src/components/ProfileCatalog/ProfileCatalog.test.tsx b/plugins/gitops-profiles/src/components/ProfileCatalog/ProfileCatalog.test.tsx index 8dba498507..e158bcf6ad 100644 --- a/plugins/gitops-profiles/src/components/ProfileCatalog/ProfileCatalog.test.tsx +++ b/plugins/gitops-profiles/src/components/ProfileCatalog/ProfileCatalog.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { lightTheme } from '@backstage/theme'; import { ThemeProvider } from '@material-ui/core'; import React from 'react'; @@ -23,7 +23,6 @@ import ProfileCatalog from './ProfileCatalog'; import { ApiProvider, - ApiRegistry, GithubAuth, OAuthRequestManager, UrlPatternDiscovery, @@ -34,7 +33,7 @@ import { githubAuthApiRef } from '@backstage/core-plugin-api'; describe('ProfileCatalog', () => { it('should render', async () => { const oauthRequestApi = new OAuthRequestManager(); - const apis = ApiRegistry.from([ + const apis = TestApiRegistry.from( [gitOpsApiRef, new GitOpsRestApi('http://localhost:3008')], [ githubAuthApiRef, @@ -45,7 +44,7 @@ describe('ProfileCatalog', () => { oauthRequestApi, }), ], - ]); + ); const { getByText } = await renderInTestApp( diff --git a/plugins/graphiql/src/components/GraphiQLPage/GraphiQLPage.test.tsx b/plugins/graphiql/src/components/GraphiQLPage/GraphiQLPage.test.tsx index 4e426d4364..ae84b549ec 100644 --- a/plugins/graphiql/src/components/GraphiQLPage/GraphiQLPage.test.tsx +++ b/plugins/graphiql/src/components/GraphiQLPage/GraphiQLPage.test.tsx @@ -19,14 +19,10 @@ import { GraphiQLPage } from './GraphiQLPage'; import { ThemeProvider } from '@material-ui/core'; import { lightTheme } from '@backstage/theme'; import { act } from 'react-dom/test-utils'; -import { renderWithEffects } from '@backstage/test-utils'; +import { renderWithEffects, TestApiProvider } from '@backstage/test-utils'; import { GraphQLBrowseApi, graphQlBrowseApiRef } from '../../lib/api'; import { configApiRef } from '@backstage/core-plugin-api'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ConfigReader } from '@backstage/core-app-api'; jest.mock('../GraphiQLBrowser', () => ({ GraphiQLBrowser: () => '', @@ -43,17 +39,17 @@ describe('GraphiQLPage', () => { }; const rendered = await renderWithEffects( - , - , + , ); act(() => { jest.advanceTimersByTime(250); @@ -71,16 +67,16 @@ describe('GraphiQLPage', () => { }; const rendered = await renderWithEffects( - - , + , ); rendered.getByText('GraphiQL'); @@ -95,16 +91,16 @@ describe('GraphiQLPage', () => { }; const rendered = await renderWithEffects( - - , + , ); rendered.getByText('GraphiQL'); diff --git a/plugins/jenkins/src/components/Cards/Cards.test.tsx b/plugins/jenkins/src/components/Cards/Cards.test.tsx index 2508461710..0af91da179 100644 --- a/plugins/jenkins/src/components/Cards/Cards.test.tsx +++ b/plugins/jenkins/src/components/Cards/Cards.test.tsx @@ -15,11 +15,10 @@ */ import React from 'react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { LatestRunCard } from './Cards'; import { EntityProvider } from '@backstage/plugin-catalog-react'; import { JenkinsApi, jenkinsApiRef } from '../../api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { Project } from '../../api/JenkinsApi'; describe('', () => { @@ -41,14 +40,12 @@ describe('', () => { }; it('should show success status of latest build', async () => { - const apis = ApiRegistry.from([[jenkinsApiRef, jenkinsApi]]); - const { getByText } = await renderInTestApp( - + - , + , ); expect(getByText('Completed')).toBeInTheDocument(); @@ -59,14 +56,12 @@ describe('', () => { getProjects: () => Promise.reject(new Error('Unauthorized')), }; - const apis = ApiRegistry.from([[jenkinsApiRef, jenkinsApiWithError]]); - const { getByText } = await renderInTestApp( - + - , + , ); expect(getByText("Error: Can't connect to Jenkins")).toBeInTheDocument(); @@ -82,14 +77,12 @@ describe('', () => { }), }; - const apis = ApiRegistry.from([[jenkinsApiRef, jenkinsApiWithError]]); - const { getByText } = await renderInTestApp( - + - , + , ); expect(getByText("Error: Can't find Jenkins project")).toBeInTheDocument(); diff --git a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx index a90d3d608e..0be9cabacd 100644 --- a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx +++ b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx @@ -26,8 +26,8 @@ import { import { useConsumerGroupsOffsetsForEntity } from './useConsumerGroupsOffsetsForEntity'; import * as data from './__fixtures__/consumer-group-offsets.json'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; +import { TestApiProvider } from '@backstage/test-utils'; const consumerGroupOffsets = data as ConsumerGroupOffsetsResponse; @@ -59,14 +59,14 @@ describe('useConsumerGroupOffsets', () => { const wrapper = ({ children }: PropsWithChildren<{}>) => { return ( - {children} - + ); }; diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx index a2c1114c2d..12de5f098f 100644 --- a/plugins/kubernetes/dev/index.tsx +++ b/plugins/kubernetes/dev/index.tsx @@ -29,7 +29,7 @@ import { } from '@backstage/plugin-kubernetes-common'; import fixture1 from '../src/__fixtures__/1-deployments.json'; import fixture2 from '../src/__fixtures__/2-deployments.json'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { TestApiProvider } from '@backstage/test-utils'; const mockEntity: Entity = { apiVersion: 'backstage.io/v1alpha1', @@ -80,32 +80,26 @@ createDevApp() path: '/fixture-1', title: 'Fixture 1', element: ( - - + ), }) .addPage({ path: '/fixture-2', title: 'Fixture 2', element: ( - - + ), }) .registerPlugin(kubernetesPlugin) diff --git a/plugins/lighthouse/src/components/AuditList/AuditListForEntity.test.tsx b/plugins/lighthouse/src/components/AuditList/AuditListForEntity.test.tsx index 1433a186fb..53de33d21b 100644 --- a/plugins/lighthouse/src/components/AuditList/AuditListForEntity.test.tsx +++ b/plugins/lighthouse/src/components/AuditList/AuditListForEntity.test.tsx @@ -30,8 +30,9 @@ import { useWebsiteForEntity } from '../../hooks/useWebsiteForEntity'; import * as data from '../../__fixtures__/website-list-response.json'; import { AuditListForEntity } from './AuditListForEntity'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; +import { TestApiRegistry } from '@backstage/test-utils'; jest.mock('../../hooks/useWebsiteForEntity', () => ({ useWebsiteForEntity: jest.fn(), @@ -41,7 +42,7 @@ const websiteListResponse = data as WebsiteListResponse; const entityWebsite = websiteListResponse.items[0]; describe('', () => { - let apis: ApiRegistry; + let apis: TestApiRegistry; const mockErrorApi: jest.Mocked = { post: jest.fn(), @@ -49,10 +50,10 @@ describe('', () => { }; beforeEach(() => { - apis = ApiRegistry.from([ + apis = TestApiRegistry.from( [lighthouseApiRef, new LighthouseRestApi('http://lighthouse')], [errorApiRef, mockErrorApi], - ]); + ); (useWebsiteForEntity as jest.Mock).mockReturnValue({ value: entityWebsite, diff --git a/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx b/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx index 4c92997755..d8a54928b2 100644 --- a/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx +++ b/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx @@ -16,7 +16,11 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { wrapInTestApp, setupRequestMockHandlers } from '@backstage/test-utils'; +import { + wrapInTestApp, + setupRequestMockHandlers, + TestApiRegistry, +} from '@backstage/test-utils'; import AuditListTable from './AuditListTable'; import { @@ -28,19 +32,20 @@ import { formatTime } from '../../utils'; import { setupServer } from 'msw/node'; import * as data from '../../__fixtures__/website-list-response.json'; -import { ApiRegistry, ApiProvider } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; const websiteListResponse = data as WebsiteListResponse; describe('AuditListTable', () => { - let apis: ApiRegistry; + let apis: TestApiRegistry; const server = setupServer(); setupRequestMockHandlers(server); beforeEach(() => { - apis = ApiRegistry.from([ - [lighthouseApiRef, new LighthouseRestApi('http://lighthouse')], + apis = TestApiRegistry.from([ + lighthouseApiRef, + new LighthouseRestApi('http://lighthouse'), ]); }); diff --git a/plugins/lighthouse/src/components/AuditList/index.test.tsx b/plugins/lighthouse/src/components/AuditList/index.test.tsx index ea3587fea9..2b422cce7a 100644 --- a/plugins/lighthouse/src/components/AuditList/index.test.tsx +++ b/plugins/lighthouse/src/components/AuditList/index.test.tsx @@ -23,7 +23,11 @@ jest.mock('react-router-dom', () => { }; }); -import { setupRequestMockHandlers, wrapInTestApp } from '@backstage/test-utils'; +import { + setupRequestMockHandlers, + TestApiRegistry, + wrapInTestApp, +} from '@backstage/test-utils'; import { fireEvent, render } from '@testing-library/react'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; @@ -35,20 +39,21 @@ import { } from '../../api'; import * as data from '../../__fixtures__/website-list-response.json'; import AuditList from './index'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; const { useNavigate } = jest.requireMock('react-router-dom'); const websiteListResponse = data as WebsiteListResponse; describe('AuditList', () => { - let apis: ApiRegistry; + let apis: TestApiRegistry; const server = setupServer(); setupRequestMockHandlers(server); beforeEach(() => { - apis = ApiRegistry.from([ - [lighthouseApiRef, new LighthouseRestApi('http://lighthouse')], + apis = TestApiRegistry.from([ + lighthouseApiRef, + new LighthouseRestApi('http://lighthouse'), ]); }); diff --git a/plugins/lighthouse/src/components/AuditView/index.test.tsx b/plugins/lighthouse/src/components/AuditView/index.test.tsx index ed1bbbcaf9..00b2843a50 100644 --- a/plugins/lighthouse/src/components/AuditView/index.test.tsx +++ b/plugins/lighthouse/src/components/AuditView/index.test.tsx @@ -26,7 +26,11 @@ jest.mock('react-router-dom', () => { }; }); -import { setupRequestMockHandlers, wrapInTestApp } from '@backstage/test-utils'; +import { + setupRequestMockHandlers, + TestApiRegistry, + wrapInTestApp, +} from '@backstage/test-utils'; import { render } from '@testing-library/react'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; @@ -35,14 +39,14 @@ import { Audit, lighthouseApiRef, LighthouseRestApi, Website } from '../../api'; import { formatTime } from '../../utils'; import * as data from '../../__fixtures__/website-response.json'; import AuditView from './index'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; const { useParams }: { useParams: jest.Mock } = jest.requireMock('react-router-dom'); const websiteResponse = data as Website; describe('AuditView', () => { - let apis: ApiRegistry; + let apis: TestApiRegistry; let id: string; const server = setupServer(); @@ -55,8 +59,9 @@ describe('AuditView', () => { ), ); - apis = ApiRegistry.from([ - [lighthouseApiRef, new LighthouseRestApi('https://lighthouse')], + apis = TestApiRegistry.from([ + lighthouseApiRef, + new LighthouseRestApi('https://lighthouse'), ]); id = websiteResponse.audits.find(a => a.status === 'COMPLETED') ?.id as string; diff --git a/plugins/lighthouse/src/components/CreateAudit/index.test.tsx b/plugins/lighthouse/src/components/CreateAudit/index.test.tsx index 84493e243f..59847b516e 100644 --- a/plugins/lighthouse/src/components/CreateAudit/index.test.tsx +++ b/plugins/lighthouse/src/components/CreateAudit/index.test.tsx @@ -23,7 +23,11 @@ jest.mock('react-router-dom', () => { }; }); -import { setupRequestMockHandlers, wrapInTestApp } from '@backstage/test-utils'; +import { + setupRequestMockHandlers, + TestApiRegistry, + wrapInTestApp, +} from '@backstage/test-utils'; import { fireEvent, render, waitFor } from '@testing-library/react'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; @@ -32,7 +36,7 @@ import { Audit, lighthouseApiRef, LighthouseRestApi } from '../../api'; import * as data from '../../__fixtures__/create-audit-response.json'; import CreateAudit from './index'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { ErrorApi, errorApiRef } from '@backstage/core-plugin-api'; const { useNavigate }: { useNavigate: jest.Mock } = @@ -41,17 +45,17 @@ const createAuditResponse = data as Audit; // TODO add act() to these tests without breaking them! describe('CreateAudit', () => { - let apis: ApiRegistry; + let apis: TestApiRegistry; let errorApi: ErrorApi; const server = setupServer(); setupRequestMockHandlers(server); beforeEach(() => { errorApi = { post: jest.fn(), error$: jest.fn() }; - apis = ApiRegistry.from([ + apis = TestApiRegistry.from( [lighthouseApiRef, new LighthouseRestApi('http://lighthouse')], [errorApiRef, errorApi], - ]); + ); }); it('renders the form', () => { diff --git a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx index 64f7483081..13da0f6f4f 100644 --- a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx +++ b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx @@ -21,8 +21,8 @@ import { lighthouseApiRef, WebsiteListResponse } from '../api'; import * as data from '../__fixtures__/website-list-response.json'; import { useWebsiteForEntity } from './useWebsiteForEntity'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; +import { TestApiProvider } from '@backstage/test-utils'; const websiteListResponse = data as WebsiteListResponse; const website = websiteListResponse.items[0]; @@ -55,14 +55,14 @@ describe('useWebsiteForEntity', () => { const wrapper = ({ children }: PropsWithChildren<{}>) => { return ( - {children} - + ); }; diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx index 0a5a0cfef1..b6b549d934 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx @@ -15,8 +15,8 @@ */ import { Entity, GroupEntity } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { catalogApiRef, EntityProvider } from '@backstage/plugin-catalog-react'; +import { TestApiProvider } from '@backstage/test-utils'; import { Grid } from '@material-ui/core'; import React from 'react'; import { MemoryRouter } from 'react-router'; @@ -99,12 +99,9 @@ const catalogApi = (items: Entity[]) => ({ getEntities: () => Promise.resolve({ items }), }); -const apiRegistry = (items: Entity[]) => - ApiRegistry.from([[catalogApiRef, catalogApi(items)]]); - export const Default = () => ( - + @@ -112,13 +109,13 @@ export const Default = () => ( - + ); export const Empty = () => ( - + @@ -126,6 +123,6 @@ export const Empty = () => ( - + ); diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx index 75cb9efd7f..b0c68d9a83 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx @@ -20,10 +20,13 @@ import { catalogApiRef, EntityProvider, } from '@backstage/plugin-catalog-react'; -import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { + renderWithEffects, + TestApiProvider, + wrapInTestApp, +} from '@backstage/test-utils'; import React from 'react'; import { MembersListCard } from './MembersListCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('MemberTab Test', () => { const groupEntity: GroupEntity = { @@ -103,17 +106,15 @@ describe('MemberTab Test', () => { }), }; - const apis = ApiRegistry.from([[catalogApiRef, catalogApi]]); - it('Display Profile Card', async () => { const rendered = await renderWithEffects( wrapInTestApp( - + , - , + , ), ); diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx index 14fed985b6..6a20035dfa 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx @@ -15,14 +15,14 @@ */ import { GroupEntity } from '@backstage/catalog-model'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { CatalogApi, catalogApiRef, catalogRouteRef, EntityProvider, } from '@backstage/plugin-catalog-react'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { BackstageTheme, createTheme, @@ -86,11 +86,11 @@ const catalogApi: Partial = { getEntities: () => Promise.resolve({ items: [serviceA, serviceB, websiteA] }), }; -const apiRegistry = ApiRegistry.from([[catalogApiRef, catalogApi]]); +const apis = TestApiRegistry.from([catalogApiRef, catalogApi]); export const Default = () => wrapInTestApp( - + @@ -123,7 +123,7 @@ const monochromeTheme = (outer: BackstageTheme) => export const Themed = () => wrapInTestApp( - + diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx index b5ffd37083..8d6fc1a002 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx @@ -21,11 +21,10 @@ import { EntityProvider, catalogRouteRef, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { queryByText } from '@testing-library/react'; import React from 'react'; import { OwnershipCard } from './OwnershipCard'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('OwnershipCard', () => { const groupEntity: GroupEntity = { @@ -121,11 +120,11 @@ describe('OwnershipCard', () => { }); const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/create': catalogRouteRef, @@ -157,11 +156,11 @@ describe('OwnershipCard', () => { }); const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/create': catalogRouteRef, @@ -205,11 +204,11 @@ describe('OwnershipCard', () => { }); const { getByText } = await renderInTestApp( - + - , + , { mountedRoutes: { '/create': catalogRouteRef, diff --git a/plugins/pagerduty/src/components/ChangeEvents/ChangeEvents.test.tsx b/plugins/pagerduty/src/components/ChangeEvents/ChangeEvents.test.tsx index 446c867f35..723e7b7b19 100644 --- a/plugins/pagerduty/src/components/ChangeEvents/ChangeEvents.test.tsx +++ b/plugins/pagerduty/src/components/ChangeEvents/ChangeEvents.test.tsx @@ -16,15 +16,15 @@ import React from 'react'; import { render, waitFor } from '@testing-library/react'; import { ChangeEvent } from '../types'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { pagerDutyApiRef } from '../../api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { ChangeEvents } from './ChangeEvents'; const mockPagerDutyApi = { - getChangeEventsByServiceId: () => [], + getChangeEventsByServiceId: jest.fn(), }; -const apis = ApiRegistry.from([[pagerDutyApiRef, mockPagerDutyApi]]); +const apis = TestApiRegistry.from([pagerDutyApiRef, mockPagerDutyApi]); describe('Incidents', () => { it('Renders an empty state when there are no change events', async () => { diff --git a/plugins/pagerduty/src/components/Escalation/Escalation.test.tsx b/plugins/pagerduty/src/components/Escalation/Escalation.test.tsx index 52aa9a860f..47f18002fe 100644 --- a/plugins/pagerduty/src/components/Escalation/Escalation.test.tsx +++ b/plugins/pagerduty/src/components/Escalation/Escalation.test.tsx @@ -16,15 +16,15 @@ import React from 'react'; import { render, waitFor } from '@testing-library/react'; import { EscalationPolicy } from './EscalationPolicy'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { User } from '../types'; import { pagerDutyApiRef } from '../../api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; const mockPagerDutyApi = { - getOnCallByPolicyId: () => [], + getOnCallByPolicyId: jest.fn(), }; -const apis = ApiRegistry.from([[pagerDutyApiRef, mockPagerDutyApi]]); +const apis = TestApiRegistry.from([pagerDutyApiRef, mockPagerDutyApi]); describe('Escalation', () => { it('Handles an empty response', async () => { diff --git a/plugins/pagerduty/src/components/Incident/Incidents.test.tsx b/plugins/pagerduty/src/components/Incident/Incidents.test.tsx index d66acc0879..74e7d82e8b 100644 --- a/plugins/pagerduty/src/components/Incident/Incidents.test.tsx +++ b/plugins/pagerduty/src/components/Incident/Incidents.test.tsx @@ -16,15 +16,15 @@ import React from 'react'; import { render, waitFor } from '@testing-library/react'; import { Incidents } from './Incidents'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { pagerDutyApiRef } from '../../api'; import { Incident } from '../types'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; const mockPagerDutyApi = { - getIncidentsByServiceId: () => [], + getIncidentsByServiceId: jest.fn(), }; -const apis = ApiRegistry.from([[pagerDutyApiRef, mockPagerDutyApi]]); +const apis = TestApiRegistry.from([pagerDutyApiRef, mockPagerDutyApi]); describe('Incidents', () => { it('Renders an empty state when there are no incidents', async () => { diff --git a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx index d644aa019a..e0a857ccc7 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx @@ -18,12 +18,12 @@ import { render, waitFor, fireEvent, act } from '@testing-library/react'; import { PagerDutyCard } from '../PagerDutyCard'; import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { pagerDutyApiRef, UnauthorizedError, PagerDutyClient } from '../../api'; import { Service, User } from '../types'; -import { alertApiRef, createApiRef } from '@backstage/core-plugin-api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { alertApiRef } from '@backstage/core-plugin-api'; +import { ApiProvider } from '@backstage/core-app-api'; const mockPagerDutyApi: Partial = { getServiceByIntegrationKey: async () => [], @@ -31,16 +31,10 @@ const mockPagerDutyApi: Partial = { getIncidentsByServiceId: async () => [], }; -const apis = ApiRegistry.from([ +const apis = TestApiRegistry.from( [pagerDutyApiRef, mockPagerDutyApi], - [ - alertApiRef, - createApiRef({ - id: 'core.alert', - description: 'Used to report alerts and forward them to the app', - }), - ], -]); + [alertApiRef, {}], +); const entity: Entity = { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', diff --git a/plugins/pagerduty/src/components/TriggerButton/index.test.tsx b/plugins/pagerduty/src/components/TriggerButton/index.test.tsx index 21f0dd5f1d..3776bcaf1c 100644 --- a/plugins/pagerduty/src/components/TriggerButton/index.test.tsx +++ b/plugins/pagerduty/src/components/TriggerButton/index.test.tsx @@ -15,16 +15,15 @@ */ import React from 'react'; import { act, fireEvent, screen, waitFor } from '@testing-library/react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { pagerDutyApiRef } from '../../api'; import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; import { TriggerButton } from './'; -import { ApiRegistry, ApiProvider } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { alertApiRef, - createApiRef, IdentityApi, identityApiRef, } from '@backstage/core-plugin-api'; @@ -39,17 +38,11 @@ describe('TriggerButton', () => { triggerAlarm: mockTriggerAlarmFn, }; - const apis = ApiRegistry.from([ - [ - alertApiRef, - createApiRef({ - id: 'core.alert', - description: 'Used to report alerts and forward them to the app', - }), - ], + const apis = TestApiRegistry.from( + [alertApiRef, {}], [identityApiRef, mockIdentityApi], [pagerDutyApiRef, mockPagerDutyApi], - ]); + ); it('renders the trigger button, opens and closes dialog', async () => { const entity: Entity = { diff --git a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx index 444e820b98..d6f378b4bf 100644 --- a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx +++ b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx @@ -15,16 +15,15 @@ */ import React from 'react'; import { fireEvent, act } from '@testing-library/react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { pagerDutyApiRef } from '../../api'; import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; import { TriggerDialog } from './TriggerDialog'; -import { ApiRegistry, ApiProvider } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { alertApiRef, - createApiRef, IdentityApi, identityApiRef, } from '@backstage/core-plugin-api'; @@ -39,17 +38,11 @@ describe('TriggerDialog', () => { triggerAlarm: mockTriggerAlarmFn, }; - const apis = ApiRegistry.from([ - [ - alertApiRef, - createApiRef({ - id: 'core.alert', - description: 'Used to report alerts and forward them to the app', - }), - ], + const apis = TestApiRegistry.from( + [alertApiRef, {}], [identityApiRef, mockIdentityApi], [pagerDutyApiRef, mockPagerDutyApi], - ]); + ); it('open the dialog and trigger an alarm', async () => { const entity: Entity = { diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx index 77c8240974..ce0354b817 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx @@ -17,8 +17,8 @@ import React from 'react'; import { ScaffolderApi, scaffolderApiRef } from '../../api'; import { ActionsPage } from './ActionsPage'; import { rootRouteRef } from '../../routes'; -import { renderInTestApp } from '@backstage/test-utils'; -import { ApiRegistry, ApiProvider } from '@backstage/core-app-api'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; +import { ApiProvider } from '@backstage/core-app-api'; const scaffolderApiMock: jest.Mocked = { scaffold: jest.fn(), @@ -29,7 +29,7 @@ const scaffolderApiMock: jest.Mocked = { listActions: jest.fn(), }; -const apis = ApiRegistry.from([[scaffolderApiRef, scaffolderApiMock]]); +const apis = TestApiRegistry.from([scaffolderApiRef, scaffolderApiMock]); describe('TemplatePage', () => { beforeEach(() => jest.resetAllMocks()); diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx index e42bcbdbdc..60e9ee8840 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx @@ -13,7 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderInTestApp, renderWithEffects } from '@backstage/test-utils'; +import { + renderInTestApp, + renderWithEffects, + TestApiRegistry, +} from '@backstage/test-utils'; import { lightTheme } from '@backstage/theme'; import { ThemeProvider } from '@material-ui/core'; import { fireEvent, within } from '@testing-library/react'; @@ -24,7 +28,7 @@ import { ScaffolderApi, scaffolderApiRef } from '../../api'; import { rootRouteRef } from '../../routes'; import { TemplatePage } from './TemplatePage'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; jest.mock('react-router-dom', () => { @@ -47,10 +51,10 @@ const scaffolderApiMock: jest.Mocked = { const errorApiMock = { post: jest.fn(), error$: jest.fn() }; -const apis = ApiRegistry.from([ +const apis = TestApiRegistry.from( [scaffolderApiRef, scaffolderApiMock], [errorApiRef, errorApiMock], -]); +); describe('TemplatePage', () => { beforeEach(() => jest.resetAllMocks()); diff --git a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx index 3d0267ff1f..c70f251eac 100644 --- a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx +++ b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx @@ -26,8 +26,8 @@ import { MockEntityListContextProvider, } from '@backstage/plugin-catalog-react'; import { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; -import { renderWithEffects } from '@backstage/test-utils'; +import { ApiProvider } from '@backstage/core-app-api'; +import { renderWithEffects, TestApiRegistry } from '@backstage/test-utils'; const entities: Entity[] = [ { @@ -62,7 +62,7 @@ const entities: Entity[] = [ }, ]; -const apis = ApiRegistry.from([ +const apis = TestApiRegistry.from( [ catalogApiRef, { @@ -77,7 +77,7 @@ const apis = ApiRegistry.from([ post: jest.fn(), } as unknown as AlertApi, ], -]); +); describe('', () => { it('renders available entity types', async () => { diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index f293969dff..b7e72e3583 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -16,12 +16,11 @@ import { Entity } from '@backstage/catalog-model'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { FieldProps } from '@rjsf/core'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { EntityPicker } from './EntityPicker'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; const makeEntity = (kind: string, namespace: string, name: string): Entity => ({ apiVersion: 'backstage.io/v1beta1', @@ -53,14 +52,15 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); entities = [ makeEntity('Group', 'default', 'team-a'), makeEntity('Group', 'default', 'squad-b'), ]; Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx index 18d6fd7e5c..31992fbc8a 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx @@ -16,11 +16,10 @@ import { Entity } from '@backstage/catalog-model'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { FieldProps } from '@rjsf/core'; import React from 'react'; import { OwnerPicker } from './OwnerPicker'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; const makeEntity = (kind: string, namespace: string, name: string): Entity => ({ apiVersion: 'backstage.io/v1beta1', @@ -50,14 +49,15 @@ describe('', () => { let Wrapper: React.ComponentType; beforeEach(() => { - const apis = ApiRegistry.with(catalogApiRef, catalogApi); entities = [ makeEntity('Group', 'default', 'team-a'), makeEntity('Group', 'default', 'squad-b'), ]; Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/search/src/components/SearchBar/SearchBar.test.tsx b/plugins/search/src/components/SearchBar/SearchBar.test.tsx index 3a11daa9fa..81f90640c1 100644 --- a/plugins/search/src/components/SearchBar/SearchBar.test.tsx +++ b/plugins/search/src/components/SearchBar/SearchBar.test.tsx @@ -21,12 +21,9 @@ import { SearchContextProvider } from '../SearchContext'; import { SearchBar } from './SearchBar'; import { configApiRef } from '@backstage/core-plugin-api'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { searchApiRef } from '../../apis'; +import { TestApiRegistry } from '@backstage/test-utils'; jest.mock('@backstage/core-plugin-api', () => ({ ...jest.requireActual('@backstage/core-plugin-api'), @@ -42,10 +39,10 @@ describe('SearchBar', () => { const query = jest.fn().mockResolvedValue({}); - const apiRegistry = ApiRegistry.from([ + const apiRegistry = TestApiRegistry.from( [configApiRef, new ConfigReader({ app: { title: 'Mock title' } })], [searchApiRef, { query }], - ]); + ); const name = 'Search'; const term = 'term'; diff --git a/plugins/search/src/components/SearchModal/SearchModal.test.tsx b/plugins/search/src/components/SearchModal/SearchModal.test.tsx index d7f873abf3..ff9622dfb9 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.test.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.test.tsx @@ -15,14 +15,10 @@ */ import React from 'react'; import { screen } from '@testing-library/react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import { configApiRef } from '@backstage/core-plugin-api'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { rootRouteRef } from '../../plugin'; import { searchApiRef } from '../../apis'; @@ -38,10 +34,10 @@ jest.mock('../SearchContext', () => ({ describe('SearchModal', () => { const query = jest.fn().mockResolvedValue({}); - const apiRegistry = ApiRegistry.from([ + const apiRegistry = TestApiRegistry.from( [configApiRef, new ConfigReader({ app: { title: 'Mock app' } })], [searchApiRef, { query }], - ]); + ); const toggleModal = jest.fn(); diff --git a/plugins/shortcuts/src/Shortcuts.test.tsx b/plugins/shortcuts/src/Shortcuts.test.tsx index 9182bcb47d..e0a70d6069 100644 --- a/plugins/shortcuts/src/Shortcuts.test.tsx +++ b/plugins/shortcuts/src/Shortcuts.test.tsx @@ -15,25 +15,31 @@ */ import React from 'react'; -import { MockStorageApi, renderInTestApp } from '@backstage/test-utils'; +import { + MockStorageApi, + renderInTestApp, + TestApiProvider, +} from '@backstage/test-utils'; import { screen, waitFor } from '@testing-library/react'; import { Shortcuts } from './Shortcuts'; import { LocalStoredShortcuts, shortcutsApiRef } from './api'; import { SidebarContext } from '@backstage/core-components'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; - -const apis = ApiRegistry.from([ - [shortcutsApiRef, new LocalStoredShortcuts(MockStorageApi.create())], -]); describe('Shortcuts', () => { it('displays an add button', async () => { await renderInTestApp( - + - + , ); await waitFor(() => !screen.queryByTestId('progress')); diff --git a/plugins/splunk-on-call/src/components/EntitySplunkOnCallCard.test.tsx b/plugins/splunk-on-call/src/components/EntitySplunkOnCallCard.test.tsx index 63d617aff2..eb5c99d4e7 100644 --- a/plugins/splunk-on-call/src/components/EntitySplunkOnCallCard.test.tsx +++ b/plugins/splunk-on-call/src/components/EntitySplunkOnCallCard.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { act, fireEvent, render, waitFor } from '@testing-library/react'; import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { splunkOnCallApiRef, SplunkOnCallClient, @@ -37,13 +37,8 @@ import { alertApiRef, ConfigApi, configApiRef, - createApiRef, } from '@backstage/core-plugin-api'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; const mockSplunkOnCallApi: Partial = { getUsers: async () => [], @@ -59,17 +54,11 @@ const configApi: ConfigApi = new ConfigReader({ }, }); -const apis = ApiRegistry.from([ +const apis = TestApiRegistry.from( [splunkOnCallApiRef, mockSplunkOnCallApi], [configApiRef, configApi], - [ - alertApiRef, - createApiRef({ - id: 'core.alert', - description: 'Used to report alerts and forward them to the app', - }), - ], -]); + [alertApiRef, {}], +); const mockEntity = { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/splunk-on-call/src/components/Escalation/Escalation.test.tsx b/plugins/splunk-on-call/src/components/Escalation/Escalation.test.tsx index 1319493742..046c6a37f9 100644 --- a/plugins/splunk-on-call/src/components/Escalation/Escalation.test.tsx +++ b/plugins/splunk-on-call/src/components/Escalation/Escalation.test.tsx @@ -16,15 +16,15 @@ import React from 'react'; import { render, waitFor } from '@testing-library/react'; import { EscalationPolicy } from './EscalationPolicy'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { splunkOnCallApiRef } from '../../api'; import { MOCKED_ON_CALL, MOCKED_USER } from '../../api/mocks'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; const mockSplunkOnCallApi = { - getOnCallUsers: () => [], + getOnCallUsers: jest.fn(), }; -const apis = ApiRegistry.from([[splunkOnCallApiRef, mockSplunkOnCallApi]]); +const apis = TestApiRegistry.from([splunkOnCallApiRef, mockSplunkOnCallApi]); describe('Escalation', () => { it('Handles an empty response', async () => { diff --git a/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx b/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx index df4254d3ad..181c2fda77 100644 --- a/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx +++ b/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx @@ -16,43 +16,39 @@ import React from 'react'; import { render, waitFor } from '@testing-library/react'; import { Incidents } from './Incidents'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { splunkOnCallApiRef } from '../../api'; import { MOCK_TEAM, MOCK_INCIDENT } from '../../api/mocks'; import { alertApiRef, - createApiRef, IdentityApi, identityApiRef, } from '@backstage/core-plugin-api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; const mockIdentityApi: Partial = { getUserId: () => 'test', }; const mockSplunkOnCallApi = { - getIncidents: () => [], - getTeams: () => [], + getIncidents: jest.fn(), + getTeams: jest.fn(), }; -const apis = ApiRegistry.from([ - [ - alertApiRef, - createApiRef({ - id: 'core.alert', - description: 'Used to report alerts and forward them to the app', - }), - ], +const apis = TestApiRegistry.from( + [alertApiRef, {}], [identityApiRef, mockIdentityApi], [splunkOnCallApiRef, mockSplunkOnCallApi], -]); +); describe('Incidents', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + it('Renders an empty state when there are no incidents', async () => { - mockSplunkOnCallApi.getTeams = jest - .fn() - .mockImplementationOnce(async () => [MOCK_TEAM]); + mockSplunkOnCallApi.getIncidents.mockResolvedValue([]); + mockSplunkOnCallApi.getTeams.mockResolvedValue([MOCK_TEAM]); const { getByText, queryByTestId } = render( wrapInTestApp( @@ -69,13 +65,9 @@ describe('Incidents', () => { }); it('Renders all incidents', async () => { - mockSplunkOnCallApi.getIncidents = jest - .fn() - .mockImplementationOnce(async () => [MOCK_INCIDENT]); + mockSplunkOnCallApi.getIncidents.mockResolvedValue([MOCK_INCIDENT]); + mockSplunkOnCallApi.getTeams.mockResolvedValue([MOCK_TEAM]); - mockSplunkOnCallApi.getTeams = jest - .fn() - .mockImplementationOnce(async () => [MOCK_TEAM]); const { getByText, getByTitle, @@ -108,9 +100,10 @@ describe('Incidents', () => { }); it('Handle errors', async () => { - mockSplunkOnCallApi.getIncidents = jest - .fn() - .mockRejectedValueOnce(new Error('Error occurred')); + mockSplunkOnCallApi.getIncidents.mockRejectedValueOnce( + new Error('Error occurred'), + ); + mockSplunkOnCallApi.getTeams.mockResolvedValue([]); const { getByText, queryByTestId } = render( wrapInTestApp( diff --git a/plugins/splunk-on-call/src/components/TriggerDialog/TriggerDialog.test.tsx b/plugins/splunk-on-call/src/components/TriggerDialog/TriggerDialog.test.tsx index 94fd40bfe5..0b64a137af 100644 --- a/plugins/splunk-on-call/src/components/TriggerDialog/TriggerDialog.test.tsx +++ b/plugins/splunk-on-call/src/components/TriggerDialog/TriggerDialog.test.tsx @@ -15,12 +15,12 @@ */ import React from 'react'; import { render, fireEvent, act } from '@testing-library/react'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { splunkOnCallApiRef } from '../../api'; import { TriggerDialog } from './TriggerDialog'; -import { ApiRegistry, ApiProvider } from '@backstage/core-app-api'; -import { alertApiRef, createApiRef } from '@backstage/core-plugin-api'; +import { ApiProvider } from '@backstage/core-app-api'; +import { alertApiRef } from '@backstage/core-plugin-api'; describe('TriggerDialog', () => { const mockTriggerAlarmFn = jest.fn(); @@ -28,16 +28,10 @@ describe('TriggerDialog', () => { incidentAction: mockTriggerAlarmFn, }; - const apis = ApiRegistry.from([ - [ - alertApiRef, - createApiRef({ - id: 'core.alert', - description: 'Used to report alerts and forward them to the app', - }), - ], + const apis = TestApiRegistry.from( + [alertApiRef, {}], [splunkOnCallApiRef, mockSplunkOnCallApi], - ]); + ); it('open the dialog and trigger an alarm', async () => { const { getByText, getByRole, getByTestId } = render( diff --git a/plugins/tech-radar/src/components/RadarComponent.test.tsx b/plugins/tech-radar/src/components/RadarComponent.test.tsx index cce411e897..2b237c8d83 100644 --- a/plugins/tech-radar/src/components/RadarComponent.test.tsx +++ b/plugins/tech-radar/src/components/RadarComponent.test.tsx @@ -19,13 +19,12 @@ import { render, waitForElement } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; import { lightTheme } from '@backstage/theme'; import { act } from 'react-dom/test-utils'; -import { withLogCollector } from '@backstage/test-utils'; +import { TestApiProvider, withLogCollector } from '@backstage/test-utils'; import GetBBoxPolyfill from '../utils/polyfills/getBBox'; import { RadarComponent } from './RadarComponent'; import { TechRadarLoaderResponse, techRadarApiRef, TechRadarApi } from '../api'; -import { ApiRegistry, ApiProvider } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; describe('RadarComponent', () => { @@ -55,18 +54,18 @@ describe('RadarComponent', () => { const errorApi = { post: () => {} }; const { getByTestId, queryByTestId } = render( - - + , ); @@ -87,18 +86,18 @@ describe('RadarComponent', () => { const { queryByTestId } = render( - - + , ); @@ -115,13 +114,13 @@ describe('RadarComponent', () => { expect(() => { render( - + - + , ); }).toThrow(); diff --git a/plugins/tech-radar/src/components/RadarPage.test.tsx b/plugins/tech-radar/src/components/RadarPage.test.tsx index 7215fc40df..7f4e69e388 100644 --- a/plugins/tech-radar/src/components/RadarPage.test.tsx +++ b/plugins/tech-radar/src/components/RadarPage.test.tsx @@ -17,6 +17,7 @@ import { MockErrorApi, renderInTestApp, + TestApiProvider, wrapInTestApp, } from '@backstage/test-utils'; import { lightTheme } from '@backstage/theme'; @@ -28,7 +29,6 @@ import GetBBoxPolyfill from '../utils/polyfills/getBBox'; import { RadarPage } from './RadarPage'; import { TechRadarLoaderResponse, techRadarApiRef, TechRadarApi } from '../api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; describe('RadarPage', () => { @@ -63,9 +63,9 @@ describe('RadarPage', () => { const { getByTestId, queryByTestId } = render( wrapInTestApp( - + - + , ), ); @@ -89,9 +89,9 @@ describe('RadarPage', () => { const { getByText, getByTestId } = await renderInTestApp( - + - + , ); @@ -115,9 +115,9 @@ describe('RadarPage', () => { const { getByTestId } = await renderInTestApp( - + - + , ); @@ -142,14 +142,14 @@ describe('RadarPage', () => { const { queryByTestId } = await renderInTestApp( - - + , ); diff --git a/plugins/techdocs/src/home/components/DefaultTechDocsHome.test.tsx b/plugins/techdocs/src/home/components/DefaultTechDocsHome.test.tsx index 1d8d7d2b04..8618c4432f 100644 --- a/plugins/techdocs/src/home/components/DefaultTechDocsHome.test.tsx +++ b/plugins/techdocs/src/home/components/DefaultTechDocsHome.test.tsx @@ -14,11 +14,7 @@ * limitations under the License. */ -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { ConfigApi, configApiRef, @@ -30,7 +26,11 @@ import { DefaultStarredEntitiesApi, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; -import { MockStorageApi, renderInTestApp } from '@backstage/test-utils'; +import { + MockStorageApi, + renderInTestApp, + TestApiRegistry, +} from '@backstage/test-utils'; import { screen } from '@testing-library/react'; import React from 'react'; import { rootDocsRouteRef } from '../../routes'; @@ -69,12 +69,12 @@ describe('TechDocs Home', () => { const storageApi = MockStorageApi.create(); - const apiRegistry = ApiRegistry.from([ + const apiRegistry = TestApiRegistry.from( [catalogApiRef, mockCatalogApi], [configApiRef, configApi], [storageApiRef, storageApi], [starredEntitiesApiRef, new DefaultStarredEntitiesApi({ storageApi })], - ]); + ); it('should render a TechDocs home page', async () => { await renderInTestApp( diff --git a/plugins/techdocs/src/home/components/LegacyTechDocsHome.test.tsx b/plugins/techdocs/src/home/components/LegacyTechDocsHome.test.tsx index d9d2c6a345..a8fd472f7c 100644 --- a/plugins/techdocs/src/home/components/LegacyTechDocsHome.test.tsx +++ b/plugins/techdocs/src/home/components/LegacyTechDocsHome.test.tsx @@ -15,16 +15,12 @@ */ import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { screen } from '@testing-library/react'; import React from 'react'; import { LegacyTechDocsHome } from './LegacyTechDocsHome'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { ConfigApi, configApiRef } from '@backstage/core-plugin-api'; import { rootDocsRouteRef } from '../../routes'; @@ -59,10 +55,10 @@ describe('Legacy TechDocs Home', () => { }, }); - const apiRegistry = ApiRegistry.from([ + const apiRegistry = TestApiRegistry.from( [catalogApiRef, mockCatalogApi], [configApiRef, configApi], - ]); + ); it('should render a TechDocs home page', async () => { await renderInTestApp( diff --git a/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx b/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx index bcbfdeed86..e9c3a55b15 100644 --- a/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx +++ b/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx @@ -15,11 +15,11 @@ */ import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { screen } from '@testing-library/react'; import React from 'react'; import { TechDocsCustomHome, PanelType } from './TechDocsCustomHome'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { rootDocsRouteRef } from '../../routes'; jest.mock('@backstage/plugin-catalog-react', () => { @@ -47,7 +47,7 @@ const mockCatalogApi = { } as Partial; describe('TechDocsCustomHome', () => { - const apiRegistry = ApiRegistry.with(catalogApiRef, mockCatalogApi); + const apiRegistry = TestApiRegistry.from([catalogApiRef, mockCatalogApi]); it('should render a TechDocs home page', async () => { const tabsConfig = [ diff --git a/plugins/techdocs/src/reader/components/Reader.test.tsx b/plugins/techdocs/src/reader/components/Reader.test.tsx index 8b5dbced3f..6e8609694d 100644 --- a/plugins/techdocs/src/reader/components/Reader.test.tsx +++ b/plugins/techdocs/src/reader/components/Reader.test.tsx @@ -19,12 +19,12 @@ import { ScmIntegrationsApi, scmIntegrationsApiRef, } from '@backstage/integration-react'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; import { TechDocsStorageApi, techdocsStorageApiRef } from '../../api'; import { Reader } from './Reader'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { searchApiRef } from '@backstage/plugin-search'; jest.mock('react-router-dom', () => { @@ -57,11 +57,11 @@ describe('', () => { results: [], }), }; - const apiRegistry = ApiRegistry.from([ + const apiRegistry = TestApiRegistry.from( [scmIntegrationsApiRef, scmIntegrationsApi], [techdocsStorageApiRef, techdocsStorageApi], [searchApiRef, searchApi], - ]); + ); await act(async () => { const rendered = render( diff --git a/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx b/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx index 6a5af982fd..b297466a62 100644 --- a/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx @@ -21,7 +21,7 @@ import { ScmIntegrationsApi, scmIntegrationsApiRef, } from '@backstage/integration-react'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { Header } from '@backstage/core-components'; import { techdocsApiRef, @@ -29,7 +29,7 @@ import { techdocsStorageApiRef, TechDocsStorageApi, } from '../../api'; -import { ApiRegistry, ApiProvider } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { searchApiRef } from '@backstage/plugin-search'; jest.mock('react-router-dom', () => { @@ -90,12 +90,12 @@ describe('', () => { results: [], }), }; - const apiRegistry = ApiRegistry.from([ + const apiRegistry = TestApiRegistry.from( [scmIntegrationsApiRef, scmIntegrationsApi], [techdocsApiRef, techdocsApi], [techdocsStorageApiRef, techdocsStorageApi], [searchApiRef, searchApi], - ]); + ); await act(async () => { const rendered = render( @@ -147,12 +147,12 @@ describe('', () => { results: [], }), }; - const apiRegistry = ApiRegistry.from([ + const apiRegistry = TestApiRegistry.from( [scmIntegrationsApiRef, scmIntegrationsApi], [techdocsApiRef, techdocsApi], [techdocsStorageApiRef, techdocsStorageApi], [searchApiRef, searchApi], - ]); + ); await act(async () => { const rendered = render( diff --git a/plugins/techdocs/src/reader/components/TechDocsSearch.test.tsx b/plugins/techdocs/src/reader/components/TechDocsSearch.test.tsx index 602a94e758..5b3d714a04 100644 --- a/plugins/techdocs/src/reader/components/TechDocsSearch.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsSearch.test.tsx @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { ApiProvider } from '@backstage/core-app-api'; import { searchApiRef } from '@backstage/plugin-search'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils'; import { act, fireEvent, @@ -54,7 +54,7 @@ describe('', () => { const querySpy = jest.fn(query); const searchApi = { query: querySpy }; - const apiRegistry = ApiRegistry.from([[searchApiRef, searchApi]]); + const apiRegistry = TestApiRegistry.from([searchApiRef, searchApi]); await act(async () => { const rendered = render( @@ -75,7 +75,7 @@ describe('', () => { const querySpy = jest.fn(query); const searchApi = { query: querySpy }; - const apiRegistry = ApiRegistry.from([[searchApiRef, searchApi]]); + const apiRegistry = TestApiRegistry.from([searchApiRef, searchApi]); await act(async () => { const rendered = render( diff --git a/plugins/techdocs/src/reader/components/useReaderState.test.tsx b/plugins/techdocs/src/reader/components/useReaderState.test.tsx index cce8282b3d..e41a114dbe 100644 --- a/plugins/techdocs/src/reader/components/useReaderState.test.tsx +++ b/plugins/techdocs/src/reader/components/useReaderState.test.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { NotFoundError } from '@backstage/errors'; +import { TestApiProvider } from '@backstage/test-utils'; import { act, renderHook } from '@testing-library/react-hooks'; import React from 'react'; import { techdocsStorageApiRef } from '../../api'; @@ -38,10 +38,10 @@ describe('useReaderState', () => { }; beforeEach(() => { - const apis = ApiRegistry.with(techdocsStorageApiRef, techdocsStorageApi); - Wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} + + {children} + ); }); diff --git a/plugins/todo/dev/index.tsx b/plugins/todo/dev/index.tsx index a4221dc710..fe547812ec 100644 --- a/plugins/todo/dev/index.tsx +++ b/plugins/todo/dev/index.tsx @@ -22,8 +22,8 @@ import OfflineIcon from '@material-ui/icons/Storage'; import React from 'react'; import { EntityTodoContent, todoApiRef, todoPlugin } from '../src'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { Content, Header, HeaderLabel, Page } from '@backstage/core-components'; +import { TestApiProvider } from '@backstage/test-utils'; const entity: Entity = { apiVersion: 'backstage.io/v1alpha1', @@ -60,7 +60,7 @@ createDevApp() .registerPlugin(todoPlugin) .addPage({ element: ( - +
@@ -71,7 +71,7 @@ createDevApp() - + ), title: 'Entity Todo Content', icon: OfflineIcon, diff --git a/plugins/todo/src/components/TodoList/TodoList.test.tsx b/plugins/todo/src/components/TodoList/TodoList.test.tsx index 0e4d64172d..2759fe40f8 100644 --- a/plugins/todo/src/components/TodoList/TodoList.test.tsx +++ b/plugins/todo/src/components/TodoList/TodoList.test.tsx @@ -16,11 +16,10 @@ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderWithEffects } from '@backstage/test-utils'; +import { renderWithEffects, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { TodoApi, todoApiRef } from '../../api'; import { TodoList } from './TodoList'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('TodoList', () => { it('should render', async () => { @@ -42,11 +41,11 @@ describe('TodoList', () => { const mockEntity = { metadata: { name: 'mock' } } as Entity; const rendered = await renderWithEffects( - + - , + , ); await expect(rendered.findByText('FIXME')).resolves.toBeInTheDocument(); diff --git a/plugins/user-settings/src/components/AuthProviders/UserSettingsAuthProviders.test.tsx b/plugins/user-settings/src/components/AuthProviders/UserSettingsAuthProviders.test.tsx index 085a884f2e..4e14dec2ef 100644 --- a/plugins/user-settings/src/components/AuthProviders/UserSettingsAuthProviders.test.tsx +++ b/plugins/user-settings/src/components/AuthProviders/UserSettingsAuthProviders.test.tsx @@ -14,22 +14,24 @@ * limitations under the License. */ -import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { + renderWithEffects, + TestApiRegistry, + wrapInTestApp, +} from '@backstage/test-utils'; import { fireEvent } from '@testing-library/react'; import React from 'react'; import { UserSettingsAuthProviders } from './UserSettingsAuthProviders'; -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; +import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { configApiRef, googleAuthApiRef } from '@backstage/core-plugin-api'; const mockSignInHandler = jest.fn().mockReturnValue(''); const mockGoogleAuth = { sessionState$: () => ({ + [Symbol.observable]: jest.fn(), subscribe: () => ({ + closed: false, unsubscribe: () => null, }), }), @@ -47,10 +49,10 @@ const createConfig = () => const config = createConfig(); -const apiRegistry = ApiRegistry.from([ +const apiRegistry = TestApiRegistry.from( [configApiRef, config], [googleAuthApiRef, mockGoogleAuth], -]); +); describe('', () => { it('displays a provider and calls its sign-in handler on click', async () => { diff --git a/plugins/user-settings/src/components/General/UserSettingsThemeToggle.test.tsx b/plugins/user-settings/src/components/General/UserSettingsThemeToggle.test.tsx index caae4d69bc..83d9e23f83 100644 --- a/plugins/user-settings/src/components/General/UserSettingsThemeToggle.test.tsx +++ b/plugins/user-settings/src/components/General/UserSettingsThemeToggle.test.tsx @@ -15,16 +15,16 @@ */ import { AppTheme, appThemeApiRef } from '@backstage/core-plugin-api'; -import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { + renderWithEffects, + TestApiRegistry, + wrapInTestApp, +} from '@backstage/test-utils'; import { lightTheme } from '@backstage/theme'; import { fireEvent } from '@testing-library/react'; import React from 'react'; import { UserSettingsThemeToggle } from './UserSettingsThemeToggle'; -import { - ApiProvider, - ApiRegistry, - AppThemeSelector, -} from '@backstage/core-app-api'; +import { ApiProvider, AppThemeSelector } from '@backstage/core-app-api'; const mockTheme: AppTheme = { id: 'light-theme', @@ -33,8 +33,9 @@ const mockTheme: AppTheme = { theme: lightTheme, }; -const apiRegistry = ApiRegistry.from([ - [appThemeApiRef, AppThemeSelector.createWithStorage([mockTheme])], +const apiRegistry = TestApiRegistry.from([ + appThemeApiRef, + AppThemeSelector.createWithStorage([mockTheme]), ]); describe('', () => { diff --git a/plugins/xcmetrics/src/components/BuildDetails/BuildDetails.test.tsx b/plugins/xcmetrics/src/components/BuildDetails/BuildDetails.test.tsx index 2d949d7abc..7083d890d6 100644 --- a/plugins/xcmetrics/src/components/BuildDetails/BuildDetails.test.tsx +++ b/plugins/xcmetrics/src/components/BuildDetails/BuildDetails.test.tsx @@ -14,8 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderInTestApp } from '@backstage/test-utils'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { BuildDetails, withRequest } from './BuildDetails'; import { xcmetricsApiRef } from '../../api'; @@ -35,11 +34,9 @@ jest.mock('../BuildTimeline', () => ({ describe('BuildDetails', () => { it('should render', async () => { const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText('accordion-Host')).toBeInTheDocument(); @@ -61,11 +58,9 @@ describe('BuildDetails with request', () => { it('should fetch the build and render', async () => { const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText(client.mockBuild.id)).toBeInTheDocument(); @@ -78,11 +73,9 @@ describe('BuildDetails with request', () => { .mockRejectedValue({ message: errorMessage }); const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText(errorMessage)).toBeInTheDocument(); @@ -92,11 +85,9 @@ describe('BuildDetails with request', () => { client.XcmetricsClient.getBuild = jest.fn().mockReturnValue(undefined); const rendered = await renderInTestApp( - + - , + , ); expect( diff --git a/plugins/xcmetrics/src/components/BuildList/BuildList.test.tsx b/plugins/xcmetrics/src/components/BuildList/BuildList.test.tsx index eb141209e7..53471f5e9f 100644 --- a/plugins/xcmetrics/src/components/BuildList/BuildList.test.tsx +++ b/plugins/xcmetrics/src/components/BuildList/BuildList.test.tsx @@ -14,8 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderInTestApp } from '@backstage/test-utils'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { BuildList } from './BuildList'; import { xcmetricsApiRef } from '../../api'; import userEvent from '@testing-library/user-event'; @@ -35,11 +34,9 @@ jest.mock('../BuildDetails', () => ({ describe('BuildList', () => { it('should render', async () => { const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText('Builds')).toBeInTheDocument(); @@ -50,11 +47,9 @@ describe('BuildList', () => { it('should show build details', async () => { const rendered = await renderInTestApp( - + - , + , ); userEvent.click( @@ -70,11 +65,9 @@ describe('BuildList', () => { .mockRejectedValue({ message }); const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText(message)).toBeInTheDocument(); diff --git a/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.test.tsx b/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.test.tsx index b997de68e0..06f4aed1b7 100644 --- a/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.test.tsx +++ b/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.test.tsx @@ -14,8 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderInTestApp } from '@backstage/test-utils'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import { BuildListFilter } from './BuildListFilter'; import { BuildFilters, xcmetricsApiRef } from '../../api'; @@ -37,14 +36,12 @@ const renderWithFiltersVisible = async ( callback?: (filters: BuildFilters) => void, ) => { const rendered = await renderInTestApp( - + - , + , ); userEvent.click(rendered.getByLabelText('show filters')); @@ -67,14 +64,12 @@ const setProjectFilter = async (rendered: RenderResult, option: string) => { describe('BuildListFilter', () => { it('should render', async () => { const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText('Filters (0)')).toBeInTheDocument(); diff --git a/plugins/xcmetrics/src/components/Overview/Overview.test.tsx b/plugins/xcmetrics/src/components/Overview/Overview.test.tsx index 3d24d2a422..42e3772d04 100644 --- a/plugins/xcmetrics/src/components/Overview/Overview.test.tsx +++ b/plugins/xcmetrics/src/components/Overview/Overview.test.tsx @@ -14,9 +14,8 @@ * limitations under the License. */ import React from 'react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { xcmetricsApiRef } from '../../api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { Overview } from './Overview'; jest.mock('../../api/XcmetricsClient'); @@ -33,11 +32,9 @@ jest.mock('../StatusMatrix', () => ({ describe('Overview', () => { it('should render', async () => { const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText('XCMetrics Dashboard')).toBeInTheDocument(); @@ -49,9 +46,9 @@ describe('Overview', () => { api.getBuilds = jest.fn().mockResolvedValue([]); const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText('No builds to show')).toBeInTheDocument(); @@ -64,9 +61,9 @@ describe('Overview', () => { api.getBuilds = jest.fn().mockRejectedValue({ message: errorMessage }); const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText(errorMessage)).toBeInTheDocument(); diff --git a/plugins/xcmetrics/src/components/OverviewTrends/OverviewTrends.test.tsx b/plugins/xcmetrics/src/components/OverviewTrends/OverviewTrends.test.tsx index 76b47f4943..db7904a8d1 100644 --- a/plugins/xcmetrics/src/components/OverviewTrends/OverviewTrends.test.tsx +++ b/plugins/xcmetrics/src/components/OverviewTrends/OverviewTrends.test.tsx @@ -15,9 +15,8 @@ */ import React from 'react'; import { OverviewTrends } from './OverviewTrends'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { xcmetricsApiRef } from '../../api'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import userEvent from '@testing-library/user-event'; jest.mock('../../api/XcmetricsClient'); @@ -26,11 +25,9 @@ const client = require('../../api/XcmetricsClient'); describe('OverviewTrends', () => { it('should render', async () => { const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText('Trends for')).toBeInTheDocument(); expect(rendered.getAllByText('Build Count').length).toEqual(3); @@ -42,20 +39,18 @@ describe('OverviewTrends', () => { api.getBuildCounts = jest.fn().mockResolvedValue([]); const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText('--')).toBeInTheDocument(); }); it('should change number of days when select is changed', async () => { const rendered = await renderInTestApp( - + - , + , ); userEvent.click(rendered.getByText('14 days')); @@ -76,9 +71,9 @@ describe('OverviewTrends', () => { .mockRejectedValue({ message: buildTimesError }); const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText(buildCountError)).toBeInTheDocument(); expect(rendered.getByText(buildTimesError)).toBeInTheDocument(); diff --git a/plugins/xcmetrics/src/components/StatusCell/StatusCell.test.tsx b/plugins/xcmetrics/src/components/StatusCell/StatusCell.test.tsx index cac111d13e..6e5b7f73b9 100644 --- a/plugins/xcmetrics/src/components/StatusCell/StatusCell.test.tsx +++ b/plugins/xcmetrics/src/components/StatusCell/StatusCell.test.tsx @@ -14,8 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderInTestApp } from '@backstage/test-utils'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import { StatusCell } from './StatusCell'; import { xcmetricsApiRef } from '../../api'; @@ -27,9 +26,7 @@ const client = require('../../api/XcmetricsClient'); describe('StatusCell', () => { it('should render', async () => { const rendered = await renderInTestApp( - + { size={10} spacing={10} /> - , + , ); userEvent.hover(rendered.getByTestId(client.mockBuild.id)); diff --git a/plugins/xcmetrics/src/components/StatusMatrix/StatusMatrix.test.tsx b/plugins/xcmetrics/src/components/StatusMatrix/StatusMatrix.test.tsx index 7d3854bbda..f18d322b43 100644 --- a/plugins/xcmetrics/src/components/StatusMatrix/StatusMatrix.test.tsx +++ b/plugins/xcmetrics/src/components/StatusMatrix/StatusMatrix.test.tsx @@ -14,8 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderInTestApp } from '@backstage/test-utils'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { StatusMatrix } from './StatusMatrix'; import { xcmetricsApiRef } from '../../api'; @@ -25,11 +24,9 @@ const client = require('../../api/XcmetricsClient'); describe('StatusMatrix', () => { it('should render', async () => { const rendered = await renderInTestApp( - + - , + , ); const cell = rendered.getByTestId(client.mockBuild.id); diff --git a/plugins/xcmetrics/src/components/XcmetricsLayout/XcmetricsLayout.test.tsx b/plugins/xcmetrics/src/components/XcmetricsLayout/XcmetricsLayout.test.tsx index 84bd25624c..29d6407b03 100644 --- a/plugins/xcmetrics/src/components/XcmetricsLayout/XcmetricsLayout.test.tsx +++ b/plugins/xcmetrics/src/components/XcmetricsLayout/XcmetricsLayout.test.tsx @@ -14,8 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderInTestApp } from '@backstage/test-utils'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { XcmetricsLayout } from './XcmetricsLayout'; import { xcmetricsApiRef } from '../../api'; import userEvent from '@testing-library/user-event'; @@ -34,11 +33,9 @@ jest.mock('../BuildList', () => ({ describe('XcmetricsLayout', () => { it('should render', async () => { const rendered = await renderInTestApp( - + - , + , ); expect(rendered.getByText('Overview')).toBeInTheDocument(); @@ -49,11 +46,9 @@ describe('XcmetricsLayout', () => { it('should show a list of builds when the Builds tab is selected', async () => { const rendered = await renderInTestApp( - + - , + , ); userEvent.click(rendered.getByText('Builds')); From d3248fb8c9577f3ad4268d206c8ad5555171eddd Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Thu, 18 Nov 2021 11:52:40 +0100 Subject: [PATCH 028/138] 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 029/138] 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 99bf179ccfe13b2c91e890c683443ea2a1c1773f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 18 Nov 2021 11:52:08 +0000 Subject: [PATCH 030/138] Version Packages --- .changeset/big-cougars-glow.md | 5 -- .changeset/big-months-float.md | 6 -- .changeset/blue-bikes-explode.md | 14 ---- .changeset/cost-insights-two-crabs-evolve.md | 5 -- .changeset/cyan-bottles-hug.md | 8 -- .changeset/early-cobras-explode.md | 5 -- .changeset/eight-months-agree.md | 19 ----- .changeset/empty-dots-attend.md | 8 -- .changeset/fluffy-moles-deny.md | 42 ---------- .changeset/forty-ligers-protect.md | 5 -- .changeset/fresh-zebras-hug.md | 5 -- .changeset/giant-drinks-wave.md | 5 -- .changeset/happy-rice-tickle.md | 5 -- .changeset/healthy-kids-mate.md | 11 --- .changeset/honest-shrimps-dance.md | 9 -- .changeset/hot-walls-fail.md | 13 --- .changeset/hungry-wombats-happen.md | 6 -- .changeset/khaki-rice-kick.md | 6 -- .changeset/little-news-retire.md | 6 -- .changeset/little-numbers-thank.md | 5 -- .changeset/lucky-ads-shout.md | 5 -- .changeset/many-sloths-cross.md | 5 -- .changeset/metal-donuts-cross.md | 8 -- .changeset/moody-snails-admire.md | 5 -- .changeset/nasty-impalas-travel.md | 5 -- .changeset/new-cobras-fly.md | 5 -- .changeset/nine-bananas-mate.md | 6 -- .changeset/ninety-grapes-love.md | 6 -- .changeset/ninety-spies-prove.md | 5 -- .changeset/orange-experts-approve.md | 5 -- .changeset/pretty-moons-drive.md | 5 -- .changeset/proud-bottles-cheat.md | 5 -- .changeset/rare-lemons-boil.md | 5 -- .changeset/rich-pillows-cough.md | 12 --- .changeset/rotten-clouds-kick.md | 5 -- .changeset/search-serious-hornets-design.md | 5 -- .changeset/sharp-meals-fetch.md | 5 -- .changeset/sharp-moons-jog.md | 5 -- .changeset/shiny-starfishes-float.md | 5 -- .changeset/silent-taxis-tan.md | 5 -- .changeset/slow-moles-act.md | 5 -- .changeset/sour-cameras-hide.md | 5 -- .changeset/spicy-rice-build.md | 5 -- .changeset/sweet-suits-sit.md | 5 -- .changeset/tame-buckets-move.md | 7 -- .../techdocs-chatt-months-report-too.md | 5 -- .changeset/techdocs-chatty-months-report.md | 5 -- .changeset/techdocs-famous-donuts-warn.md | 5 -- .changeset/techdocs-orange-cougars-relax.md | 6 -- .changeset/techdocs-real-geese-dress.md | 5 -- .changeset/techdocs-sharp-knives-unite.md | 5 -- .changeset/techdocs-silver-plums-speak.md | 5 -- .changeset/ten-planes-remember.md | 8 -- .changeset/tender-gorillas-peel.md | 5 -- .changeset/tidy-beans-reflect.md | 5 -- .changeset/twenty-swans-matter.md | 9 -- .changeset/unlucky-chefs-arrive.md | 5 -- .changeset/violet-panthers-care.md | 5 -- .changeset/yellow-deers-act.md | 5 -- .changeset/yellow-falcons-whisper.md | 5 -- packages/app-defaults/CHANGELOG.md | 10 +++ packages/app-defaults/package.json | 12 +-- packages/app/CHANGELOG.md | 45 ++++++++++ packages/app/package.json | 82 +++++++++---------- packages/backend-common/CHANGELOG.md | 24 ++++++ packages/backend-common/package.json | 10 +-- packages/backend-tasks/package.json | 6 +- packages/backend-test-utils/CHANGELOG.md | 9 ++ packages/backend-test-utils/package.json | 8 +- packages/backend/package.json | 26 +++--- packages/catalog-client/CHANGELOG.md | 8 ++ packages/catalog-client/package.json | 6 +- packages/catalog-model/CHANGELOG.md | 6 ++ packages/catalog-model/package.json | 4 +- packages/cli-common/CHANGELOG.md | 8 ++ packages/cli-common/package.json | 2 +- packages/cli/CHANGELOG.md | 23 ++++++ packages/cli/package.json | 18 ++-- packages/codemods/CHANGELOG.md | 10 +++ packages/codemods/package.json | 4 +- packages/config-loader/CHANGELOG.md | 21 +++++ packages/config-loader/package.json | 4 +- packages/core-app-api/CHANGELOG.md | 19 +++++ packages/core-app-api/package.json | 12 +-- packages/core-components/CHANGELOG.md | 10 +++ packages/core-components/package.json | 10 +-- packages/core-plugin-api/CHANGELOG.md | 13 +++ packages/core-plugin-api/package.json | 8 +- packages/create-app/CHANGELOG.md | 27 ++++++ packages/create-app/package.json | 4 +- packages/dev-utils/CHANGELOG.md | 16 ++++ packages/dev-utils/package.json | 20 ++--- packages/embedded-techdocs-app/CHANGELOG.md | 17 ++++ packages/embedded-techdocs-app/package.json | 24 +++--- packages/errors/package.json | 2 +- packages/integration-react/CHANGELOG.md | 8 ++ packages/integration-react/package.json | 12 +-- packages/integration/package.json | 6 +- packages/search-common/package.json | 2 +- packages/techdocs-cli/CHANGELOG.md | 12 +++ packages/techdocs-cli/package.json | 12 +-- packages/techdocs-common/CHANGELOG.md | 10 +++ packages/techdocs-common/package.json | 8 +- packages/test-utils/CHANGELOG.md | 10 +++ packages/test-utils/package.json | 8 +- packages/theme/package.json | 2 +- packages/types/package.json | 2 +- packages/version-bridge/package.json | 2 +- plugins/allure/CHANGELOG.md | 11 +++ plugins/allure/package.json | 18 ++-- plugins/analytics-module-ga/CHANGELOG.md | 8 ++ plugins/analytics-module-ga/package.json | 14 ++-- plugins/api-docs/CHANGELOG.md | 12 +++ plugins/api-docs/package.json | 20 ++--- plugins/app-backend/CHANGELOG.md | 8 ++ plugins/app-backend/package.json | 8 +- plugins/auth-backend/CHANGELOG.md | 11 +++ plugins/auth-backend/package.json | 12 +-- plugins/azure-devops-backend/CHANGELOG.md | 9 ++ plugins/azure-devops-backend/package.json | 8 +- plugins/azure-devops-common/CHANGELOG.md | 6 ++ plugins/azure-devops-common/package.json | 4 +- plugins/azure-devops/CHANGELOG.md | 14 ++++ plugins/azure-devops/package.json | 20 ++--- plugins/badges-backend/package.json | 8 +- plugins/badges/CHANGELOG.md | 11 +++ plugins/badges/package.json | 18 ++-- plugins/bazaar-backend/CHANGELOG.md | 10 +++ plugins/bazaar-backend/package.json | 8 +- plugins/bazaar/CHANGELOG.md | 14 ++++ plugins/bazaar/package.json | 18 ++-- plugins/bitrise/CHANGELOG.md | 10 +++ plugins/bitrise/package.json | 18 ++-- .../catalog-backend-module-ldap/package.json | 6 +- .../package.json | 10 +-- plugins/catalog-backend/CHANGELOG.md | 16 ++++ plugins/catalog-backend/package.json | 14 ++-- plugins/catalog-graph/CHANGELOG.md | 12 +++ plugins/catalog-graph/package.json | 20 ++--- plugins/catalog-graphql/package.json | 6 +- plugins/catalog-import/CHANGELOG.md | 13 +++ plugins/catalog-import/package.json | 22 ++--- plugins/catalog-react/CHANGELOG.md | 12 +++ plugins/catalog-react/package.json | 16 ++-- plugins/catalog/CHANGELOG.md | 15 ++++ plugins/catalog/package.json | 22 ++--- plugins/circleci/CHANGELOG.md | 11 +++ plugins/circleci/package.json | 18 ++-- plugins/cloudbuild/CHANGELOG.md | 11 +++ plugins/cloudbuild/package.json | 18 ++-- plugins/code-coverage-backend/package.json | 8 +- plugins/code-coverage/CHANGELOG.md | 11 +++ plugins/code-coverage/package.json | 18 ++-- plugins/config-schema/CHANGELOG.md | 9 ++ plugins/config-schema/package.json | 14 ++-- plugins/cost-insights/CHANGELOG.md | 10 +++ plugins/cost-insights/package.json | 14 ++-- plugins/explore-react/CHANGELOG.md | 7 ++ plugins/explore-react/package.json | 10 +-- plugins/explore/CHANGELOG.md | 12 +++ plugins/explore/package.json | 20 ++--- plugins/firehydrant/CHANGELOG.md | 10 +++ plugins/firehydrant/package.json | 16 ++-- plugins/fossa/CHANGELOG.md | 10 +++ plugins/fossa/package.json | 18 ++-- plugins/gcp-projects/CHANGELOG.md | 25 ++++++ plugins/gcp-projects/package.json | 14 ++-- plugins/git-release-manager/CHANGELOG.md | 9 ++ plugins/git-release-manager/package.json | 14 ++-- plugins/github-actions/CHANGELOG.md | 11 +++ plugins/github-actions/package.json | 18 ++-- plugins/github-deployments/CHANGELOG.md | 11 +++ plugins/github-deployments/package.json | 20 ++--- plugins/gitops-profiles/CHANGELOG.md | 9 ++ plugins/gitops-profiles/package.json | 14 ++-- plugins/graphiql/CHANGELOG.md | 8 ++ plugins/graphiql/package.json | 14 ++-- plugins/graphql-backend/package.json | 4 +- plugins/home/CHANGELOG.md | 9 ++ plugins/home/package.json | 14 ++-- plugins/ilert/CHANGELOG.md | 11 +++ plugins/ilert/package.json | 18 ++-- plugins/jenkins-backend/package.json | 8 +- plugins/jenkins/CHANGELOG.md | 11 +++ plugins/jenkins/package.json | 18 ++-- plugins/kafka-backend/CHANGELOG.md | 9 ++ plugins/kafka-backend/package.json | 8 +- plugins/kafka/CHANGELOG.md | 11 +++ plugins/kafka/package.json | 18 ++-- plugins/kubernetes-backend/package.json | 6 +- plugins/kubernetes-common/package.json | 4 +- plugins/kubernetes/CHANGELOG.md | 11 +++ plugins/kubernetes/package.json | 18 ++-- plugins/lighthouse/CHANGELOG.md | 11 +++ plugins/lighthouse/package.json | 18 ++-- plugins/newrelic/CHANGELOG.md | 9 ++ plugins/newrelic/package.json | 14 ++-- plugins/org/CHANGELOG.md | 10 +++ plugins/org/package.json | 18 ++-- plugins/pagerduty/CHANGELOG.md | 11 +++ plugins/pagerduty/package.json | 18 ++-- plugins/permission-common/package.json | 2 +- plugins/proxy-backend/package.json | 4 +- plugins/rollbar-backend/package.json | 4 +- plugins/rollbar/CHANGELOG.md | 11 +++ plugins/rollbar/package.json | 18 ++-- .../package.json | 6 +- .../package.json | 6 +- plugins/scaffolder-backend/CHANGELOG.md | 12 +++ plugins/scaffolder-backend/package.json | 14 ++-- plugins/scaffolder-common/package.json | 4 +- plugins/scaffolder/CHANGELOG.md | 14 ++++ plugins/scaffolder/package.json | 22 ++--- .../package.json | 4 +- plugins/search-backend-module-pg/package.json | 6 +- plugins/search-backend-node/package.json | 4 +- plugins/search-backend/package.json | 4 +- plugins/search/CHANGELOG.md | 12 +++ plugins/search/package.json | 18 ++-- plugins/sentry/CHANGELOG.md | 11 +++ plugins/sentry/package.json | 18 ++-- plugins/shortcuts/CHANGELOG.md | 9 ++ plugins/shortcuts/package.json | 14 ++-- plugins/sonarqube/CHANGELOG.md | 10 +++ plugins/sonarqube/package.json | 18 ++-- plugins/splunk-on-call/CHANGELOG.md | 11 +++ plugins/splunk-on-call/package.json | 18 ++-- .../package.json | 4 +- plugins/tech-insights-backend/CHANGELOG.md | 15 ++++ plugins/tech-insights-backend/package.json | 12 +-- plugins/tech-insights-common/package.json | 2 +- plugins/tech-insights-node/package.json | 4 +- plugins/tech-radar/CHANGELOG.md | 9 ++ plugins/tech-radar/package.json | 14 ++-- plugins/techdocs-backend/CHANGELOG.md | 12 +++ plugins/techdocs-backend/package.json | 14 ++-- plugins/techdocs/CHANGELOG.md | 17 ++++ plugins/techdocs/package.json | 24 +++--- plugins/todo-backend/package.json | 8 +- plugins/todo/CHANGELOG.md | 11 +++ plugins/todo/package.json | 18 ++-- plugins/user-settings/CHANGELOG.md | 10 +++ plugins/user-settings/package.json | 14 ++-- plugins/xcmetrics/CHANGELOG.md | 9 ++ plugins/xcmetrics/package.json | 14 ++-- yarn.lock | 20 ++++- 246 files changed, 1632 insertions(+), 1086 deletions(-) delete mode 100644 .changeset/big-cougars-glow.md delete mode 100644 .changeset/big-months-float.md delete mode 100644 .changeset/blue-bikes-explode.md delete mode 100644 .changeset/cost-insights-two-crabs-evolve.md delete mode 100644 .changeset/cyan-bottles-hug.md delete mode 100644 .changeset/early-cobras-explode.md delete mode 100644 .changeset/eight-months-agree.md delete mode 100644 .changeset/empty-dots-attend.md delete mode 100644 .changeset/fluffy-moles-deny.md delete mode 100644 .changeset/forty-ligers-protect.md delete mode 100644 .changeset/fresh-zebras-hug.md delete mode 100644 .changeset/giant-drinks-wave.md delete mode 100644 .changeset/happy-rice-tickle.md delete mode 100644 .changeset/healthy-kids-mate.md delete mode 100644 .changeset/honest-shrimps-dance.md delete mode 100644 .changeset/hot-walls-fail.md delete mode 100644 .changeset/hungry-wombats-happen.md delete mode 100644 .changeset/khaki-rice-kick.md delete mode 100644 .changeset/little-news-retire.md delete mode 100644 .changeset/little-numbers-thank.md delete mode 100644 .changeset/lucky-ads-shout.md delete mode 100644 .changeset/many-sloths-cross.md delete mode 100644 .changeset/metal-donuts-cross.md delete mode 100644 .changeset/moody-snails-admire.md delete mode 100644 .changeset/nasty-impalas-travel.md delete mode 100644 .changeset/new-cobras-fly.md delete mode 100644 .changeset/nine-bananas-mate.md delete mode 100644 .changeset/ninety-grapes-love.md delete mode 100644 .changeset/ninety-spies-prove.md delete mode 100644 .changeset/orange-experts-approve.md delete mode 100644 .changeset/pretty-moons-drive.md delete mode 100644 .changeset/proud-bottles-cheat.md delete mode 100644 .changeset/rare-lemons-boil.md delete mode 100644 .changeset/rich-pillows-cough.md delete mode 100644 .changeset/rotten-clouds-kick.md delete mode 100644 .changeset/search-serious-hornets-design.md delete mode 100644 .changeset/sharp-meals-fetch.md delete mode 100644 .changeset/sharp-moons-jog.md delete mode 100644 .changeset/shiny-starfishes-float.md delete mode 100644 .changeset/silent-taxis-tan.md delete mode 100644 .changeset/slow-moles-act.md delete mode 100644 .changeset/sour-cameras-hide.md delete mode 100644 .changeset/spicy-rice-build.md delete mode 100644 .changeset/sweet-suits-sit.md delete mode 100644 .changeset/tame-buckets-move.md delete mode 100644 .changeset/techdocs-chatt-months-report-too.md delete mode 100644 .changeset/techdocs-chatty-months-report.md delete mode 100644 .changeset/techdocs-famous-donuts-warn.md delete mode 100644 .changeset/techdocs-orange-cougars-relax.md delete mode 100644 .changeset/techdocs-real-geese-dress.md delete mode 100644 .changeset/techdocs-sharp-knives-unite.md delete mode 100644 .changeset/techdocs-silver-plums-speak.md delete mode 100644 .changeset/ten-planes-remember.md delete mode 100644 .changeset/tender-gorillas-peel.md delete mode 100644 .changeset/tidy-beans-reflect.md delete mode 100644 .changeset/twenty-swans-matter.md delete mode 100644 .changeset/unlucky-chefs-arrive.md delete mode 100644 .changeset/violet-panthers-care.md delete mode 100644 .changeset/yellow-deers-act.md delete mode 100644 .changeset/yellow-falcons-whisper.md create mode 100644 packages/app-defaults/CHANGELOG.md create mode 100644 packages/embedded-techdocs-app/CHANGELOG.md create mode 100644 plugins/bazaar-backend/CHANGELOG.md create mode 100644 plugins/tech-insights-backend/CHANGELOG.md diff --git a/.changeset/big-cougars-glow.md b/.changeset/big-cougars-glow.md deleted file mode 100644 index d1630905db..0000000000 --- a/.changeset/big-cougars-glow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/dev-utils': patch ---- - -Add theme switcher to sidebar of dev app. diff --git a/.changeset/big-months-float.md b/.changeset/big-months-float.md deleted file mode 100644 index 9acb7002e7..0000000000 --- a/.changeset/big-months-float.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Remove the "View Api" icon in the AboutCard, as the information is misleading for some users and is -duplicated in the tabs above. diff --git a/.changeset/blue-bikes-explode.md b/.changeset/blue-bikes-explode.md deleted file mode 100644 index 1c10a08a46..0000000000 --- a/.changeset/blue-bikes-explode.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@backstage/config-loader': minor ---- - -Update `loadConfig` to return `LoadConfigResult` instead of an array of `AppConfig`. - -This function is primarily used internally by other config loaders like `loadBackendConfig` which means no changes are required for most users. - -If you use `loadConfig` directly you will need to update your usage from: - -```diff -- const appConfigs = await loadConfig(options) -+ const { appConfigs } = await loadConfig(options) -``` diff --git a/.changeset/cost-insights-two-crabs-evolve.md b/.changeset/cost-insights-two-crabs-evolve.md deleted file mode 100644 index 8a932ea59c..0000000000 --- a/.changeset/cost-insights-two-crabs-evolve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -Fixed generation of sample data in the example Cost Insights client diff --git a/.changeset/cyan-bottles-hug.md b/.changeset/cyan-bottles-hug.md deleted file mode 100644 index 7c2083c4ff..0000000000 --- a/.changeset/cyan-bottles-hug.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/cli': patch -'@backstage/cli-common': patch ---- - -Keep backstage.json in sync - -The `versions:bump` script now takes care about updating the `version` property inside `backstage.json` file. The file is created if is not present. diff --git a/.changeset/early-cobras-explode.md b/.changeset/early-cobras-explode.md deleted file mode 100644 index 34b4cb0e98..0000000000 --- a/.changeset/early-cobras-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-client': patch ---- - -Update to the right version of @backstage/errors diff --git a/.changeset/eight-months-agree.md b/.changeset/eight-months-agree.md deleted file mode 100644 index 0f117d8a40..0000000000 --- a/.changeset/eight-months-agree.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@backstage/plugin-gcp-projects': patch ---- - -UI updates to GCP-projects plugin - -Adds the following to the project list page: - -- pagination -- filtering -- sorting -- rows per page -- show/hide columns - -Makes breadcrumb a link back to project list for the project details and new project views. - -In project list page, updates New project button to use RouterLink instead of `href` to avoid login prompt. - -In project details view, links to project details and logs now work, clicking on these will open the project or logs in GCP in new tab. diff --git a/.changeset/empty-dots-attend.md b/.changeset/empty-dots-attend.md deleted file mode 100644 index 3903dfa22b..0000000000 --- a/.changeset/empty-dots-attend.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/catalog-model': patch -'@backstage/cli': patch -'@backstage/config-loader': patch -'@backstage/plugin-scaffolder': patch ---- - -Update the json-schema dependency version. diff --git a/.changeset/fluffy-moles-deny.md b/.changeset/fluffy-moles-deny.md deleted file mode 100644 index 4b4abc36fa..0000000000 --- a/.changeset/fluffy-moles-deny.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -'@backstage/plugin-allure': patch -'@backstage/plugin-api-docs': patch -'@backstage/plugin-azure-devops': patch -'@backstage/plugin-badges': patch -'@backstage/plugin-bazaar': patch -'@backstage/plugin-catalog': patch -'@backstage/plugin-catalog-graph': patch -'@backstage/plugin-catalog-import': patch -'@backstage/plugin-catalog-react': patch -'@backstage/plugin-circleci': patch -'@backstage/plugin-cloudbuild': patch -'@backstage/plugin-code-coverage': patch -'@backstage/plugin-config-schema': patch -'@backstage/plugin-cost-insights': patch -'@backstage/plugin-explore': patch -'@backstage/plugin-firehydrant': patch -'@backstage/plugin-gcp-projects': patch -'@backstage/plugin-git-release-manager': patch -'@backstage/plugin-github-actions': patch -'@backstage/plugin-gitops-profiles': patch -'@backstage/plugin-home': patch -'@backstage/plugin-ilert': patch -'@backstage/plugin-jenkins': patch -'@backstage/plugin-kafka': patch -'@backstage/plugin-kubernetes': patch -'@backstage/plugin-lighthouse': patch -'@backstage/plugin-newrelic': patch -'@backstage/plugin-pagerduty': patch -'@backstage/plugin-rollbar': patch -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-search': patch -'@backstage/plugin-sentry': patch -'@backstage/plugin-splunk-on-call': patch -'@backstage/plugin-tech-radar': patch -'@backstage/plugin-techdocs': patch -'@backstage/plugin-todo': patch -'@backstage/plugin-user-settings': patch -'@backstage/plugin-xcmetrics': patch ---- - -Refactor out the deprecated path and icon from RouteRefs diff --git a/.changeset/forty-ligers-protect.md b/.changeset/forty-ligers-protect.md deleted file mode 100644 index e3e46fb7f3..0000000000 --- a/.changeset/forty-ligers-protect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -remove double config dep diff --git a/.changeset/fresh-zebras-hug.md b/.changeset/fresh-zebras-hug.md deleted file mode 100644 index c295dc2287..0000000000 --- a/.changeset/fresh-zebras-hug.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kafka-backend': patch ---- - -Update Kafka configuration types diff --git a/.changeset/giant-drinks-wave.md b/.changeset/giant-drinks-wave.md deleted file mode 100644 index ecf4c8fbdd..0000000000 --- a/.changeset/giant-drinks-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/dev-utils': patch ---- - -Migrated to using `@backstage/app-defaults`. diff --git a/.changeset/happy-rice-tickle.md b/.changeset/happy-rice-tickle.md deleted file mode 100644 index 1e39dc2e9c..0000000000 --- a/.changeset/happy-rice-tickle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Added the `isDatabaseConflictError` function. diff --git a/.changeset/healthy-kids-mate.md b/.changeset/healthy-kids-mate.md deleted file mode 100644 index 10e8222a15..0000000000 --- a/.changeset/healthy-kids-mate.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Create backstage.json file - -`@backstage/create-app` will create a new `backstage.json` file. At this point, the file will contain a `version` property, representing the version of `@backstage/create-app` used for creating the application. If the backstage's application has been bootstrapped using an older version of `@backstage/create-app`, the `backstage.json` file can be created and kept in sync, together with all the changes of the latest version of backstage, by running the following script: - -```bash -yarn backstage-cli versions:bump -``` diff --git a/.changeset/honest-shrimps-dance.md b/.changeset/honest-shrimps-dance.md deleted file mode 100644 index 8c7852b96b..0000000000 --- a/.changeset/honest-shrimps-dance.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/backend-test-utils': patch -'@backstage/create-app': patch -'@techdocs/cli': patch -'@backstage/plugin-techdocs-backend': patch ---- - -Bumping minimum requirements for `dockerode` and `testcontainers` diff --git a/.changeset/hot-walls-fail.md b/.changeset/hot-walls-fail.md deleted file mode 100644 index 3728e10ff6..0000000000 --- a/.changeset/hot-walls-fail.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Migrated the app template use the new `@backstage/app-defaults` for the `createApp` import, since the `createApp` exported by `@backstage/app-core-api` will be removed in the future. - -To migrate an existing application, add the latest version of `@backstage/app-defaults` as a dependency in `packages/app/package.json`, and make the following change to `packages/app/src/App.tsx`: - -```diff --import { createApp, FlatRoutes } from '@backstage/core-app-api'; -+import { createApp } from '@backstage/app-defaults'; -+import { FlatRoutes } from '@backstage/core-app-api'; -``` diff --git a/.changeset/hungry-wombats-happen.md b/.changeset/hungry-wombats-happen.md deleted file mode 100644 index 018e7ae9e8..0000000000 --- a/.changeset/hungry-wombats-happen.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/cli': patch ---- - -Update internal usage of `configLoader.loadConfig` that now returns an object instead of an array of configs. diff --git a/.changeset/khaki-rice-kick.md b/.changeset/khaki-rice-kick.md deleted file mode 100644 index 54819b855a..0000000000 --- a/.changeset/khaki-rice-kick.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-components': patch -'@backstage/plugin-user-settings': patch ---- - -Add Props Icon for Sidebar Item SidebarSearchField and Settings diff --git a/.changeset/little-news-retire.md b/.changeset/little-news-retire.md deleted file mode 100644 index 4304cf2d19..0000000000 --- a/.changeset/little-news-retire.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-bazaar': patch -'@backstage/plugin-bazaar-backend': patch ---- - -A Bazaar project has been extended with the following fields: size, start date (optional), end date (optional) and a responsible person. diff --git a/.changeset/little-numbers-thank.md b/.changeset/little-numbers-thank.md deleted file mode 100644 index f444a904c0..0000000000 --- a/.changeset/little-numbers-thank.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Changing the `Header` styles to use more theme variables. With this the title `font-size` will not change on resizing the window. diff --git a/.changeset/lucky-ads-shout.md b/.changeset/lucky-ads-shout.md deleted file mode 100644 index 73063bb911..0000000000 --- a/.changeset/lucky-ads-shout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-plugin-api': patch ---- - -Add deprecation warnings around `title` `icon` and `path` as they are no longer controlled when creating `routeRefs` diff --git a/.changeset/many-sloths-cross.md b/.changeset/many-sloths-cross.md deleted file mode 100644 index 07cb6d2f61..0000000000 --- a/.changeset/many-sloths-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Refactor and add regression tests for create-app tasks diff --git a/.changeset/metal-donuts-cross.md b/.changeset/metal-donuts-cross.md deleted file mode 100644 index 6c2699ed61..0000000000 --- a/.changeset/metal-donuts-cross.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -This fixes a bug where locations couldn't be added unless the processing engine is started. -It's now possible to run the catalog backend without starting the processing engine and still allowing locations registrations. - -This is done by refactor the `EntityProvider.connect` to happen outside the engine. diff --git a/.changeset/moody-snails-admire.md b/.changeset/moody-snails-admire.md deleted file mode 100644 index 7622546989..0000000000 --- a/.changeset/moody-snails-admire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': minor ---- - -Tweaked style insertion logic to make sure that JSS stylesheets always receive the highest priority. diff --git a/.changeset/nasty-impalas-travel.md b/.changeset/nasty-impalas-travel.md deleted file mode 100644 index f6eb321628..0000000000 --- a/.changeset/nasty-impalas-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Paths can be specified in backend.reading.allow to further restrict allowed targets diff --git a/.changeset/new-cobras-fly.md b/.changeset/new-cobras-fly.md deleted file mode 100644 index f39f1b0fbb..0000000000 --- a/.changeset/new-cobras-fly.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-azure-devops': patch ---- - -Added entity view for Azure Repo Pull Requests diff --git a/.changeset/nine-bananas-mate.md b/.changeset/nine-bananas-mate.md deleted file mode 100644 index e119eb722f..0000000000 --- a/.changeset/nine-bananas-mate.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-app-api': patch -'@backstage/test-utils': patch ---- - -Migrated to using new `ErrorApiError` and `ErrorApiErrorContext` names. diff --git a/.changeset/ninety-grapes-love.md b/.changeset/ninety-grapes-love.md deleted file mode 100644 index 9143bddd30..0000000000 --- a/.changeset/ninety-grapes-love.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-components': patch -'@backstage/plugin-auth-backend': patch ---- - -Update OAuthAdapter to create identity.token from identity.idToken if it does not exist, and prevent overwrites to identity.toke. Update login page commonProvider to prefer .token over .idToken diff --git a/.changeset/ninety-spies-prove.md b/.changeset/ninety-spies-prove.md deleted file mode 100644 index 509aedd66f..0000000000 --- a/.changeset/ninety-spies-prove.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Skip empty file names when scaffolding with nunjucks diff --git a/.changeset/orange-experts-approve.md b/.changeset/orange-experts-approve.md deleted file mode 100644 index 13d1b022da..0000000000 --- a/.changeset/orange-experts-approve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Adjust entity query construction to ensure sub-queries are always isolated from one another. diff --git a/.changeset/pretty-moons-drive.md b/.changeset/pretty-moons-drive.md deleted file mode 100644 index 51dc69332e..0000000000 --- a/.changeset/pretty-moons-drive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Adding config prop `pluginDivisionMode` to allow plugins using the `pg` client to create their own management schemas in the db. This allows `pg` client plugins to work in separate schemas in the same db. diff --git a/.changeset/proud-bottles-cheat.md b/.changeset/proud-bottles-cheat.md deleted file mode 100644 index 0c724352c7..0000000000 --- a/.changeset/proud-bottles-cheat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Add `AbortSignal` support to `UrlReader` diff --git a/.changeset/rare-lemons-boil.md b/.changeset/rare-lemons-boil.md deleted file mode 100644 index b882ab0b91..0000000000 --- a/.changeset/rare-lemons-boil.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Deprecated the `BackstagePluginWithAnyOutput` type. diff --git a/.changeset/rich-pillows-cough.md b/.changeset/rich-pillows-cough.md deleted file mode 100644 index 959eb69214..0000000000 --- a/.changeset/rich-pillows-cough.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Make sure that server builder `start()` propagates errors (such as failing to bind to the required port) properly and doesn't resolve the promise prematurely. - -After this change, the backend logger will be able to actually capture the error as it happens: - -``` -2021-11-11T10:54:21.334Z backstage info Initializing http server -2021-11-11T10:54:21.335Z backstage error listen EADDRINUSE: address already in use :::7000 code=EADDRINUSE errno=-48 syscall=listen address=:: port=7000 -``` diff --git a/.changeset/rotten-clouds-kick.md b/.changeset/rotten-clouds-kick.md deleted file mode 100644 index 2c4772c6e5..0000000000 --- a/.changeset/rotten-clouds-kick.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Start exporting and marking several types as public to address errors in the API report. diff --git a/.changeset/search-serious-hornets-design.md b/.changeset/search-serious-hornets-design.md deleted file mode 100644 index 638f8ae73b..0000000000 --- a/.changeset/search-serious-hornets-design.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Smaller UX improvements to search components such as optional autoFocus prop to SearchBar components, decreased debounce value and closing modal on link click of SearchModal, terminology updates of SearchResultPager. diff --git a/.changeset/sharp-meals-fetch.md b/.changeset/sharp-meals-fetch.md deleted file mode 100644 index 1d3df65ba4..0000000000 --- a/.changeset/sharp-meals-fetch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-plugin-api': minor ---- - -Removed the unused `UserFlags` type. diff --git a/.changeset/sharp-moons-jog.md b/.changeset/sharp-moons-jog.md deleted file mode 100644 index d3329af08e..0000000000 --- a/.changeset/sharp-moons-jog.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-plugin-api': patch ---- - -Deprecated the `theme` property on `AppTheme`, replacing it with `Provider`. See https://backstage.io/docs/api/deprecations#app-theme for more details. diff --git a/.changeset/shiny-starfishes-float.md b/.changeset/shiny-starfishes-float.md deleted file mode 100644 index 0673791375..0000000000 --- a/.changeset/shiny-starfishes-float.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Added a scaffolder backend module template for the `create` command. diff --git a/.changeset/silent-taxis-tan.md b/.changeset/silent-taxis-tan.md deleted file mode 100644 index 286ef40a4c..0000000000 --- a/.changeset/silent-taxis-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-plugin-api': minor ---- - -Remove exports of unused types(`RouteOptions` and `RoutePath`). diff --git a/.changeset/slow-moles-act.md b/.changeset/slow-moles-act.md deleted file mode 100644 index ab920bfa5d..0000000000 --- a/.changeset/slow-moles-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/test-utils': patch ---- - -Migrated to using `createSpecializedApp`. diff --git a/.changeset/sour-cameras-hide.md b/.changeset/sour-cameras-hide.md deleted file mode 100644 index a31e7a13c3..0000000000 --- a/.changeset/sour-cameras-hide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fixed a bug where calling `backstage-cli backend:bundle --build-dependencies` with no dependencies to be built would cause all monorepo packages to be built instead. diff --git a/.changeset/spicy-rice-build.md b/.changeset/spicy-rice-build.md deleted file mode 100644 index c0322d778a..0000000000 --- a/.changeset/spicy-rice-build.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Do not redact empty or one-character strings. These imply that it's just a test or local dev, and unnecessarily ruin the log output. diff --git a/.changeset/sweet-suits-sit.md b/.changeset/sweet-suits-sit.md deleted file mode 100644 index b6f7fbadf5..0000000000 --- a/.changeset/sweet-suits-sit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-shortcuts': patch ---- - -Add tooltip to display shortcut title on hover. This should improve the readability of shortcuts with long names, which are cutoff by ellipsis. diff --git a/.changeset/tame-buckets-move.md b/.changeset/tame-buckets-move.md deleted file mode 100644 index f7ee3deb90..0000000000 --- a/.changeset/tame-buckets-move.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-azure-devops': patch -'@backstage/plugin-azure-devops-backend': patch -'@backstage/plugin-azure-devops-common': minor ---- - -Improved Date handling for the Azure DevOps set of plugins by using strings and letting the frontend handle the conversion to DateTime diff --git a/.changeset/techdocs-chatt-months-report-too.md b/.changeset/techdocs-chatt-months-report-too.md deleted file mode 100644 index 612a4506a5..0000000000 --- a/.changeset/techdocs-chatt-months-report-too.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Fixed entity triplet case handling for certain locales. diff --git a/.changeset/techdocs-chatty-months-report.md b/.changeset/techdocs-chatty-months-report.md deleted file mode 100644 index 7d3fa773bf..0000000000 --- a/.changeset/techdocs-chatty-months-report.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/techdocs-common': patch ---- - -Added OpenStack Swift case migration support. diff --git a/.changeset/techdocs-famous-donuts-warn.md b/.changeset/techdocs-famous-donuts-warn.md deleted file mode 100644 index 2fd9346ee2..0000000000 --- a/.changeset/techdocs-famous-donuts-warn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@techdocs/cli': patch ---- - -Add support for specifying bucketRootPath for AWS and GCS publishers diff --git a/.changeset/techdocs-orange-cougars-relax.md b/.changeset/techdocs-orange-cougars-relax.md deleted file mode 100644 index 376de6a0e5..0000000000 --- a/.changeset/techdocs-orange-cougars-relax.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/techdocs-common': patch -'@backstage/plugin-techdocs-backend': patch ---- - -Allow amazon web services s3 buckets to pass an server side encryption configuration so they can publish to encrypted buckets diff --git a/.changeset/techdocs-real-geese-dress.md b/.changeset/techdocs-real-geese-dress.md deleted file mode 100644 index 0d5f1978f9..0000000000 --- a/.changeset/techdocs-real-geese-dress.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@techdocs/cli': patch ---- - -Adds ability to use encrypted S3 buckets by utilizing the SSE option in the AWS SDK diff --git a/.changeset/techdocs-sharp-knives-unite.md b/.changeset/techdocs-sharp-knives-unite.md deleted file mode 100644 index aa3625b883..0000000000 --- a/.changeset/techdocs-sharp-knives-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Use a better checkbox rendering in a task list. diff --git a/.changeset/techdocs-silver-plums-speak.md b/.changeset/techdocs-silver-plums-speak.md deleted file mode 100644 index 84d04fc1ef..0000000000 --- a/.changeset/techdocs-silver-plums-speak.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Updates reader component used to display techdocs documentation. A previous change made this component not usable out of a page which don't have entityRef in url parameters. Reader component EntityRef parameter is now used instead of url parameters. Techdocs documentation component can now be used in our custom pages. diff --git a/.changeset/ten-planes-remember.md b/.changeset/ten-planes-remember.md deleted file mode 100644 index 3fefe650af..0000000000 --- a/.changeset/ten-planes-remember.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-tech-insights-backend': patch ---- - -Add catalog fact retrievers - -Add fact retrievers which generate facts related to the completeness -of entity data in the catalog. diff --git a/.changeset/tender-gorillas-peel.md b/.changeset/tender-gorillas-peel.md deleted file mode 100644 index f7d7022740..0000000000 --- a/.changeset/tender-gorillas-peel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -bump `@rollup/plugin-commonjs` from 17.1.0 to 21.0.1 diff --git a/.changeset/tidy-beans-reflect.md b/.changeset/tidy-beans-reflect.md deleted file mode 100644 index 20796075f0..0000000000 --- a/.changeset/tidy-beans-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Introduces new `backstage-cli create` command to replace `create-plugin` and make space for creating a wider array of things. The create command also adds a new template for creating isomorphic common plugin packages. diff --git a/.changeset/twenty-swans-matter.md b/.changeset/twenty-swans-matter.md deleted file mode 100644 index 55cd3d6dc3..0000000000 --- a/.changeset/twenty-swans-matter.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -The `createApp` function from `@backstage/core-app-api` has been deprecated, with two new options being provided as a replacement. - -The first and most commonly used one is `createApp` from the new `@backstage/app-defaults` package, which behaves just like the existing `createApp`. In the future this method is likely to be expanded to add more APIs and other pieces into the default setup, for example the Utility APIs from `@backstage/integration-react`. - -The other option that we now provide is to use `createSpecializedApp` from `@backstage/core-app-api`. This is a more low-level API where you need to provide a full set of options, including your own `components`, `icons`, `defaultApis`, and `themes`. The `createSpecializedApp` way of creating an app is particularly useful if you are not using `@backstage/core-components` or MUI, as it allows you to avoid those dependencies completely. diff --git a/.changeset/unlucky-chefs-arrive.md b/.changeset/unlucky-chefs-arrive.md deleted file mode 100644 index 4b1450b281..0000000000 --- a/.changeset/unlucky-chefs-arrive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -move the BehaviorSubject init into the constructor diff --git a/.changeset/violet-panthers-care.md b/.changeset/violet-panthers-care.md deleted file mode 100644 index 7a43c87f37..0000000000 --- a/.changeset/violet-panthers-care.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -adds getDefaultProcessor method to CatalogBuilder diff --git a/.changeset/yellow-deers-act.md b/.changeset/yellow-deers-act.md deleted file mode 100644 index a9008ea41e..0000000000 --- a/.changeset/yellow-deers-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-plugin-api': patch ---- - -Deprecated the `Error` and `ErrorContext` types, replacing them with identical `ErrorApiError` and `ErrorApiErrorContext` types. diff --git a/.changeset/yellow-falcons-whisper.md b/.changeset/yellow-falcons-whisper.md deleted file mode 100644 index 63a5d42fb0..0000000000 --- a/.changeset/yellow-falcons-whisper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Expose template metadata to custom action handler in Scaffolder. diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md new file mode 100644 index 0000000000..b2b50ae48b --- /dev/null +++ b/packages/app-defaults/CHANGELOG.md @@ -0,0 +1,10 @@ +# @backstage/app-defaults + +## 0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/core-app-api@0.1.21 diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 9438966b3b..7388a44ce0 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "0.1.0", + "version": "0.1.1", "private": false, "publishConfig": { "access": "public", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-app-api": "^0.1.20", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-app-api": "^0.1.21", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -39,8 +39,8 @@ "react-router-dom": "6.0.0-beta.0" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@types/jest": "^26.0.7", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 1dee41af56..f6f6049d68 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,50 @@ # example-app +## 0.2.53 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@0.7.3 + - @backstage/plugin-cost-insights@0.11.11 + - @backstage/cli@0.9.0 + - @backstage/plugin-gcp-projects@0.3.9 + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-scaffolder@0.11.11 + - @backstage/plugin-api-docs@0.6.14 + - @backstage/plugin-azure-devops@0.1.4 + - @backstage/plugin-badges@0.2.14 + - @backstage/plugin-catalog-graph@0.2.2 + - @backstage/plugin-catalog-import@0.7.4 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/plugin-circleci@0.2.29 + - @backstage/plugin-cloudbuild@0.2.28 + - @backstage/plugin-code-coverage@0.1.18 + - @backstage/plugin-explore@0.3.21 + - @backstage/plugin-github-actions@0.4.24 + - @backstage/plugin-home@0.4.6 + - @backstage/plugin-jenkins@0.5.12 + - @backstage/plugin-kafka@0.2.21 + - @backstage/plugin-kubernetes@0.4.20 + - @backstage/plugin-lighthouse@0.2.30 + - @backstage/plugin-newrelic@0.3.9 + - @backstage/plugin-pagerduty@0.3.18 + - @backstage/plugin-rollbar@0.3.19 + - @backstage/plugin-search@0.4.18 + - @backstage/plugin-sentry@0.3.29 + - @backstage/plugin-tech-radar@0.4.12 + - @backstage/plugin-techdocs@0.12.6 + - @backstage/plugin-todo@0.1.15 + - @backstage/plugin-user-settings@0.3.11 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/core-app-api@0.1.21 + - @backstage/plugin-shortcuts@0.1.14 + - @backstage/app-defaults@0.1.1 + - @backstage/integration-react@0.1.14 + - @backstage/plugin-graphiql@0.2.21 + - @backstage/plugin-org@0.3.28 + ## 0.2.51 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 9a1fb108f6..a77afd13d6 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,48 +1,48 @@ { "name": "example-app", - "version": "0.2.51", + "version": "0.2.53", "private": true, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^0.1.0", - "@backstage/catalog-model": "^0.9.5", - "@backstage/cli": "^0.8.0", - "@backstage/core-app-api": "^0.1.18", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/integration-react": "^0.1.12", - "@backstage/plugin-api-docs": "^0.6.12", - "@backstage/plugin-azure-devops": "^0.1.1", - "@backstage/plugin-badges": "^0.2.13", - "@backstage/plugin-catalog": "^0.7.2", - "@backstage/plugin-catalog-graph": "^0.2.1", - "@backstage/plugin-catalog-import": "^0.7.3", - "@backstage/plugin-catalog-react": "^0.6.1", - "@backstage/plugin-circleci": "^0.2.27", - "@backstage/plugin-cloudbuild": "^0.2.27", - "@backstage/plugin-code-coverage": "^0.1.15", - "@backstage/plugin-cost-insights": "^0.11.10", - "@backstage/plugin-explore": "^0.3.20", - "@backstage/plugin-gcp-projects": "^0.3.8", - "@backstage/plugin-github-actions": "^0.4.22", - "@backstage/plugin-graphiql": "^0.2.20", - "@backstage/plugin-home": "^0.4.4", - "@backstage/plugin-jenkins": "^0.5.11", - "@backstage/plugin-kafka": "^0.2.19", - "@backstage/plugin-kubernetes": "^0.4.17", - "@backstage/plugin-lighthouse": "^0.2.29", - "@backstage/plugin-newrelic": "^0.3.8", - "@backstage/plugin-org": "^0.3.27", - "@backstage/plugin-pagerduty": "0.3.17", - "@backstage/plugin-rollbar": "^0.3.18", - "@backstage/plugin-scaffolder": "^0.11.8", - "@backstage/plugin-search": "^0.4.15", - "@backstage/plugin-sentry": "^0.3.26", - "@backstage/plugin-shortcuts": "^0.1.12", - "@backstage/plugin-tech-radar": "^0.4.11", - "@backstage/plugin-techdocs": "^0.12.3", - "@backstage/plugin-todo": "^0.1.14", - "@backstage/plugin-user-settings": "^0.3.10", + "@backstage/app-defaults": "^0.1.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/integration-react": "^0.1.14", + "@backstage/plugin-api-docs": "^0.6.14", + "@backstage/plugin-azure-devops": "^0.1.4", + "@backstage/plugin-badges": "^0.2.14", + "@backstage/plugin-catalog": "^0.7.3", + "@backstage/plugin-catalog-graph": "^0.2.2", + "@backstage/plugin-catalog-import": "^0.7.4", + "@backstage/plugin-catalog-react": "^0.6.4", + "@backstage/plugin-circleci": "^0.2.29", + "@backstage/plugin-cloudbuild": "^0.2.28", + "@backstage/plugin-code-coverage": "^0.1.18", + "@backstage/plugin-cost-insights": "^0.11.11", + "@backstage/plugin-explore": "^0.3.21", + "@backstage/plugin-gcp-projects": "^0.3.9", + "@backstage/plugin-github-actions": "^0.4.24", + "@backstage/plugin-graphiql": "^0.2.21", + "@backstage/plugin-home": "^0.4.6", + "@backstage/plugin-jenkins": "^0.5.12", + "@backstage/plugin-kafka": "^0.2.21", + "@backstage/plugin-kubernetes": "^0.4.20", + "@backstage/plugin-lighthouse": "^0.2.30", + "@backstage/plugin-newrelic": "^0.3.9", + "@backstage/plugin-org": "^0.3.28", + "@backstage/plugin-pagerduty": "0.3.18", + "@backstage/plugin-rollbar": "^0.3.19", + "@backstage/plugin-scaffolder": "^0.11.11", + "@backstage/plugin-search": "^0.4.18", + "@backstage/plugin-sentry": "^0.3.29", + "@backstage/plugin-shortcuts": "^0.1.14", + "@backstage/plugin-tech-radar": "^0.4.12", + "@backstage/plugin-techdocs": "^0.12.6", + "@backstage/plugin-todo": "^0.1.15", + "@backstage/plugin-user-settings": "^0.3.11", "@backstage/search-common": "^0.2.0", "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", @@ -64,7 +64,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/test-utils": "^0.1.19", + "@backstage/test-utils": "^0.1.22", "@rjsf/core": "^3.0.0", "@testing-library/cypress": "^7.0.1", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index f3464917aa..3ab36cc679 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/backend-common +## 0.9.10 + +### Patch Changes + +- d7c1e0e34a: Added the `isDatabaseConflictError` function. +- e21e3c6102: Bumping minimum requirements for `dockerode` and `testcontainers` +- 1e99c73c75: Update internal usage of `configLoader.loadConfig` that now returns an object instead of an array of configs. +- 1daada3a06: Paths can be specified in backend.reading.allow to further restrict allowed targets +- 7ad9a07b27: Adding config prop `pluginDivisionMode` to allow plugins using the `pg` client to create their own management schemas in the db. This allows `pg` client plugins to work in separate schemas in the same db. +- 01f74aa878: Add `AbortSignal` support to `UrlReader` +- a8732a1200: Make sure that server builder `start()` propagates errors (such as failing to bind to the required port) properly and doesn't resolve the promise prematurely. + + After this change, the backend logger will be able to actually capture the error as it happens: + + ``` + 2021-11-11T10:54:21.334Z backstage info Initializing http server + 2021-11-11T10:54:21.335Z backstage error listen EADDRINUSE: address already in use :::7000 code=EADDRINUSE errno=-48 syscall=listen address=:: port=7000 + ``` + +- 26b5da1c1a: Do not redact empty or one-character strings. These imply that it's just a test or local dev, and unnecessarily ruin the log output. +- Updated dependencies + - @backstage/config-loader@0.8.0 + - @backstage/cli-common@0.1.6 + ## 0.9.9 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index ce392a782b..9e0187137d 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.9.9", + "version": "0.9.10", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli-common": "^0.1.5", + "@backstage/cli-common": "^0.1.6", "@backstage/config": "^0.1.11", - "@backstage/config-loader": "^0.7.2", + "@backstage/config-loader": "^0.8.0", "@backstage/errors": "^0.1.4", "@backstage/integration": "^0.6.9", "@backstage/types": "^0.1.1", @@ -80,8 +80,8 @@ } }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@types/archiver": "^5.1.0", "@types/compression": "^1.7.0", "@types/concat-stream": "^1.6.0", diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 10db5cfaac..2bc6474615 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.8", + "@backstage/backend-common": "^0.9.10", "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.4", "@backstage/types": "^0.1.1", @@ -43,8 +43,8 @@ "zod": "^3.9.5" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.8", - "@backstage/cli": "^0.8.1", + "@backstage/backend-test-utils": "^0.1.9", + "@backstage/cli": "^0.9.0", "jest": "^26.0.1", "wait-for-expect": "^3.0.2" }, diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 287e40a296..9927aa3cc7 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-test-utils +## 0.1.9 + +### Patch Changes + +- e21e3c6102: Bumping minimum requirements for `dockerode` and `testcontainers` +- Updated dependencies + - @backstage/cli@0.9.0 + - @backstage/backend-common@0.9.10 + ## 0.1.8 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 299b5588a2..c3d4f730b7 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-test-utils", "description": "Test helpers library for Backstage backends", - "version": "0.1.8", + "version": "0.1.9", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/cli": "^0.8.0", + "@backstage/backend-common": "^0.9.10", + "@backstage/cli": "^0.9.0", "@backstage/config": "^0.1.9", "knex": "^0.95.1", "mysql2": "^2.2.5", @@ -41,7 +41,7 @@ "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "jest": "^26.0.1" }, "files": [ diff --git a/packages/backend/package.json b/packages/backend/package.json index 7fdffc087f..4fb692f040 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -24,31 +24,31 @@ "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "@backstage/backend-common": "^0.9.9", - "@backstage/catalog-client": "^0.5.1", - "@backstage/catalog-model": "^0.9.5", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", "@backstage/integration": "^0.6.8", - "@backstage/plugin-app-backend": "^0.3.17", - "@backstage/plugin-auth-backend": "^0.4.7", - "@backstage/plugin-azure-devops-backend": "^0.2.0", + "@backstage/plugin-app-backend": "^0.3.19", + "@backstage/plugin-auth-backend": "^0.4.8", + "@backstage/plugin-azure-devops-backend": "^0.2.1", "@backstage/plugin-badges-backend": "^0.1.11", - "@backstage/plugin-catalog-backend": "^0.17.3", + "@backstage/plugin-catalog-backend": "^0.17.4", "@backstage/plugin-code-coverage-backend": "^0.1.14", "@backstage/plugin-graphql-backend": "^0.1.9", "@backstage/plugin-jenkins-backend": "^0.1.7", "@backstage/plugin-kubernetes-backend": "^0.3.18", - "@backstage/plugin-kafka-backend": "^0.2.10", + "@backstage/plugin-kafka-backend": "^0.2.11", "@backstage/plugin-proxy-backend": "^0.2.13", "@backstage/plugin-rollbar-backend": "^0.1.15", - "@backstage/plugin-scaffolder-backend": "^0.15.12", + "@backstage/plugin-scaffolder-backend": "^0.15.13", "@backstage/plugin-scaffolder-backend-module-rails": "^0.1.7", "@backstage/plugin-search-backend": "^0.2.6", "@backstage/plugin-search-backend-node": "^0.4.2", "@backstage/plugin-search-backend-module-elasticsearch": "^0.0.5", "@backstage/plugin-search-backend-module-pg": "^0.2.1", - "@backstage/plugin-techdocs-backend": "^0.10.5", - "@backstage/plugin-tech-insights-backend": "^0.1.0", + "@backstage/plugin-techdocs-backend": "^0.10.8", + "@backstage/plugin-tech-insights-backend": "^0.1.1", "@backstage/plugin-tech-insights-node": "^0.1.0", "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.0", "@backstage/plugin-todo-backend": "^0.1.13", @@ -56,7 +56,7 @@ "@octokit/rest": "^18.5.3", "azure-devops-node-api": "^11.0.1", "dockerode": "^3.3.1", - "example-app": "^0.2.51", + "example-app": "^0.2.53", "express": "^4.17.1", "express-promise-router": "^4.1.0", "express-prom-bundle": "^6.3.6", @@ -68,7 +68,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5" diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index f5ec2116f7..1b11e3bcb2 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-client +## 0.5.2 + +### Patch Changes + +- 3bf2238187: Update to the right version of @backstage/errors +- Updated dependencies + - @backstage/catalog-model@0.9.7 + ## 0.5.1 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 9caac50c90..4ab727b6b3 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "0.5.1", + "version": "0.5.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", + "@backstage/catalog-model": "^0.9.7", "@backstage/errors": "^0.1.4", "cross-fetch": "^3.0.6" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@types/jest": "^26.0.7", "msw": "^0.35.0" }, diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index e0c067c9c7..efd6513cdd 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/catalog-model +## 0.9.7 + +### Patch Changes + +- 8809b6c0dd: Update the json-schema dependency version. + ## 0.9.6 ### Patch Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 17c89ed824..0ba07aec3c 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "0.9.6", + "version": "0.9.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -42,7 +42,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.8.1", + "@backstage/cli": "^0.9.0", "@types/jest": "^26.0.7", "@types/lodash": "^4.14.151", "yaml": "^1.9.2" diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md index f3978798c6..e588c02edf 100644 --- a/packages/cli-common/CHANGELOG.md +++ b/packages/cli-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/cli-common +## 0.1.6 + +### Patch Changes + +- 677bfc2dd0: Keep backstage.json in sync + + The `versions:bump` script now takes care about updating the `version` property inside `backstage.json` file. The file is created if is not present. + ## 0.1.5 ### Patch Changes diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index 5916cdb017..cdb4b01b6d 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-common", "description": "Common functionality used by cli, backend, and create-app", - "version": "0.1.5", + "version": "0.1.6", "private": false, "main": "src/index.ts", "types": "src/index.ts", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 0fc702851d..407c4fcbf2 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/cli +## 0.9.0 + +### Minor Changes + +- 25f637f39f: Tweaked style insertion logic to make sure that JSS stylesheets always receive the highest priority. + +### Patch Changes + +- 677bfc2dd0: Keep backstage.json in sync + + The `versions:bump` script now takes care about updating the `version` property inside `backstage.json` file. The file is created if is not present. + +- 8809b6c0dd: Update the json-schema dependency version. +- fdfd2f8a62: remove double config dep +- 1e99c73c75: Update internal usage of `configLoader.loadConfig` that now returns an object instead of an array of configs. +- 6dcfe227a2: Added a scaffolder backend module template for the `create` command. +- 4ca3542fdd: Fixed a bug where calling `backstage-cli backend:bundle --build-dependencies` with no dependencies to be built would cause all monorepo packages to be built instead. +- 867ea81d15: bump `@rollup/plugin-commonjs` from 17.1.0 to 21.0.1 +- 16d06f6ac3: Introduces new `backstage-cli create` command to replace `create-plugin` and make space for creating a wider array of things. The create command also adds a new template for creating isomorphic common plugin packages. +- Updated dependencies + - @backstage/config-loader@0.8.0 + - @backstage/cli-common@0.1.6 + ## 0.8.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index fcbc00f47d..1eed5a742c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.8.2", + "version": "0.9.0", "private": false, "publishConfig": { "access": "public" @@ -28,9 +28,9 @@ "backstage-cli": "bin/backstage-cli" }, "dependencies": { - "@backstage/cli-common": "^0.1.5", + "@backstage/cli-common": "^0.1.6", "@backstage/config": "^0.1.11", - "@backstage/config-loader": "^0.7.2", + "@backstage/config-loader": "^0.8.0", "@backstage/errors": "^0.1.4", "@backstage/types": "^0.1.1", "@hot-loader/react-dom": "^16.13.0", @@ -117,13 +117,13 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.9.9", + "@backstage/backend-common": "^0.9.10", "@backstage/config": "^0.1.11", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@backstage/theme": "^0.2.13", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 1043d9718f..bf0711ad6f 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/codemods +## 0.1.22 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.6 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/core-app-api@0.1.21 + ## 0.1.21 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 17e89c86f0..bfb8d4d4b3 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.21", + "version": "0.1.22", "private": false, "publishConfig": { "access": "public", @@ -31,7 +31,7 @@ "backstage-codemods": "bin/backstage-codemods" }, "dependencies": { - "@backstage/cli-common": "0.1.5", + "@backstage/cli-common": "0.1.6", "@backstage/core-app-api": "*", "@backstage/core-components": "*", "@backstage/core-plugin-api": "*", diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 0f1bc27996..00ace6e704 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/config-loader +## 0.8.0 + +### Minor Changes + +- 1e99c73c75: Update `loadConfig` to return `LoadConfigResult` instead of an array of `AppConfig`. + + This function is primarily used internally by other config loaders like `loadBackendConfig` which means no changes are required for most users. + + If you use `loadConfig` directly you will need to update your usage from: + + ```diff + - const appConfigs = await loadConfig(options) + + const { appConfigs } = await loadConfig(options) + ``` + +### Patch Changes + +- 8809b6c0dd: Update the json-schema dependency version. +- Updated dependencies + - @backstage/cli-common@0.1.6 + ## 0.7.2 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 76dcec35c6..b4c0350def 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "0.7.2", + "version": "0.8.0", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli-common": "^0.1.5", + "@backstage/cli-common": "^0.1.6", "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.4", "@backstage/types": "^0.1.1", diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index b9e60b7dab..342d453eae 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/core-app-api +## 0.1.21 + +### Patch Changes + +- 0b1de52732: Migrated to using new `ErrorApiError` and `ErrorApiErrorContext` names. +- ecd1fcb80a: Deprecated the `BackstagePluginWithAnyOutput` type. +- 32bfbafb0f: Start exporting and marking several types as public to address errors in the API report. +- 014cbf8cb9: The `createApp` function from `@backstage/core-app-api` has been deprecated, with two new options being provided as a replacement. + + The first and most commonly used one is `createApp` from the new `@backstage/app-defaults` package, which behaves just like the existing `createApp`. In the future this method is likely to be expanded to add more APIs and other pieces into the default setup, for example the Utility APIs from `@backstage/integration-react`. + + The other option that we now provide is to use `createSpecializedApp` from `@backstage/core-app-api`. This is a more low-level API where you need to provide a full set of options, including your own `components`, `icons`, `defaultApis`, and `themes`. The `createSpecializedApp` way of creating an app is particularly useful if you are not using `@backstage/core-components` or MUI, as it allows you to avoid those dependencies completely. + +- 475edb5bc5: move the BehaviorSubject init into the constructor +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/app-defaults@0.1.1 + ## 0.1.20 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index fc6c103109..4c79f9eb3f 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.20", + "version": "0.1.21", "private": false, "publishConfig": { "access": "public", @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/app-defaults": "^0.1.0", - "@backstage/core-components": "^0.7.3", + "@backstage/app-defaults": "^0.1.1", + "@backstage/core-components": "^0.7.4", "@backstage/config": "^0.1.11", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@backstage/types": "^0.1.1", "@backstage/version-bridge": "^0.1.0", @@ -47,8 +47,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 1e62df337d..c62ba9e90d 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-components +## 0.7.4 + +### Patch Changes + +- 274a4fc633: Add Props Icon for Sidebar Item SidebarSearchField and Settings +- 682945e233: Changing the `Header` styles to use more theme variables. With this the title `font-size` will not change on resizing the window. +- 892c1d9202: Update OAuthAdapter to create identity.token from identity.idToken if it does not exist, and prevent overwrites to identity.toke. Update login page commonProvider to prefer .token over .idToken +- Updated dependencies + - @backstage/core-plugin-api@0.2.0 + ## 0.7.3 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index ffbde0072a..afa9af0341 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.7.3", + "version": "0.7.4", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.11", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.4", "@backstage/theme": "^0.2.13", "@material-table/core": "^3.1.0", @@ -67,9 +67,9 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/core-app-api": "^0.1.20", - "@backstage/cli": "^0.8.2", - "@backstage/test-utils": "^0.1.21", + "@backstage/core-app-api": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index d92922ddb4..a8d35e5a14 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/core-plugin-api +## 0.2.0 + +### Minor Changes + +- 7e18ed7f29: Removed the unused `UserFlags` type. +- 7df99cdb77: Remove exports of unused types(`RouteOptions` and `RoutePath`). + +### Patch Changes + +- 37ebea2d68: Add deprecation warnings around `title` `icon` and `path` as they are no longer controlled when creating `routeRefs` +- 2dd2a7b2cc: Deprecated the `theme` property on `AppTheme`, replacing it with `Provider`. See https://backstage.io/docs/api/deprecations#app-theme for more details. +- b6a4bacdc4: Deprecated the `Error` and `ErrorContext` types, replacing them with identical `ErrorApiError` and `ErrorApiErrorContext` types. + ## 0.1.13 ### Patch Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 6679e89645..e5b4572dff 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "0.1.13", + "version": "0.2.0", "private": false, "publishConfig": { "access": "public", @@ -43,9 +43,9 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 7e53d0cde5..af1fd58ead 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/create-app +## 0.4.4 + +### Patch Changes + +- 4ebc9fd277: Create backstage.json file + + `@backstage/create-app` will create a new `backstage.json` file. At this point, the file will contain a `version` property, representing the version of `@backstage/create-app` used for creating the application. If the backstage's application has been bootstrapped using an older version of `@backstage/create-app`, the `backstage.json` file can be created and kept in sync, together with all the changes of the latest version of backstage, by running the following script: + + ```bash + yarn backstage-cli versions:bump + ``` + +- e21e3c6102: Bumping minimum requirements for `dockerode` and `testcontainers` +- 014cbf8cb9: Migrated the app template use the new `@backstage/app-defaults` for the `createApp` import, since the `createApp` exported by `@backstage/app-core-api` will be removed in the future. + + To migrate an existing application, add the latest version of `@backstage/app-defaults` as a dependency in `packages/app/package.json`, and make the following change to `packages/app/src/App.tsx`: + + ```diff + -import { createApp, FlatRoutes } from '@backstage/core-app-api'; + +import { createApp } from '@backstage/app-defaults'; + +import { FlatRoutes } from '@backstage/core-app-api'; + ``` + +- 2163e83fa2: Refactor and add regression tests for create-app tasks +- Updated dependencies + - @backstage/cli-common@0.1.6 + ## 0.4.3 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 7c1feec683..d5ee616ff5 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.4.3", + "version": "0.4.4", "private": false, "publishConfig": { "access": "public" @@ -28,7 +28,7 @@ "start": "nodemon --" }, "dependencies": { - "@backstage/cli-common": "^0.1.5", + "@backstage/cli-common": "^0.1.6", "chalk": "^4.0.0", "commander": "^6.1.0", "fs-extra": "9.1.0", diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 6afb45d79b..b882155a3d 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/dev-utils +## 0.2.13 + +### Patch Changes + +- 58a4e67ded: Add theme switcher to sidebar of dev app. +- 014cbf8cb9: Migrated to using `@backstage/app-defaults`. +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/core-app-api@0.1.21 + - @backstage/test-utils@0.1.22 + - @backstage/app-defaults@0.1.1 + - @backstage/integration-react@0.1.14 + ## 0.2.12 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 974329e8d4..32d287d35d 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "0.2.12", + "version": "0.2.13", "private": false, "publishConfig": { "access": "public", @@ -29,14 +29,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/app-defaults": "^0.1.0", - "@backstage/core-app-api": "^0.1.18", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/catalog-model": "^0.9.5", - "@backstage/integration-react": "^0.1.12", - "@backstage/plugin-catalog-react": "^0.6.1", - "@backstage/test-utils": "^0.1.19", + "@backstage/app-defaults": "^0.1.1", + "@backstage/core-app-api": "^0.1.21", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/catalog-model": "^0.9.7", + "@backstage/integration-react": "^0.1.14", + "@backstage/plugin-catalog-react": "^0.6.4", + "@backstage/test-utils": "^0.1.22", "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -53,7 +53,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/embedded-techdocs-app/CHANGELOG.md b/packages/embedded-techdocs-app/CHANGELOG.md new file mode 100644 index 0000000000..6a9583c2dc --- /dev/null +++ b/packages/embedded-techdocs-app/CHANGELOG.md @@ -0,0 +1,17 @@ +# embedded-techdocs-app + +## 0.2.53 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@0.7.3 + - @backstage/cli@0.9.0 + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-techdocs@0.12.6 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/core-app-api@0.1.21 + - @backstage/test-utils@0.1.22 + - @backstage/app-defaults@0.1.1 + - @backstage/integration-react@0.1.14 diff --git a/packages/embedded-techdocs-app/package.json b/packages/embedded-techdocs-app/package.json index 412fd80357..b2d7882f8f 100644 --- a/packages/embedded-techdocs-app/package.json +++ b/packages/embedded-techdocs-app/package.json @@ -1,20 +1,20 @@ { "name": "embedded-techdocs-app", - "version": "0.0.0", + "version": "0.2.53", "private": true, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^0.1.0", - "@backstage/catalog-model": "^0.9.5", - "@backstage/cli": "^0.8.0", + "@backstage/app-defaults": "^0.1.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/cli": "^0.9.0", "@backstage/config": "^0.1.10", - "@backstage/core-app-api": "^0.1.18", - "@backstage/core-components": "^0.7.1", - "@backstage/core-plugin-api": "^0.1.11", - "@backstage/integration-react": "^0.1.12", - "@backstage/plugin-catalog": "^0.7.2", - "@backstage/plugin-techdocs": "^0.12.3", - "@backstage/test-utils": "^0.1.19", + "@backstage/core-app-api": "^0.1.21", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/integration-react": "^0.1.14", + "@backstage/plugin-catalog": "^0.7.3", + "@backstage/plugin-techdocs": "^0.12.6", + "@backstage/test-utils": "^0.1.22", "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -26,7 +26,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/packages/errors/package.json b/packages/errors/package.json index fe62bb3bba..38fe6c634e 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -35,7 +35,7 @@ "serialize-error": "^8.0.1" }, "devDependencies": { - "@backstage/cli": "^0.8.1", + "@backstage/cli": "^0.9.0", "@types/jest": "^26.0.7" }, "files": [ diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index a2a0d0c368..e972b4d4e8 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration-react +## 0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.13 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index b703203ab2..f3c79cc56c 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "0.1.13", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,8 +22,8 @@ }, "dependencies": { "@backstage/config": "^0.1.11", - "@backstage/core-components": "^0.7.2", - "@backstage/core-plugin-api": "^0.1.12", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/integration": "^0.6.9", "@backstage/theme": "^0.2.12", "@material-ui/core": "^4.12.2", @@ -34,9 +34,9 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.1", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.20", + "@backstage/cli": "^0.9.0", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/packages/integration/package.json b/packages/integration/package.json index bd49ecc419..4ccde52a70 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -39,9 +39,9 @@ "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/cli": "^0.8.1", - "@backstage/config-loader": "^0.7.1", - "@backstage/test-utils": "^0.1.20", + "@backstage/cli": "^0.9.0", + "@backstage/config-loader": "^0.8.0", + "@backstage/test-utils": "^0.1.22", "@types/jest": "^26.0.7", "@types/luxon": "^2.0.4", "msw": "^0.35.0" diff --git a/packages/search-common/package.json b/packages/search-common/package.json index e913ef66ff..d65e9bcbdc 100644 --- a/packages/search-common/package.json +++ b/packages/search-common/package.json @@ -39,7 +39,7 @@ "@backstage/types": "^0.1.1" }, "devDependencies": { - "@backstage/cli": "^0.8.1" + "@backstage/cli": "^0.9.0" }, "jest": { "roots": [ diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 0f7c6be52f..6d69e452ad 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,17 @@ # @techdocs/cli +## 0.8.6 + +### Patch Changes + +- e21e3c6102: Bumping minimum requirements for `dockerode` and `testcontainers` +- 1578ad341b: Add support for specifying bucketRootPath for AWS and GCS publishers +- f2694e3750: Adds ability to use encrypted S3 buckets by utilizing the SSE option in the AWS SDK +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/backend-common@0.9.10 + - @backstage/techdocs-common@0.10.7 + ## 0.8.5 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 28903ccb9a..70ca0a9668 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "0.8.5", + "version": "0.8.6", "private": false, "publishConfig": { "access": "public" @@ -32,7 +32,7 @@ "techdocs-cli": "bin/techdocs-cli" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/commander": "^2.12.2", "@types/fs-extra": "^9.0.6", "@types/http-proxy": "^1.17.4", @@ -41,7 +41,7 @@ "@types/react-dev-utils": "^9.0.4", "@types/serve-handler": "^6.1.0", "@types/webpack-env": "^1.15.3", - "embedded-techdocs-app": "0.0.0", + "embedded-techdocs-app": "0.2.53", "find-process": "^1.4.5", "nodemon": "^2.0.2", "ts-node": "^10.0.0" @@ -56,10 +56,10 @@ "ext": "ts" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/catalog-model": "^0.9.5", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", - "@backstage/techdocs-common": "^0.10.4", + "@backstage/techdocs-common": "^0.10.7", "@types/dockerode": "^3.3.0", "commander": "^6.1.0", "dockerode": "^3.3.1", diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md index 87e9e12193..69bcbcdaeb 100644 --- a/packages/techdocs-common/CHANGELOG.md +++ b/packages/techdocs-common/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/techdocs-common +## 0.10.7 + +### Patch Changes + +- 0b60a051c9: Added OpenStack Swift case migration support. +- 9e64a7ac1e: Allow amazon web services s3 buckets to pass an server side encryption configuration so they can publish to encrypted buckets +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/backend-common@0.9.10 + ## 0.10.6 ### Patch Changes diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index b44e68374d..b13b94a1a7 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/techdocs-common", "description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "0.10.6", + "version": "0.10.7", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -38,8 +38,8 @@ "dependencies": { "@azure/identity": "^1.5.0", "@azure/storage-blob": "^12.5.0", - "@backstage/backend-common": "^0.9.9", - "@backstage/catalog-model": "^0.9.6", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.4", "@backstage/search-common": "^0.2.1", @@ -60,7 +60,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@types/fs-extra": "^9.0.5", "@types/js-yaml": "^4.0.0", "@types/mime-types": "^2.1.0", diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 6fcacc30fa..3460e6c714 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/test-utils +## 0.1.22 + +### Patch Changes + +- 0b1de52732: Migrated to using new `ErrorApiError` and `ErrorApiErrorContext` names. +- 2dd2a7b2cc: Migrated to using `createSpecializedApp`. +- Updated dependencies + - @backstage/core-plugin-api@0.2.0 + - @backstage/core-app-api@0.1.21 + ## 0.1.21 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 6f5f78de8c..79667c236a 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "0.1.21", + "version": "0.1.22", "private": false, "publishConfig": { "access": "public", @@ -29,8 +29,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-app-api": "^0.1.20", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-app-api": "^0.1.21", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@backstage/types": "^0.1.1", "@material-ui/core": "^4.12.2", @@ -46,7 +46,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/theme/package.json b/packages/theme/package.json index d9e89c969f..28a05af98d 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -31,7 +31,7 @@ "@material-ui/core": "^4.12.2" }, "devDependencies": { - "@backstage/cli": "^0.8.2" + "@backstage/cli": "^0.9.0" }, "files": [ "dist" diff --git a/packages/types/package.json b/packages/types/package.json index 8632422a25..197d51b061 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -31,7 +31,7 @@ }, "dependencies": {}, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/zen-observable": "^0.8.0", "zen-observable": "^0.8.15" }, diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index 7cc0b56a34..35a6e8f71d 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -33,7 +33,7 @@ "react": "^16.12.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2" diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index 3de49b9b74..f769b6e133 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-allure +## 0.1.7 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.6 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index b157795eec..6a9a55bceb 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.6", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,10 +22,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -36,10 +36,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index a59bcb6351..acc5c235f9 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-analytics-module-ga +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 4970f50c04..b83aed37c0 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,8 +22,8 @@ }, "dependencies": { "@backstage/config": "^0.1.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -34,10 +34,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 78f4b08bd7..0b0bd4890c 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-api-docs +## 0.6.14 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/plugin-catalog@0.7.3 + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.6.13 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 61ae26c776..16f2d0d188 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.6.13", + "version": "0.6.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ }, "dependencies": { "@asyncapi/react-component": "^0.23.0", - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog": "^0.7.2", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog": "^0.7.3", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -53,10 +53,10 @@ "swagger-ui-react": "^4.0.0-rc.3" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 0658b10ebb..a58b028049 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-app-backend +## 0.3.19 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@0.8.0 + - @backstage/backend-common@0.9.10 + ## 0.3.18 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index d989457c79..ebb0393192 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-backend", "description": "A Backstage backend plugin that serves the Backstage frontend app", - "version": "0.3.18", + "version": "0.3.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.8", - "@backstage/config-loader": "^0.7.1", + "@backstage/backend-common": "^0.9.10", + "@backstage/config-loader": "^0.8.0", "@backstage/config": "^0.1.11", "@backstage/types": "^0.1.1", "@types/express": "^4.17.6", @@ -42,7 +42,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.1", + "@backstage/cli": "^0.9.0", "@backstage/types": "^0.1.1", "@types/supertest": "^2.0.8", "msw": "^0.35.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index a11f561986..5dc0cdb861 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-auth-backend +## 0.4.8 + +### Patch Changes + +- 892c1d9202: Update OAuthAdapter to create identity.token from identity.idToken if it does not exist, and prevent overwrites to identity.toke. Update login page commonProvider to prefer .token over .idToken +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/backend-common@0.9.10 + - @backstage/test-utils@0.1.22 + ## 0.4.7 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index e9ec29970b..3a9e8102eb 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.4.7", + "version": "0.4.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.9", - "@backstage/catalog-client": "^0.5.1", - "@backstage/catalog-model": "^0.9.6", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.4", - "@backstage/test-utils": "^0.1.21", + "@backstage/test-utils": "^0.1.22", "@google-cloud/firestore": "^4.15.1", "@types/express": "^4.17.6", "@types/passport": "^1.0.3", @@ -73,7 +73,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index d2fe981eb0..06fc4833c4 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-azure-devops-backend +## 0.2.1 + +### Patch Changes + +- 2b5ccd2964: Improved Date handling for the Azure DevOps set of plugins by using strings and letting the frontend handle the conversion to DateTime +- Updated dependencies + - @backstage/backend-common@0.9.10 + - @backstage/plugin-azure-devops-common@0.1.0 + ## 0.2.0 ### Minor Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 901ad0b960..6d213cbce6 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.2.0", + "version": "0.2.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.9", + "@backstage/backend-common": "^0.9.10", "@backstage/config": "^0.1.11", - "@backstage/plugin-azure-devops-common": "^0.0.2", + "@backstage/plugin-azure-devops-common": "^0.1.0", "@types/express": "^4.17.6", "azure-devops-node-api": "^11.0.1", "express": "^4.17.1", @@ -31,7 +31,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@types/supertest": "^2.0.8", "supertest": "^4.0.2", "msw": "^0.35.0" diff --git a/plugins/azure-devops-common/CHANGELOG.md b/plugins/azure-devops-common/CHANGELOG.md index b414cd3ce6..4a834fb068 100644 --- a/plugins/azure-devops-common/CHANGELOG.md +++ b/plugins/azure-devops-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-azure-devops-common +## 0.1.0 + +### Minor Changes + +- 2b5ccd2964: Improved Date handling for the Azure DevOps set of plugins by using strings and letting the frontend handle the conversion to DateTime + ## 0.0.2 ### Patch Changes diff --git a/plugins/azure-devops-common/package.json b/plugins/azure-devops-common/package.json index a1ddddcbe0..fe9df644b1 100644 --- a/plugins/azure-devops-common/package.json +++ b/plugins/azure-devops-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-common", - "version": "0.0.2", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "devDependencies": { - "@backstage/cli": "^0.8.2" + "@backstage/cli": "^0.9.0" }, "files": [ "dist" diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index 2f75f64236..0bcd9bc686 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-azure-devops +## 0.1.4 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- b5eac957f2: Added entity view for Azure Repo Pull Requests +- 2b5ccd2964: Improved Date handling for the Azure DevOps set of plugins by using strings and letting the frontend handle the conversion to DateTime +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/plugin-azure-devops-common@0.1.0 + ## 0.1.3 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 3f1876b974..0642a24cac 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,12 +27,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.6", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.4", - "@backstage/plugin-azure-devops-common": "^0.0.2", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/plugin-azure-devops-common": "^0.1.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -45,10 +45,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 51a181612a..2186c8d52e 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.5", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", "@backstage/errors": "^0.1.3", "@types/express": "^4.17.6", @@ -46,7 +46,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 3a6ed61717..44bc597d0a 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-badges +## 0.2.14 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.13 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 0c792808bc..dcc422ec19 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.13", + "version": "0.2.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,11 +27,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.3", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,10 +42,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md new file mode 100644 index 0000000000..88e646b5e3 --- /dev/null +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -0,0 +1,10 @@ +# @backstage/plugin-bazaar-backend + +## 0.1.2 + +### Patch Changes + +- f6ba309d9e: A Bazaar project has been extended with the following fields: size, start date (optional), end date (optional) and a responsible person. +- Updated dependencies + - @backstage/backend-common@0.9.10 + - @backstage/backend-test-utils@0.1.9 diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index a9ac0153b8..a6610493e2 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/backend-test-utils": "^0.1.8", + "@backstage/backend-common": "^0.9.10", + "@backstage/backend-test-utils": "^0.1.9", "@backstage/config": "^0.1.5", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -31,7 +31,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0" + "@backstage/cli": "^0.9.0" }, "files": [ "dist", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index 731f62b9e9..8988bf5d62 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-bazaar +## 0.1.4 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- f6ba309d9e: A Bazaar project has been extended with the following fields: size, start date (optional), end date (optional) and a responsible person. +- Updated dependencies + - @backstage/plugin-catalog@0.7.3 + - @backstage/cli@0.9.0 + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.3 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 094741bf36..fd07a3b5c7 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,12 +21,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/cli": "^0.8.2", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog": "^0.7.2", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/catalog-model": "^0.9.7", + "@backstage/cli": "^0.9.0", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog": "^0.7.3", + "@backstage/plugin-catalog-react": "^0.6.4", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/dev-utils": "^0.2.12", + "@backstage/cli": "^0.9.0", + "@backstage/dev-utils": "^0.2.13", "@testing-library/jest-dom": "^5.10.1", "cross-fetch": "^3.0.6" }, diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 7e364ca294..874cbe2c6c 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-bitrise +## 0.1.17 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.16 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 5ebfd453a2..28a3c88ad1 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.16", + "version": "0.1.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -39,10 +39,10 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index a8c3b71345..5e3cec24d9 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.6", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.4", - "@backstage/plugin-catalog-backend": "^0.17.2", + "@backstage/plugin-catalog-backend": "^0.17.4", "@backstage/types": "^0.1.1", "@types/ldapjs": "^2.2.0", "ldapjs": "^2.2.0", @@ -40,7 +40,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.1", + "@backstage/cli": "^0.9.0", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index b3c9494f78..222f56b022 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -30,9 +30,9 @@ }, "dependencies": { "@azure/msal-node": "^1.1.0", - "@backstage/catalog-model": "^0.9.5", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", - "@backstage/plugin-catalog-backend": "^0.17.3", + "@backstage/plugin-catalog-backend": "^0.17.4", "@microsoft/microsoft-graph-types": "^2.6.0", "cross-fetch": "^3.0.6", "lodash": "^4.17.21", @@ -41,9 +41,9 @@ "qs": "^6.9.4" }, "devDependencies": { - "@backstage/backend-common": "^0.9.9", - "@backstage/cli": "^0.8.2", - "@backstage/test-utils": "^0.1.21", + "@backstage/backend-common": "^0.9.10", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@types/lodash": "^4.14.151", "msw": "^0.35.0" }, diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index abb50a345c..92b57f3483 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend +## 0.17.4 + +### Patch Changes + +- 5d2a7303bd: This fixes a bug where locations couldn't be added unless the processing engine is started. + It's now possible to run the catalog backend without starting the processing engine and still allowing locations registrations. + + This is done by refactor the `EntityProvider.connect` to happen outside the engine. + +- 06934f2f52: Adjust entity query construction to ensure sub-queries are always isolated from one another. +- b90fc74d70: adds getDefaultProcessor method to CatalogBuilder +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/backend-common@0.9.10 + ## 0.17.3 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index f13ff2d66c..a9a35d5858 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "0.17.3", + "version": "0.17.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.9", - "@backstage/catalog-client": "^0.5.1", - "@backstage/catalog-model": "^0.9.6", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.4", "@backstage/integration": "^0.6.9", @@ -62,9 +62,9 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.8", - "@backstage/cli": "^0.8.2", - "@backstage/test-utils": "^0.1.21", + "@backstage/backend-test-utils": "^0.1.9", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/lodash": "^4.14.151", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index a156be8fe0..c107a4e758 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-graph +## 0.2.2 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.1 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index e58d66b1f2..53fde11c7b 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.1", + "version": "0.2.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -41,10 +41,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 5df4f9ba5c..a7070a1634 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.6", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", "@backstage/types": "^0.1.1", "@graphql-modules/core": "^0.7.17", @@ -43,8 +43,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.1", - "@backstage/test-utils": "^0.1.20", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@graphql-codegen/cli": "^1.21.3", "@graphql-codegen/typescript": "^1.17.7", "@graphql-codegen/typescript-resolvers": "^1.17.7", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index d06f38698b..6397718fd7 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-import +## 0.7.4 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/integration-react@0.1.14 + ## 0.7.3 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 242231bf81..bd7f99c884 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.7.3", + "version": "0.7.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,14 +31,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.3", "@backstage/integration": "^0.6.8", - "@backstage/integration-react": "^0.1.12", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/integration-react": "^0.1.14", + "@backstage/plugin-catalog-react": "^0.6.4", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -55,10 +55,10 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 79dfa5e72a..e6d00b2f8f 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-react +## 0.6.4 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/core-app-api@0.1.21 + ## 0.6.3 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 9778163391..2ae853650a 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "0.6.3", + "version": "0.6.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,11 +29,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.5.1", - "@backstage/catalog-model": "^0.9.6", - "@backstage/core-app-api": "^0.1.20", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-app-api": "^0.1.21", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.4", "@backstage/integration": "^0.6.9", "@backstage/types": "^0.1.1", @@ -51,8 +51,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 0030f702ec..7fda738d32 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog +## 0.7.3 + +### Patch Changes + +- 38d6df6bb9: Remove the "View Api" icon in the AboutCard, as the information is misleading for some users and is + duplicated in the tabs above. +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/integration-react@0.1.14 + ## 0.7.2 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 9697741dde..254718bd3c 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "0.7.2", + "version": "0.7.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,13 +31,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.3", - "@backstage/integration-react": "^0.1.12", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/integration-react": "^0.1.14", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -51,10 +51,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 78cd6d9711..18e227627b 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-circleci +## 0.2.29 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.28 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index c57d19ea00..d7cd3b0fd2 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.2.28", + "version": "0.2.29", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "postpack": "backstage-cli postpack" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -52,10 +52,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index dfd17e9908..735f5d2167 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-cloudbuild +## 0.2.28 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.27 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 6521816f73..32b860ec23 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.2.27", + "version": "0.2.28", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,10 +31,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 53d52a9246..90320d0e41 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.5", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", "@backstage/errors": "^0.1.3", "@backstage/integration": "^0.6.8", @@ -37,7 +37,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", "msw": "^0.35.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 572e0f7800..b5b413b9d2 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-code-coverage +## 0.1.18 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.17 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 0d6e998b69..0c32718e97 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage", "description": "A Backstage plugin that helps you keep track of your code coverage", - "version": "0.1.17", + "version": "0.1.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,12 +21,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.6", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.4", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,10 +42,10 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index c8372532f6..ca889ebdbd 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-config-schema +## 0.1.13 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.12 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 0708115270..0385a64ec8 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-config-schema", "description": "A Backstage plugin that lets you browse the configuration schema of your app", - "version": "0.1.12", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,8 +22,8 @@ }, "dependencies": { "@backstage/config": "^0.1.11", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.4", "@backstage/theme": "^0.2.13", "@backstage/types": "^0.1.1", @@ -37,10 +37,10 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 8a7b07af3b..7096af37c6 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-cost-insights +## 0.11.11 + +### Patch Changes + +- 4576f82858: Fixed generation of sample data in the example Cost Insights client +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.11.10 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 064b24bd0c..04e4f41701 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cost-insights", "description": "A Backstage plugin that helps you keep track of your cloud spend", - "version": "0.11.10", + "version": "0.11.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ }, "dependencies": { "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -55,10 +55,10 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/explore-react/CHANGELOG.md b/plugins/explore-react/CHANGELOG.md index 4af81f6d8b..0560527f80 100644 --- a/plugins/explore-react/CHANGELOG.md +++ b/plugins/explore-react/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-explore-react +## 0.0.7 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@0.2.0 + ## 0.0.6 ### Patch Changes diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 1dfd24dff8..a67f8b6892 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore-react", "description": "A frontend library for Backstage plugins that want to interact with the explore plugin", - "version": "0.0.6", + "version": "0.0.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,12 +29,12 @@ "postpack": "backstage-cli postpack" }, "dependencies": { - "@backstage/core-plugin-api": "^0.1.11" + "@backstage/core-plugin-api": "^0.2.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", - "@backstage/dev-utils": "^0.2.0", - "@backstage/test-utils": "^0.1.14", + "@backstage/cli": "^0.9.0", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index f051691dc5..73117d7f32 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-explore +## 0.3.21 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/plugin-explore-react@0.0.7 + ## 0.3.20 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 30890c7176..5732e3fca6 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore", "description": "A Backstage plugin for building an exploration page of your software ecosystem", - "version": "0.3.20", + "version": "0.3.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", - "@backstage/plugin-explore-react": "^0.0.6", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", + "@backstage/plugin-explore-react": "^0.0.7", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 2343eb1c2e..b137ed1f73 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-firehydrant +## 0.1.8 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.7 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 4e3fbdd3c8..dce261617d 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-firehydrant", "description": "A Backstage plugin that integrates towards FireHydrant", - "version": "0.1.7", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,9 +22,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -35,10 +35,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index f422dfbe41..af99e13c4a 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-fossa +## 0.2.22 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.21 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 94528a3126..8090fdc1c7 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-fossa", "description": "A Backstage plugin that integrates towards FOSSA", - "version": "0.2.21", + "version": "0.2.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.3", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 28c40f6221..ac8dd570a6 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-gcp-projects +## 0.3.9 + +### Patch Changes + +- 741bcb168e: UI updates to GCP-projects plugin + + Adds the following to the project list page: + + - pagination + - filtering + - sorting + - rows per page + - show/hide columns + + Makes breadcrumb a link back to project list for the project details and new project views. + + In project list page, updates New project button to use RouterLink instead of `href` to avoid login prompt. + + In project details view, links to project details and logs now work, clicking on these will open the project or logs in GCP in new tab. + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.8 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 471b9d80f1..0e33130274 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gcp-projects", "description": "A Backstage plugin that helps you manage projects in GCP", - "version": "0.3.8", + "version": "0.3.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -43,10 +43,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 72bcf87b2a..1c627ab086 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-git-release-manager +## 0.3.3 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.2 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index b1b2c11732..0c52381514 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-git-release-manager", "description": "A Backstage plugin that helps you manage releases in git", - "version": "0.3.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/integration": "^0.6.8", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", @@ -39,10 +39,10 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index c8fce8e501..5eed309d68 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-github-actions +## 0.4.24 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.4.23 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 1a4079a5ca..789385308e 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.4.23", + "version": "0.4.24", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/integration": "^0.6.8", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -52,10 +52,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 5259ea11b2..701b167135 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-github-deployments +## 0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/integration-react@0.1.14 + ## 0.1.20 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 78061951f5..a52bbfa95a 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-deployments", "description": "A Backstage plugin that integrates towards GitHub Deployments", - "version": "0.1.20", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,13 +21,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.3", "@backstage/integration": "^0.6.8", - "@backstage/integration-react": "^0.1.12", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/integration-react": "^0.1.14", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -39,10 +39,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index 08f256cdb5..42f3533d31 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gitops-profiles +## 0.3.9 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.8 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index c290599c2c..226a45332c 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gitops-profiles", "description": "A Backstage plugin that helps you manage GitOps profiles", - "version": "0.3.8", + "version": "0.3.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -44,10 +44,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index aa58dbd332..f6c8b9fde8 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-graphiql +## 0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.20 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index df1ad6f887..aeefce3340 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.20", + "version": "0.2.21", "private": false, "publishConfig": { "access": "public", @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -44,10 +44,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index 9d90dd8782..335545021e 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", + "@backstage/backend-common": "^0.9.10", "@backstage/config": "^0.1.8", "@backstage/plugin-catalog-graphql": "^0.2.12", "@graphql-modules/core": "^0.7.17", @@ -47,7 +47,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/supertest": "^2.0.8", "eslint-plugin-graphql": "^4.0.0", "msw": "^0.35.0", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 06beb827a6..09e379a625 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-home +## 0.4.6 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.4.5 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index 8020d7af03..74336d80be 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.4.5", + "version": "0.4.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -35,10 +35,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index f43f2add09..1bff4b22ef 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-ilert +## 0.1.17 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.16 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 69c4025181..e0ccd3cd2d 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-ilert", "description": "A Backstage plugin that integrates towards iLert", - "version": "0.1.16", + "version": "0.1.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.3", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@date-io/luxon": "1.x", "@material-ui/core": "^4.12.2", @@ -39,10 +39,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 7049fc0a32..ac9efb3ffd 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -22,9 +22,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.9", - "@backstage/catalog-client": "^0.5.1", - "@backstage/catalog-model": "^0.9.5", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", @@ -35,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@types/jenkins": "^0.23.1", "@types/supertest": "^2.0.8", "msw": "^0.35.0", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 84db4728bc..369676b195 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-jenkins +## 0.5.12 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.5.11 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 80d8b40322..e8115c3800 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins", "description": "A Backstage plugin that integrates towards Jenkins", - "version": "0.5.11", + "version": "0.5.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,10 +48,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index 88111cd1de..482c1f75b1 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-kafka-backend +## 0.2.11 + +### Patch Changes + +- 9145449220: Update Kafka configuration types +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/backend-common@0.9.10 + ## 0.2.10 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index e271decc8b..dea803890f 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka-backend", "description": "A Backstage backend plugin that integrates towards Kafka", - "version": "0.2.10", + "version": "0.2.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/catalog-model": "^0.9.5", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", "@backstage/errors": "^0.1.3", "@types/express": "^4.17.6", @@ -44,7 +44,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/jest-when": "^2.7.2", "@types/lodash": "^4.14.151", "jest-when": "^3.1.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index 2fe42565da..33ec4bd95a 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-kafka +## 0.2.21 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.20 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 888c79db59..bea4aadcba 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka", "description": "A Backstage plugin that integrates towards Kafka", - "version": "0.2.20", + "version": "0.2.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -35,10 +35,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index be2903dff5..4edc7b238a 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -32,8 +32,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/catalog-model": "^0.9.5", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", "@backstage/errors": "^0.1.3", "@backstage/plugin-kubernetes-common": "^0.1.4", @@ -55,7 +55,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/aws4": "^1.5.1", "supertest": "^6.1.3", "aws-sdk-mock": "^5.2.1", diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 28dfc94c49..3c9cb5e357 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -35,11 +35,11 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", + "@backstage/catalog-model": "^0.9.7", "@kubernetes/client-node": "^0.15.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0" + "@backstage/cli": "^0.9.0" }, "jest": { "roots": [ diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index a757041b32..0ae3a6c012 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-kubernetes +## 0.4.20 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.4.19 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 9dbca8aff8..8f4e3356c5 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes", "description": "A Backstage plugin that integrates towards Kubernetes", - "version": "0.4.19", + "version": "0.4.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.6", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/plugin-kubernetes-common": "^0.1.5", "@backstage/theme": "^0.2.13", "@kubernetes/client-node": "^0.15.0", @@ -51,10 +51,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 4ff76d4f1b..48ef9a178d 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-lighthouse +## 0.2.30 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.29 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index f0dca639fc..b1e0290b4c 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse", "description": "A Backstage plugin that integrates towards Lighthouse", - "version": "0.2.29", + "version": "0.2.30", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,10 +47,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index 7ffd4b06d1..89b77e9866 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-newrelic +## 0.3.9 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.8 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 271daa566e..c19bc9ed37 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-newrelic", "description": "A Backstage plugin that integrates towards New Relic", - "version": "0.3.8", + "version": "0.3.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -43,10 +43,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 6e1cc7064f..f46095f46a 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-org +## 0.3.28 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.27 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 5348f67523..035ae50c3b 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-org", "description": "A Backstage plugin that helps you create entity pages for your organization", - "version": "0.3.27", + "version": "0.3.28", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -37,10 +37,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 11ae548db8..bb74598f2a 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-pagerduty +## 0.3.18 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.17 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 7b42a15bc6..735b541451 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.3.17", + "version": "0.3.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,10 +31,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,10 +48,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index 5e79c1ba7b..95a0d9d3c3 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -44,7 +44,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/jest": "^26.0.7", "msw": "^0.35.0" } diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index c43ea8b31a..05499d88e8 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", + "@backstage/backend-common": "^0.9.10", "@backstage/config": "^0.1.8", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -43,7 +43,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 1d7be09b85..be8b6e65e5 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", + "@backstage/backend-common": "^0.9.10", "@backstage/config": "^0.1.10", "@types/express": "^4.17.6", "axios": "^0.21.1", @@ -48,7 +48,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 4f7f3c9a16..aee0a74525 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-rollbar +## 0.3.19 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.18 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 2e2da0a284..f3d32eed11 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.3.18", + "version": "0.3.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 36a6310aa2..90258d3c28 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -20,10 +20,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.9", + "@backstage/backend-common": "^0.9.10", "@backstage/errors": "^0.1.4", "@backstage/integration": "^0.6.9", - "@backstage/plugin-scaffolder-backend": "^0.15.12", + "@backstage/plugin-scaffolder-backend": "^0.15.13", "@backstage/config": "^0.1.11", "@backstage/types": "^0.1.1", "command-exists": "^1.2.9", @@ -33,7 +33,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", "@types/jest": "^26.0.7", diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index f4ace02eca..37b077568e 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.9", - "@backstage/plugin-scaffolder-backend": "^0.15.12", + "@backstage/backend-common": "^0.9.10", + "@backstage/plugin-scaffolder-backend": "^0.15.13", "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.4", "@backstage/integration": "^0.6.9", @@ -31,7 +31,7 @@ "fs-extra": "^9.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.2", + "@backstage/cli": "^0.9.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "@types/command-exists": "^1.2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index de033eabbd..f71849a1d2 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend +## 0.15.13 + +### Patch Changes + +- 26eb174ce8: Skip empty file names when scaffolding with nunjucks +- ecdcbd08ee: Expose template metadata to custom action handler in Scaffolder. +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/backend-common@0.9.10 + - @backstage/plugin-catalog-backend@0.17.4 + ## 0.15.12 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index e5d13801ba..374cfeffd6 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend", "description": "The Backstage backend plugin that helps you create new things", - "version": "0.15.12", + "version": "0.15.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,13 +30,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.9", - "@backstage/catalog-client": "^0.5.1", - "@backstage/catalog-model": "^0.9.6", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.4", "@backstage/integration": "^0.6.9", - "@backstage/plugin-catalog-backend": "^0.17.3", + "@backstage/plugin-catalog-backend": "^0.17.4", "@backstage/plugin-scaffolder-common": "^0.1.1", "@backstage/plugin-scaffolder-backend-module-cookiecutter": "^0.1.4", "@backstage/types": "^0.1.1", @@ -71,8 +71,8 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 006d8ad7aa..05d5ae3031 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -36,10 +36,10 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^0.9.6", + "@backstage/catalog-model": "^0.9.7", "@backstage/types": "^0.1.1" }, "devDependencies": { - "@backstage/cli": "^0.8.1" + "@backstage/cli": "^0.9.0" } } diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index dd5653240a..8c43d8d010 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder +## 0.11.11 + +### Patch Changes + +- 8809b6c0dd: Update the json-schema dependency version. +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/integration-react@0.1.14 + ## 0.11.10 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 594a8e6423..3d7bde77c9 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder", "description": "The Backstage plugin that helps you create new things", - "version": "0.11.10", + "version": "0.11.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,15 +31,15 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.5.1", - "@backstage/catalog-model": "^0.9.6", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.4", "@backstage/integration": "^0.6.9", - "@backstage/integration-react": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/integration-react": "^0.1.14", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@backstage/types": "^0.1.1", "@material-ui/core": "^4.12.2", @@ -66,10 +66,10 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index df0a783396..5ebc7850a9 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -30,8 +30,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.9.9", - "@backstage/cli": "^0.8.2", + "@backstage/backend-common": "^0.9.10", + "@backstage/cli": "^0.9.0", "@elastic/elasticsearch-mock": "^0.3.0" }, "files": [ diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index a31d908ac4..74e9698ea4 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -20,15 +20,15 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", + "@backstage/backend-common": "^0.9.10", "@backstage/search-common": "^0.2.0", "@backstage/plugin-search-backend-node": "^0.4.2", "lodash": "^4.17.21", "knex": "^0.95.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.8", - "@backstage/cli": "^0.8.0" + "@backstage/backend-test-utils": "^0.1.9", + "@backstage/cli": "^0.9.0" }, "files": [ "dist", diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 4514d07756..369c52a4f6 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -26,8 +26,8 @@ "@types/lunr": "^2.3.3" }, "devDependencies": { - "@backstage/backend-common": "^0.9.8", - "@backstage/cli": "^0.8.1" + "@backstage/backend-common": "^0.9.10", + "@backstage/cli": "^0.9.0" }, "files": [ "dist" diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 18d4484451..2df51e1bb4 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -20,7 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", + "@backstage/backend-common": "^0.9.10", "@backstage/search-common": "^0.2.0", "@backstage/plugin-search-backend-node": "^0.4.2", "@types/express": "^4.17.6", @@ -30,7 +30,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 808c847914..ef3736b1df 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search +## 0.4.18 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- 704b267e1c: Smaller UX improvements to search components such as optional autoFocus prop to SearchBar components, decreased debounce value and closing modal on link click of SearchModal, terminology updates of SearchResultPager. +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.4.17 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 9d25ec723d..24984d10e7 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search", "description": "The Backstage plugin that provides your backstage app with search", - "version": "0.4.17", + "version": "0.4.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.6", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.4", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/search-common": "^0.2.1", "@backstage/theme": "^0.2.13", "@backstage/types": "^0.1.1", @@ -51,10 +51,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index b0bcaad261..cad08289ed 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-sentry +## 0.3.29 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.28 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index ee2421bf7f..fd7cc34b1f 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sentry", "description": "A Backstage plugin that integrates towards Sentry", - "version": "0.3.28", + "version": "0.3.29", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.6", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.3", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,10 +48,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 41581cc5b4..fdd9f44231 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-shortcuts +## 0.1.14 + +### Patch Changes + +- f93e56ae3a: Add tooltip to display shortcut title on hover. This should improve the readability of shortcuts with long names, which are cutoff by ellipsis. +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.13 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index e73e047bc1..8fad41f0a8 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-shortcuts", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", - "version": "0.1.13", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@backstage/types": "^0.1.1", "@material-ui/core": "^4.12.2", @@ -38,10 +38,10 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 8886ca3645..7de1ea6552 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-sonarqube +## 0.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.6 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index bb55e68954..07467ac1cf 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.2.6", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,10 +33,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index 4bd0b9e9bc..b6d77a50cc 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-splunk-on-call +## 0.3.15 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.14 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 9d9ffdb370..dfb1c58aca 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-splunk-on-call", "description": "A Backstage plugin that integrates towards Splunk On-Call", - "version": "0.3.14", + "version": "0.3.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,10 +31,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,10 +47,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index 8943b0e461..5504cb2d81 100644 --- a/plugins/tech-insights-backend-module-jsonfc/package.json +++ b/plugins/tech-insights-backend-module-jsonfc/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.0", + "@backstage/backend-common": "^0.9.10", "@backstage/config": "^0.1.8", "@backstage/errors": "^0.1.1", "@backstage/plugin-tech-insights-common": "^0.1.0", @@ -43,7 +43,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/node-cron": "^2.0.4" }, "files": [ diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md new file mode 100644 index 0000000000..abb8eaac6f --- /dev/null +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -0,0 +1,15 @@ +# @backstage/plugin-tech-insights-backend + +## 0.1.1 + +### Patch Changes + +- 5c00e45045: Add catalog fact retrievers + + Add fact retrievers which generate facts related to the completeness + of entity data in the catalog. + +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/backend-common@0.9.10 diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index 678bec25c4..5bc616db71 100644 --- a/plugins/tech-insights-backend/package.json +++ b/plugins/tech-insights-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend", - "version": "0.1.0", + "version": "0.1.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.0", - "@backstage/catalog-client": "^0.3.16", - "@backstage/catalog-model": "^0.9.0", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.8", "@backstage/errors": "^0.1.1", "@backstage/plugin-tech-insights-common": "^0.1.0", @@ -52,8 +52,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.8", - "@backstage/cli": "^0.8.0", + "@backstage/backend-test-utils": "^0.1.9", + "@backstage/cli": "^0.9.0", "@types/supertest": "^2.0.8", "@types/node-cron": "^3.0.0", "@types/semver": "^7.3.8", diff --git a/plugins/tech-insights-common/package.json b/plugins/tech-insights-common/package.json index 5e02c9e4b0..26d8922329 100644 --- a/plugins/tech-insights-common/package.json +++ b/plugins/tech-insights-common/package.json @@ -34,7 +34,7 @@ "luxon": "^2.0.2" }, "devDependencies": { - "@backstage/cli": "^0.8.0" + "@backstage/cli": "^0.9.0" }, "files": [ "dist" diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 4a7cf3589b..3c2ba5da08 100644 --- a/plugins/tech-insights-node/package.json +++ b/plugins/tech-insights-node/package.json @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.0", + "@backstage/backend-common": "^0.9.10", "@backstage/config": "^0.1.8", "@backstage/plugin-tech-insights-common": "^0.1.0 ", "@types/luxon": "^2.0.5", @@ -38,7 +38,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.0" + "@backstage/cli": "^0.9.0" }, "files": [ "dist" diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index 8e7b5875a9..cef7885007 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-tech-radar +## 0.4.12 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.4.11 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 839ad1b399..d07b75c401 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-tech-radar", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", - "version": "0.4.11", + "version": "0.4.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -45,10 +45,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 7331ea0147..ad7a8af85e 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-techdocs-backend +## 0.10.8 + +### Patch Changes + +- e21e3c6102: Bumping minimum requirements for `dockerode` and `testcontainers` +- 9e64a7ac1e: Allow amazon web services s3 buckets to pass an server side encryption configuration so they can publish to encrypted buckets +- Updated dependencies + - @backstage/catalog-client@0.5.2 + - @backstage/catalog-model@0.9.7 + - @backstage/backend-common@0.9.10 + - @backstage/techdocs-common@0.10.7 + ## 0.10.7 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 30be9c9063..332884c694 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "0.10.7", + "version": "0.10.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,14 +31,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.8", - "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.6", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", "@backstage/errors": "^0.1.4", "@backstage/integration": "^0.6.9", "@backstage/search-common": "^0.2.1", - "@backstage/techdocs-common": "^0.10.5", + "@backstage/techdocs-common": "^0.10.7", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", "dockerode": "^3.3.1", @@ -51,8 +51,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.8.1", - "@backstage/test-utils": "^0.1.20", + "@backstage/cli": "^0.9.0", + "@backstage/test-utils": "^0.1.22", "@types/dockerode": "^3.3.0", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index be100b9dea..6b8a8f0ff9 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-techdocs +## 0.12.6 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- c1858c4cf9: Fixed entity triplet case handling for certain locales. +- f7703981a9: Use a better checkbox rendering in a task list. +- e266687580: Updates reader component used to display techdocs documentation. A previous change made this component not usable out of a page which don't have entityRef in url parameters. Reader component EntityRef parameter is now used instead of url parameters. Techdocs documentation component can now be used in our custom pages. +- Updated dependencies + - @backstage/plugin-catalog@0.7.3 + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/plugin-search@0.4.18 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + - @backstage/integration-react@0.1.14 + ## 0.12.5 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 79841a0621..d1c337754a 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "0.12.5", + "version": "0.12.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,16 +32,16 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.6", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.11", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.4", "@backstage/integration": "^0.6.9", - "@backstage/integration-react": "^0.1.13", - "@backstage/plugin-catalog": "^0.7.2", - "@backstage/plugin-catalog-react": "^0.6.3", - "@backstage/plugin-search": "^0.4.17", + "@backstage/integration-react": "^0.1.14", + "@backstage/plugin-catalog": "^0.7.3", + "@backstage/plugin-catalog-react": "^0.6.4", + "@backstage/plugin-search": "^0.4.18", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -61,10 +61,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index c3f0e469aa..be1dc658f1 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -25,9 +25,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.7", - "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.5", + "@backstage/backend-common": "^0.9.10", + "@backstage/catalog-client": "^0.5.2", + "@backstage/catalog-model": "^0.9.7", "@backstage/config": "^0.1.10", "@backstage/errors": "^0.1.3", "@backstage/integration": "^0.6.7", @@ -40,7 +40,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.8.0", + "@backstage/cli": "^0.9.0", "@types/supertest": "^2.0.8", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index 99c33c425e..1a6a352e73 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-todo +## 0.1.15 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/catalog-model@0.9.7 + - @backstage/plugin-catalog-react@0.6.4 + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.1.14 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 5e32d84497..b11721695a 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.1.14", + "version": "0.1.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,11 +27,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.5", - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/catalog-model": "^0.9.7", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.3", - "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.4", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -41,10 +41,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index ae3bc1c72d..a309afb497 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-user-settings +## 0.3.11 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- 274a4fc633: Add Props Icon for Sidebar Item SidebarSearchField and Settings +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.3.10 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index dc63957cb9..6b7ef01538 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.3.10", + "version": "0.3.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -43,10 +43,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index a7d2d480b7..4ae5c49c32 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-xcmetrics +## 0.2.10 + +### Patch Changes + +- a125278b81: Refactor out the deprecated path and icon from RouteRefs +- Updated dependencies + - @backstage/core-components@0.7.4 + - @backstage/core-plugin-api@0.2.0 + ## 0.2.9 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index bbab66e455..c23a5487db 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-xcmetrics", "description": "A Backstage plugin that shows XCode build metrics for your components", - "version": "0.2.9", + "version": "0.2.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.7.3", - "@backstage/core-plugin-api": "^0.1.13", + "@backstage/core-components": "^0.7.4", + "@backstage/core-plugin-api": "^0.2.0", "@backstage/errors": "^0.1.3", "@backstage/theme": "^0.2.13", "@material-ui/core": "^4.12.2", @@ -36,10 +36,10 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.8.2", - "@backstage/core-app-api": "^0.1.20", - "@backstage/dev-utils": "^0.2.12", - "@backstage/test-utils": "^0.1.21", + "@backstage/cli": "^0.9.0", + "@backstage/core-app-api": "^0.1.21", + "@backstage/dev-utils": "^0.2.13", + "@backstage/test-utils": "^0.1.22", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/yarn.lock b/yarn.lock index 597ae5e487..9b934191d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2172,7 +2172,7 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" -"@backstage/catalog-client@^0.3.16", "@backstage/catalog-client@^0.3.18": +"@backstage/catalog-client@^0.3.18": version "0.3.19" resolved "https://registry.npmjs.org/@backstage/catalog-client/-/catalog-client-0.3.19.tgz#109b0fde1cc2d9a306635f3775fc8f6174172b14" integrity sha512-0ydcC/1ISNgR8SggOUnMNNHtsRwrKN5GX+AXgTVdZk4qpz1MqG1+fzrNld9V7KVvXdsbGDZAl/b5a7/FJEpCqg== @@ -2360,6 +2360,24 @@ remark-gfm "^1.0.0" zen-observable "^0.8.15" +"@backstage/core-plugin-api@^0.1.10", "@backstage/core-plugin-api@^0.1.3", "@backstage/core-plugin-api@^0.1.4", "@backstage/core-plugin-api@^0.1.6", "@backstage/core-plugin-api@^0.1.8": + version "0.1.13" + resolved "https://registry.npmjs.org/@backstage/core-plugin-api/-/core-plugin-api-0.1.13.tgz#583c0fe3440450c304f13dcc85eac3bd80f357d7" + integrity sha512-BWEqleTXR7m7nsCyt6cEnc+Gx/VT4vLdNr9fc1kXfzSAA7cUT4VKjlVmm5kdyih3BSQ4+0k7Pm/NIf0jfa7rlg== + dependencies: + "@backstage/config" "^0.1.11" + "@backstage/theme" "^0.2.13" + "@backstage/types" "^0.1.1" + "@backstage/version-bridge" "^0.1.0" + "@material-ui/core" "^4.12.2" + "@types/react" "*" + history "^5.0.0" + prop-types "^15.7.2" + react "^16.12.0" + react-router-dom "6.0.0-beta.0" + react-use "^17.2.4" + zen-observable "^0.8.15" + "@backstage/plugin-catalog-react@^0.4.0": version "0.4.6" resolved "https://registry.npmjs.org/@backstage/plugin-catalog-react/-/plugin-catalog-react-0.4.6.tgz#f33f3cd734f110d3c547f7eae4e25d14806ec796" From 587265a4891eccbbbc3346494e3209f41885d62c Mon Sep 17 00:00:00 2001 From: Gauthier Date: Thu, 18 Nov 2021 20:21:08 +0800 Subject: [PATCH 031/138] Update README.md Signed-off-by: Gauthier Roebroeck --- plugins/todo-backend/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/todo-backend/README.md b/plugins/todo-backend/README.md index fd3410e42e..5540ca598e 100644 --- a/plugins/todo-backend/README.md +++ b/plugins/todo-backend/README.md @@ -46,7 +46,7 @@ async function main() { // ... const todoEnv = useHotMemoize(module, () => createEnv('todo')); // ... - apiRouter.use('/todo', await kafka(todoEnv)); + apiRouter.use('/todo', await todo(todoEnv)); ``` ## Scanned Files From 6a2cc4cfa787eb3598c8b1da8e5beb87f4dfb182 Mon Sep 17 00:00:00 2001 From: Gauthier Date: Thu, 18 Nov 2021 20:22:38 +0800 Subject: [PATCH 032/138] Update README.md Signed-off-by: Gauthier Roebroeck --- plugins/todo/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/todo/README.md b/plugins/todo/README.md index 3e1c370d8a..ad0ad4fc1d 100644 --- a/plugins/todo/README.md +++ b/plugins/todo/README.md @@ -56,7 +56,7 @@ async function main() { // ... const todoEnv = useHotMemoize(module, () => createEnv('todo')); // ... - apiRouter.use('/todo', await kafka(todoEnv)); + apiRouter.use('/todo', await todo(todoEnv)); ``` 3. Add the plugin as a tab to your service entities: From 9f21236a294afa9755673599cc0cb9435a773676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 18 Nov 2021 14:19:28 +0100 Subject: [PATCH 033/138] Fixed a missing `await` when throwing server side errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/sharp-carrots-press.md | 6 ++++++ plugins/config-schema/src/api/StaticSchemaLoader.ts | 2 +- plugins/scaffolder/src/api.ts | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 .changeset/sharp-carrots-press.md diff --git a/.changeset/sharp-carrots-press.md b/.changeset/sharp-carrots-press.md new file mode 100644 index 0000000000..a7c31d6759 --- /dev/null +++ b/.changeset/sharp-carrots-press.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-config-schema': patch +'@backstage/plugin-scaffolder': patch +--- + +Fixed a missing `await` when throwing server side errors diff --git a/plugins/config-schema/src/api/StaticSchemaLoader.ts b/plugins/config-schema/src/api/StaticSchemaLoader.ts index 48a125f38e..71eae63376 100644 --- a/plugins/config-schema/src/api/StaticSchemaLoader.ts +++ b/plugins/config-schema/src/api/StaticSchemaLoader.ts @@ -49,7 +49,7 @@ export class StaticSchemaLoader implements ConfigSchemaApi { return undefined; } - throw ResponseError.fromResponse(res); + throw await ResponseError.fromResponse(res); } return await res.json(); diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index a16ab59053..34e16708ea 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -187,7 +187,7 @@ export class ScaffolderClient implements ScaffolderApi { }); if (!response.ok) { - throw ResponseError.fromResponse(response); + throw await ResponseError.fromResponse(response); } return await response.json(); @@ -302,7 +302,7 @@ export class ScaffolderClient implements ScaffolderApi { }); if (!response.ok) { - throw ResponseError.fromResponse(response); + throw await ResponseError.fromResponse(response); } return await response.json(); From 860254207c7e85dcbc62486f60f018c4dcb42fbe Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Thu, 18 Nov 2021 14:45:06 +0100 Subject: [PATCH 034/138] 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 035/138] 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 036/138] 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 037/138] 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 038/138] 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 039/138] 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 040/138] 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 041/138] 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 042/138] 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 043/138] 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 044/138] 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 045/138] 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 046/138] 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 047/138] 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 048/138] 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 049/138] 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 050/138] 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 051/138] 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 8866b62f3ddb2a9e1cd842feea7002b30b5276bb Mon Sep 17 00:00:00 2001 From: Nicolas Arnold Date: Thu, 18 Nov 2021 17:42:17 +0000 Subject: [PATCH 052/138] Fail when adding duplicate locations using the dry run flag This change here adds in logic to the DefaultLocationService that will prematurely terminate the dry run addition of locations if there is a duplicate entity in the unprocessed entities. Adding this logic here will avoid an infinite loop if a monorepo arch is used (for example if a target references itself). It will also enforce some best practices. I have also added tests. You can test this out using this catalog-info.yaml: https://github.com/RoadieHQ/monorepo-infinte-loop/blob/main/catalog-info.yaml Signed-off-by: Nicolas Arnold --- .changeset/thirty-fireants-occur.md | 5 ++ .../service/DefaultLocationService.test.ts | 51 +++++++++++++++++++ .../src/service/DefaultLocationService.ts | 50 +++++++++++------- 3 files changed, 88 insertions(+), 18 deletions(-) create mode 100644 .changeset/thirty-fireants-occur.md diff --git a/.changeset/thirty-fireants-occur.md b/.changeset/thirty-fireants-occur.md new file mode 100644 index 0000000000..dc9348ac6e --- /dev/null +++ b/.changeset/thirty-fireants-occur.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Detect a duplicate entities when adding locations through dry run diff --git a/plugins/catalog-backend/src/service/DefaultLocationService.test.ts b/plugins/catalog-backend/src/service/DefaultLocationService.test.ts index a089989d20..e2b82ad2c0 100644 --- a/plugins/catalog-backend/src/service/DefaultLocationService.test.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.test.ts @@ -148,6 +148,57 @@ describe('DefaultLocationServiceTest', () => { expect(result.exists).toBe(true); }); + it('should fail when there are duplicate entities using dry run', async () => { + store.listLocations.mockResolvedValueOnce([]); + orchestrator.process.mockResolvedValueOnce({ + ok: true, + state: {}, + completedEntity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Location', + metadata: { + name: 'foo', + }, + }, + deferredEntities: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Location', + metadata: { + name: 'foo', + }, + }, + locationKey: 'file:///tmp/mock.yaml', + }, + ], + relations: [], + errors: [], + }); + + orchestrator.process.mockResolvedValueOnce({ + ok: true, + state: {}, + completedEntity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Location', + metadata: { + name: 'foo', + }, + }, + deferredEntities: [], + relations: [], + errors: [], + }); + + await expect( + locationService.createLocation( + { type: 'url', target: 'https://backstage.io/catalog-info.yaml' }, + true, + ), + ).rejects.toThrowError('Duplicate nested entity: foo'); + }); + it('should return exists false when the location does not exist beforehand', async () => { orchestrator.process.mockResolvedValueOnce({ ok: true, diff --git a/plugins/catalog-backend/src/service/DefaultLocationService.ts b/plugins/catalog-backend/src/service/DefaultLocationService.ts index 2166341935..d339064d33 100644 --- a/plugins/catalog-backend/src/service/DefaultLocationService.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.ts @@ -54,6 +54,34 @@ export class DefaultLocationService implements LocationService { return this.store.deleteLocation(id); } + private async getUnprocessedEntities( + unprocessed: DeferredEntity[], + entities: Entity[], + ): Promise { + const currentEntity = unprocessed.pop(); + if (!currentEntity) { + return []; + } + const processed = await this.orchestrator.process({ + entity: currentEntity.entity, + state: {}, // we process without the existing cache + }); + + if (processed.ok) { + const { metadata, kind } = processed.completedEntity; + if ( + entities.some(e => e.metadata.name === metadata.name && e.kind === kind) + ) { + throw new Error(`Duplicate nested entity: ${metadata.name}`); + } + return await this.getUnprocessedEntities( + [...unprocessed, ...processed.deferredEntities], + [...entities, processed.completedEntity], + ); + } + throw Error(processed.errors.map(String).join(', ')); + } + private async dryRunCreateLocation( spec: LocationSpec, ): Promise<{ location: Location; entities: Entity[]; exists?: boolean }> { @@ -86,24 +114,10 @@ export class DefaultLocationService implements LocationService { const unprocessedEntities: DeferredEntity[] = [ { entity, locationKey: `${spec.type}:${spec.target}` }, ]; - const entities: Entity[] = []; - while (unprocessedEntities.length) { - const currentEntity = unprocessedEntities.pop(); - if (!currentEntity) { - continue; - } - const processed = await this.orchestrator.process({ - entity: currentEntity.entity, - state: {}, // we process without the existing cache - }); - - if (processed.ok) { - unprocessedEntities.push(...processed.deferredEntities); - entities.push(processed.completedEntity); - } else { - throw Error(processed.errors.map(String).join(', ')); - } - } + const entities: Entity[] = await this.getUnprocessedEntities( + unprocessedEntities, + [], + ); return { exists: await existsPromise, From 3c6141c37ab0af1cba9d7a803b0d058b33370f9d Mon Sep 17 00:00:00 2001 From: Nicolas Arnold Date: Fri, 19 Nov 2021 11:09:37 +0000 Subject: [PATCH 053/138] Fix return type Signed-off-by: Nicolas Arnold --- plugins/catalog-backend/src/service/DefaultLocationService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/service/DefaultLocationService.ts b/plugins/catalog-backend/src/service/DefaultLocationService.ts index d339064d33..0e5f2380f8 100644 --- a/plugins/catalog-backend/src/service/DefaultLocationService.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.ts @@ -60,7 +60,7 @@ export class DefaultLocationService implements LocationService { ): Promise { const currentEntity = unprocessed.pop(); if (!currentEntity) { - return []; + return entities; } const processed = await this.orchestrator.process({ entity: currentEntity.entity, From ab7f280cb491ce2dee52773e52d609978c2927ac Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Fri, 19 Nov 2021 07:31:10 -0600 Subject: [PATCH 054/138] 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 055/138] 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 142ae64a58c4461cc3bd1c985851c6d78643260e Mon Sep 17 00:00:00 2001 From: Chad Jensen Date: Fri, 19 Nov 2021 15:51:06 -0600 Subject: [PATCH 056/138] fixing prettier issue Signed-off-by: Chad Jensen --- .changeset/young-sheep-impress.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/young-sheep-impress.md b/.changeset/young-sheep-impress.md index ac185bbfb4..b69447d4d4 100644 --- a/.changeset/young-sheep-impress.md +++ b/.changeset/young-sheep-impress.md @@ -1,5 +1,5 @@ --- -"@backstage/plugin-graphiql": patch +'@backstage/plugin-graphiql': patch --- Letting GraphiQL use headers From 0f7665a10bc28e13d15fc77418338aaa1cb8cf54 Mon Sep 17 00:00:00 2001 From: Chad Jensen Date: Fri, 19 Nov 2021 22:13:16 -0600 Subject: [PATCH 057/138] fixing other prettier issue Signed-off-by: Chad Jensen --- .../src/components/GraphiQLBrowser/GraphiQLBrowser.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx index 3a75b9a6cc..84368dbd68 100644 --- a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx +++ b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx @@ -73,7 +73,12 @@ export const GraphiQLBrowser = ({ endpoints }: GraphiQLBrowserProps) => {
- +
From 0179bd1f139b9e7383a965b0adf53075ad0eaf7a Mon Sep 17 00:00:00 2001 From: goenning Date: Sat, 20 Nov 2021 09:37:57 +0000 Subject: [PATCH 058/138] draft implementation for AzureDevOps Discovery Signed-off-by: goenning --- .../AzureDevOpsDiscoveryProcessor.ts | 128 ++++++++++++++++++ .../src/ingestion/processors/index.ts | 1 + .../src/legacy/service/CatalogBuilder.ts | 2 + .../src/service/NextCatalogBuilder.ts | 2 + 4 files changed, 133 insertions(+) create mode 100644 plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts diff --git a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts new file mode 100644 index 0000000000..8300b503f3 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts @@ -0,0 +1,128 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { LocationSpec } from '@backstage/catalog-model'; +import fetch from 'cross-fetch'; +import { Config } from '@backstage/config'; +import { + getAzureRequestOptions, + ScmIntegrations, +} from '@backstage/integration'; +import { Logger } from 'winston'; +import * as results from './results'; +import { CatalogProcessor, CatalogProcessorEmit } from './types'; + +/** + * TODO + **/ +export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { + private readonly integrations: ScmIntegrations; + private readonly logger: Logger; + + static fromConfig(config: Config, options: { logger: Logger }) { + const integrations = ScmIntegrations.fromConfig(config); + + return new AzureDevOpsDiscoveryProcessor({ + ...options, + integrations, + }); + } + + constructor(options: { integrations: ScmIntegrations; logger: Logger }) { + this.integrations = options.integrations; + this.logger = options.logger; + } + + async readLocation( + location: LocationSpec, + _optional: boolean, + emit: CatalogProcessorEmit, + ): Promise { + if (location.type !== 'azure-discovery') { + return false; + } + + const azureConfig = this.integrations.azure.byUrl(location.target)?.config; + if (!azureConfig) { + throw new Error( + `There is no Azure integration that matches ${location.target}. Please add a configuration entry for it under integrations.azure`, + ); + } + + // TODO: extract this from configured URL + const { org, project } = { org: 'myOrg', project: 'myProject' }; + + // TODO: What's the search URL for self hosted DevOps? + const searchUrl = `https://almsearch.dev.azure.com/${org}/${project}/_apis/search/codesearchresults?api-version=6.0-preview.1`; + const opts = getAzureRequestOptions(azureConfig); + + const response = await fetch(searchUrl, { + method: 'POST', + headers: { + ...opts.headers, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + searchText: 'catalog-info.yaml', + $top: 1000, + }), + }); + + // TODO: more logging + if (response.status === 200) { + const responseBody: AzureDevOpsCodeSearchResults = await response.json(); + + // TODO: should we support different file names? + const matches = responseBody.results.filter( + r => r.fileName === 'catalog-info.yaml', + ); + + for (const match of matches) { + emit( + results.location( + { + type: 'url', + // TODO: Do we need to support non-default branches? + target: `${location.target}/_git/${match.repository.name}?path=${match.path}`, + }, + // Not all locations may actually exist, since the user defined them as a wildcard pattern. + // Thus, we emit them as optional and let the downstream processor find them while not outputting + // an error if it couldn't. + true, + ), + ); + } + } + + return true; + } +} + +interface AzureDevOpsCodeSearchResults { + count: number; + results: Array<{ + fileName: string; + path: string; + project: { + id: string; + name: string; + }; + repository: { + id: string; + name: string; + }; + }>; +} diff --git a/plugins/catalog-backend/src/ingestion/processors/index.ts b/plugins/catalog-backend/src/ingestion/processors/index.ts index 4f3c502a8e..63feac51af 100644 --- a/plugins/catalog-backend/src/ingestion/processors/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/index.ts @@ -26,6 +26,7 @@ export { BuiltinKindsEntityProcessor } from './BuiltinKindsEntityProcessor'; export { CodeOwnersProcessor } from './CodeOwnersProcessor'; export { FileReaderProcessor } from './FileReaderProcessor'; export { GithubDiscoveryProcessor } from './GithubDiscoveryProcessor'; +export { AzureDevOpsDiscoveryProcessor } from './AzureDevOpsDiscoveryProcessor'; export { GithubOrgReaderProcessor } from './GithubOrgReaderProcessor'; export { GithubMultiOrgReaderProcessor } from './GithubMultiOrgReaderProcessor'; export { GitLabDiscoveryProcessor } from './GitLabDiscoveryProcessor'; diff --git a/plugins/catalog-backend/src/legacy/service/CatalogBuilder.ts b/plugins/catalog-backend/src/legacy/service/CatalogBuilder.ts index b8e45c7cf3..6fb52e245e 100644 --- a/plugins/catalog-backend/src/legacy/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/legacy/service/CatalogBuilder.ts @@ -42,6 +42,7 @@ import { CodeOwnersProcessor, FileReaderProcessor, GithubDiscoveryProcessor, + AzureDevOpsDiscoveryProcessor, GithubOrgReaderProcessor, GitLabDiscoveryProcessor, LocationEntityProcessor, @@ -317,6 +318,7 @@ export class CatalogBuilder { new FileReaderProcessor(), BitbucketDiscoveryProcessor.fromConfig(config, { logger }), GithubDiscoveryProcessor.fromConfig(config, { logger }), + AzureDevOpsDiscoveryProcessor.fromConfig(config, { logger }), GithubOrgReaderProcessor.fromConfig(config, { logger }), GitLabDiscoveryProcessor.fromConfig(config, { logger }), new UrlReaderProcessor({ reader, logger }), diff --git a/plugins/catalog-backend/src/service/NextCatalogBuilder.ts b/plugins/catalog-backend/src/service/NextCatalogBuilder.ts index bbda6f070c..a694030701 100644 --- a/plugins/catalog-backend/src/service/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/NextCatalogBuilder.ts @@ -44,6 +44,7 @@ import { CatalogProcessorParser, CodeOwnersProcessor, FileReaderProcessor, + AzureDevOpsDiscoveryProcessor, GithubDiscoveryProcessor, GithubOrgReaderProcessor, GitLabDiscoveryProcessor, @@ -291,6 +292,7 @@ export class NextCatalogBuilder { return [ new FileReaderProcessor(), BitbucketDiscoveryProcessor.fromConfig(config, { logger }), + AzureDevOpsDiscoveryProcessor.fromConfig(config, { logger }), GithubDiscoveryProcessor.fromConfig(config, { logger }), GithubOrgReaderProcessor.fromConfig(config, { logger }), GitLabDiscoveryProcessor.fromConfig(config, { logger }), From 719cc87d2f2183a6595c60fe8d14b30a50e44188 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 20 Nov 2021 11:24:08 +0100 Subject: [PATCH 059/138] 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 060/138] 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 061/138] 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 062/138] 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 063/138] 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 064/138] 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 51e42bc2c81846765b11ca9288259225a0b4346e Mon Sep 17 00:00:00 2001 From: goenning Date: Sat, 20 Nov 2021 21:20:47 +0000 Subject: [PATCH 065/138] add support for search queries Signed-off-by: goenning --- docs/integrations/azure/discovery.md | 49 ++++++ .../AzureDevOpsDiscoveryProcessor.test.ts | 63 +++++++ .../AzureDevOpsDiscoveryProcessor.ts | 160 +++++++++++++----- 3 files changed, 230 insertions(+), 42 deletions(-) create mode 100644 docs/integrations/azure/discovery.md create mode 100644 plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts diff --git a/docs/integrations/azure/discovery.md b/docs/integrations/azure/discovery.md new file mode 100644 index 0000000000..ad452f47af --- /dev/null +++ b/docs/integrations/azure/discovery.md @@ -0,0 +1,49 @@ +--- +id: discovery +title: Azure DevOps Discovery +sidebar_label: Discovery +# prettier-ignore +description: Automatically discovering catalog entities from repositories in an Azure DevOps organization +--- + +The Azure DevOps integration has a special discovery processor for discovering +catalog entities within an Azure DevOps. The processor will crawl the Azure +DevOps organization and register entities matching the configured path. This can +be useful as an alternative to static locations or manually adding things to the +catalog. + +To use the discovery processor, you'll need a GitHub integration +[set up](locations.md) with a `AZURE_TOKEN`. Then you can add a location target +to the catalog configuration: + +```yaml +catalog: + locations: + # Scan all repositories for a catalog-info.yaml in the root of the default branch + - type: azure-discovery + target: https://dev.azure.com/myorg/myproject + # Or use a custom pattern for a subset of all repositories with default repository + - type: azure-discovery + target: https://dev.azure.com/myorg/myproject/_git/service-* + # Or use a custom file format and location + - type: azure-discovery + target: https://dev.azure.com/myorg/myproject/_git/*?path=/src/*/catalog-info.yaml +``` + +Note the `azure-discovery` type, as this is not a regular `url` processor. + +When using a custom pattern, the target is composed of five parts: + +- The base instance URL, `https://dev.azure.com` in this case +- The organization name which is required, `myorg` in this case +- The project name which is required, `myproject` in this case +- The repository blob to scan, which accepts \* wildcard tokens and must be + added after `_git/`. This can simply be `*` to scan all repositories in the + project. +- The path within each repository to find the catalog YAML file. This will + usually be `/catalog-info.yaml`, `/src/*/catalog-info.yaml` or a similar + variation for catalog files stored in the root directory of each repository. + +_Note:_ the path parameter follows the same rules as the search on Azure DevOps +web interface. For more details visit the +[official search documentation](https://docs.microsoft.com/en-us/azure/devops/project/search/get-started-search?view=azure-devops) diff --git a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts new file mode 100644 index 0000000000..9d468acf15 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts @@ -0,0 +1,63 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { parseUrl } from './AzureDevOpsDiscoveryProcessor'; + +describe('AzureDevOpsDiscoveryProcessor', () => { + describe('parseUrl', () => { + it('parses well formed URLs', () => { + expect(parseUrl('https://dev.azure.com/my-org/my-proj')).toEqual({ + baseUrl: 'https://dev.azure.com', + org: 'my-org', + project: 'my-proj', + repo: '', + catalogPath: '/catalog-info.yaml', + }); + + expect( + parseUrl( + 'https://dev.azure.com/spotify/engineering/_git/backstage?path=/catalog.yaml', + ), + ).toEqual({ + baseUrl: 'https://dev.azure.com', + org: 'spotify', + project: 'engineering', + repo: 'backstage', + catalogPath: '/catalog.yaml', + }); + + expect( + parseUrl( + 'https://azuredevops.mycompany.com/spotify/engineering/_git/backstage?path=/src/*/catalog.yaml', + ), + ).toEqual({ + baseUrl: 'https://azuredevops.mycompany.com', + org: 'spotify', + project: 'engineering', + repo: 'backstage', + catalogPath: '/src/*/catalog.yaml', + }); + }); + + it('throws on incorrectly formed URLs', () => { + expect(() => parseUrl('https://dev.azure.com')).toThrow(); + expect(() => parseUrl('https://dev.azure.com//')).toThrow(); + expect(() => parseUrl('https://dev.azure.com//foo')).toThrow(); + }); + }); + + // TODO: add tests for AzureDevOpsDiscoveryProcessor +}); diff --git a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts index 8300b503f3..a938e230e7 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts @@ -18,6 +18,7 @@ import { LocationSpec } from '@backstage/catalog-model'; import fetch from 'cross-fetch'; import { Config } from '@backstage/config'; import { + AzureIntegrationConfig, getAzureRequestOptions, ScmIntegrations, } from '@backstage/integration'; @@ -26,7 +27,18 @@ import * as results from './results'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; /** - * TODO + * Extracts repositories out of an Azure DevOps org. + * + * The following will create locations for all projects which have a catalog-info.yaml + * on the default branch. The first is shorthand for the second. + * + * target: "https://dev.azure.com/org/project" + * or + * target: https://dev.azure.com/org/project?path=/catalog-info.yaml + * + * You may also explicitly specify a single repo: + * + * target: https://dev.azure.com/org/project/_git/repo **/ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { private readonly integrations: ScmIntegrations; @@ -62,13 +74,49 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { ); } - // TODO: extract this from configured URL - const { org, project } = { org: 'myOrg', project: 'myProject' }; + const { baseUrl, org, project, repo, catalogPath } = parseUrl( + location.target, + ); + this.logger.info( + `Reading Azure DevOps repositories from ${location.target}`, + ); - // TODO: What's the search URL for self hosted DevOps? + const files = await this.search( + azureConfig, + org, + project, + repo, + catalogPath, + ); + for (const file of files) { + emit( + results.location( + { + type: 'url', + target: `${baseUrl}/${org}/${project}/_git/${file.repository.name}?path=${file.path}`, + }, + // Not all locations may actually exist, since the user defined them as a wildcard pattern. + // Thus, we emit them as optional and let the downstream processor find them while not outputting + // an error if it couldn't. + true, + ), + ); + } + + return true; + } + + // search returns all files that matches the given search path. + async search( + azureConfig: AzureIntegrationConfig, + org: string, + project: string, + repo: string, + path: string, + ): Promise { + // TODO: What's the search URL for onpremises DevOps? const searchUrl = `https://almsearch.dev.azure.com/${org}/${project}/_apis/search/codesearchresults?api-version=6.0-preview.1`; const opts = getAzureRequestOptions(azureConfig); - const response = await fetch(searchUrl, { method: 'POST', headers: { @@ -76,53 +124,81 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { 'Content-Type': 'application/json', }, body: JSON.stringify({ - searchText: 'catalog-info.yaml', + searchText: `path:${path} repo:${repo || '*'}`, $top: 1000, }), }); - // TODO: more logging - if (response.status === 200) { - const responseBody: AzureDevOpsCodeSearchResults = await response.json(); - - // TODO: should we support different file names? - const matches = responseBody.results.filter( - r => r.fileName === 'catalog-info.yaml', + if (response.status !== 200) { + this.logger.warn( + `Azure DevOps search failed with response status ${response.status}`, ); - - for (const match of matches) { - emit( - results.location( - { - type: 'url', - // TODO: Do we need to support non-default branches? - target: `${location.target}/_git/${match.repository.name}?path=${match.path}`, - }, - // Not all locations may actually exist, since the user defined them as a wildcard pattern. - // Thus, we emit them as optional and let the downstream processor find them while not outputting - // an error if it couldn't. - true, - ), - ); - } + return []; } - return true; + const responseBody: CodeSearchResponse = await response.json(); + this.logger.info(`Azure DevOps search found ${responseBody.count} files`); + + return responseBody.results; } } -interface AzureDevOpsCodeSearchResults { - count: number; - results: Array<{ - fileName: string; - path: string; - project: { - id: string; - name: string; +/** + * parseUrl extracts segments from the Azure DevOps URL. + **/ +export function parseUrl(urlString: string): { + baseUrl: string; + org: string; + project: string; + repo: string; + catalogPath: string; +} { + const url = new URL(urlString); + const path = url.pathname.substr(1).split('/'); + + const catalogPath = url.searchParams.get('path') || '/catalog-info.yaml'; + + if (path.length === 2 && path[0].length && path[1].length) { + return { + baseUrl: url.origin, + org: decodeURIComponent(path[0]), + project: decodeURIComponent(path[1]), + repo: '', + catalogPath, }; - repository: { - id: string; - name: string; + } else if ( + path.length === 4 && + path[0].length && + path[1].length && + path[2].length && + path[3].length + ) { + return { + baseUrl: url.origin, + org: decodeURIComponent(path[0]), + project: decodeURIComponent(path[1]), + repo: decodeURIComponent(path[3]), + catalogPath, }; - }>; + } + + throw new Error(`Failed to parse ${urlString}`); +} + +interface CodeSearchResponse { + count: number; + results: CodeSearchResultItem[]; +} + +interface CodeSearchResultItem { + fileName: string; + path: string; + project: { + id: string; + name: string; + }; + repository: { + id: string; + name: string; + }; } From 05ccc8276c4db381bd0390b646fc4213863ea73f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 21 Nov 2021 13:53:33 +0100 Subject: [PATCH 066/138] 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 067/138] 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 5919df85d15832fbba75122f5fa624a13399c9ec Mon Sep 17 00:00:00 2001 From: Colton Padden Date: Sun, 21 Nov 2021 09:39:02 -0500 Subject: [PATCH 068/138] Add .snyk ignore file for @techdocs/cli Ignores with 6-month duration for vulnerabilities that have also been ignored for @backstage/cli: - SNYK-JS-BROWSERSLIST-1090194 - SNYK-JS-IMMER-1540542 Signed-off-by: Colton Padden --- packages/techdocs-cli/.snyk | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 packages/techdocs-cli/.snyk diff --git a/packages/techdocs-cli/.snyk b/packages/techdocs-cli/.snyk new file mode 100644 index 0000000000..cfb30e5aa7 --- /dev/null +++ b/packages/techdocs-cli/.snyk @@ -0,0 +1,17 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.22.1 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-BROWSERSLIST-1090194: + - '*': + reason: Developer tools are not a valid target for ReDoS attacks + expires: 2022-05-20T00:00:00.000Z + created: 2021-11-20T00:00:00.000Z + + SNYK-JS-IMMER-1540542: + - '*': + reason: Prototype pollution is not an effective attack against a CLI as it already executes arbitrary code + expires: 2022-05-20T00:00:00.000Z + created: 2021-11-20T00:00:00.000Z + +patch: {} From ac724ea8aee28c2deec0099fa46347853113be5a Mon Sep 17 00:00:00 2001 From: goenning Date: Sun, 21 Nov 2021 14:45:41 +0000 Subject: [PATCH 069/138] adding tests Signed-off-by: goenning --- .../AzureDevOpsDiscoveryProcessor.test.ts | 218 +++++++++++++++++- .../AzureDevOpsDiscoveryProcessor.ts | 67 +----- .../ingestion/processors/azure/azure.test.ts | 140 +++++++++++ .../src/ingestion/processors/azure/azure.ts | 67 ++++++ .../src/ingestion/processors/azure/index.ts | 17 ++ 5 files changed, 446 insertions(+), 63 deletions(-) create mode 100644 plugins/catalog-backend/src/ingestion/processors/azure/azure.test.ts create mode 100644 plugins/catalog-backend/src/ingestion/processors/azure/azure.ts create mode 100644 plugins/catalog-backend/src/ingestion/processors/azure/index.ts diff --git a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts index 9d468acf15..ab053e8748 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts @@ -14,7 +14,17 @@ * limitations under the License. */ -import { parseUrl } from './AzureDevOpsDiscoveryProcessor'; +import { getVoidLogger } from '@backstage/backend-common'; +import { LocationSpec } from '@backstage/catalog-model'; +import { ConfigReader } from '@backstage/config'; +import { codeSearch } from './azure'; +import { + AzureDevOpsDiscoveryProcessor, + parseUrl, +} from './AzureDevOpsDiscoveryProcessor'; + +jest.mock('./azure'); +const mockCodeSearch = codeSearch as jest.MockedFunction; describe('AzureDevOpsDiscoveryProcessor', () => { describe('parseUrl', () => { @@ -59,5 +69,209 @@ describe('AzureDevOpsDiscoveryProcessor', () => { }); }); - // TODO: add tests for AzureDevOpsDiscoveryProcessor + describe('reject unrelated entries', () => { + it('rejects unknown types', async () => { + const processor = AzureDevOpsDiscoveryProcessor.fromConfig( + new ConfigReader({ + integrations: { + azure: [{ host: 'dev.azure.com', token: 'blob' }], + }, + }), + { logger: getVoidLogger() }, + ); + const location: LocationSpec = { + type: 'not-azure-discovery', + target: 'https://dev.azure.com', + }; + await expect( + processor.readLocation(location, false, () => {}), + ).resolves.toBeFalsy(); + }); + }); + + it('rejects unknown targets', async () => { + const processor = AzureDevOpsDiscoveryProcessor.fromConfig( + new ConfigReader({ + integrations: { + github: [ + { host: 'dev.azure.com', token: 'blob' }, + { host: 'azure.myorg.com', token: 'blob' }, + ], + }, + }), + { logger: getVoidLogger() }, + ); + const location: LocationSpec = { + type: 'azure-discovery', + target: 'https://not.azure.com/org/project', + }; + await expect( + processor.readLocation(location, false, () => {}), + ).rejects.toThrow( + /There is no Azure integration that matches https:\/\/not.azure.com\/org\/project. Please add a configuration entry for it under integrations.azure/, + ); + }); + + describe('handles repositories', () => { + const processor = AzureDevOpsDiscoveryProcessor.fromConfig( + new ConfigReader({ + integrations: { + github: [{ host: 'dev.azure.com', token: 'blob' }], + }, + }), + { logger: getVoidLogger() }, + ); + + beforeEach(() => { + mockCodeSearch.mockClear(); + }); + + it('output all locations found on from code search', async () => { + const location: LocationSpec = { + type: 'azure-discovery', + target: 'https://dev.azure.com/shopify/engineering', + }; + mockCodeSearch.mockResolvedValueOnce([ + { + fileName: 'catalog-info.yaml', + path: '/catalog-info.yaml', + repository: { + name: 'backstage', + }, + }, + { + fileName: 'catalog-info.yaml', + path: '/src/catalog-info.yaml', + repository: { + name: 'ios-app', + }, + }, + ]); + const emitter = jest.fn(); + + await processor.readLocation(location, false, emitter); + + expect(mockCodeSearch).toHaveBeenCalledWith( + { host: 'dev.azure.com' }, + 'shopify', + 'engineering', + '', + '/catalog-info.yaml', + ); + expect(emitter).toHaveBeenCalledTimes(2); + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'url', + target: + 'https://dev.azure.com/shopify/engineering/_git/backstage?path=/catalog-info.yaml', + }, + optional: true, + }); + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'url', + target: + 'https://dev.azure.com/shopify/engineering/_git/ios-app?path=/src/catalog-info.yaml', + }, + optional: true, + }); + }); + + it('output single locations from code search', async () => { + const location: LocationSpec = { + type: 'azure-discovery', + target: 'https://dev.azure.com/shopify/engineering/_git/backstage', + }; + mockCodeSearch.mockResolvedValueOnce([ + { + fileName: 'catalog-info.yaml', + path: '/catalog-info.yaml', + repository: { + name: 'backstage', + }, + }, + ]); + const emitter = jest.fn(); + + await processor.readLocation(location, false, emitter); + + expect(mockCodeSearch).toHaveBeenCalledWith( + { host: 'dev.azure.com' }, + 'shopify', + 'engineering', + 'backstage', + '/catalog-info.yaml', + ); + expect(emitter).toHaveBeenCalledTimes(1); + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'url', + target: + 'https://dev.azure.com/shopify/engineering/_git/backstage?path=/catalog-info.yaml', + }, + optional: true, + }); + }); + + it('output single locations with different file name from code search', async () => { + const location: LocationSpec = { + type: 'azure-discovery', + target: + 'https://dev.azure.com/shopify/engineering?path=/src/*/catalog.yaml', + }; + mockCodeSearch.mockResolvedValueOnce([ + { + fileName: 'catalog.yaml', + path: '/src/main/catalog.yaml', + repository: { + name: 'backstage', + }, + }, + ]); + const emitter = jest.fn(); + + await processor.readLocation(location, false, emitter); + + expect(mockCodeSearch).toHaveBeenCalledWith( + { host: 'dev.azure.com' }, + 'shopify', + 'engineering', + '', + '/src/*/catalog.yaml', + ); + expect(emitter).toHaveBeenCalledTimes(1); + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'url', + target: + 'https://dev.azure.com/shopify/engineering/_git/backstage?path=/src/main/catalog.yaml', + }, + optional: true, + }); + }); + + it('output nothing when code search does not find anything', async () => { + const location: LocationSpec = { + type: 'azure-discovery', + target: 'https://dev.azure.com/shopify/engineering/_git/backstage', + }; + mockCodeSearch.mockResolvedValueOnce([]); + const emitter = jest.fn(); + + await processor.readLocation(location, false, emitter); + + expect(mockCodeSearch).toHaveBeenCalledWith( + { host: 'dev.azure.com' }, + 'shopify', + 'engineering', + 'backstage', + '/catalog-info.yaml', + ); + expect(emitter).not.toHaveBeenCalled(); + }); + }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts index a938e230e7..b86e3f9c82 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts @@ -15,16 +15,12 @@ */ import { LocationSpec } from '@backstage/catalog-model'; -import fetch from 'cross-fetch'; import { Config } from '@backstage/config'; -import { - AzureIntegrationConfig, - getAzureRequestOptions, - ScmIntegrations, -} from '@backstage/integration'; +import { ScmIntegrations } from '@backstage/integration'; import { Logger } from 'winston'; import * as results from './results'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; +import { codeSearch } from './azure'; /** * Extracts repositories out of an Azure DevOps org. @@ -81,13 +77,16 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { `Reading Azure DevOps repositories from ${location.target}`, ); - const files = await this.search( + const files = await codeSearch( azureConfig, org, project, repo, catalogPath, ); + + this.logger.info(`Found ${files.length} files in Azure DevOps.`); + for (const file of files) { emit( results.location( @@ -105,42 +104,6 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { return true; } - - // search returns all files that matches the given search path. - async search( - azureConfig: AzureIntegrationConfig, - org: string, - project: string, - repo: string, - path: string, - ): Promise { - // TODO: What's the search URL for onpremises DevOps? - const searchUrl = `https://almsearch.dev.azure.com/${org}/${project}/_apis/search/codesearchresults?api-version=6.0-preview.1`; - const opts = getAzureRequestOptions(azureConfig); - const response = await fetch(searchUrl, { - method: 'POST', - headers: { - ...opts.headers, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - searchText: `path:${path} repo:${repo || '*'}`, - $top: 1000, - }), - }); - - if (response.status !== 200) { - this.logger.warn( - `Azure DevOps search failed with response status ${response.status}`, - ); - return []; - } - - const responseBody: CodeSearchResponse = await response.json(); - this.logger.info(`Azure DevOps search found ${responseBody.count} files`); - - return responseBody.results; - } } /** @@ -184,21 +147,3 @@ export function parseUrl(urlString: string): { throw new Error(`Failed to parse ${urlString}`); } - -interface CodeSearchResponse { - count: number; - results: CodeSearchResultItem[]; -} - -interface CodeSearchResultItem { - fileName: string; - path: string; - project: { - id: string; - name: string; - }; - repository: { - id: string; - name: string; - }; -} diff --git a/plugins/catalog-backend/src/ingestion/processors/azure/azure.test.ts b/plugins/catalog-backend/src/ingestion/processors/azure/azure.test.ts new file mode 100644 index 0000000000..d9dfe5d1f4 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/azure/azure.test.ts @@ -0,0 +1,140 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { setupServer } from 'msw/node'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; +import { rest } from 'msw'; +import { codeSearch, CodeSearchResponse } from './azure'; + +describe('azure', () => { + const server = setupServer(); + setupRequestMockHandlers(server); + + describe('codeSearch', () => { + it('returns empty when nothing is found', async () => { + const response: CodeSearchResponse = { count: 0, results: [] }; + + server.use( + rest.post( + `https://almsearch.dev.azure.com/shopify/engineering/_apis/search/codesearchresults`, + (req, res, ctx) => { + expect(req.headers.get('Authorization')).toBe('Basic OkFCQw=='); + expect(req.body).toEqual({ + searchText: 'path:/catalog-info.yaml repo:*', + $top: 1000, + }); + return res(ctx.json(response)); + }, + ), + ); + + await expect( + codeSearch( + { host: 'dev.azure.com', token: 'ABC' }, + 'shopify', + 'engineering', + '', + '/catalog-info.yaml', + ), + ).resolves.toEqual([]); + }); + }); + + it('returns entries when request matches some files', async () => { + const response: CodeSearchResponse = { + count: 2, + results: [ + { + fileName: 'catalog-info.yaml', + path: '/catalog-info.yaml', + repository: { + name: 'backstage', + }, + }, + { + fileName: 'catalog-info.yaml', + path: '/catalog-info.yaml', + repository: { + name: 'ios-app', + }, + }, + ], + }; + + server.use( + rest.post( + `https://almsearch.dev.azure.com/shopify/engineering/_apis/search/codesearchresults`, + (req, res, ctx) => { + expect(req.headers.get('Authorization')).toBe('Basic OkFCQw=='); + expect(req.body).toEqual({ + searchText: 'path:/catalog-info.yaml repo:*', + $top: 1000, + }); + return res(ctx.json(response)); + }, + ), + ); + + await expect( + codeSearch( + { host: 'dev.azure.com', token: 'ABC' }, + 'shopify', + 'engineering', + '', + '/catalog-info.yaml', + ), + ).resolves.toEqual(response.results); + }); + + it('searches in specific repo if parameter is set', async () => { + const response: CodeSearchResponse = { + count: 1, + results: [ + { + fileName: 'catalog-info.yaml', + path: '/catalog-info.yaml', + repository: { + name: 'backstage', + }, + }, + ], + }; + + server.use( + rest.post( + `https://almsearch.dev.azure.com/shopify/engineering/_apis/search/codesearchresults`, + (req, res, ctx) => { + expect(req.headers.get('Authorization')).toBe('Basic OkFCQw=='); + expect(req.body).toEqual({ + searchText: 'path:/catalog-info.yaml repo:backstage', + $top: 1000, + }); + return res(ctx.json(response)); + }, + ), + ); + + await expect( + codeSearch( + { host: 'dev.azure.com', token: 'ABC' }, + 'shopify', + 'engineering', + 'backstage', + '/catalog-info.yaml', + ), + ).resolves.toEqual(response.results); + }); +}); diff --git a/plugins/catalog-backend/src/ingestion/processors/azure/azure.ts b/plugins/catalog-backend/src/ingestion/processors/azure/azure.ts new file mode 100644 index 0000000000..ec1b9ba0fb --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/azure/azure.ts @@ -0,0 +1,67 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import fetch from 'cross-fetch'; +import { + AzureIntegrationConfig, + getAzureRequestOptions, +} from '@backstage/integration'; + +export interface CodeSearchResponse { + count: number; + results: CodeSearchResultItem[]; +} + +export interface CodeSearchResultItem { + fileName: string; + path: string; + repository: { + name: string; + }; +} + +// codeSearch returns all files that matches the given search path. +export async function codeSearch( + azureConfig: AzureIntegrationConfig, + org: string, + project: string, + repo: string, + path: string, +): Promise { + // TODO: What's the search URL for onpremises DevOps? + const searchUrl = `https://almsearch.dev.azure.com/${org}/${project}/_apis/search/codesearchresults?api-version=6.0-preview.1`; + const opts = getAzureRequestOptions(azureConfig); + const response = await fetch(searchUrl, { + method: 'POST', + headers: { + ...opts.headers, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + searchText: `path:${path} repo:${repo || '*'}`, + $top: 1000, + }), + }); + + if (response.status !== 200) { + throw new Error( + `Azure DevOps search failed with response status ${response.status}`, + ); + } + + const responseBody: CodeSearchResponse = await response.json(); + return responseBody.results; +} diff --git a/plugins/catalog-backend/src/ingestion/processors/azure/index.ts b/plugins/catalog-backend/src/ingestion/processors/azure/index.ts new file mode 100644 index 0000000000..d4ff56c4c0 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/azure/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './azure'; From 563b039f0b6ea67ef7adc04912ef728af8117fd9 Mon Sep 17 00:00:00 2001 From: goenning Date: Sun, 21 Nov 2021 14:51:33 +0000 Subject: [PATCH 070/138] add api-report and changeset Signed-off-by: goenning --- .changeset/strong-seahorses-scream.md | 5 +++++ plugins/catalog-backend/api-report.md | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 .changeset/strong-seahorses-scream.md diff --git a/.changeset/strong-seahorses-scream.md b/.changeset/strong-seahorses-scream.md new file mode 100644 index 0000000000..445ed65c81 --- /dev/null +++ b/.changeset/strong-seahorses-scream.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Added Azure DevOps discovery processor diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 6660912dda..ece074fe94 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -174,6 +174,26 @@ export class AwsS3DiscoveryProcessor implements CatalogProcessor { ): Promise; } +// Warning: (ae-missing-release-tag) "AzureDevOpsDiscoveryProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { + constructor(options: { integrations: ScmIntegrations; logger: Logger_2 }); + // (undocumented) + static fromConfig( + config: Config, + options: { + logger: Logger_2; + }, + ): AzureDevOpsDiscoveryProcessor; + // (undocumented) + readLocation( + location: LocationSpec, + _optional: boolean, + emit: CatalogProcessorEmit, + ): Promise; +} + // Warning: (ae-missing-release-tag) "BitbucketDiscoveryProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) 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 071/138] 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 072/138] 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 073/138] 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 3739d3f7735ed5ecb5aaf7a0a343a58f0e27cd66 Mon Sep 17 00:00:00 2001 From: Morgan Martinet Date: Mon, 22 Nov 2021 00:05:55 -0500 Subject: [PATCH 074/138] implement openshiftFormatter Signed-off-by: Morgan Martinet --- .changeset/green-bags-hug.md | 5 + .github/styles/vocab.txt | 1 + .../clusterLinks/formatters/openshift.test.ts | 113 ++++++++++++++++-- .../clusterLinks/formatters/openshift.ts | 32 ++++- 4 files changed, 132 insertions(+), 19 deletions(-) create mode 100644 .changeset/green-bags-hug.md diff --git a/.changeset/green-bags-hug.md b/.changeset/green-bags-hug.md new file mode 100644 index 0000000000..16409401ab --- /dev/null +++ b/.changeset/green-bags-hug.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes': minor +--- + +Implement support for formatting Openshift dashboard url links diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index d65e31b4c4..217342b448 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -189,6 +189,7 @@ oidc Okta onboarding Onboarding +Openshift orgs pagerduty pageview diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts b/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts index df2529a8ac..b6cd60b85c 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts @@ -15,21 +15,108 @@ */ import { openshiftFormatter } from './openshift'; -describe('clusterLinks - OpenShift formatter', () => { +function formatUrl(url: URL) { + return url.toString(); +} + +describe('clusterLinks - Openshift formatter', () => { it('should return an url on the workloads when there is a namespace only', () => { - expect(() => - openshiftFormatter({ - dashboardUrl: new URL('https://k8s.foo.com'), - object: { - metadata: { - name: 'foobar', - namespace: 'bar', - }, + const url = openshiftFormatter({ + dashboardUrl: new URL('https://k8s.foo.com'), + object: { + metadata: { + namespace: 'bar', }, - kind: 'Deployment', - }), - ).toThrowError( - 'OpenShift formatter is not yet implemented. Please, contribute!', + }, + kind: 'foo', + }); + expect(formatUrl(url)).toBe('https://k8s.foo.com/k8s/cluster/projects/bar'); + }); + it('should return an url on the workloads when the kind is not recognizeed', () => { + const url = openshiftFormatter({ + dashboardUrl: new URL('https://k8s.foo.com'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'UnknownKind', + }); + expect(formatUrl(url)).toBe('https://k8s.foo.com/k8s/cluster/projects/bar'); + }); + it('should return an url on the deployment', () => { + const url = openshiftFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Deployment', + }); + expect(formatUrl(url)).toBe( + 'https://k8s.foo.com/k8s/ns/bar/deployments/foobar', + ); + }); + it('should return an url on the service', () => { + const url = openshiftFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Service', + }); + expect(formatUrl(url)).toBe( + 'https://k8s.foo.com/k8s/ns/bar/services/foobar', + ); + }); + it('should return an url on the ingress', () => { + const url = openshiftFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Ingress', + }); + expect(formatUrl(url)).toBe( + 'https://k8s.foo.com/k8s/ns/bar/ingresses/foobar', + ); + }); + it('should return an url on the deployment for a hpa', () => { + const url = openshiftFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'HorizontalPodAutoscaler', + }); + expect(formatUrl(url)).toBe( + 'https://k8s.foo.com/k8s/ns/bar/horizontalpodautoscalers/foobar', + ); + }); + it('should return an url on the PV', () => { + const url = openshiftFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/'), + object: { + metadata: { + name: 'foobar', + }, + }, + kind: 'PersistentVolume', + }); + expect(formatUrl(url)).toBe( + 'https://k8s.foo.com/k8s/cluster/persistentvolumes/foobar', ); }); }); diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts b/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts index bacb747ebb..4300212a03 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts @@ -15,10 +15,30 @@ */ import { ClusterLinksFormatterOptions } from '../../../types/types'; -export function openshiftFormatter( - _options: ClusterLinksFormatterOptions, -): URL { - throw new Error( - 'OpenShift formatter is not yet implemented. Please, contribute!', - ); +const kindMappings: Record = { + deployment: 'deployments', + ingress: 'ingresses', + service: 'services', + horizontalpodautoscaler: 'horizontalpodautoscalers', + persistentvolume: 'persistentvolumes', +}; + +export function openshiftFormatter(options: ClusterLinksFormatterOptions): URL { + const result = new URL(options.dashboardUrl.href); + const name = options.object.metadata?.name; + const namespace = options.object.metadata?.namespace; + const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; + if (namespace) { + if (name && validKind) { + result.pathname = `k8s/ns/${namespace}/${validKind}/${name}`; + } else { + result.pathname = `k8s/cluster/projects/${namespace}`; + } + } else if (validKind) { + result.pathname = `k8s/cluster/${validKind}`; + if (name) { + result.pathname += `/${name}`; + } + } + return result; } From f9c0ad85d9741cb90b57d668577bb93a69a7f171 Mon Sep 17 00:00:00 2001 From: Nicolas Arnold Date: Mon, 22 Nov 2021 09:12:38 +0000 Subject: [PATCH 075/138] Addressing comments Signed-off-by: Nicolas Arnold --- .../src/service/DefaultLocationService.ts | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultLocationService.ts b/plugins/catalog-backend/src/service/DefaultLocationService.ts index 0e5f2380f8..d28112eda3 100644 --- a/plugins/catalog-backend/src/service/DefaultLocationService.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.ts @@ -54,32 +54,36 @@ export class DefaultLocationService implements LocationService { return this.store.deleteLocation(id); } - private async getUnprocessedEntities( - unprocessed: DeferredEntity[], - entities: Entity[], + private async processEntities( + unprocessedEntities: DeferredEntity[], ): Promise { - const currentEntity = unprocessed.pop(); - if (!currentEntity) { - return entities; - } - const processed = await this.orchestrator.process({ - entity: currentEntity.entity, - state: {}, // we process without the existing cache - }); - - if (processed.ok) { - const { metadata, kind } = processed.completedEntity; - if ( - entities.some(e => e.metadata.name === metadata.name && e.kind === kind) - ) { - throw new Error(`Duplicate nested entity: ${metadata.name}`); + const entities: Entity[] = []; + while (unprocessedEntities.length) { + const currentEntity = unprocessedEntities.pop(); + if (!currentEntity) { + continue; + } + const processed = await this.orchestrator.process({ + entity: currentEntity.entity, + state: {}, // we process without the existing cache + }); + + if (processed.ok) { + const { metadata, kind } = processed.completedEntity; + if ( + entities.some( + e => e.metadata.name === metadata.name && e.kind === kind, + ) + ) { + throw new Error(`Duplicate nested entity: ${metadata.name}`); + } + unprocessedEntities.push(...processed.deferredEntities); + entities.push(processed.completedEntity); + } else { + throw Error(processed.errors.map(String).join(', ')); } - return await this.getUnprocessedEntities( - [...unprocessed, ...processed.deferredEntities], - [...entities, processed.completedEntity], - ); } - throw Error(processed.errors.map(String).join(', ')); + return entities; } private async dryRunCreateLocation( @@ -114,10 +118,7 @@ export class DefaultLocationService implements LocationService { const unprocessedEntities: DeferredEntity[] = [ { entity, locationKey: `${spec.type}:${spec.target}` }, ]; - const entities: Entity[] = await this.getUnprocessedEntities( - unprocessedEntities, - [], - ); + const entities: Entity[] = await this.processEntities(unprocessedEntities); return { exists: await existsPromise, From 73438d1ff10b751701e948d5be01b800916cd7fc Mon Sep 17 00:00:00 2001 From: Ainhoa Larumbe Date: Mon, 22 Nov 2021 09:41:00 +0000 Subject: [PATCH 076/138] 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 077/138] 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 078/138] 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 079/138] 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 080/138] 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 081/138] 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 082/138] 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 083/138] 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 90ad18e1a7da230bb673f7df056a482a62134d68 Mon Sep 17 00:00:00 2001 From: Morgan Martinet Date: Mon, 22 Nov 2021 09:06:20 -0500 Subject: [PATCH 084/138] switch to patch release Signed-off-by: Morgan Martinet --- .changeset/green-bags-hug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/green-bags-hug.md b/.changeset/green-bags-hug.md index 16409401ab..fb6240321c 100644 --- a/.changeset/green-bags-hug.md +++ b/.changeset/green-bags-hug.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-kubernetes': minor +'@backstage/plugin-kubernetes': patch --- Implement support for formatting Openshift dashboard url links From 7b4db0d1aa2d6e7d102a85c5c956241e33add840 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 22 Nov 2021 09:17:19 -0500 Subject: [PATCH 085/138] 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 --- From c844898a73fae11dffef7a311495ae4f3962e22c Mon Sep 17 00:00:00 2001 From: Chad Jensen Date: Mon, 22 Nov 2021 08:22:36 -0600 Subject: [PATCH 086/138] fixing another prettier issue Signed-off-by: Chad Jensen --- .../graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx index 84368dbd68..2bd173f720 100644 --- a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx +++ b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx @@ -74,7 +74,7 @@ export const GraphiQLBrowser = ({ endpoints }: GraphiQLBrowserProps) => {
Date: Wed, 10 Nov 2021 16:00:21 -0700 Subject: [PATCH 087/138] Add permission-node package Signed-off-by: Tim Hansen Co-authored-by: Mike Lewis Co-authored-by: Himanshu Mishra Co-authored-by: Joe Porpeglia Co-authored-by: Vincenzo Scamporlino --- plugins/permission-node/.eslintrc.js | 3 + plugins/permission-node/README.md | 7 + plugins/permission-node/api-report.md | 126 +++++++++++ plugins/permission-node/package.json | 33 +++ plugins/permission-node/src/index.ts | 25 +++ .../src/integration/conditionFor.ts | 24 +++ .../createPermissionIntegration.ts | 203 ++++++++++++++++++ .../permission-node/src/integration/index.ts | 18 ++ plugins/permission-node/src/policy/index.ts | 21 ++ plugins/permission-node/src/policy/types.ts | 81 +++++++ plugins/permission-node/src/setupTests.ts | 17 ++ plugins/permission-node/src/types.ts | 49 +++++ 12 files changed, 607 insertions(+) create mode 100644 plugins/permission-node/.eslintrc.js create mode 100644 plugins/permission-node/README.md create mode 100644 plugins/permission-node/api-report.md create mode 100644 plugins/permission-node/package.json create mode 100644 plugins/permission-node/src/index.ts create mode 100644 plugins/permission-node/src/integration/conditionFor.ts create mode 100644 plugins/permission-node/src/integration/createPermissionIntegration.ts create mode 100644 plugins/permission-node/src/integration/index.ts create mode 100644 plugins/permission-node/src/policy/index.ts create mode 100644 plugins/permission-node/src/policy/types.ts create mode 100644 plugins/permission-node/src/setupTests.ts create mode 100644 plugins/permission-node/src/types.ts diff --git a/plugins/permission-node/.eslintrc.js b/plugins/permission-node/.eslintrc.js new file mode 100644 index 0000000000..16a033dbc6 --- /dev/null +++ b/plugins/permission-node/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint.backend')], +}; diff --git a/plugins/permission-node/README.md b/plugins/permission-node/README.md new file mode 100644 index 0000000000..82dfe54f9c --- /dev/null +++ b/plugins/permission-node/README.md @@ -0,0 +1,7 @@ +# @backstage/plugin-permission-node + +> NOTE: THIS PACKAGE IS EXPERIMENTAL, HERE BE DRAGONS + +Common permission and authorization utilities for backend plugins. For more +information, see the [authorization +PRFC](https://github.com/backstage/backstage/pull/7761). diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md new file mode 100644 index 0000000000..1285207e61 --- /dev/null +++ b/plugins/permission-node/api-report.md @@ -0,0 +1,126 @@ +## API Report File for "@backstage/plugin-permission-node" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { AuthorizeResult } from '@backstage/permission-common'; +import { BackstageIdentity } from '@backstage/plugin-auth-backend'; +import { DefinitiveAuthorizeResult } from '@backstage/permission-common'; +import { OpaqueAuthorizeRequest } from '@backstage/permission-common'; +import { PermissionCondition } from '@backstage/permission-common'; +import { PermissionCriteria } from '@backstage/permission-common'; +import { Router } from 'express'; + +// Warning: (ae-missing-release-tag) "AllowAllPermissionPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class AllowAllPermissionPolicy implements PermissionPolicy { + // (undocumented) + handle( + _request: OpaqueAuthorizeRequest, + _user?: BackstageIdentity, + ): Promise; +} + +// Warning: (ae-missing-release-tag) "ApplyConditionsRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ApplyConditionsRequest = { + resourceRef: string; + resourceType: string; + conditions: PermissionCriteria>; +}; + +// Warning: (ae-missing-release-tag) "ConditionalPolicyResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ConditionalPolicyResult = { + result: AuthorizeResult.MAYBE; + conditions: { + pluginId: string; + resourceType: string; + conditions: PermissionCriteria; + }; +}; + +// Warning: (ae-missing-release-tag) "conditionFor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const conditionFor: ( + rule: PermissionRule, +) => (...params: TParams) => { + rule: string; + params: TParams; +}; + +// Warning: (ae-missing-release-tag) "createPermissionIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const createPermissionIntegration: < + TResource, + TRules extends { + [key: string]: PermissionRule; + }, + TGetResourceParams extends any[] = [], +>({ + pluginId, + resourceType, + rules, + getResource, +}: { + pluginId: string; + resourceType: string; + rules: TRules; + getResource: ( + resourceRef: string, + ...params: TGetResourceParams + ) => Promise; +}) => { + createPermissionIntegrationRouter: (...params: TGetResourceParams) => Router; + toQuery: ( + conditions: PermissionCriteria, + ) => PermissionCriteria>; + conditions: Conditions; + createConditions: (conditions: PermissionCriteria) => { + pluginId: string; + resourceType: string; + conditions: PermissionCriteria; + }; + registerPermissionRule: ( + rule: PermissionRule, any>, + ) => void; +}; + +// Warning: (ae-missing-release-tag) "PermissionPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface PermissionPolicy { + // (undocumented) + handle( + request: OpaqueAuthorizeRequest, + user?: BackstageIdentity, + ): Promise; +} + +// Warning: (ae-missing-release-tag) "PermissionRule" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PermissionRule = { + name: string; + description: string; + apply(resource: TResource, ...params: TParams): boolean; + toQuery(...params: TParams): TQuery | PermissionCriteria; +}; + +// Warning: (ae-missing-release-tag) "PolicyResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PolicyResult = DefinitiveAuthorizeResult | ConditionalPolicyResult; + +// Warnings were encountered during analysis: +// +// src/integration/createPermissionIntegration.d.ts:23:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts +// src/integration/createPermissionIntegration.d.ts:24:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json new file mode 100644 index 0000000000..112976b78b --- /dev/null +++ b/plugins/permission-node/package.json @@ -0,0 +1,33 @@ +{ + "name": "@backstage/plugin-permission-node", + "description": "Common permission and authorization utilities for backend plugins", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "scripts": { + "build": "backstage-cli backend:build", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/permission-common": "^0.1.0", + "@backstage/plugin-auth-backend": "^0.4.6", + "@types/express": "*", + "express": "^4.17.1" + }, + "devDependencies": { + "@backstage/cli": "^0.8.1" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/permission-node/src/index.ts b/plugins/permission-node/src/index.ts new file mode 100644 index 0000000000..697c02ab22 --- /dev/null +++ b/plugins/permission-node/src/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +/** + * Common permission and authorization utilities for backend plugins + * + * @packageDocumentation + */ + +export * from './integration'; +export * from './policy'; +export * from './types'; diff --git a/plugins/permission-node/src/integration/conditionFor.ts b/plugins/permission-node/src/integration/conditionFor.ts new file mode 100644 index 0000000000..6cead51716 --- /dev/null +++ b/plugins/permission-node/src/integration/conditionFor.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { PermissionRule } from '../types'; + +export const conditionFor = + (rule: PermissionRule) => + (...params: TParams) => ({ + rule: rule.name, + params, + }); diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.ts b/plugins/permission-node/src/integration/createPermissionIntegration.ts new file mode 100644 index 0000000000..88a05a7cf8 --- /dev/null +++ b/plugins/permission-node/src/integration/createPermissionIntegration.ts @@ -0,0 +1,203 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AuthorizeResult, + PermissionCondition, + PermissionCriteria, +} from '@backstage/permission-common'; +import express, { Response, Router } from 'express'; +import { PermissionRule } from '../types'; +import { conditionFor } from './conditionFor'; + +/** + * A request to load the referenced resource and apply conditions, to finalize a conditional + * authorization response. + * @public + */ +export type ApplyConditionsRequest = { + resourceRef: string; + resourceType: string; + conditions: PermissionCriteria>; +}; + +type Condition = TRule extends PermissionRule + ? (...params: TParams) => PermissionCondition + : never; + +type Conditions>> = { + [Name in keyof TRules]: Condition; +}; + +type QueryType = TRules extends Record< + string, + PermissionRule +> + ? TQuery + : never; + +// TODO(permission-node): this is no longer correct +function isPermissionCriteria( + criteria: unknown, +): criteria is PermissionCriteria { + return Object.prototype.hasOwnProperty.call(criteria, 'anyOf'); +} + +export const createPermissionIntegration = < + TResource, + TRules extends { [key: string]: PermissionRule }, + TGetResourceParams extends any[] = [], +>({ + pluginId, + resourceType, + rules, + getResource, +}: { + pluginId: string; + resourceType: string; + rules: TRules; + getResource: ( + resourceRef: string, + ...params: TGetResourceParams + ) => Promise; +}): { + createPermissionIntegrationRouter: (...params: TGetResourceParams) => Router; + toQuery: ( + conditions: PermissionCriteria>>, + ) => PermissionCriteria>; + conditions: Conditions; + createConditions: ( + conditions: PermissionCriteria>>, + ) => { + pluginId: string; + resourceType: string; + conditions: PermissionCriteria>>; + }; + registerPermissionRule: ( + rule: PermissionRule>, + ) => void; +} => { + const rulesMap = new Map(Object.values(rules).map(rule => [rule.name, rule])); + + const getRule = ( + name: string, + ): PermissionRule> => { + const rule = rulesMap.get(name); + + if (!rule) { + throw new Error(`Unexpected permission rule: ${name}`); + } + + return rule; + }; + + return { + createPermissionIntegrationRouter: ( + ...getResourceParams: TGetResourceParams + ) => { + const router = Router(); + + router.use('/permissions/', express.json()); + + router.post( + '/permissions/apply-conditions', + async ( + req, + res: Response>, + ) => { + // TODO(authorization-framework): validate input + const body = req.body as ApplyConditionsRequest; + + if (body.resourceType !== resourceType) { + throw new Error(`Unexpected resource type: ${body.resourceType}`); + } + + const resource = await getResource( + body.resourceRef, + ...getResourceParams, + ); + + if (!resource) { + return res.status(400).end(); + } + + const resolveCriteria = ( + criteria: PermissionCriteria< + PermissionCondition> + >, + ): boolean => { + return criteria.anyOf.some(({ allOf }) => + allOf.every(child => + isPermissionCriteria(child) + ? resolveCriteria(child) + : getRule(child.rule).apply(resource, ...child.params), + ), + ); + }; + + return res.status(200).json({ + result: resolveCriteria(body.conditions) + ? AuthorizeResult.ALLOW + : AuthorizeResult.DENY, + }); + }, + ); + + return router; + }, + toQuery: ( + conditions: PermissionCriteria>>, + ): PermissionCriteria> => { + const mapCriteria = ( + criteria: PermissionCriteria>>, + mapFn: ( + condition: PermissionCondition>, + ) => QueryType | PermissionCriteria>, + ): PermissionCriteria> => { + return { + anyOf: criteria.anyOf.map(({ allOf }) => ({ + allOf: allOf.map(child => + isPermissionCriteria(child) + ? mapCriteria(child, mapFn) + : mapFn(child), + ), + })), + }; + }; + + return mapCriteria(conditions, condition => + getRule(condition.rule).toQuery(...condition.params), + ); + }, + conditions: Object.entries(rules).reduce( + (acc, [key, rule]) => ({ + ...acc, + [key]: conditionFor(rule), + }), + {} as Conditions, + ), + createConditions: ( + conditions: PermissionCriteria>>, + ) => ({ + pluginId, + resourceType, + conditions, + }), + registerPermissionRule: rule => { + rulesMap.set(rule.name, rule); + }, + }; +}; diff --git a/plugins/permission-node/src/integration/index.ts b/plugins/permission-node/src/integration/index.ts new file mode 100644 index 0000000000..697d25f65d --- /dev/null +++ b/plugins/permission-node/src/integration/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './conditionFor'; +export * from './createPermissionIntegration'; diff --git a/plugins/permission-node/src/policy/index.ts b/plugins/permission-node/src/policy/index.ts new file mode 100644 index 0000000000..226d50df21 --- /dev/null +++ b/plugins/permission-node/src/policy/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export type { + ConditionalPolicyResult, + PermissionPolicy, + PolicyResult, +} from './types'; diff --git a/plugins/permission-node/src/policy/types.ts b/plugins/permission-node/src/policy/types.ts new file mode 100644 index 0000000000..b1b3881c3e --- /dev/null +++ b/plugins/permission-node/src/policy/types.ts @@ -0,0 +1,81 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AuthorizeRequest, + AuthorizeResult, + PermissionCondition, + PermissionCriteria, +} from '@backstage/permission-common'; +import { BackstageIdentity } from '@backstage/plugin-auth-backend'; + +/** + * An authorization request to be evaluated by the {@link PermissionPolicy}. + * + * This differs from {@link AuthorizeRequest} in that `resourceRef` should never be provided. This + * forces policies to be written in a way that's compatible with filtering collections of resources + * at data load time. + * @public + */ +export type PolicyAuthorizeRequest = Omit; + +/** + * A conditional result to an authorization request, returned by the {@link PermissionPolicy}. + * + * This indicates that the policy allows authorization for the request, given that the returned + * conditions hold when evaluated. The conditions will be evaluated by the corresponding plugin + * which knows about the referenced permission rules. + * + * Similar to {@link AuthorizeResult}, but with the plugin and resource identifiers needed to + * evaluate the returned conditions. + * @public + */ +export type ConditionalPolicyResult = { + result: AuthorizeResult.CONDITIONAL; + conditions: { + pluginId: string; + resourceType: string; + conditions: PermissionCriteria>; + }; +}; + +/** + * The result of evaluating an authorization request with a {@link PermissionPolicy}. + * @public + */ +export type PolicyResult = + | { result: AuthorizeResult.ALLOW | AuthorizeResult.DENY } + | ConditionalPolicyResult; + +/** + * A policy to evaluate authorization requests for any permissioned action performed in Backstage. + * + * This takes as input a permission and an optional Backstage identity, and should return ALLOW if + * the user is permitted to execute that action; otherwise DENY. For permissions relating to + * resources, such a catalog entities, a conditional response can also be returned. This states + * that the action is allowed if the conditions provided hold true. + * + * Conditions are a rule, and parameters to evaluate against that rule. For example, the rule might + * be `isOwner` and the parameters a collection of entityRefs; if one of the entityRefs matches + * the `owner` field on a catalog entity, this would resolve to ALLOW. + * @public + */ +export interface PermissionPolicy { + handle( + request: PolicyAuthorizeRequest, + user?: BackstageIdentity, + ): Promise; +} diff --git a/plugins/permission-node/src/setupTests.ts b/plugins/permission-node/src/setupTests.ts new file mode 100644 index 0000000000..a330613afb --- /dev/null +++ b/plugins/permission-node/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export {}; diff --git a/plugins/permission-node/src/types.ts b/plugins/permission-node/src/types.ts new file mode 100644 index 0000000000..6d2622119b --- /dev/null +++ b/plugins/permission-node/src/types.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { PermissionCriteria } from '@backstage/permission-common'; + +/** + * A conditional rule that can be provided in an {@link AuthorizeResult} response to an + * authorization request. + * + * Rules can either be evaluated against a resource loaded in memory, or used as filters when + * loading a collection of resources from a data source. The `apply` and `toQuery` methods implement + * these two concepts. + * + * The two operations should always have the same logical result. If they don’t, the effective + * outcome of an authorization operation will sometimes differ depending on how the authorization + * check was performed. + * @public + */ +export type PermissionRule = { + name: string; + description: string; + + /** + * Apply this rule to a resource already loaded from a backing data source. The params are + * arguments supplied for the rule; for example, a rule could be `isOwner` with entityRefs as the + * params. + */ + apply(resource: TResource, ...params: TParams): boolean; + + /** + * Translate this rule to criteria suitable for use in querying a backing data store. The criteria + * can be used for loading a collection of resources efficiently with conditional criteria already + * applied. + */ + toQuery(...params: TParams): TQuery | PermissionCriteria; +}; From a82709c38f4225331fd8f6fc91e81f91fd64a5d3 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 09:53:50 +0000 Subject: [PATCH 088/138] authz: update unused type params in conditionFor to unknown Signed-off-by: Mike Lewis --- plugins/permission-node/src/integration/conditionFor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/permission-node/src/integration/conditionFor.ts b/plugins/permission-node/src/integration/conditionFor.ts index 6cead51716..3a13a3afe3 100644 --- a/plugins/permission-node/src/integration/conditionFor.ts +++ b/plugins/permission-node/src/integration/conditionFor.ts @@ -17,7 +17,7 @@ import { PermissionRule } from '../types'; export const conditionFor = - (rule: PermissionRule) => + (rule: PermissionRule) => (...params: TParams) => ({ rule: rule.name, params, From 4083fcdb5e5dfd1bf7712c8e3c75204d3da1d859 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 13:54:29 +0000 Subject: [PATCH 089/138] authz: fix PermissionCondition type parameter `unknown` doesn't satisfy the (recently added) `extends unknown[]` constraint. In these two cases, we can remove the parameter entirely and rely instead on the default of `unknown[]`. Signed-off-by: Mike Lewis --- .../src/integration/createPermissionIntegration.ts | 2 +- plugins/permission-node/src/policy/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.ts b/plugins/permission-node/src/integration/createPermissionIntegration.ts index 88a05a7cf8..bbd1c8af2a 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegration.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegration.ts @@ -31,7 +31,7 @@ import { conditionFor } from './conditionFor'; export type ApplyConditionsRequest = { resourceRef: string; resourceType: string; - conditions: PermissionCriteria>; + conditions: PermissionCriteria; }; type Condition = TRule extends PermissionRule diff --git a/plugins/permission-node/src/policy/types.ts b/plugins/permission-node/src/policy/types.ts index b1b3881c3e..e81757d59c 100644 --- a/plugins/permission-node/src/policy/types.ts +++ b/plugins/permission-node/src/policy/types.ts @@ -48,7 +48,7 @@ export type ConditionalPolicyResult = { conditions: { pluginId: string; resourceType: string; - conditions: PermissionCriteria>; + conditions: PermissionCriteria; }; }; From f3d2ccfeb883b6e79dc9e3177e4ca9a6b36a7082 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 13:56:07 +0000 Subject: [PATCH 090/138] authz: switch to unknown[] in PermissionRule type parameter Signed-off-by: Mike Lewis --- plugins/permission-node/src/types.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/permission-node/src/types.ts b/plugins/permission-node/src/types.ts index 6d2622119b..308eafe481 100644 --- a/plugins/permission-node/src/types.ts +++ b/plugins/permission-node/src/types.ts @@ -29,7 +29,11 @@ import type { PermissionCriteria } from '@backstage/permission-common'; * check was performed. * @public */ -export type PermissionRule = { +export type PermissionRule< + TResource, + TQuery, + TParams extends unknown[] = unknown[], +> = { name: string; description: string; From 652af0834ae886da9310bf60b9e84be0bb0f46ba Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 13:58:05 +0000 Subject: [PATCH 091/138] authz: add test suite for conditionFor Signed-off-by: Mike Lewis --- .../src/integration/conditionFor.test.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 plugins/permission-node/src/integration/conditionFor.test.ts diff --git a/plugins/permission-node/src/integration/conditionFor.test.ts b/plugins/permission-node/src/integration/conditionFor.test.ts new file mode 100644 index 0000000000..d1099e7555 --- /dev/null +++ b/plugins/permission-node/src/integration/conditionFor.test.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { conditionFor } from './conditionFor'; + +describe('conditionFor', () => { + const testRule = { + name: 'test-rule', + description: 'test-description', + apply: jest.fn(), + toQuery: jest.fn(), + }; + + it('returns a function', () => { + expect(conditionFor(testRule)).toEqual(expect.any(Function)); + }); + + describe('return value', () => { + it('constructs a condition with the rule name and supplied params', () => { + const conditionFactory = conditionFor(testRule); + expect(conditionFactory('a', 'b', 1, 2)).toEqual({ + rule: 'test-rule', + params: ['a', 'b', 1, 2], + }); + }); + }); +}); From 64b6ff368f1e5081a8739cbad6c162c8bb402ce7 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 13:58:28 +0000 Subject: [PATCH 092/138] authz: fix expected response type for /apply-conditions route Signed-off-by: Mike Lewis --- .../src/integration/createPermissionIntegration.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.ts b/plugins/permission-node/src/integration/createPermissionIntegration.ts index bbd1c8af2a..d70da5f7df 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegration.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegration.ts @@ -116,7 +116,9 @@ export const createPermissionIntegration = < '/permissions/apply-conditions', async ( req, - res: Response>, + res: Response<{ + result: Omit; + }>, ) => { // TODO(authorization-framework): validate input const body = req.body as ApplyConditionsRequest; From d0a99e3219e67fb1b81e205d2cf864c61fc8a81c Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 14:12:38 +0000 Subject: [PATCH 093/138] authz: update permission-node api-report Signed-off-by: Mike Lewis --- plugins/permission-node/api-report.md | 74 ++++++++++++--------------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index 1285207e61..fac7e8d7fa 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -3,39 +3,25 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AuthorizeRequest } from '@backstage/permission-common'; import { AuthorizeResult } from '@backstage/permission-common'; import { BackstageIdentity } from '@backstage/plugin-auth-backend'; -import { DefinitiveAuthorizeResult } from '@backstage/permission-common'; -import { OpaqueAuthorizeRequest } from '@backstage/permission-common'; import { PermissionCondition } from '@backstage/permission-common'; import { PermissionCriteria } from '@backstage/permission-common'; import { Router } from 'express'; -// Warning: (ae-missing-release-tag) "AllowAllPermissionPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export class AllowAllPermissionPolicy implements PermissionPolicy { - // (undocumented) - handle( - _request: OpaqueAuthorizeRequest, - _user?: BackstageIdentity, - ): Promise; -} - -// Warning: (ae-missing-release-tag) "ApplyConditionsRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type ApplyConditionsRequest = { resourceRef: string; resourceType: string; - conditions: PermissionCriteria>; + conditions: PermissionCriteria; }; -// Warning: (ae-missing-release-tag) "ConditionalPolicyResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-permission-node" does not have an export "AuthorizeResult" // -// @public (undocumented) +// @public export type ConditionalPolicyResult = { - result: AuthorizeResult.MAYBE; + result: AuthorizeResult.CONDITIONAL; conditions: { pluginId: string; resourceType: string; @@ -47,7 +33,7 @@ export type ConditionalPolicyResult = { // // @public (undocumented) export const conditionFor: ( - rule: PermissionRule, + rule: PermissionRule, ) => (...params: TParams) => { rule: string; params: TParams; @@ -59,7 +45,7 @@ export const conditionFor: ( export const createPermissionIntegration: < TResource, TRules extends { - [key: string]: PermissionRule; + [key: string]: PermissionRule; }, TGetResourceParams extends any[] = [], >({ @@ -78,49 +64,55 @@ export const createPermissionIntegration: < }) => { createPermissionIntegrationRouter: (...params: TGetResourceParams) => Router; toQuery: ( - conditions: PermissionCriteria, + conditions: PermissionCriteria>>, ) => PermissionCriteria>; conditions: Conditions; - createConditions: (conditions: PermissionCriteria) => { + createConditions: ( + conditions: PermissionCriteria>>, + ) => { pluginId: string; resourceType: string; - conditions: PermissionCriteria; + conditions: PermissionCriteria>>; }; registerPermissionRule: ( - rule: PermissionRule, any>, + rule: PermissionRule, unknown[]>, ) => void; }; -// Warning: (ae-missing-release-tag) "PermissionPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export interface PermissionPolicy { + // Warning: (ae-forgotten-export) The symbol "PolicyAuthorizeRequest" needs to be exported by the entry point index.d.ts + // // (undocumented) handle( - request: OpaqueAuthorizeRequest, + request: PolicyAuthorizeRequest, user?: BackstageIdentity, ): Promise; } -// Warning: (ae-missing-release-tag) "PermissionRule" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-permission-node" does not have an export "AuthorizeResult" // -// @public (undocumented) -export type PermissionRule = { +// @public +export type PermissionRule< + TResource, + TQuery, + TParams extends unknown[] = unknown[], +> = { name: string; description: string; apply(resource: TResource, ...params: TParams): boolean; toQuery(...params: TParams): TQuery | PermissionCriteria; }; -// Warning: (ae-missing-release-tag) "PolicyResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type PolicyResult = DefinitiveAuthorizeResult | ConditionalPolicyResult; +// @public +export type PolicyResult = + | { + result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; + } + | ConditionalPolicyResult; // Warnings were encountered during analysis: // -// src/integration/createPermissionIntegration.d.ts:23:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts -// src/integration/createPermissionIntegration.d.ts:24:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts - -// (No @packageDocumentation comment for this package) +// src/integration/createPermissionIntegration.d.ts:28:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts +// src/integration/createPermissionIntegration.d.ts:29:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts ``` From 22f5de984007ecd6a4d24316e816a64b9c092d4b Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 14:13:26 +0000 Subject: [PATCH 094/138] authz: update createPermissionIntegration to work with new PermissionCriteria type Signed-off-by: Mike Lewis --- plugins/permission-node/api-report.md | 12 +- .../createPermissionIntegration.ts | 68 ++---- .../src/integration/util.test.ts | 217 ++++++++++++++++++ .../permission-node/src/integration/util.ts | 68 ++++++ 4 files changed, 304 insertions(+), 61 deletions(-) create mode 100644 plugins/permission-node/src/integration/util.test.ts create mode 100644 plugins/permission-node/src/integration/util.ts diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index fac7e8d7fa..407ea3dc84 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -64,15 +64,13 @@ export const createPermissionIntegration: < }) => { createPermissionIntegrationRouter: (...params: TGetResourceParams) => Router; toQuery: ( - conditions: PermissionCriteria>>, + conditions: PermissionCriteria, ) => PermissionCriteria>; conditions: Conditions; - createConditions: ( - conditions: PermissionCriteria>>, - ) => { + createConditions: (conditions: PermissionCriteria) => { pluginId: string; resourceType: string; - conditions: PermissionCriteria>>; + conditions: PermissionCriteria; }; registerPermissionRule: ( rule: PermissionRule, unknown[]>, @@ -113,6 +111,6 @@ export type PolicyResult = // Warnings were encountered during analysis: // -// src/integration/createPermissionIntegration.d.ts:28:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts -// src/integration/createPermissionIntegration.d.ts:29:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts +// src/integration/createPermissionIntegration.d.ts:38:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts +// src/integration/createPermissionIntegration.d.ts:39:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.ts b/plugins/permission-node/src/integration/createPermissionIntegration.ts index d70da5f7df..35d6f0da54 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegration.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegration.ts @@ -14,14 +14,15 @@ * limitations under the License. */ +import express, { Response, Router } from 'express'; import { AuthorizeResult, PermissionCondition, PermissionCriteria, } from '@backstage/permission-common'; -import express, { Response, Router } from 'express'; import { PermissionRule } from '../types'; import { conditionFor } from './conditionFor'; +import { applyConditions, mapConditions } from './util'; /** * A request to load the referenced resource and apply conditions, to finalize a conditional @@ -49,13 +50,6 @@ type QueryType = TRules extends Record< ? TQuery : never; -// TODO(permission-node): this is no longer correct -function isPermissionCriteria( - criteria: unknown, -): criteria is PermissionCriteria { - return Object.prototype.hasOwnProperty.call(criteria, 'anyOf'); -} - export const createPermissionIntegration = < TResource, TRules extends { [key: string]: PermissionRule }, @@ -76,15 +70,13 @@ export const createPermissionIntegration = < }): { createPermissionIntegrationRouter: (...params: TGetResourceParams) => Router; toQuery: ( - conditions: PermissionCriteria>>, + conditions: PermissionCriteria, ) => PermissionCriteria>; conditions: Conditions; - createConditions: ( - conditions: PermissionCriteria>>, - ) => { + createConditions: (conditions: PermissionCriteria) => { pluginId: string; resourceType: string; - conditions: PermissionCriteria>>; + conditions: PermissionCriteria; }; registerPermissionRule: ( rule: PermissionRule>, @@ -92,9 +84,7 @@ export const createPermissionIntegration = < } => { const rulesMap = new Map(Object.values(rules).map(rule => [rule.name, rule])); - const getRule = ( - name: string, - ): PermissionRule> => { + const getRule = (name: string) => { const rule = rulesMap.get(name); if (!rule) { @@ -110,10 +100,9 @@ export const createPermissionIntegration = < ) => { const router = Router(); - router.use('/permissions/', express.json()); - router.post( '/permissions/apply-conditions', + express.json(), async ( req, res: Response<{ @@ -136,22 +125,10 @@ export const createPermissionIntegration = < return res.status(400).end(); } - const resolveCriteria = ( - criteria: PermissionCriteria< - PermissionCondition> - >, - ): boolean => { - return criteria.anyOf.some(({ allOf }) => - allOf.every(child => - isPermissionCriteria(child) - ? resolveCriteria(child) - : getRule(child.rule).apply(resource, ...child.params), - ), - ); - }; - return res.status(200).json({ - result: resolveCriteria(body.conditions) + result: applyConditions(body.conditions, ({ rule, params }) => + getRule(rule).apply(resource, ...params), + ) ? AuthorizeResult.ALLOW : AuthorizeResult.DENY, }); @@ -161,27 +138,10 @@ export const createPermissionIntegration = < return router; }, toQuery: ( - conditions: PermissionCriteria>>, + conditions: PermissionCriteria, ): PermissionCriteria> => { - const mapCriteria = ( - criteria: PermissionCriteria>>, - mapFn: ( - condition: PermissionCondition>, - ) => QueryType | PermissionCriteria>, - ): PermissionCriteria> => { - return { - anyOf: criteria.anyOf.map(({ allOf }) => ({ - allOf: allOf.map(child => - isPermissionCriteria(child) - ? mapCriteria(child, mapFn) - : mapFn(child), - ), - })), - }; - }; - - return mapCriteria(conditions, condition => - getRule(condition.rule).toQuery(...condition.params), + return mapConditions(conditions, ({ rule, params }) => + getRule(rule).toQuery(...params), ); }, conditions: Object.entries(rules).reduce( @@ -192,7 +152,7 @@ export const createPermissionIntegration = < {} as Conditions, ), createConditions: ( - conditions: PermissionCriteria>>, + conditions: PermissionCriteria, ) => ({ pluginId, resourceType, diff --git a/plugins/permission-node/src/integration/util.test.ts b/plugins/permission-node/src/integration/util.test.ts new file mode 100644 index 0000000000..44a000d395 --- /dev/null +++ b/plugins/permission-node/src/integration/util.test.ts @@ -0,0 +1,217 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + PermissionCondition, + PermissionCriteria, +} from '@backstage/permission-common'; +import { applyConditions, mapConditions } from './util'; + +describe('integration utils', () => { + const testCases: { + criteria: PermissionCriteria; + expectedResult: { + applyConditions: boolean; + mapConditions: PermissionCriteria<{ query: string; params: unknown[] }>; + }; + }[] = [ + { + criteria: { rule: 'test-rule-1', params: [] }, + expectedResult: { + applyConditions: true, + mapConditions: { query: 'test-rule-1', params: [] }, + }, + }, + { + criteria: { rule: 'test-rule-2', params: [] }, + expectedResult: { + applyConditions: false, + mapConditions: { query: 'test-rule-2', params: [] }, + }, + }, + { + criteria: { + anyOf: [ + { rule: 'test-rule-1', params: ['a', 'b'] }, + { rule: 'test-rule-2', params: ['c', 'd'] }, + ], + }, + expectedResult: { + applyConditions: true, + mapConditions: { + anyOf: [ + { query: 'test-rule-1', params: ['a', 'b'] }, + { query: 'test-rule-2', params: ['c', 'd'] }, + ], + }, + }, + }, + { + criteria: { + allOf: [ + { rule: 'test-rule-1', params: ['e', 'f'] }, + { rule: 'test-rule-2', params: ['g', 'h'] }, + ], + }, + expectedResult: { + applyConditions: false, + mapConditions: { + allOf: [ + { query: 'test-rule-1', params: ['e', 'f'] }, + { query: 'test-rule-2', params: ['g', 'h'] }, + ], + }, + }, + }, + { + criteria: { + not: { rule: 'test-rule-2', params: ['i'] }, + }, + expectedResult: { + applyConditions: true, + mapConditions: { + not: { query: 'test-rule-2', params: ['i'] }, + }, + }, + }, + { + criteria: { + allOf: [ + { + anyOf: [ + { rule: 'test-rule-1', params: ['j'] }, + { rule: 'test-rule-2', params: ['k'] }, + ], + }, + { + not: { + allOf: [ + { rule: 'test-rule-1', params: ['l'] }, + { rule: 'test-rule-2', params: ['m'] }, + ], + }, + }, + ], + }, + expectedResult: { + applyConditions: true, + mapConditions: { + allOf: [ + { + anyOf: [ + { query: 'test-rule-1', params: ['j'] }, + { query: 'test-rule-2', params: ['k'] }, + ], + }, + { + not: { + allOf: [ + { query: 'test-rule-1', params: ['l'] }, + { query: 'test-rule-2', params: ['m'] }, + ], + }, + }, + ], + }, + }, + }, + { + criteria: { + allOf: [ + { + anyOf: [ + { rule: 'test-rule-1', params: ['j'] }, + { rule: 'test-rule-2', params: ['k'] }, + ], + }, + { + not: { + allOf: [ + { rule: 'test-rule-1', params: ['l'] }, + { not: { rule: 'test-rule-2', params: ['m'] } }, + ], + }, + }, + ], + }, + expectedResult: { + applyConditions: false, + mapConditions: { + allOf: [ + { + anyOf: [ + { query: 'test-rule-1', params: ['j'] }, + { query: 'test-rule-2', params: ['k'] }, + ], + }, + { + not: { + allOf: [ + { query: 'test-rule-1', params: ['l'] }, + { not: { query: 'test-rule-2', params: ['m'] } }, + ], + }, + }, + ], + }, + }, + }, + ]; + + describe('applyConditions', () => { + const applyFn = jest.fn(condition => condition.rule === 'test-rule-1'); + + it('invokes applyFn with rules to determine result', () => { + applyConditions({ rule: 'test-rule-1', params: ['foo', 'bar'] }, applyFn); + + expect(applyFn).toHaveBeenCalledWith({ + rule: 'test-rule-1', + params: ['foo', 'bar'], + }); + }); + + it.each(testCases)( + 'works with criteria %#', + ({ criteria, expectedResult }) => { + expect(applyConditions(criteria, applyFn)).toEqual( + expectedResult.applyConditions, + ); + }, + ); + }); + + describe('mapConditions', () => { + const mapFn = jest.fn(({ rule, params }) => ({ query: rule, params })); + + it('invokes mapFn to transform conditions', () => { + mapConditions({ rule: 'test-rule-1', params: ['foo', 'bar'] }, mapFn); + + expect(mapFn).toHaveBeenCalledWith({ + rule: 'test-rule-1', + params: ['foo', 'bar'], + }); + }); + + it.each(testCases)( + 'works with criteria %#', + ({ criteria, expectedResult }) => { + expect(mapConditions(criteria, mapFn)).toEqual( + expectedResult.mapConditions, + ); + }, + ); + }); +}); diff --git a/plugins/permission-node/src/integration/util.ts b/plugins/permission-node/src/integration/util.ts new file mode 100644 index 0000000000..355964d573 --- /dev/null +++ b/plugins/permission-node/src/integration/util.ts @@ -0,0 +1,68 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { PermissionCriteria } from '@backstage/permission-common'; + +const isAndCriteria = ( + filter: PermissionCriteria, +): filter is { allOf: PermissionCriteria[] } => + Object.prototype.hasOwnProperty.call(filter, 'allOf'); + +const isOrCriteria = ( + filter: PermissionCriteria, +): filter is { anyOf: PermissionCriteria[] } => + Object.prototype.hasOwnProperty.call(filter, 'anyOf'); + +const isNotCriteria = ( + filter: PermissionCriteria, +): filter is { not: PermissionCriteria } => + Object.prototype.hasOwnProperty.call(filter, 'not'); + +export const mapConditions = ( + criteria: PermissionCriteria, + mapFn: (condition: TQueryIn) => TQueryOut, +): PermissionCriteria => { + if (isAndCriteria(criteria)) { + return { + allOf: criteria.allOf.map(child => mapConditions(child, mapFn)), + }; + } else if (isOrCriteria(criteria)) { + return { + anyOf: criteria.anyOf.map(child => mapConditions(child, mapFn)), + }; + } else if (isNotCriteria(criteria)) { + return { + not: mapConditions(criteria.not, mapFn), + }; + } + + return mapFn(criteria); +}; + +export const applyConditions = ( + criteria: PermissionCriteria, + applyFn: (condition: TQuery) => boolean, +): boolean => { + if (isAndCriteria(criteria)) { + return criteria.allOf.every(child => applyConditions(child, applyFn)); + } else if (isOrCriteria(criteria)) { + return criteria.anyOf.some(child => applyConditions(child, applyFn)); + } else if (isNotCriteria(criteria)) { + return !applyConditions(criteria.not, applyFn); + } + + return applyFn(criteria); +}; From 2b668f2eb886970a73b7f9498d5641a5fbe5d45b Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 18:26:46 +0000 Subject: [PATCH 095/138] build(deps): add dependency on zod in permission-node Signed-off-by: Mike Lewis --- plugins/permission-node/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 112976b78b..85e21049ed 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -22,7 +22,8 @@ "@backstage/permission-common": "^0.1.0", "@backstage/plugin-auth-backend": "^0.4.6", "@types/express": "*", - "express": "^4.17.1" + "express": "^4.17.1", + "zod": "^3.11.6" }, "devDependencies": { "@backstage/cli": "^0.8.1" From 5c75c89106f824ae2d202cc2ee3eaef396160d28 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 18:27:27 +0000 Subject: [PATCH 096/138] authz: improve error handling in permission-node apply-conditions route Signed-off-by: Mike Lewis --- plugins/permission-node/api-report.md | 4 +- .../createPermissionIntegration.ts | 47 ++++++++++++++++--- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index 407ea3dc84..fe26dc2a1a 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -111,6 +111,6 @@ export type PolicyResult = // Warnings were encountered during analysis: // -// src/integration/createPermissionIntegration.d.ts:38:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts -// src/integration/createPermissionIntegration.d.ts:39:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts +// src/integration/createPermissionIntegration.d.ts:28:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts +// src/integration/createPermissionIntegration.d.ts:29:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.ts b/plugins/permission-node/src/integration/createPermissionIntegration.ts index 35d6f0da54..cbdcb72041 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegration.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegration.ts @@ -15,6 +15,7 @@ */ import express, { Response, Router } from 'express'; +import { z } from 'zod'; import { AuthorizeResult, PermissionCondition, @@ -24,6 +25,26 @@ import { PermissionRule } from '../types'; import { conditionFor } from './conditionFor'; import { applyConditions, mapConditions } from './util'; +const permissionCriteriaSchema: z.ZodSchema< + PermissionCriteria +> = z.lazy(() => + z.union([ + z.object({ anyOf: z.array(permissionCriteriaSchema) }), + z.object({ allOf: z.array(permissionCriteriaSchema) }), + z.object({ not: permissionCriteriaSchema }), + z.object({ + rule: z.string(), + params: z.array(z.unknown()), + }), + ]), +); + +const applyConditionsRequestSchema = z.object({ + resourceRef: z.string(), + resourceType: z.string(), + conditions: permissionCriteriaSchema, +}); + /** * A request to load the referenced resource and apply conditions, to finalize a conditional * authorization response. @@ -105,15 +126,25 @@ export const createPermissionIntegration = < express.json(), async ( req, - res: Response<{ - result: Omit; - }>, + res: Response< + | { + result: Omit; + } + | string + >, ) => { - // TODO(authorization-framework): validate input - const body = req.body as ApplyConditionsRequest; + const parseResult = applyConditionsRequestSchema.safeParse(req.body); + + if (!parseResult.success) { + return res.status(400).send(`Invalid request body.`); + } + + const { data: body } = parseResult; if (body.resourceType !== resourceType) { - throw new Error(`Unexpected resource type: ${body.resourceType}`); + return res + .status(400) + .send(`Unexpected resource type: ${body.resourceType}.`); } const resource = await getResource( @@ -122,7 +153,9 @@ export const createPermissionIntegration = < ); if (!resource) { - return res.status(400).end(); + return res + .status(400) + .send(`Resource for ref ${body.resourceRef} not found.`); } return res.status(200).json({ From f72d7bba0e1a93343b76568b351220c0a608e040 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 11 Nov 2021 18:27:46 +0000 Subject: [PATCH 097/138] authz: add testsuite for createPermissionIntegration Signed-off-by: Mike Lewis --- plugins/permission-node/package.json | 4 +- .../createPermissionIntegration.test.ts | 293 ++++++++++++++++++ 2 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 plugins/permission-node/src/integration/createPermissionIntegration.test.ts diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 85e21049ed..a23cb0fae2 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -26,7 +26,9 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.8.1" + "@backstage/cli": "^0.8.1", + "@types/supertest": "^2.0.8", + "supertest": "^6.1.3" }, "files": [ "dist" diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.test.ts b/plugins/permission-node/src/integration/createPermissionIntegration.test.ts new file mode 100644 index 0000000000..6b0ca948bf --- /dev/null +++ b/plugins/permission-node/src/integration/createPermissionIntegration.test.ts @@ -0,0 +1,293 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AuthorizeResult } from '@backstage/permission-common'; +import express, { Express, Router } from 'express'; +import request from 'supertest'; +import { createPermissionIntegration } from './createPermissionIntegration'; + +const mockGetResource: jest.MockedFunction< + (resourceRef: string) => Promise +> = jest.fn((resourceRef: string) => + Promise.resolve({ + resourceRef, + }), +); + +const testIntegration = () => + createPermissionIntegration({ + pluginId: 'test-plugin', + resourceType: 'test-resource', + getResource: mockGetResource, + rules: { + testRule1: { + name: 'testRule1', + description: 'Test rule 1', + apply: jest.fn( + (_resource: any, _firstParam: string, _secondParam: number) => true, + ), + toQuery: jest.fn((firstParam: string, secondParam: number) => ({ + query: 'testRule1', + params: [firstParam, secondParam], + })), + }, + testRule2: { + name: 'testRule2', + description: 'Test rule 2', + apply: jest.fn((_firstParam: object) => false), + toQuery: jest.fn((firstParam: object) => ({ + query: 'testRule2', + params: [firstParam], + })), + }, + }, + }); + +describe('createPermissionIntegration', () => { + describe('createPermissionIntegrationRouter', () => { + let app: Express; + let router: Router; + + beforeEach(() => { + const { createPermissionIntegrationRouter } = testIntegration(); + + router = createPermissionIntegrationRouter(); + app = express().use(router); + }); + + it('works', async () => { + expect(router).toBeDefined(); + }); + + describe('POST /permissions/apply-conditions', () => { + it('returns 200/ALLOW when criteria match', async () => { + const response = await request(app) + .post('/permissions/apply-conditions') + .send({ + resourceRef: 'default:test/resource', + resourceType: 'test-resource', + conditions: { + rule: 'testRule1', + params: ['a', 1], + }, + }); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ result: AuthorizeResult.ALLOW }); + }); + + it('returns 200/DENY when criteria do not match', async () => { + const response = await request(app) + .post('/permissions/apply-conditions') + .send({ + resourceRef: 'default:test/resource', + resourceType: 'test-resource', + conditions: { + anyOf: [], + }, + }); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ result: AuthorizeResult.DENY }); + }); + + it('returns 400 when called with incorrect resource type', async () => { + const response = await request(app) + .post('/permissions/apply-conditions') + .send({ + resourceRef: 'default:test/resource', + resourceType: 'test-incorrect-resource', + conditions: { + anyOf: [], + }, + }); + + expect(response.status).toEqual(400); + expect(response.error && response.error.text).toMatch( + /unexpected resource type: test-incorrect-resource/i, + ); + }); + + it('returns 400 when resource is not found', async () => { + mockGetResource.mockReturnValueOnce(Promise.resolve(undefined)); + + const response = await request(app) + .post('/permissions/apply-conditions') + .send({ + resourceRef: 'default:test/resource', + resourceType: 'test-resource', + conditions: { + not: { + rule: 'testRule1', + params: ['a', 1], + }, + }, + }); + + expect(response.status).toEqual(400); + expect(response.error && response.error.text).toMatch( + /resource for ref default:test\/resource not found/i, + ); + }); + + it.each([ + undefined, + {}, + { resourceType: 'test-resource-type' }, + { resourceRef: 'test/resource-ref' }, + { + resourceType: 'test-resource-type', + resourceRef: 'test/resource-ref', + }, + { conditions: { anyOf: [] } }, + ])(`returns 400 for invalid input %#`, async input => { + const response = await request(app) + .post('/permissions/apply-conditions') + .send(input); + + expect(response.status).toEqual(400); + expect(response.error && response.error.text).toMatch( + /invalid request body/i, + ); + }); + }); + }); + + describe('toQuery', () => { + it('converts conditions to plugin-specific queries using rule toQuery methods', () => { + const { toQuery } = testIntegration(); + + expect( + toQuery({ + anyOf: [ + { + allOf: [ + { rule: 'testRule1', params: ['a', 1] }, + { rule: 'testRule2', params: [{ foo: 'bar' }] }, + ], + }, + { + not: { rule: 'testRule1', params: ['b', 2] }, + }, + ], + }), + ).toEqual({ + anyOf: [ + { + allOf: [ + { query: 'testRule1', params: ['a', 1] }, + { query: 'testRule2', params: [{ foo: 'bar' }] }, + ], + }, + { + not: { query: 'testRule1', params: ['b', 2] }, + }, + ], + }); + }); + }); + + describe('conditions', () => { + it('creates condition factories for the supplied rules', () => { + const { conditions } = testIntegration(); + + expect(conditions.testRule1('a', 1)).toEqual({ + rule: 'testRule1', + params: ['a', 1], + }); + + expect(conditions.testRule2({ baz: 'quux' })).toEqual({ + rule: 'testRule2', + params: [{ baz: 'quux' }], + }); + }); + }); + + describe('createConditions', () => { + it('wraps conditions in an object with resourceType and pluginId', () => { + const { createConditions } = testIntegration(); + + expect( + createConditions({ allOf: [{ rule: 'testRule1', params: ['a', 1] }] }), + ).toEqual({ + pluginId: 'test-plugin', + resourceType: 'test-resource', + conditions: { + allOf: [{ rule: 'testRule1', params: ['a', 1] }], + }, + }); + }); + }); + + describe('registerPermissionRule', () => { + it('adds support for the new rule in toQuery', () => { + const { registerPermissionRule, toQuery } = testIntegration(); + + registerPermissionRule({ + name: 'testRule3', + description: 'Test rule 3', + apply: jest.fn((_resource: any, _firstParam: string) => false), + toQuery: jest.fn((firstParam: string) => ({ + query: 'testRule3', + params: [firstParam], + })), + }); + + expect( + toQuery({ + rule: 'testRule3', + params: ['abc'], + }), + ).toEqual({ + query: 'testRule3', + params: ['abc'], + }); + }); + + it('adds support for the new rule in the apply-conditions endpoint', async () => { + const { registerPermissionRule, createPermissionIntegrationRouter } = + testIntegration(); + + const app = express().use(createPermissionIntegrationRouter()); + + registerPermissionRule({ + name: 'testRule3', + description: 'Test rule 3', + apply: jest.fn((_resource: any, _firstParam: string) => false), + toQuery: jest.fn((firstParam: string) => ({ + query: 'testRule3', + params: [firstParam], + })), + }); + + const response = await request(app) + .post('/permissions/apply-conditions') + .send({ + resourceRef: 'default:test/resource', + resourceType: 'test-resource', + conditions: { + not: { + rule: 'testRule3', + params: ['a'], + }, + }, + }); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ result: AuthorizeResult.ALLOW }); + }); + }); +}); From e2088541ddc81dbeff9331ae7711ed452233021f Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 12 Nov 2021 12:30:04 +0000 Subject: [PATCH 098/138] authz: update references to permission-common after move to plugins Signed-off-by: Mike Lewis --- plugins/permission-node/api-report.md | 8 ++++---- plugins/permission-node/package.json | 2 +- .../src/integration/createPermissionIntegration.test.ts | 2 +- .../src/integration/createPermissionIntegration.ts | 2 +- plugins/permission-node/src/integration/util.test.ts | 2 +- plugins/permission-node/src/integration/util.ts | 2 +- plugins/permission-node/src/policy/types.ts | 2 +- plugins/permission-node/src/types.ts | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index fe26dc2a1a..0044807857 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -3,11 +3,11 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AuthorizeRequest } from '@backstage/permission-common'; -import { AuthorizeResult } from '@backstage/permission-common'; +import { AuthorizeRequest } from '@backstage/plugin-permission-common'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { BackstageIdentity } from '@backstage/plugin-auth-backend'; -import { PermissionCondition } from '@backstage/permission-common'; -import { PermissionCriteria } from '@backstage/permission-common'; +import { PermissionCondition } from '@backstage/plugin-permission-common'; +import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { Router } from 'express'; // @public diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index a23cb0fae2..eaf9efdbba 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -19,8 +19,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/permission-common": "^0.1.0", "@backstage/plugin-auth-backend": "^0.4.6", + "@backstage/plugin-permission-common": "^0.1.0", "@types/express": "*", "express": "^4.17.1", "zod": "^3.11.6" diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.test.ts b/plugins/permission-node/src/integration/createPermissionIntegration.test.ts index 6b0ca948bf..1ef310954f 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegration.test.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegration.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { AuthorizeResult } from '@backstage/permission-common'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; import express, { Express, Router } from 'express'; import request from 'supertest'; import { createPermissionIntegration } from './createPermissionIntegration'; diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.ts b/plugins/permission-node/src/integration/createPermissionIntegration.ts index cbdcb72041..7a7ae0ea4b 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegration.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegration.ts @@ -20,7 +20,7 @@ import { AuthorizeResult, PermissionCondition, PermissionCriteria, -} from '@backstage/permission-common'; +} from '@backstage/plugin-permission-common'; import { PermissionRule } from '../types'; import { conditionFor } from './conditionFor'; import { applyConditions, mapConditions } from './util'; diff --git a/plugins/permission-node/src/integration/util.test.ts b/plugins/permission-node/src/integration/util.test.ts index 44a000d395..93f51d8275 100644 --- a/plugins/permission-node/src/integration/util.test.ts +++ b/plugins/permission-node/src/integration/util.test.ts @@ -17,7 +17,7 @@ import { PermissionCondition, PermissionCriteria, -} from '@backstage/permission-common'; +} from '@backstage/plugin-permission-common'; import { applyConditions, mapConditions } from './util'; describe('integration utils', () => { diff --git a/plugins/permission-node/src/integration/util.ts b/plugins/permission-node/src/integration/util.ts index 355964d573..631aee269e 100644 --- a/plugins/permission-node/src/integration/util.ts +++ b/plugins/permission-node/src/integration/util.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { PermissionCriteria } from '@backstage/permission-common'; +import { PermissionCriteria } from '@backstage/plugin-permission-common'; const isAndCriteria = ( filter: PermissionCriteria, diff --git a/plugins/permission-node/src/policy/types.ts b/plugins/permission-node/src/policy/types.ts index e81757d59c..d594d3bdb7 100644 --- a/plugins/permission-node/src/policy/types.ts +++ b/plugins/permission-node/src/policy/types.ts @@ -19,7 +19,7 @@ import { AuthorizeResult, PermissionCondition, PermissionCriteria, -} from '@backstage/permission-common'; +} from '@backstage/plugin-permission-common'; import { BackstageIdentity } from '@backstage/plugin-auth-backend'; /** diff --git a/plugins/permission-node/src/types.ts b/plugins/permission-node/src/types.ts index 308eafe481..d3379c40a6 100644 --- a/plugins/permission-node/src/types.ts +++ b/plugins/permission-node/src/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { PermissionCriteria } from '@backstage/permission-common'; +import type { PermissionCriteria } from '@backstage/plugin-permission-common'; /** * A conditional rule that can be provided in an {@link AuthorizeResult} response to an From 75dd00c8b627b4d80e1b1c0ca714897ff6a9af5e Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 12 Nov 2021 12:37:23 +0000 Subject: [PATCH 099/138] authz: add missing fields to permission-node package.json Signed-off-by: Mike Lewis --- plugins/permission-node/package.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index eaf9efdbba..4e17d7ecfb 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -10,6 +10,16 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/permission-node" + }, + "keywords": [ + "backstage", + "permissions" + ], "scripts": { "build": "backstage-cli backend:build", "lint": "backstage-cli lint", From 5c5a1d16e41ee5e1baddba44bcaa7d95e5fcaa07 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 12 Nov 2021 13:43:59 +0000 Subject: [PATCH 100/138] authz: remove superfluous union type PermissionCriteria is a union type which already includes TQuery itself, so we don't need a second union here. Signed-off-by: Mike Lewis --- plugins/permission-node/api-report.md | 2 +- plugins/permission-node/src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index 0044807857..4ee8953d70 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -99,7 +99,7 @@ export type PermissionRule< name: string; description: string; apply(resource: TResource, ...params: TParams): boolean; - toQuery(...params: TParams): TQuery | PermissionCriteria; + toQuery(...params: TParams): PermissionCriteria; }; // @public diff --git a/plugins/permission-node/src/types.ts b/plugins/permission-node/src/types.ts index d3379c40a6..f983c80ea5 100644 --- a/plugins/permission-node/src/types.ts +++ b/plugins/permission-node/src/types.ts @@ -49,5 +49,5 @@ export type PermissionRule< * can be used for loading a collection of resources efficiently with conditional criteria already * applied. */ - toQuery(...params: TParams): TQuery | PermissionCriteria; + toQuery(...params: TParams): PermissionCriteria; }; From 27d5f5fed3e4343f2f2389fa5ba57ebf9e496550 Mon Sep 17 00:00:00 2001 From: Tim Hansen Date: Wed, 17 Nov 2021 11:17:50 -0700 Subject: [PATCH 101/138] Improve api-report Signed-off-by: Tim Hansen --- plugins/permission-node/api-report.md | 44 ++++++++++------ plugins/permission-node/package.json | 1 + .../src/integration/conditionFor.ts | 13 +++++ .../createPermissionIntegration.ts | 50 +++++++++++++++++-- plugins/permission-node/src/policy/index.ts | 1 + plugins/permission-node/src/policy/types.ts | 10 ++-- plugins/permission-node/src/types.ts | 4 +- 7 files changed, 97 insertions(+), 26 deletions(-) diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index 4ee8953d70..a292f6acd2 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -17,8 +17,15 @@ export type ApplyConditionsRequest = { conditions: PermissionCriteria; }; -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-permission-node" does not have an export "AuthorizeResult" -// +// @public +export type Condition = TRule extends PermissionRule< + any, + any, + infer TParams +> + ? (...params: TParams) => PermissionCondition + : never; + // @public export type ConditionalPolicyResult = { result: AuthorizeResult.CONDITIONAL; @@ -29,9 +36,7 @@ export type ConditionalPolicyResult = { }; }; -// Warning: (ae-missing-release-tag) "conditionFor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const conditionFor: ( rule: PermissionRule, ) => (...params: TParams) => { @@ -39,9 +44,14 @@ export const conditionFor: ( params: TParams; }; -// Warning: (ae-missing-release-tag) "createPermissionIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public +export type Conditions< + TRules extends Record>, +> = { + [Name in keyof TRules]: Condition; +}; + +// @public export const createPermissionIntegration: < TResource, TRules extends { @@ -79,8 +89,6 @@ export const createPermissionIntegration: < // @public export interface PermissionPolicy { - // Warning: (ae-forgotten-export) The symbol "PolicyAuthorizeRequest" needs to be exported by the entry point index.d.ts - // // (undocumented) handle( request: PolicyAuthorizeRequest, @@ -88,8 +96,6 @@ export interface PermissionPolicy { ): Promise; } -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-permission-node" does not have an export "AuthorizeResult" -// // @public export type PermissionRule< TResource, @@ -102,6 +108,9 @@ export type PermissionRule< toQuery(...params: TParams): PermissionCriteria; }; +// @public +export type PolicyAuthorizeRequest = Omit; + // @public export type PolicyResult = | { @@ -109,8 +118,11 @@ export type PolicyResult = } | ConditionalPolicyResult; -// Warnings were encountered during analysis: -// -// src/integration/createPermissionIntegration.d.ts:28:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts -// src/integration/createPermissionIntegration.d.ts:29:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts +// @public +export type QueryType = TRules extends Record< + string, + PermissionRule +> + ? TQuery + : never; ``` diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 4e17d7ecfb..830c945158 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -8,6 +8,7 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, "homepage": "https://backstage.io", diff --git a/plugins/permission-node/src/integration/conditionFor.ts b/plugins/permission-node/src/integration/conditionFor.ts index 3a13a3afe3..7451b35bca 100644 --- a/plugins/permission-node/src/integration/conditionFor.ts +++ b/plugins/permission-node/src/integration/conditionFor.ts @@ -16,6 +16,19 @@ import { PermissionRule } from '../types'; +/** + * Creates a condition function for a given authorization rule and parameter type. + * + * For example, an isEntityOwner rule for catalog entities might take an array of entityRef strings. + * The rule itself defines _how_ to check a given resource, whereas a condition also includes _what_ + * to verify. + * + * Plugin authors should generally use the {@link createPermissionIntegration} helper, which creates + * conditions for the rules supplied. However, a different plugin can also add rules to this + * integration (using the returned `registerPermissionRule` from this function), and create the + * condition to be used in an {@link PermissionPolicy} using this method directly. + * @public + */ export const conditionFor = (rule: PermissionRule) => (...params: TParams) => ({ diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.ts b/plugins/permission-node/src/integration/createPermissionIntegration.ts index 7a7ae0ea4b..72118572e5 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegration.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegration.ts @@ -56,21 +56,65 @@ export type ApplyConditionsRequest = { conditions: PermissionCriteria; }; -type Condition = TRule extends PermissionRule +/** + * An authorization condition, which is a function to evaluate a given {@link PermissionRule} with + * a specific set of parameters. + * @see createPermissionIntegration + * @public + */ +export type Condition = TRule extends PermissionRule< + any, + any, + infer TParams +> ? (...params: TParams) => PermissionCondition : never; -type Conditions>> = { +/** + * A collection of keyed {@link Condition} functions produced from {@link PermissionRule}. + * @see createPermissionIntegration + * @public + */ +export type Conditions< + TRules extends Record>, +> = { [Name in keyof TRules]: Condition; }; -type QueryType = TRules extends Record< +/** + * The plugin-specific type which authorization conditions are translated into, for plugin use in + * filtering resources. + * @public + */ +export type QueryType = TRules extends Record< string, PermissionRule > ? TQuery : never; +/** + * Create a permission and authorization integration for a plugin that supports _conditional + * authorization_ for resources. + * + * To make this concrete, we can use the Backstage software catalog as an example. The catalog has + * conditional rules around access to specific _entities_ in the catalog. The _type_ of resource is + * captured here as `resourceType`, a string identifier (`catalog-entity` in this example) that can + * be provided with permission definitions. This is merely a _type_ to verify that conditions in an + * authorization policy are constructed correctly, not a reference to a specific resource. + * + * The `rules` are a map of {@link PermissionRule} that introduce conditional filtering logic for + * resources; for the catalog, these are things like `isEntityOwner` or `hasAnnotation`. Rules + * describe how to filter a list of resources, and the `conditions` returned allow these rules to be + * applied with specific parameters (such as 'group:default/team-a', or 'backstage.io/edit-url'). + * + * The `getResource` argument should load a resource by reference. For the catalog, this is an + * {@link @backstage/catalog-model#EntityRef}. For other plugins, this can be any serialized format. + * This is used to construct the `createPermissionIntegrationRouter`, a function to add an + * authorization route to your backend plugin. This route will be called by the `permission-backend` + * when authorization conditions relating to this plugin need to be evaluated. + * @public + */ export const createPermissionIntegration = < TResource, TRules extends { [key: string]: PermissionRule }, diff --git a/plugins/permission-node/src/policy/index.ts b/plugins/permission-node/src/policy/index.ts index 226d50df21..f04c2a094c 100644 --- a/plugins/permission-node/src/policy/index.ts +++ b/plugins/permission-node/src/policy/index.ts @@ -17,5 +17,6 @@ export type { ConditionalPolicyResult, PermissionPolicy, + PolicyAuthorizeRequest, PolicyResult, } from './types'; diff --git a/plugins/permission-node/src/policy/types.ts b/plugins/permission-node/src/policy/types.ts index d594d3bdb7..36186d5e57 100644 --- a/plugins/permission-node/src/policy/types.ts +++ b/plugins/permission-node/src/policy/types.ts @@ -25,9 +25,9 @@ import { BackstageIdentity } from '@backstage/plugin-auth-backend'; /** * An authorization request to be evaluated by the {@link PermissionPolicy}. * - * This differs from {@link AuthorizeRequest} in that `resourceRef` should never be provided. This - * forces policies to be written in a way that's compatible with filtering collections of resources - * at data load time. + * This differs from {@link @backstage/permission-common#AuthorizeRequest} in that `resourceRef` + * should never be provided. This forces policies to be written in a way that's compatible with + * filtering collections of resources at data load time. * @public */ export type PolicyAuthorizeRequest = Omit; @@ -39,8 +39,8 @@ export type PolicyAuthorizeRequest = Omit; * conditions hold when evaluated. The conditions will be evaluated by the corresponding plugin * which knows about the referenced permission rules. * - * Similar to {@link AuthorizeResult}, but with the plugin and resource identifiers needed to - * evaluate the returned conditions. + * Similar to {@link @backstage/permission-common#AuthorizeResult}, but with the plugin and resource + * identifiers needed to evaluate the returned conditions. * @public */ export type ConditionalPolicyResult = { diff --git a/plugins/permission-node/src/types.ts b/plugins/permission-node/src/types.ts index f983c80ea5..a4e95fbd61 100644 --- a/plugins/permission-node/src/types.ts +++ b/plugins/permission-node/src/types.ts @@ -17,8 +17,8 @@ import type { PermissionCriteria } from '@backstage/plugin-permission-common'; /** - * A conditional rule that can be provided in an {@link AuthorizeResult} response to an - * authorization request. + * A conditional rule that can be provided in an + * {@link @backstage/permission-common#AuthorizeResult} response to an authorization request. * * Rules can either be evaluated against a resource loaded in memory, or used as filters when * loading a collection of resources from a data source. The `apply` and `toQuery` methods implement From 0eb339c3a482cab5ac323d9cd89e0db7d3bf8809 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Thu, 18 Nov 2021 13:54:28 +0000 Subject: [PATCH 102/138] permission-node: more visible condition transform in mapCriteria test Signed-off-by: Mike Lewis --- .../src/integration/util.test.ts | 43 ++++++------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/plugins/permission-node/src/integration/util.test.ts b/plugins/permission-node/src/integration/util.test.ts index 93f51d8275..72e87b2a7b 100644 --- a/plugins/permission-node/src/integration/util.test.ts +++ b/plugins/permission-node/src/integration/util.test.ts @@ -25,21 +25,21 @@ describe('integration utils', () => { criteria: PermissionCriteria; expectedResult: { applyConditions: boolean; - mapConditions: PermissionCriteria<{ query: string; params: unknown[] }>; + mapConditions: PermissionCriteria; }; }[] = [ { criteria: { rule: 'test-rule-1', params: [] }, expectedResult: { applyConditions: true, - mapConditions: { query: 'test-rule-1', params: [] }, + mapConditions: 'test-rule-1', }, }, { criteria: { rule: 'test-rule-2', params: [] }, expectedResult: { applyConditions: false, - mapConditions: { query: 'test-rule-2', params: [] }, + mapConditions: 'test-rule-2', }, }, { @@ -52,10 +52,7 @@ describe('integration utils', () => { expectedResult: { applyConditions: true, mapConditions: { - anyOf: [ - { query: 'test-rule-1', params: ['a', 'b'] }, - { query: 'test-rule-2', params: ['c', 'd'] }, - ], + anyOf: ['test-rule-1:a,b', 'test-rule-2:c,d'], }, }, }, @@ -69,10 +66,7 @@ describe('integration utils', () => { expectedResult: { applyConditions: false, mapConditions: { - allOf: [ - { query: 'test-rule-1', params: ['e', 'f'] }, - { query: 'test-rule-2', params: ['g', 'h'] }, - ], + allOf: ['test-rule-1:e,f', 'test-rule-2:g,h'], }, }, }, @@ -83,7 +77,7 @@ describe('integration utils', () => { expectedResult: { applyConditions: true, mapConditions: { - not: { query: 'test-rule-2', params: ['i'] }, + not: 'test-rule-2:i', }, }, }, @@ -111,17 +105,11 @@ describe('integration utils', () => { mapConditions: { allOf: [ { - anyOf: [ - { query: 'test-rule-1', params: ['j'] }, - { query: 'test-rule-2', params: ['k'] }, - ], + anyOf: ['test-rule-1:j', 'test-rule-2:k'], }, { not: { - allOf: [ - { query: 'test-rule-1', params: ['l'] }, - { query: 'test-rule-2', params: ['m'] }, - ], + allOf: ['test-rule-1:l', 'test-rule-2:m'], }, }, ], @@ -152,17 +140,11 @@ describe('integration utils', () => { mapConditions: { allOf: [ { - anyOf: [ - { query: 'test-rule-1', params: ['j'] }, - { query: 'test-rule-2', params: ['k'] }, - ], + anyOf: ['test-rule-1:j', 'test-rule-2:k'], }, { not: { - allOf: [ - { query: 'test-rule-1', params: ['l'] }, - { not: { query: 'test-rule-2', params: ['m'] } }, - ], + allOf: ['test-rule-1:l', { not: 'test-rule-2:m' }], }, }, ], @@ -194,7 +176,10 @@ describe('integration utils', () => { }); describe('mapConditions', () => { - const mapFn = jest.fn(({ rule, params }) => ({ query: rule, params })); + const mapFn = jest.fn( + ({ rule, params }) => + `${rule}${params.length ? `:${params.join(',')}` : ''}`, + ); it('invokes mapFn to transform conditions', () => { mapConditions({ rule: 'test-rule-1', params: ['foo', 'bar'] }, mapFn); From 70ce7c91e269d8ed84405daae49eed3096da6ff6 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 19 Nov 2021 18:40:41 +0000 Subject: [PATCH 103/138] permission-node: bump @backstage/cli version Signed-off-by: Mike Lewis --- plugins/permission-node/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 830c945158..79923eae97 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -37,7 +37,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.8.1", + "@backstage/cli": "^0.9.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, From 3254303a96937f9b346ae9259107a823c6d78b9e Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 19 Nov 2021 13:43:59 +0000 Subject: [PATCH 104/138] permission-node: refactor and split createPermissionIntegration This refactor makes the createPermissionIntegration system much more flexible by splitting it up into a few different helpers with different responsibilities. This frees up plugin authors to connect together the different parts of the permission integration in whatever way is convenient for them, and makes the process of registering additional permission rules a bit more explicit, by requiring them to be passed in when constructing the systems for transforming or applying conditions. Signed-off-by: Mike Lewis Co-authored-by: Joon Park Co-authored-by: Tim Hansen --- plugins/permission-node/api-report.md | 67 ++-- plugins/permission-node/package.json | 3 +- .../createConditionExports.test.ts | 79 +++++ .../src/integration/createConditionExports.ts | 94 ++++++ ...test.ts => createConditionFactory.test.ts} | 8 +- ...ditionFor.ts => createConditionFactory.ts} | 13 +- .../createConditionTransformer.test.ts | 158 ++++++++++ .../integration/createConditionTransformer.ts | 78 +++++ .../createPermissionIntegration.test.ts | 293 ------------------ .../createPermissionIntegration.ts | 242 --------------- .../createPermissionIntegrationRouter.test.ts | 210 +++++++++++++ .../createPermissionIntegrationRouter.ts | 165 ++++++++++ .../permission-node/src/integration/index.ts | 6 +- .../src/integration/util.test.ts | 230 ++++---------- .../permission-node/src/integration/util.ts | 53 +--- 15 files changed, 908 insertions(+), 791 deletions(-) create mode 100644 plugins/permission-node/src/integration/createConditionExports.test.ts create mode 100644 plugins/permission-node/src/integration/createConditionExports.ts rename plugins/permission-node/src/integration/{conditionFor.test.ts => createConditionFactory.test.ts} (80%) rename plugins/permission-node/src/integration/{conditionFor.ts => createConditionFactory.ts} (68%) create mode 100644 plugins/permission-node/src/integration/createConditionTransformer.test.ts create mode 100644 plugins/permission-node/src/integration/createConditionTransformer.ts delete mode 100644 plugins/permission-node/src/integration/createPermissionIntegration.test.ts delete mode 100644 plugins/permission-node/src/integration/createPermissionIntegration.ts create mode 100644 plugins/permission-node/src/integration/createPermissionIntegrationRouter.test.ts create mode 100644 plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index a292f6acd2..1aab9e1f47 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -36,14 +36,6 @@ export type ConditionalPolicyResult = { }; }; -// @public -export const conditionFor: ( - rule: PermissionRule, -) => (...params: TParams) => { - rule: string; - params: TParams; -}; - // @public export type Conditions< TRules extends Record>, @@ -52,41 +44,58 @@ export type Conditions< }; // @public -export const createPermissionIntegration: < +export type ConditionTransformer = ( + conditions: PermissionCriteria, +) => PermissionCriteria; + +// @public +export const createConditionExports: < TResource, - TRules extends { - [key: string]: PermissionRule; - }, - TGetResourceParams extends any[] = [], + TRules extends Record>, >({ pluginId, resourceType, rules, - getResource, }: { pluginId: string; resourceType: string; rules: TRules; - getResource: ( - resourceRef: string, - ...params: TGetResourceParams - ) => Promise; }) => { - createPermissionIntegrationRouter: (...params: TGetResourceParams) => Router; - toQuery: ( - conditions: PermissionCriteria, - ) => PermissionCriteria>; conditions: Conditions; createConditions: (conditions: PermissionCriteria) => { pluginId: string; resourceType: string; conditions: PermissionCriteria; }; - registerPermissionRule: ( - rule: PermissionRule, unknown[]>, - ) => void; }; +// @public +export const createConditionFactory: ( + rule: PermissionRule, +) => (...params: TParams) => { + rule: string; + params: TParams; +}; + +// @public +export const createConditionTransformer: < + TQuery, + TRules extends PermissionRule[], +>( + permissionRules: [...TRules], +) => ConditionTransformer; + +// @public +export const createPermissionIntegrationRouter: ({ + resourceType, + rules, + getResource, +}: { + resourceType: string; + rules: PermissionRule[]; + getResource: (resourceRef: string) => Promise; +}) => Router; + // @public export interface PermissionPolicy { // (undocumented) @@ -117,12 +126,4 @@ export type PolicyResult = result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; } | ConditionalPolicyResult; - -// @public -export type QueryType = TRules extends Record< - string, - PermissionRule -> - ? TQuery - : never; ``` diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 79923eae97..4a9c837eb6 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -8,7 +8,6 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, "homepage": "https://backstage.io", @@ -32,7 +31,7 @@ "dependencies": { "@backstage/plugin-auth-backend": "^0.4.6", "@backstage/plugin-permission-common": "^0.1.0", - "@types/express": "*", + "@types/express": "^4.17.6", "express": "^4.17.1", "zod": "^3.11.6" }, diff --git a/plugins/permission-node/src/integration/createConditionExports.test.ts b/plugins/permission-node/src/integration/createConditionExports.test.ts new file mode 100644 index 0000000000..6f0f8f8632 --- /dev/null +++ b/plugins/permission-node/src/integration/createConditionExports.test.ts @@ -0,0 +1,79 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createConditionExports } from './createConditionExports'; + +const testIntegration = () => + createConditionExports({ + pluginId: 'test-plugin', + resourceType: 'test-resource', + rules: { + testRule1: { + name: 'testRule1', + description: 'Test rule 1', + apply: jest.fn( + (_resource: any, _firstParam: string, _secondParam: number) => true, + ), + toQuery: jest.fn((firstParam: string, secondParam: number) => ({ + query: 'testRule1', + params: [firstParam, secondParam], + })), + }, + testRule2: { + name: 'testRule2', + description: 'Test rule 2', + apply: jest.fn((_firstParam: object) => false), + toQuery: jest.fn((firstParam: object) => ({ + query: 'testRule2', + params: [firstParam], + })), + }, + }, + }); + +describe('createConditionExports', () => { + describe('conditions', () => { + it('creates condition factories for the supplied rules', () => { + const { conditions } = testIntegration(); + + expect(conditions.testRule1('a', 1)).toEqual({ + rule: 'testRule1', + params: ['a', 1], + }); + + expect(conditions.testRule2({ baz: 'quux' })).toEqual({ + rule: 'testRule2', + params: [{ baz: 'quux' }], + }); + }); + }); + + describe('createConditions', () => { + it('wraps conditions in an object with resourceType and pluginId', () => { + const { createConditions } = testIntegration(); + + expect( + createConditions({ allOf: [{ rule: 'testRule1', params: ['a', 1] }] }), + ).toEqual({ + pluginId: 'test-plugin', + resourceType: 'test-resource', + conditions: { + allOf: [{ rule: 'testRule1', params: ['a', 1] }], + }, + }); + }); + }); +}); diff --git a/plugins/permission-node/src/integration/createConditionExports.ts b/plugins/permission-node/src/integration/createConditionExports.ts new file mode 100644 index 0000000000..d7f8c675d2 --- /dev/null +++ b/plugins/permission-node/src/integration/createConditionExports.ts @@ -0,0 +1,94 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + PermissionCondition, + PermissionCriteria, +} from '@backstage/plugin-permission-common'; +import { PermissionRule } from '../types'; +import { createConditionFactory } from './createConditionFactory'; + +/** + * A utility type for mapping a single {@link PermissionRule} to its + * corresponding {@link @backstage/plugin-permission-common#PermissionCondition}. + * + * @public + */ +export type Condition = TRule extends PermissionRule< + any, + any, + infer TParams +> + ? (...params: TParams) => PermissionCondition + : never; + +/** + * A utility type for mapping {@link PermissionRule}s to their corresponding + * {@link @backstage/plugin-permission-common#PermissionCondition}s. + * + * @public + */ +export type Conditions< + TRules extends Record>, +> = { + [Name in keyof TRules]: Condition; +}; + +/** + * Creates the recommended condition-related exports for a given plugin based on the built-in + * {@link PermissionRule}s it supports. It returns a `conditions` object containing a + * {@link @backstage/plugin-permission-common#PermissionCondition} factory for each of the + * supplied {@link PermissionRule}s, along with a `createConditions` function which builds the + * wrapper object needed to enclose conditions when authoring {@link PermissionPolicy} implementations. + * + * Plugin authors should generally call this method with all the built-in {@link PermissionRule}s + * the plugin supports, and export the resulting `conditions` object and `createConditions` + * function so that they can be used by {@link PermissionPolicy} authors. + * + * @public + */ +export const createConditionExports = < + TResource, + TRules extends Record>, +>({ + pluginId, + resourceType, + rules, +}: { + pluginId: string; + resourceType: string; + rules: TRules; +}): { + conditions: Conditions; + createConditions: (conditions: PermissionCriteria) => { + pluginId: string; + resourceType: string; + conditions: PermissionCriteria; + }; +} => ({ + conditions: Object.entries(rules).reduce( + (acc, [key, rule]) => ({ + ...acc, + [key]: createConditionFactory(rule), + }), + {} as Conditions, + ), + createConditions: (conditions: PermissionCriteria) => ({ + pluginId, + resourceType, + conditions, + }), +}); diff --git a/plugins/permission-node/src/integration/conditionFor.test.ts b/plugins/permission-node/src/integration/createConditionFactory.test.ts similarity index 80% rename from plugins/permission-node/src/integration/conditionFor.test.ts rename to plugins/permission-node/src/integration/createConditionFactory.test.ts index d1099e7555..8dd43f5da6 100644 --- a/plugins/permission-node/src/integration/conditionFor.test.ts +++ b/plugins/permission-node/src/integration/createConditionFactory.test.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import { conditionFor } from './conditionFor'; +import { createConditionFactory } from './createConditionFactory'; -describe('conditionFor', () => { +describe('createConditionFactory', () => { const testRule = { name: 'test-rule', description: 'test-description', @@ -25,12 +25,12 @@ describe('conditionFor', () => { }; it('returns a function', () => { - expect(conditionFor(testRule)).toEqual(expect.any(Function)); + expect(createConditionFactory(testRule)).toEqual(expect.any(Function)); }); describe('return value', () => { it('constructs a condition with the rule name and supplied params', () => { - const conditionFactory = conditionFor(testRule); + const conditionFactory = createConditionFactory(testRule); expect(conditionFactory('a', 'b', 1, 2)).toEqual({ rule: 'test-rule', params: ['a', 'b', 1, 2], diff --git a/plugins/permission-node/src/integration/conditionFor.ts b/plugins/permission-node/src/integration/createConditionFactory.ts similarity index 68% rename from plugins/permission-node/src/integration/conditionFor.ts rename to plugins/permission-node/src/integration/createConditionFactory.ts index 7451b35bca..066233bf41 100644 --- a/plugins/permission-node/src/integration/conditionFor.ts +++ b/plugins/permission-node/src/integration/createConditionFactory.ts @@ -17,19 +17,20 @@ import { PermissionRule } from '../types'; /** - * Creates a condition function for a given authorization rule and parameter type. + * Creates a condition factory function for a given authorization rule and parameter types. * * For example, an isEntityOwner rule for catalog entities might take an array of entityRef strings. * The rule itself defines _how_ to check a given resource, whereas a condition also includes _what_ * to verify. * - * Plugin authors should generally use the {@link createPermissionIntegration} helper, which creates - * conditions for the rules supplied. However, a different plugin can also add rules to this - * integration (using the returned `registerPermissionRule` from this function), and create the - * condition to be used in an {@link PermissionPolicy} using this method directly. + * Plugin authors should generally use the {@link createConditionExports} in order to efficiently + * create multiple condition factories. This helper should generally only be used to construct + * condition factories for third-party rules that aren't part of the backend plugin with which + * they're intended to integrate with. + * * @public */ -export const conditionFor = +export const createConditionFactory = (rule: PermissionRule) => (...params: TParams) => ({ rule: rule.name, diff --git a/plugins/permission-node/src/integration/createConditionTransformer.test.ts b/plugins/permission-node/src/integration/createConditionTransformer.test.ts new file mode 100644 index 0000000000..8a93a4ea27 --- /dev/null +++ b/plugins/permission-node/src/integration/createConditionTransformer.test.ts @@ -0,0 +1,158 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + PermissionCondition, + PermissionCriteria, +} from '@backstage/plugin-permission-common'; +import { createConditionTransformer } from './createConditionTransformer'; + +const transformConditions = createConditionTransformer([ + { + name: 'test-rule-1', + description: 'Test rule 1', + apply: jest.fn(), + toQuery: jest.fn( + (firstParam: string, secondParam: number) => + `test-rule-1:${firstParam}/${secondParam}`, + ), + }, + { + name: 'test-rule-2', + description: 'Test rule 2', + apply: jest.fn(), + toQuery: jest.fn( + (firstParam: object) => `test-rule-2:${JSON.stringify(firstParam)}`, + ), + }, +]); + +describe('createConditionTransformer', () => { + const testCases: { + conditions: PermissionCriteria; + expectedResult: PermissionCriteria; + }[] = [ + { + conditions: { rule: 'test-rule-1', params: ['abc', 123] }, + expectedResult: 'test-rule-1:abc/123', + }, + { + conditions: { rule: 'test-rule-2', params: [{ foo: 0 }] }, + expectedResult: 'test-rule-2:{"foo":0}', + }, + { + conditions: { + anyOf: [ + { rule: 'test-rule-1', params: ['a', 1] }, + { rule: 'test-rule-2', params: [{}] }, + ], + }, + expectedResult: { + anyOf: ['test-rule-1:a/1', 'test-rule-2:{}'], + }, + }, + { + conditions: { + allOf: [ + { rule: 'test-rule-1', params: ['a', 1] }, + { rule: 'test-rule-2', params: [{}] }, + ], + }, + expectedResult: { + allOf: ['test-rule-1:a/1', 'test-rule-2:{}'], + }, + }, + { + conditions: { + not: { rule: 'test-rule-2', params: [{}] }, + }, + expectedResult: { + not: 'test-rule-2:{}', + }, + }, + { + conditions: { + allOf: [ + { + anyOf: [ + { rule: 'test-rule-1', params: ['a', 1] }, + { rule: 'test-rule-2', params: [{}] }, + ], + }, + { + not: { + allOf: [ + { rule: 'test-rule-1', params: ['b', 2] }, + { rule: 'test-rule-2', params: [{ c: 3 }] }, + ], + }, + }, + ], + }, + expectedResult: { + allOf: [ + { + anyOf: ['test-rule-1:a/1', 'test-rule-2:{}'], + }, + { + not: { + allOf: ['test-rule-1:b/2', 'test-rule-2:{"c":3}'], + }, + }, + ], + }, + }, + { + conditions: { + allOf: [ + { + anyOf: [ + { rule: 'test-rule-1', params: ['a', 1] }, + { rule: 'test-rule-2', params: [{ b: 2 }] }, + ], + }, + { + not: { + allOf: [ + { rule: 'test-rule-1', params: ['c', 3] }, + { not: { rule: 'test-rule-2', params: [{ d: 4 }] } }, + ], + }, + }, + ], + }, + expectedResult: { + allOf: [ + { + anyOf: ['test-rule-1:a/1', 'test-rule-2:{"b":2}'], + }, + { + not: { + allOf: ['test-rule-1:c/3', { not: 'test-rule-2:{"d":4}' }], + }, + }, + ], + }, + }, + ]; + + it.each(testCases)( + 'works with criteria %#', + ({ conditions, expectedResult }) => { + expect(transformConditions(conditions)).toEqual(expectedResult); + }, + ); +}); diff --git a/plugins/permission-node/src/integration/createConditionTransformer.ts b/plugins/permission-node/src/integration/createConditionTransformer.ts new file mode 100644 index 0000000000..0e736b832c --- /dev/null +++ b/plugins/permission-node/src/integration/createConditionTransformer.ts @@ -0,0 +1,78 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + PermissionCondition, + PermissionCriteria, +} from '@backstage/plugin-permission-common'; +import { PermissionRule } from '../types'; +import { + createGetRule, + isAndCriteria, + isNotCriteria, + isOrCriteria, +} from './util'; + +const mapConditions = ( + criteria: PermissionCriteria, + getRule: (name: string) => PermissionRule, +): PermissionCriteria => { + if (isAndCriteria(criteria)) { + return { + allOf: criteria.allOf.map(child => mapConditions(child, getRule)), + }; + } else if (isOrCriteria(criteria)) { + return { + anyOf: criteria.anyOf.map(child => mapConditions(child, getRule)), + }; + } else if (isNotCriteria(criteria)) { + return { + not: mapConditions(criteria.not, getRule), + }; + } + + return getRule(criteria.rule).toQuery(...criteria.params); +}; + +/** + * A function which accepts {@link @backstage/plugin-permission-common#PermissionCondition}s + * logically grouped in a {@link @backstage/plugin-permission-common#PermissionCriteria} + * object, and transforms the {@link @backstage/plugin-permission-common#PermissionCondition}s + * into plugin specific query fragments while retaining the enclosing criteria shape. + * + * @public + */ +export type ConditionTransformer = ( + conditions: PermissionCriteria, +) => PermissionCriteria; + +/** + * A higher-order helper function which accepts an array of + * {@link PermissionRule}s, and returns a {@link ConditionTransformer} + * which transforms input conditions into equivalent plugin-specific + * query fragments using the supplied rules. + * + * @public + */ +export const createConditionTransformer = < + TQuery, + TRules extends PermissionRule[], +>( + permissionRules: [...TRules], +): ConditionTransformer => { + const getRule = createGetRule(permissionRules); + + return conditions => mapConditions(conditions, getRule); +}; diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.test.ts b/plugins/permission-node/src/integration/createPermissionIntegration.test.ts deleted file mode 100644 index 1ef310954f..0000000000 --- a/plugins/permission-node/src/integration/createPermissionIntegration.test.ts +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AuthorizeResult } from '@backstage/plugin-permission-common'; -import express, { Express, Router } from 'express'; -import request from 'supertest'; -import { createPermissionIntegration } from './createPermissionIntegration'; - -const mockGetResource: jest.MockedFunction< - (resourceRef: string) => Promise -> = jest.fn((resourceRef: string) => - Promise.resolve({ - resourceRef, - }), -); - -const testIntegration = () => - createPermissionIntegration({ - pluginId: 'test-plugin', - resourceType: 'test-resource', - getResource: mockGetResource, - rules: { - testRule1: { - name: 'testRule1', - description: 'Test rule 1', - apply: jest.fn( - (_resource: any, _firstParam: string, _secondParam: number) => true, - ), - toQuery: jest.fn((firstParam: string, secondParam: number) => ({ - query: 'testRule1', - params: [firstParam, secondParam], - })), - }, - testRule2: { - name: 'testRule2', - description: 'Test rule 2', - apply: jest.fn((_firstParam: object) => false), - toQuery: jest.fn((firstParam: object) => ({ - query: 'testRule2', - params: [firstParam], - })), - }, - }, - }); - -describe('createPermissionIntegration', () => { - describe('createPermissionIntegrationRouter', () => { - let app: Express; - let router: Router; - - beforeEach(() => { - const { createPermissionIntegrationRouter } = testIntegration(); - - router = createPermissionIntegrationRouter(); - app = express().use(router); - }); - - it('works', async () => { - expect(router).toBeDefined(); - }); - - describe('POST /permissions/apply-conditions', () => { - it('returns 200/ALLOW when criteria match', async () => { - const response = await request(app) - .post('/permissions/apply-conditions') - .send({ - resourceRef: 'default:test/resource', - resourceType: 'test-resource', - conditions: { - rule: 'testRule1', - params: ['a', 1], - }, - }); - - expect(response.status).toEqual(200); - expect(response.body).toEqual({ result: AuthorizeResult.ALLOW }); - }); - - it('returns 200/DENY when criteria do not match', async () => { - const response = await request(app) - .post('/permissions/apply-conditions') - .send({ - resourceRef: 'default:test/resource', - resourceType: 'test-resource', - conditions: { - anyOf: [], - }, - }); - - expect(response.status).toEqual(200); - expect(response.body).toEqual({ result: AuthorizeResult.DENY }); - }); - - it('returns 400 when called with incorrect resource type', async () => { - const response = await request(app) - .post('/permissions/apply-conditions') - .send({ - resourceRef: 'default:test/resource', - resourceType: 'test-incorrect-resource', - conditions: { - anyOf: [], - }, - }); - - expect(response.status).toEqual(400); - expect(response.error && response.error.text).toMatch( - /unexpected resource type: test-incorrect-resource/i, - ); - }); - - it('returns 400 when resource is not found', async () => { - mockGetResource.mockReturnValueOnce(Promise.resolve(undefined)); - - const response = await request(app) - .post('/permissions/apply-conditions') - .send({ - resourceRef: 'default:test/resource', - resourceType: 'test-resource', - conditions: { - not: { - rule: 'testRule1', - params: ['a', 1], - }, - }, - }); - - expect(response.status).toEqual(400); - expect(response.error && response.error.text).toMatch( - /resource for ref default:test\/resource not found/i, - ); - }); - - it.each([ - undefined, - {}, - { resourceType: 'test-resource-type' }, - { resourceRef: 'test/resource-ref' }, - { - resourceType: 'test-resource-type', - resourceRef: 'test/resource-ref', - }, - { conditions: { anyOf: [] } }, - ])(`returns 400 for invalid input %#`, async input => { - const response = await request(app) - .post('/permissions/apply-conditions') - .send(input); - - expect(response.status).toEqual(400); - expect(response.error && response.error.text).toMatch( - /invalid request body/i, - ); - }); - }); - }); - - describe('toQuery', () => { - it('converts conditions to plugin-specific queries using rule toQuery methods', () => { - const { toQuery } = testIntegration(); - - expect( - toQuery({ - anyOf: [ - { - allOf: [ - { rule: 'testRule1', params: ['a', 1] }, - { rule: 'testRule2', params: [{ foo: 'bar' }] }, - ], - }, - { - not: { rule: 'testRule1', params: ['b', 2] }, - }, - ], - }), - ).toEqual({ - anyOf: [ - { - allOf: [ - { query: 'testRule1', params: ['a', 1] }, - { query: 'testRule2', params: [{ foo: 'bar' }] }, - ], - }, - { - not: { query: 'testRule1', params: ['b', 2] }, - }, - ], - }); - }); - }); - - describe('conditions', () => { - it('creates condition factories for the supplied rules', () => { - const { conditions } = testIntegration(); - - expect(conditions.testRule1('a', 1)).toEqual({ - rule: 'testRule1', - params: ['a', 1], - }); - - expect(conditions.testRule2({ baz: 'quux' })).toEqual({ - rule: 'testRule2', - params: [{ baz: 'quux' }], - }); - }); - }); - - describe('createConditions', () => { - it('wraps conditions in an object with resourceType and pluginId', () => { - const { createConditions } = testIntegration(); - - expect( - createConditions({ allOf: [{ rule: 'testRule1', params: ['a', 1] }] }), - ).toEqual({ - pluginId: 'test-plugin', - resourceType: 'test-resource', - conditions: { - allOf: [{ rule: 'testRule1', params: ['a', 1] }], - }, - }); - }); - }); - - describe('registerPermissionRule', () => { - it('adds support for the new rule in toQuery', () => { - const { registerPermissionRule, toQuery } = testIntegration(); - - registerPermissionRule({ - name: 'testRule3', - description: 'Test rule 3', - apply: jest.fn((_resource: any, _firstParam: string) => false), - toQuery: jest.fn((firstParam: string) => ({ - query: 'testRule3', - params: [firstParam], - })), - }); - - expect( - toQuery({ - rule: 'testRule3', - params: ['abc'], - }), - ).toEqual({ - query: 'testRule3', - params: ['abc'], - }); - }); - - it('adds support for the new rule in the apply-conditions endpoint', async () => { - const { registerPermissionRule, createPermissionIntegrationRouter } = - testIntegration(); - - const app = express().use(createPermissionIntegrationRouter()); - - registerPermissionRule({ - name: 'testRule3', - description: 'Test rule 3', - apply: jest.fn((_resource: any, _firstParam: string) => false), - toQuery: jest.fn((firstParam: string) => ({ - query: 'testRule3', - params: [firstParam], - })), - }); - - const response = await request(app) - .post('/permissions/apply-conditions') - .send({ - resourceRef: 'default:test/resource', - resourceType: 'test-resource', - conditions: { - not: { - rule: 'testRule3', - params: ['a'], - }, - }, - }); - - expect(response.status).toEqual(200); - expect(response.body).toEqual({ result: AuthorizeResult.ALLOW }); - }); - }); -}); diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.ts b/plugins/permission-node/src/integration/createPermissionIntegration.ts deleted file mode 100644 index 72118572e5..0000000000 --- a/plugins/permission-node/src/integration/createPermissionIntegration.ts +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import express, { Response, Router } from 'express'; -import { z } from 'zod'; -import { - AuthorizeResult, - PermissionCondition, - PermissionCriteria, -} from '@backstage/plugin-permission-common'; -import { PermissionRule } from '../types'; -import { conditionFor } from './conditionFor'; -import { applyConditions, mapConditions } from './util'; - -const permissionCriteriaSchema: z.ZodSchema< - PermissionCriteria -> = z.lazy(() => - z.union([ - z.object({ anyOf: z.array(permissionCriteriaSchema) }), - z.object({ allOf: z.array(permissionCriteriaSchema) }), - z.object({ not: permissionCriteriaSchema }), - z.object({ - rule: z.string(), - params: z.array(z.unknown()), - }), - ]), -); - -const applyConditionsRequestSchema = z.object({ - resourceRef: z.string(), - resourceType: z.string(), - conditions: permissionCriteriaSchema, -}); - -/** - * A request to load the referenced resource and apply conditions, to finalize a conditional - * authorization response. - * @public - */ -export type ApplyConditionsRequest = { - resourceRef: string; - resourceType: string; - conditions: PermissionCriteria; -}; - -/** - * An authorization condition, which is a function to evaluate a given {@link PermissionRule} with - * a specific set of parameters. - * @see createPermissionIntegration - * @public - */ -export type Condition = TRule extends PermissionRule< - any, - any, - infer TParams -> - ? (...params: TParams) => PermissionCondition - : never; - -/** - * A collection of keyed {@link Condition} functions produced from {@link PermissionRule}. - * @see createPermissionIntegration - * @public - */ -export type Conditions< - TRules extends Record>, -> = { - [Name in keyof TRules]: Condition; -}; - -/** - * The plugin-specific type which authorization conditions are translated into, for plugin use in - * filtering resources. - * @public - */ -export type QueryType = TRules extends Record< - string, - PermissionRule -> - ? TQuery - : never; - -/** - * Create a permission and authorization integration for a plugin that supports _conditional - * authorization_ for resources. - * - * To make this concrete, we can use the Backstage software catalog as an example. The catalog has - * conditional rules around access to specific _entities_ in the catalog. The _type_ of resource is - * captured here as `resourceType`, a string identifier (`catalog-entity` in this example) that can - * be provided with permission definitions. This is merely a _type_ to verify that conditions in an - * authorization policy are constructed correctly, not a reference to a specific resource. - * - * The `rules` are a map of {@link PermissionRule} that introduce conditional filtering logic for - * resources; for the catalog, these are things like `isEntityOwner` or `hasAnnotation`. Rules - * describe how to filter a list of resources, and the `conditions` returned allow these rules to be - * applied with specific parameters (such as 'group:default/team-a', or 'backstage.io/edit-url'). - * - * The `getResource` argument should load a resource by reference. For the catalog, this is an - * {@link @backstage/catalog-model#EntityRef}. For other plugins, this can be any serialized format. - * This is used to construct the `createPermissionIntegrationRouter`, a function to add an - * authorization route to your backend plugin. This route will be called by the `permission-backend` - * when authorization conditions relating to this plugin need to be evaluated. - * @public - */ -export const createPermissionIntegration = < - TResource, - TRules extends { [key: string]: PermissionRule }, - TGetResourceParams extends any[] = [], ->({ - pluginId, - resourceType, - rules, - getResource, -}: { - pluginId: string; - resourceType: string; - rules: TRules; - getResource: ( - resourceRef: string, - ...params: TGetResourceParams - ) => Promise; -}): { - createPermissionIntegrationRouter: (...params: TGetResourceParams) => Router; - toQuery: ( - conditions: PermissionCriteria, - ) => PermissionCriteria>; - conditions: Conditions; - createConditions: (conditions: PermissionCriteria) => { - pluginId: string; - resourceType: string; - conditions: PermissionCriteria; - }; - registerPermissionRule: ( - rule: PermissionRule>, - ) => void; -} => { - const rulesMap = new Map(Object.values(rules).map(rule => [rule.name, rule])); - - const getRule = (name: string) => { - const rule = rulesMap.get(name); - - if (!rule) { - throw new Error(`Unexpected permission rule: ${name}`); - } - - return rule; - }; - - return { - createPermissionIntegrationRouter: ( - ...getResourceParams: TGetResourceParams - ) => { - const router = Router(); - - router.post( - '/permissions/apply-conditions', - express.json(), - async ( - req, - res: Response< - | { - result: Omit; - } - | string - >, - ) => { - const parseResult = applyConditionsRequestSchema.safeParse(req.body); - - if (!parseResult.success) { - return res.status(400).send(`Invalid request body.`); - } - - const { data: body } = parseResult; - - if (body.resourceType !== resourceType) { - return res - .status(400) - .send(`Unexpected resource type: ${body.resourceType}.`); - } - - const resource = await getResource( - body.resourceRef, - ...getResourceParams, - ); - - if (!resource) { - return res - .status(400) - .send(`Resource for ref ${body.resourceRef} not found.`); - } - - return res.status(200).json({ - result: applyConditions(body.conditions, ({ rule, params }) => - getRule(rule).apply(resource, ...params), - ) - ? AuthorizeResult.ALLOW - : AuthorizeResult.DENY, - }); - }, - ); - - return router; - }, - toQuery: ( - conditions: PermissionCriteria, - ): PermissionCriteria> => { - return mapConditions(conditions, ({ rule, params }) => - getRule(rule).toQuery(...params), - ); - }, - conditions: Object.entries(rules).reduce( - (acc, [key, rule]) => ({ - ...acc, - [key]: conditionFor(rule), - }), - {} as Conditions, - ), - createConditions: ( - conditions: PermissionCriteria, - ) => ({ - pluginId, - resourceType, - conditions, - }), - registerPermissionRule: rule => { - rulesMap.set(rule.name, rule); - }, - }; -}; diff --git a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.test.ts b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.test.ts new file mode 100644 index 0000000000..af216dfcb8 --- /dev/null +++ b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.test.ts @@ -0,0 +1,210 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import express, { Express, Router } from 'express'; +import request from 'supertest'; +import { createPermissionIntegrationRouter } from './createPermissionIntegrationRouter'; + +const mockGetResource: jest.MockedFunction< + (resourceRef: string) => Promise +> = jest.fn((resourceRef: string) => + Promise.resolve({ + resourceRef, + }), +); + +const testRule1 = { + name: 'test-rule-1', + description: 'Test rule 1', + apply: jest.fn( + (_resource: any, _firstParam: string, _secondParam: number) => true, + ), + toQuery: jest.fn(), +}; + +const testRule2 = { + name: 'test-rule-2', + description: 'Test rule 2', + apply: jest.fn((_firstParam: object) => false), + toQuery: jest.fn(), +}; + +describe('createPermissionIntegrationRouter', () => { + let app: Express; + let router: Router; + + beforeEach(() => { + router = createPermissionIntegrationRouter({ + resourceType: 'test-resource', + getResource: mockGetResource, + rules: [testRule1, testRule2], + }); + + app = express().use(router); + }); + + it('works', async () => { + expect(router).toBeDefined(); + }); + + describe('POST /permissions/apply-conditions', () => { + it.each([ + { rule: 'test-rule-1', params: ['abc', 123] }, + { + anyOf: [ + { rule: 'test-rule-1', params: ['a', 1] }, + { rule: 'test-rule-2', params: [{}] }, + ], + }, + + { + not: { rule: 'test-rule-2', params: [{}] }, + }, + { + allOf: [ + { + anyOf: [ + { rule: 'test-rule-1', params: ['a', 1] }, + { rule: 'test-rule-2', params: [{}] }, + ], + }, + { + not: { + allOf: [ + { rule: 'test-rule-1', params: ['b', 2] }, + { rule: 'test-rule-2', params: [{ c: 3 }] }, + ], + }, + }, + ], + }, + ])('returns 200/ALLOW when criteria match (case %#)', async conditions => { + const response = await request(app) + .post('/permissions/apply-conditions') + .send({ + resourceRef: 'default:test/resource', + resourceType: 'test-resource', + conditions, + }); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ result: AuthorizeResult.ALLOW }); + }); + + it.each([ + { rule: 'test-rule-2', params: [{ foo: 0 }] }, + { + allOf: [ + { rule: 'test-rule-1', params: ['a', 1] }, + { rule: 'test-rule-2', params: [{}] }, + ], + }, + { + allOf: [ + { + anyOf: [ + { rule: 'test-rule-1', params: ['a', 1] }, + { rule: 'test-rule-2', params: [{ b: 2 }] }, + ], + }, + { + not: { + allOf: [ + { rule: 'test-rule-1', params: ['c', 3] }, + { not: { rule: 'test-rule-2', params: [{ d: 4 }] } }, + ], + }, + }, + ], + }, + ])( + 'returns 200/DENY when criteria do not match (case %#)', + async conditions => { + const response = await request(app) + .post('/permissions/apply-conditions') + .send({ + resourceRef: 'default:test/resource', + resourceType: 'test-resource', + conditions, + }); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ result: AuthorizeResult.DENY }); + }, + ); + + it('returns 400 when called with incorrect resource type', async () => { + const response = await request(app) + .post('/permissions/apply-conditions') + .send({ + resourceRef: 'default:test/resource', + resourceType: 'test-incorrect-resource', + conditions: { + anyOf: [], + }, + }); + + expect(response.status).toEqual(400); + expect(response.error && response.error.text).toMatch( + /unexpected resource type: test-incorrect-resource/i, + ); + }); + + it('returns 400 when resource is not found', async () => { + mockGetResource.mockReturnValueOnce(Promise.resolve(undefined)); + + const response = await request(app) + .post('/permissions/apply-conditions') + .send({ + resourceRef: 'default:test/resource', + resourceType: 'test-resource', + conditions: { + not: { + rule: 'testRule1', + params: ['a', 1], + }, + }, + }); + + expect(response.status).toEqual(400); + expect(response.error && response.error.text).toMatch( + /resource for ref default:test\/resource not found/i, + ); + }); + + it.each([ + undefined, + {}, + { resourceType: 'test-resource-type' }, + { resourceRef: 'test/resource-ref' }, + { + resourceType: 'test-resource-type', + resourceRef: 'test/resource-ref', + }, + { conditions: { anyOf: [] } }, + ])(`returns 400 for invalid input %#`, async input => { + const response = await request(app) + .post('/permissions/apply-conditions') + .send(input); + + expect(response.status).toEqual(400); + expect(response.error && response.error.text).toMatch( + /invalid request body/i, + ); + }); + }); +}); diff --git a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts new file mode 100644 index 0000000000..6694b893b7 --- /dev/null +++ b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts @@ -0,0 +1,165 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import express, { Response, Router } from 'express'; +import { z } from 'zod'; +import { + AuthorizeResult, + PermissionCondition, + PermissionCriteria, +} from '@backstage/plugin-permission-common'; +import { PermissionRule } from '../types'; +import { + createGetRule, + isAndCriteria, + isNotCriteria, + isOrCriteria, +} from './util'; + +const permissionCriteriaSchema: z.ZodSchema< + PermissionCriteria +> = z.lazy(() => + z.union([ + z.object({ anyOf: z.array(permissionCriteriaSchema) }), + z.object({ allOf: z.array(permissionCriteriaSchema) }), + z.object({ not: permissionCriteriaSchema }), + z.object({ + rule: z.string(), + params: z.array(z.unknown()), + }), + ]), +); + +const applyConditionsRequestSchema = z.object({ + resourceRef: z.string(), + resourceType: z.string(), + conditions: permissionCriteriaSchema, +}); + +/** + * A request to load the referenced resource and apply conditions in order to + * finalize a conditional authorization response. + * + * @public + */ +export type ApplyConditionsRequest = { + resourceRef: string; + resourceType: string; + conditions: PermissionCriteria; +}; + +const applyConditions = ( + criteria: PermissionCriteria, + resource: TResource, + getRule: (name: string) => PermissionRule, +): boolean => { + if (isAndCriteria(criteria)) { + return criteria.allOf.every(child => + applyConditions(child, resource, getRule), + ); + } else if (isOrCriteria(criteria)) { + return criteria.anyOf.some(child => + applyConditions(child, resource, getRule), + ); + } else if (isNotCriteria(criteria)) { + return !applyConditions(criteria.not, resource, getRule); + } + + return getRule(criteria.rule).apply(resource, ...criteria.params); +}; + +/** + * Create an express Router which provides an authorization route to allow integration between the + * permission backend and other Backstage backend plugins. Plugin owners that wish to support + * conditional authorization for their resources should add the router created by this function + * to their express app inside their `createRouter` implementation. + * + * To make this concrete, we can use the Backstage software catalog as an example. The catalog has + * conditional rules around access to specific _entities_ in the catalog. The _type_ of resource is + * captured here as `resourceType`, a string identifier (`catalog-entity` in this example) that can + * be provided with permission definitions. This is merely a _type_ to verify that conditions in an + * authorization policy are constructed correctly, not a reference to a specific resource. + * + * The `rules` parameter is an array of {@link PermissionRule}s that introduce conditional + * filtering logic for resources; for the catalog, these are things like `isEntityOwner` or + * `hasAnnotation`. Rules describe how to filter a list of resources, and the `conditions` returned + * allow these rules to be applied with specific parameters (such as 'group:default/team-a', or + * 'backstage.io/edit-url'). + * + * The `getResource` argument should load a resource by reference. For the catalog, this is an + * {@link @backstage/catalog-model#EntityRef}. For other plugins, this can be any serialized format. + * This is used to construct the `createPermissionIntegrationRouter`, a function to add an + * authorization route to your backend plugin. This route will be called by the `permission-backend` + * when authorization conditions relating to this plugin need to be evaluated. + * @public + */ +export const createPermissionIntegrationRouter = ({ + resourceType, + rules, + getResource, +}: { + resourceType: string; + rules: PermissionRule[]; + getResource: (resourceRef: string) => Promise; +}): Router => { + const router = Router(); + + const getRule = createGetRule(rules); + + router.post( + '/permissions/apply-conditions', + express.json(), + async ( + req, + res: Response< + | { + result: Omit; + } + | string + >, + ) => { + const parseResult = applyConditionsRequestSchema.safeParse(req.body); + + if (!parseResult.success) { + return res.status(400).send(`Invalid request body.`); + } + + const { data: body } = parseResult; + + if (body.resourceType !== resourceType) { + return res + .status(400) + .send(`Unexpected resource type: ${body.resourceType}.`); + } + + const resource = await getResource(body.resourceRef); + + if (!resource) { + return res + .status(400) + .send(`Resource for ref ${body.resourceRef} not found.`); + } + + return res.status(200).json({ + result: applyConditions(body.conditions, resource, getRule) + ? AuthorizeResult.ALLOW + : AuthorizeResult.DENY, + }); + }, + ); + + return router; +}; diff --git a/plugins/permission-node/src/integration/index.ts b/plugins/permission-node/src/integration/index.ts index 697d25f65d..f070d57c8f 100644 --- a/plugins/permission-node/src/integration/index.ts +++ b/plugins/permission-node/src/integration/index.ts @@ -14,5 +14,7 @@ * limitations under the License. */ -export * from './conditionFor'; -export * from './createPermissionIntegration'; +export * from './createConditionFactory'; +export * from './createConditionExports'; +export * from './createConditionTransformer'; +export * from './createPermissionIntegrationRouter'; diff --git a/plugins/permission-node/src/integration/util.test.ts b/plugins/permission-node/src/integration/util.test.ts index 72e87b2a7b..d27c0a4243 100644 --- a/plugins/permission-node/src/integration/util.test.ts +++ b/plugins/permission-node/src/integration/util.test.ts @@ -15,188 +15,72 @@ */ import { - PermissionCondition, - PermissionCriteria, -} from '@backstage/plugin-permission-common'; -import { applyConditions, mapConditions } from './util'; + createGetRule, + isAndCriteria, + isNotCriteria, + isOrCriteria, +} from './util'; -describe('integration utils', () => { - const testCases: { - criteria: PermissionCriteria; - expectedResult: { - applyConditions: boolean; - mapConditions: PermissionCriteria; +describe('permission integration utils', () => { + describe('createGetRule', () => { + let getRule: ReturnType; + + const testRule1 = { + name: 'test-rule-1', + description: 'Test rule 1', + apply: jest.fn(), + toQuery: jest.fn(), }; - }[] = [ - { - criteria: { rule: 'test-rule-1', params: [] }, - expectedResult: { - applyConditions: true, - mapConditions: 'test-rule-1', - }, - }, - { - criteria: { rule: 'test-rule-2', params: [] }, - expectedResult: { - applyConditions: false, - mapConditions: 'test-rule-2', - }, - }, - { - criteria: { - anyOf: [ - { rule: 'test-rule-1', params: ['a', 'b'] }, - { rule: 'test-rule-2', params: ['c', 'd'] }, - ], - }, - expectedResult: { - applyConditions: true, - mapConditions: { - anyOf: ['test-rule-1:a,b', 'test-rule-2:c,d'], - }, - }, - }, - { - criteria: { - allOf: [ - { rule: 'test-rule-1', params: ['e', 'f'] }, - { rule: 'test-rule-2', params: ['g', 'h'] }, - ], - }, - expectedResult: { - applyConditions: false, - mapConditions: { - allOf: ['test-rule-1:e,f', 'test-rule-2:g,h'], - }, - }, - }, - { - criteria: { - not: { rule: 'test-rule-2', params: ['i'] }, - }, - expectedResult: { - applyConditions: true, - mapConditions: { - not: 'test-rule-2:i', - }, - }, - }, - { - criteria: { - allOf: [ - { - anyOf: [ - { rule: 'test-rule-1', params: ['j'] }, - { rule: 'test-rule-2', params: ['k'] }, - ], - }, - { - not: { - allOf: [ - { rule: 'test-rule-1', params: ['l'] }, - { rule: 'test-rule-2', params: ['m'] }, - ], - }, - }, - ], - }, - expectedResult: { - applyConditions: true, - mapConditions: { - allOf: [ - { - anyOf: ['test-rule-1:j', 'test-rule-2:k'], - }, - { - not: { - allOf: ['test-rule-1:l', 'test-rule-2:m'], - }, - }, - ], - }, - }, - }, - { - criteria: { - allOf: [ - { - anyOf: [ - { rule: 'test-rule-1', params: ['j'] }, - { rule: 'test-rule-2', params: ['k'] }, - ], - }, - { - not: { - allOf: [ - { rule: 'test-rule-1', params: ['l'] }, - { not: { rule: 'test-rule-2', params: ['m'] } }, - ], - }, - }, - ], - }, - expectedResult: { - applyConditions: false, - mapConditions: { - allOf: [ - { - anyOf: ['test-rule-1:j', 'test-rule-2:k'], - }, - { - not: { - allOf: ['test-rule-1:l', { not: 'test-rule-2:m' }], - }, - }, - ], - }, - }, - }, - ]; - describe('applyConditions', () => { - const applyFn = jest.fn(condition => condition.rule === 'test-rule-1'); + const testRule2 = { + name: 'test-rule-2', + description: 'Test rule 2', + apply: jest.fn(), + toQuery: jest.fn(), + }; - it('invokes applyFn with rules to determine result', () => { - applyConditions({ rule: 'test-rule-1', params: ['foo', 'bar'] }, applyFn); - - expect(applyFn).toHaveBeenCalledWith({ - rule: 'test-rule-1', - params: ['foo', 'bar'], - }); + beforeEach(() => { + getRule = createGetRule([testRule1, testRule2]); }); - it.each(testCases)( - 'works with criteria %#', - ({ criteria, expectedResult }) => { - expect(applyConditions(criteria, applyFn)).toEqual( - expectedResult.applyConditions, - ); - }, - ); + it('returns the rule matching the supplied name', () => { + expect(getRule('test-rule-1')).toBe(testRule1); + }); + + it('throws if there is no rule for the supplied name', () => { + expect(() => getRule('test-rule-3')).toThrowError( + /unexpected permission rule/i, + ); + }); }); - describe('mapConditions', () => { - const mapFn = jest.fn( - ({ rule, params }) => - `${rule}${params.length ? `:${params.join(',')}` : ''}`, - ); - - it('invokes mapFn to transform conditions', () => { - mapConditions({ rule: 'test-rule-1', params: ['foo', 'bar'] }, mapFn); - - expect(mapFn).toHaveBeenCalledWith({ - rule: 'test-rule-1', - params: ['foo', 'bar'], - }); + describe('isOrCriteria', () => { + it('returns true if input has a top-level "anyOf" property', () => { + expect(isOrCriteria({ anyOf: { not: { allOf: [] } } })).toEqual(true); }); - it.each(testCases)( - 'works with criteria %#', - ({ criteria, expectedResult }) => { - expect(mapConditions(criteria, mapFn)).toEqual( - expectedResult.mapConditions, - ); - }, - ); + it('returns false if input does not have a top-level "anyOf" property', () => { + expect(isOrCriteria({ allOf: { not: { anyOf: [] } } })).toEqual(false); + }); + }); + + describe('isAndCriteria', () => { + it('returns true if input has a top-level "allOf" property', () => { + expect(isAndCriteria({ allOf: { not: { anyOf: [] } } })).toEqual(true); + }); + + it('returns false if input does not have a top-level "allOf" property', () => { + expect(isAndCriteria({ anyOf: { not: { allOf: [] } } })).toEqual(false); + }); + }); + + describe('isNotCriteria', () => { + it('returns true if input has a top-level "not" property', () => { + expect(isNotCriteria({ not: { allOf: [{ anyOf: [] }] } })).toEqual(true); + }); + + it('returns false if input does not have a top-level "not" property', () => { + expect(isNotCriteria({ anyOf: { not: { allOf: [] } } })).toEqual(false); + }); }); }); diff --git a/plugins/permission-node/src/integration/util.ts b/plugins/permission-node/src/integration/util.ts index 631aee269e..d9457cfefc 100644 --- a/plugins/permission-node/src/integration/util.ts +++ b/plugins/permission-node/src/integration/util.ts @@ -15,54 +15,35 @@ */ import { PermissionCriteria } from '@backstage/plugin-permission-common'; +import { PermissionRule } from '../types'; -const isAndCriteria = ( +export const isAndCriteria = ( filter: PermissionCriteria, ): filter is { allOf: PermissionCriteria[] } => Object.prototype.hasOwnProperty.call(filter, 'allOf'); -const isOrCriteria = ( +export const isOrCriteria = ( filter: PermissionCriteria, ): filter is { anyOf: PermissionCriteria[] } => Object.prototype.hasOwnProperty.call(filter, 'anyOf'); -const isNotCriteria = ( +export const isNotCriteria = ( filter: PermissionCriteria, ): filter is { not: PermissionCriteria } => Object.prototype.hasOwnProperty.call(filter, 'not'); -export const mapConditions = ( - criteria: PermissionCriteria, - mapFn: (condition: TQueryIn) => TQueryOut, -): PermissionCriteria => { - if (isAndCriteria(criteria)) { - return { - allOf: criteria.allOf.map(child => mapConditions(child, mapFn)), - }; - } else if (isOrCriteria(criteria)) { - return { - anyOf: criteria.anyOf.map(child => mapConditions(child, mapFn)), - }; - } else if (isNotCriteria(criteria)) { - return { - not: mapConditions(criteria.not, mapFn), - }; - } +export const createGetRule = ( + rules: PermissionRule[], +) => { + const rulesMap = new Map(Object.values(rules).map(rule => [rule.name, rule])); - return mapFn(criteria); -}; - -export const applyConditions = ( - criteria: PermissionCriteria, - applyFn: (condition: TQuery) => boolean, -): boolean => { - if (isAndCriteria(criteria)) { - return criteria.allOf.every(child => applyConditions(child, applyFn)); - } else if (isOrCriteria(criteria)) { - return criteria.anyOf.some(child => applyConditions(child, applyFn)); - } else if (isNotCriteria(criteria)) { - return !applyConditions(criteria.not, applyFn); - } - - return applyFn(criteria); + return (name: string): PermissionRule => { + const rule = rulesMap.get(name); + + if (!rule) { + throw new Error(`Unexpected permission rule: ${name}`); + } + + return rule; + }; }; From 5bff67aac43eb68ceece4704fa788959b9e07c73 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Mon, 22 Nov 2021 13:06:39 +0000 Subject: [PATCH 105/138] permission-node: expose ApplyConditionsResponse type This type will be shared with the backend. Signed-off-by: Mike Lewis --- plugins/permission-node/api-report.md | 5 +++++ .../integration/createPermissionIntegrationRouter.ts | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index 1aab9e1f47..95e1eb0711 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -17,6 +17,11 @@ export type ApplyConditionsRequest = { conditions: PermissionCriteria; }; +// @public +export type ApplyConditionsResponse = { + result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; +}; + // @public export type Condition = TRule extends PermissionRule< any, diff --git a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts index 6694b893b7..7757678128 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts @@ -61,6 +61,16 @@ export type ApplyConditionsRequest = { conditions: PermissionCriteria; }; +/** + * The result of applying the conditions, expressed as a definitive authorize + * result of ALLOW or DENY. + * + * @public + */ +export type ApplyConditionsResponse = { + result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; +}; + const applyConditions = ( criteria: PermissionCriteria, resource: TResource, From 52d3ca287ea617a42b7083c1399ccc26def93f75 Mon Sep 17 00:00:00 2001 From: Tim Jacomb <21194782+timja@users.noreply.github.com> Date: Mon, 22 Nov 2021 16:28:48 +0000 Subject: [PATCH 106/138] Fix broken ssl postgres docs Signed-off-by: Tim Jacomb --- packages/create-app/templates/default-app/app-config.yaml.hbs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 55e2a80c27..ab4858edd6 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -32,7 +32,9 @@ backend: user: ${POSTGRES_USER} password: ${POSTGRES_PASSWORD} # https://node-postgres.com/features/ssl - # ssl: require # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require) + # you can set the sslmode configuration option via the `PGSSLMODE` environment variable + # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require) + # ssl: # ca: # if you have a CA file and want to verify it you can uncomment this section # $file: /ca/server.crt {{/if}} From 2d7d165737bb36f4f26c81965308822c533d3024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 22 Nov 2021 19:58:16 +0100 Subject: [PATCH 107/138] bump rjsf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/early-dragons-wave.md | 5 +++++ packages/app/package.json | 2 +- plugins/scaffolder/package.json | 4 ++-- yarn.lock | 26 +++++++++++++------------- 4 files changed, 21 insertions(+), 16 deletions(-) create mode 100644 .changeset/early-dragons-wave.md diff --git a/.changeset/early-dragons-wave.md b/.changeset/early-dragons-wave.md new file mode 100644 index 0000000000..4c6631de7f --- /dev/null +++ b/.changeset/early-dragons-wave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Bump rjsf diff --git a/packages/app/package.json b/packages/app/package.json index a77afd13d6..5b9e97d317 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -65,7 +65,7 @@ }, "devDependencies": { "@backstage/test-utils": "^0.1.22", - "@rjsf/core": "^3.0.0", + "@rjsf/core": "^3.2.1", "@testing-library/cypress": "^7.0.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index a47cee2d75..ce185403bb 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -45,8 +45,8 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", - "@rjsf/core": "^3.0.0", - "@rjsf/material-ui": "^3.0.0", + "@rjsf/core": "^3.2.1", + "@rjsf/material-ui": "^3.2.1", "@types/react": "*", "classnames": "^2.2.6", "git-url-parse": "^11.6.0", diff --git a/yarn.lock b/yarn.lock index 27da8beb90..387db7670b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5207,25 +5207,25 @@ prop-types "^15.6.1" react-lifecycles-compat "^3.0.4" -"@rjsf/core@^3.0.0": - version "3.2.0" - resolved "https://registry.npmjs.org/@rjsf/core/-/core-3.2.0.tgz#189ff7fb132cb223463792d75fb1e04e9dd5d9f9" - integrity sha512-Cgonq9bBWlpE0yeeIv7rAIDuJvO1wAvp9G7tT/UvhODAyb4tDb1q8J/8ubWuRRiEyzYUkuxN0W8uPIzQsJgtTQ== +"@rjsf/core@^3.2.1": + version "3.2.1" + resolved "https://registry.npmjs.org/@rjsf/core/-/core-3.2.1.tgz#8a7b24c9a6f01f0ecb093fdfc777172c12b1b009" + integrity sha512-dk8ihvxFbcuIwU7G+HiJbFgwyIvaumPt5g5zfnuC26mwTUPlaDGFXKK2yITp8tJ3+hcwS5zEXtAN9wUkfuM4jA== dependencies: "@types/json-schema" "^7.0.7" ajv "^6.7.0" core-js-pure "^3.6.5" json-schema-merge-allof "^0.6.0" - jsonpointer "^4.0.1" + jsonpointer "^5.0.0" lodash "^4.17.15" nanoid "^3.1.23" prop-types "^15.7.2" react-is "^16.9.0" -"@rjsf/material-ui@^3.0.0": - version "3.1.0" - resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-3.1.0.tgz#ed15fc75de1594f87cd8336b7f2ebc492a432d8b" - integrity sha512-kWz37spT5SOXkb8Axq4g4BzQjXRylQr6B7eFAg1NPhSK7KrJYwSMSsFJ9Ze2vEBxwEiR0Z0n/4puaamGuGFRBw== +"@rjsf/material-ui@^3.2.1": + version "3.2.1" + resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-3.2.1.tgz#84fbf322485aee3a84101e189161f0687779ec8d" + integrity sha512-8UiDeDbjCImFSfOegGu13otQ7OdP9FOYpcLjeouppnhs+MPeIEAtYS+jCcBKmi3reyTagC15/KVSRhde1wS1vg== "@roadiehq/backstage-plugin-buildkite@^1.0.8": version "1.0.8" @@ -18559,10 +18559,10 @@ jsonpath-plus@^5.0.7: resolved "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-5.1.0.tgz#2fc4b2e461950626c98525425a3a3518b85af6c3" integrity sha512-890w2Pjtj0iswAxalRlt2kHthi6HKrXEfZcn+ZNZptv7F3rUGIeDuZo+C+h4vXBHLEsVjJrHeCm35nYeZLzSBQ== -jsonpointer@^4.0.1: - version "4.1.0" - resolved "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.1.0.tgz#501fb89986a2389765ba09e6053299ceb4f2c2cc" - integrity sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg== +jsonpointer@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz#f802669a524ec4805fa7389eadbc9921d5dc8072" + integrity sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg== jsonschema@^1.2.6: version "1.4.0" From 740f9582905654276c7582bd0aa66e7117f4b47c Mon Sep 17 00:00:00 2001 From: Joon Park Date: Mon, 22 Nov 2021 21:01:51 +0000 Subject: [PATCH 108/138] Handle empty values array in EntityFilter While an empty values array is not really a sensible input, if an empty array is provided, technically nothing should be returned as a matching value, thus the existing behavior was technically a bug. Signed-off-by: Joon Park --- .changeset/many-waves-visit.md | 5 +++ .../src/service/NextEntitiesCatalog.test.ts | 32 +++++++++++++++++++ .../src/service/NextEntitiesCatalog.ts | 2 +- 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 .changeset/many-waves-visit.md diff --git a/.changeset/many-waves-visit.md b/.changeset/many-waves-visit.md new file mode 100644 index 0000000000..4f4711f371 --- /dev/null +++ b/.changeset/many-waves-visit.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Providing an empty values array in an EntityFilter will now return no matches. diff --git a/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts index ee86e78c6b..d0f284c11c 100644 --- a/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts @@ -435,5 +435,37 @@ describe('NextEntitiesCatalog', () => { expect(entities).toContainEqual(entity1); }, ); + + it.each(databases.eachSupportedId())( + 'should return no matches for an empty values array', + // NOTE: An empty values array is not a sensible input in a realistic scenario. + 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: {}, + }; + await addEntityToSearch(knex, entity1); + await addEntityToSearch(knex, entity2); + const catalog = new NextEntitiesCatalog(knex); + + const testFilter = { + key: 'kind', + values: [], + }; + const request = { filter: testFilter }; + const { entities } = await catalog.entities(request); + + expect(entities.length).toBe(0); + }, + ); }); }); diff --git a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts index 8c2de9d7c1..f9b3abf190 100644 --- a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts @@ -91,7 +91,7 @@ function addCondition( if (filter.values) { if (filter.values.length === 1) { this.where({ value: filter.values[0].toLowerCase() }); - } else if (filter.values.length > 1) { + } else { this.andWhere( 'value', 'in', From c9ddb070c23201e9230ef88c512aced059f23e90 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 23 Nov 2021 09:42:08 +0100 Subject: [PATCH 109/138] chore: fixing changeset formatting Signed-off-by: blam --- .changeset/early-dragons-wave.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/early-dragons-wave.md b/.changeset/early-dragons-wave.md index 4c6631de7f..641f36a9f3 100644 --- a/.changeset/early-dragons-wave.md +++ b/.changeset/early-dragons-wave.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder': patch --- -Bump rjsf +Bump `react-jsonschema-form` From 7e4a1ea4cbdf8e9370762418f1bdc1a5871fa65f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 23 Nov 2021 10:05:07 +0100 Subject: [PATCH 110/138] docs/deprecations: add note about working around AppTheme type Signed-off-by: Patrik Oldsberg --- docs/api/deprecations.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/api/deprecations.md b/docs/api/deprecations.md index 774c8ef03d..aca7e42d96 100644 --- a/docs/api/deprecations.md +++ b/docs/api/deprecations.md @@ -54,3 +54,10 @@ const darkTheme = { ), }; ``` + +Note that the existing `AppTheme` type still requires the `theme` property to be +set since it's the type that's consumed in the `AppThemeApi`, and it would be a +breaking change to make `theme` optional. This means that if you currently +construct the themes that you pass on to `createApp` using `AppTheme` as an +intermediate type, you will need to work around this in some way, for example by +passing the themes to `createApp` more directly. From b922d3be1b9b07de70f8ed0e5789e24365fc2b51 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 23 Nov 2021 12:10:37 +0100 Subject: [PATCH 111/138] yarn.lock: bump rollup-plugin-postcss Signed-off-by: Patrik Oldsberg --- yarn.lock | 681 ++++++++++++++++++++++-------------------------------- 1 file changed, 277 insertions(+), 404 deletions(-) diff --git a/yarn.lock b/yarn.lock index 07a5febcb8..ed2be71ddb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6742,6 +6742,11 @@ axios-cached-dns-resolve "0.5.2" file-type "16.5.3" +"@trysound/sax@0.2.0": + version "0.2.0" + resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" + integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + "@tsconfig/node10@^1.0.7": version "1.0.8" resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" @@ -8938,7 +8943,7 @@ ajv@^8.0.1: require-from-string "^2.0.2" uri-js "^4.2.2" -alphanum-sort@^1.0.0: +alphanum-sort@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= @@ -10388,7 +10393,7 @@ browserslist@4.14.2: escalade "^3.0.2" node-releases "^1.1.61" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.6: +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.0, browserslist@^4.16.6: version "4.18.1" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.18.1.tgz#60d3920f25b6860eb917c6c7b185576f4d8b017f" integrity sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ== @@ -10670,25 +10675,6 @@ call-me-maybe@^1.0.1: resolved "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - callsites@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -11332,7 +11318,7 @@ color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.2, color-string@^1.5.4, color-string@^1.6.0: +color-string@^1.5.2, color-string@^1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz#c3915f61fe267672cb7e1e064c9d692219f6c312" integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA== @@ -11348,14 +11334,6 @@ color@3.0.x: color-convert "^1.9.1" color-string "^1.5.2" -color@^3.0.0: - version "3.1.3" - resolved "https://registry.npmjs.org/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" - integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.4" - color@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/color/-/color-4.0.1.tgz#21df44cd10245a91b1ccf5ba031609b0e10e7d67" @@ -11364,6 +11342,11 @@ color@^4.0.1: color-convert "^2.0.1" color-string "^1.6.0" +colord@^2.9.1: + version "2.9.1" + resolved "https://registry.npmjs.org/colord/-/colord-2.9.1.tgz#c961ea0efeb57c9f0f4834458f26cb9cc4a3f90e" + integrity sha512-4LBMSt09vR0uLnPVkOUBnmxgoaeN4ewRbx801wY/bXcltXfpR/G46OdWn96XpYmCWuYvO46aBZP4NgX8HpNAcw== + colorette@1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" @@ -11878,16 +11861,6 @@ cosmiconfig@7.0.0, cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -cosmiconfig@^5.0.0: - version "5.2.1" - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -12084,17 +12057,11 @@ css-color-converter@^2.0.0: color-name "^1.1.4" css-unit-converter "^1.1.2" -css-color-names@0.0.4, css-color-names@^0.0.4: - version "0.0.4" - resolved "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= - -css-declaration-sorter@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== +css-declaration-sorter@^6.0.3: + version "6.1.3" + resolved "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.3.tgz#e9852e4cf940ba79f509d9425b137d1f94438dc2" + integrity sha512-SvjQjNRZgh4ULK1LDJ2AduPKUKxIqmtU7ZAyi47BTV+M90Qvxr9AB6lKlLbDUfXqI9IQeYA8LbAsCZPpJEV3aA== dependencies: - postcss "^7.0.1" timsort "^0.3.0" css-in-js-utils@^2.0.0: @@ -12182,6 +12149,14 @@ css-tree@^1.1.2: mdn-data "2.0.14" source-map "^0.6.1" +css-tree@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + css-unit-converter@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21" @@ -12229,73 +12204,55 @@ cssfilter@0.0.10: resolved "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= -cssnano-preset-default@^4.0.7: - version "4.0.7" - resolved "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" - integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== +cssnano-preset-default@^5.1.7: + version "5.1.7" + resolved "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.7.tgz#68c3ad1ec6a810482ec7d06b2d70fc34b6b0d70c" + integrity sha512-bWDjtTY+BOqrqBtsSQIbN0RLGD2Yr2CnecpP0ydHNafh9ZUEre8c8VYTaH9FEbyOt0eIfEUAYYk5zj92ioO8LA== dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^7.0.1" - postcss-colormin "^4.0.3" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.2" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.11" - postcss-merge-rules "^4.0.3" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.2" - postcss-minify-params "^4.0.2" - postcss-minify-selectors "^4.0.2" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.2" - postcss-normalize-positions "^4.0.2" - postcss-normalize-repeat-style "^4.0.2" - postcss-normalize-string "^4.0.2" - postcss-normalize-timing-functions "^4.0.2" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.2" - postcss-ordered-values "^4.1.2" - postcss-reduce-initial "^4.0.3" - postcss-reduce-transforms "^4.0.2" - postcss-svgo "^4.0.2" - postcss-unique-selectors "^4.0.1" + css-declaration-sorter "^6.0.3" + cssnano-utils "^2.0.1" + postcss-calc "^8.0.0" + postcss-colormin "^5.2.1" + postcss-convert-values "^5.0.2" + postcss-discard-comments "^5.0.1" + postcss-discard-duplicates "^5.0.1" + postcss-discard-empty "^5.0.1" + postcss-discard-overridden "^5.0.1" + postcss-merge-longhand "^5.0.4" + postcss-merge-rules "^5.0.3" + postcss-minify-font-values "^5.0.1" + postcss-minify-gradients "^5.0.3" + postcss-minify-params "^5.0.2" + postcss-minify-selectors "^5.1.0" + postcss-normalize-charset "^5.0.1" + postcss-normalize-display-values "^5.0.1" + postcss-normalize-positions "^5.0.1" + postcss-normalize-repeat-style "^5.0.1" + postcss-normalize-string "^5.0.1" + postcss-normalize-timing-functions "^5.0.1" + postcss-normalize-unicode "^5.0.1" + postcss-normalize-url "^5.0.3" + postcss-normalize-whitespace "^5.0.1" + postcss-ordered-values "^5.0.2" + postcss-reduce-initial "^5.0.1" + postcss-reduce-transforms "^5.0.1" + postcss-svgo "^5.0.3" + postcss-unique-selectors "^5.0.2" -cssnano-util-get-arguments@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= +cssnano-utils@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-2.0.1.tgz#8660aa2b37ed869d2e2f22918196a9a8b6498ce2" + integrity sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ== -cssnano-util-get-match@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= - -cssnano-util-raw-cache@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== +cssnano@^5.0.1: + version "5.0.11" + resolved "https://registry.npmjs.org/cssnano/-/cssnano-5.0.11.tgz#743397a05e04cb87e9df44b7659850adfafc3646" + integrity sha512-5SHM31NAAe29jvy0MJqK40zZ/8dGlnlzcfHKw00bWMVFp8LWqtuyPSFwbaoIoxvt71KWJOfg8HMRGrBR3PExCg== dependencies: - postcss "^7.0.0" - -cssnano-util-same-parent@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== - -cssnano@^4.1.10: - version "4.1.10" - resolved "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" - integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== - dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.7" - is-resolvable "^1.0.0" - postcss "^7.0.0" + cssnano-preset-default "^5.1.7" + is-resolvable "^1.1.0" + lilconfig "^2.0.3" + yaml "^1.10.2" csso@^4.0.2: version "4.0.2" @@ -12304,6 +12261,13 @@ csso@^4.0.2: dependencies: css-tree "1.0.0-alpha.37" +csso@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== + dependencies: + css-tree "^1.1.2" + cssom@^0.4.4: version "0.4.4" resolved "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" @@ -16055,7 +16019,7 @@ has-yarn@^2.1.0: resolved "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== -has@^1.0.0, has@^1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -16179,11 +16143,6 @@ helmet@^4.0.0: resolved "https://registry.npmjs.org/helmet/-/helmet-4.4.1.tgz#a17e1444d81d7a83ddc6e6f9bc6e2055b994efe7" integrity sha512-G8tp0wUMI7i8wkMk2xLcEvESg5PiCitFMYgGRc/PwULB0RVhTP5GFdxOwvJwp9XVha8CuS8mnhmE8I/8dx/pbw== -hex-color-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== - highlight.js@^10.1.0, highlight.js@^10.1.1, highlight.js@^10.4.1, highlight.js@^10.6.0: version "10.7.2" resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.2.tgz#89319b861edc66c48854ed1e6da21ea89f847360" @@ -16256,16 +16215,6 @@ hpagent@^0.1.1: resolved "https://registry.npmjs.org/hpagent/-/hpagent-0.1.2.tgz#cab39c66d4df2d4377dbd212295d878deb9bdaa9" integrity sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ== -hsl-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= - -hsla-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= - 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" @@ -16639,14 +16588,6 @@ import-cwd@^3.0.0: dependencies: import-from "^3.0.0" -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: version "3.2.1" resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" @@ -16916,10 +16857,10 @@ ipaddr.js@^2.0.1: resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== is-absolute@^1.0.0: version "1.0.0" @@ -17039,18 +16980,6 @@ is-ci@^3.0.0: dependencies: ci-info "^3.1.1" -is-color-stop@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= - dependencies: - css-color-names "^0.0.4" - hex-color-regex "^1.1.0" - hsl-regex "^1.0.0" - hsla-regex "^1.0.0" - rgb-regex "^1.0.1" - rgba-regex "^1.0.0" - is-core-module@^2.1.0, is-core-module@^2.2.0: version "2.4.0" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1" @@ -17105,11 +17034,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" @@ -17423,7 +17347,7 @@ is-relative@^1.0.0: dependencies: is-unc-path "^1.0.0" -is-resolvable@^1.0.0: +is-resolvable@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== @@ -19001,6 +18925,11 @@ libnpmpublish@^4.0.0: semver "^7.1.3" ssri "^8.0.0" +lilconfig@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" + integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== + lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -21361,7 +21290,7 @@ normalize-range@^0.1.2: resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= -normalize-url@^3.0.0, normalize-url@^3.3.0: +normalize-url@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== @@ -21371,6 +21300,11 @@ normalize-url@^4.1.0: resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + npm-bundled@^1.0.1, npm-bundled@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" @@ -22820,61 +22754,50 @@ posix-character-classes@^0.1.0: resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= -postcss-calc@^7.0.1: - version "7.0.2" - resolved "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" - integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== +postcss-calc@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.0.0.tgz#a05b87aacd132740a5db09462a3612453e5df90a" + integrity sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g== dependencies: - postcss "^7.0.27" postcss-selector-parser "^6.0.2" postcss-value-parser "^4.0.2" -postcss-colormin@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== +postcss-colormin@^5.2.1: + version "5.2.1" + resolved "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.1.tgz#6e444a806fd3c578827dbad022762df19334414d" + integrity sha512-VVwMrEYLcHYePUYV99Ymuoi7WhKrMGy/V9/kTS0DkCoJYmmjdOMneyhzYUxcNgteKDVbrewOkSM7Wje/MFwxzA== dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + browserslist "^4.16.6" + caniuse-api "^3.0.0" + colord "^2.9.1" + postcss-value-parser "^4.1.0" -postcss-convert-values@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== +postcss-convert-values@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.2.tgz#879b849dc3677c7d6bc94b6a2c1a3f0808798059" + integrity sha512-KQ04E2yadmfa1LqXm7UIDwW1ftxU/QWZmz6NKnHnUvJ3LEYbbcX6i329f/ig+WnEByHegulocXrECaZGLpL8Zg== dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-discard-comments@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== - dependencies: - postcss "^7.0.0" +postcss-discard-comments@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz#9eae4b747cf760d31f2447c27f0619d5718901fe" + integrity sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg== -postcss-discard-duplicates@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== - dependencies: - postcss "^7.0.0" +postcss-discard-duplicates@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz#68f7cc6458fe6bab2e46c9f55ae52869f680e66d" + integrity sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA== -postcss-discard-empty@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== - dependencies: - postcss "^7.0.0" +postcss-discard-empty@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz#ee136c39e27d5d2ed4da0ee5ed02bc8a9f8bf6d8" + integrity sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw== -postcss-discard-overridden@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== - dependencies: - postcss "^7.0.0" +postcss-discard-overridden@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz#454b41f707300b98109a75005ca4ab0ff2743ac6" + integrity sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q== postcss-flexbugs-fixes@^4.2.1: version "4.2.1" @@ -22902,67 +22825,57 @@ postcss-loader@^4.2.0: schema-utils "^3.0.0" semver "^7.3.4" -postcss-merge-longhand@^4.0.11: - version "4.0.11" - resolved "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== +postcss-merge-longhand@^5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.4.tgz#41f4f3270282ea1a145ece078b7679f0cef21c32" + integrity sha512-2lZrOVD+d81aoYkZDpWu6+3dTAAGkCKbV5DoRhnIR7KOULVrI/R7bcMjhrH9KTRy6iiHKqmtG+n/MMj1WmqHFw== dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" + postcss-value-parser "^4.1.0" + stylehacks "^5.0.1" -postcss-merge-rules@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== +postcss-merge-rules@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.3.tgz#b5cae31f53129812a77e3eb1eeee448f8cf1a1db" + integrity sha512-cEKTMEbWazVa5NXd8deLdCnXl+6cYG7m2am+1HzqH0EnTdy8fRysatkaXb2dEnR+fdaDxTvuZ5zoBdv6efF6hg== dependencies: - browserslist "^4.0.0" + browserslist "^4.16.6" caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" + cssnano-utils "^2.0.1" + postcss-selector-parser "^6.0.5" -postcss-minify-font-values@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== +postcss-minify-font-values@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz#a90cefbfdaa075bd3dbaa1b33588bb4dc268addf" + integrity sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA== dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-minify-gradients@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== +postcss-minify-gradients@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.3.tgz#f970a11cc71e08e9095e78ec3a6b34b91c19550e" + integrity sha512-Z91Ol22nB6XJW+5oe31+YxRsYooxOdFKcbOqY/V8Fxse1Y3vqlNRpi1cxCqoACZTQEhl+xvt4hsbWiV5R+XI9Q== dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + colord "^2.9.1" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-minify-params@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== +postcss-minify-params@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.2.tgz#1b644da903473fbbb18fbe07b8e239883684b85c" + integrity sha512-qJAPuBzxO1yhLad7h2Dzk/F7n1vPyfHfCCh5grjGfjhi1ttCnq4ZXGIW77GSrEbh9Hus9Lc/e/+tB4vh3/GpDg== dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - uniqs "^2.0.0" + alphanum-sort "^1.0.2" + browserslist "^4.16.6" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-minify-selectors@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== +postcss-minify-selectors@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz#4385c845d3979ff160291774523ffa54eafd5a54" + integrity sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og== dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" + alphanum-sort "^1.0.2" + postcss-selector-parser "^6.0.5" postcss-modules-extract-imports@^2.0.0: version "2.0.0" @@ -23039,124 +22952,96 @@ postcss-modules@^4.0.0: postcss-modules-values "^4.0.0" string-hash "^1.1.1" -postcss-normalize-charset@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== - dependencies: - postcss "^7.0.0" +postcss-normalize-charset@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz#121559d1bebc55ac8d24af37f67bd4da9efd91d0" + integrity sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg== -postcss-normalize-display-values@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== +postcss-normalize-display-values@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz#62650b965981a955dffee83363453db82f6ad1fd" + integrity sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ== dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-normalize-positions@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== +postcss-normalize-positions@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz#868f6af1795fdfa86fbbe960dceb47e5f9492fe5" + integrity sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg== dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-repeat-style@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== +postcss-normalize-repeat-style@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz#cbc0de1383b57f5bb61ddd6a84653b5e8665b2b5" + integrity sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w== dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-normalize-string@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== +postcss-normalize-string@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz#d9eafaa4df78c7a3b973ae346ef0e47c554985b0" + integrity sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA== dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-timing-functions@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== +postcss-normalize-timing-functions@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz#8ee41103b9130429c6cbba736932b75c5e2cb08c" + integrity sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q== dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-normalize-unicode@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== +postcss-normalize-unicode@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz#82d672d648a411814aa5bf3ae565379ccd9f5e37" + integrity sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA== dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + browserslist "^4.16.0" + postcss-value-parser "^4.1.0" -postcss-normalize-url@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== +postcss-normalize-url@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.3.tgz#42eca6ede57fe69075fab0f88ac8e48916ef931c" + integrity sha512-qWiUMbvkRx3kc1Dp5opzUwc7MBWZcSDK2yofCmdvFBCpx+zFPkxBC1FASQ59Pt+flYfj/nTZSkmF56+XG5elSg== dependencies: - is-absolute-url "^2.0.0" - normalize-url "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + is-absolute-url "^3.0.3" + normalize-url "^6.0.1" + postcss-value-parser "^4.1.0" -postcss-normalize-whitespace@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== +postcss-normalize-whitespace@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz#b0b40b5bcac83585ff07ead2daf2dcfbeeef8e9a" + integrity sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA== dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-ordered-values@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== +postcss-ordered-values@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.2.tgz#1f351426977be00e0f765b3164ad753dac8ed044" + integrity sha512-8AFYDSOYWebJYLyJi3fyjl6CqMEG/UVworjiyK1r573I56kb3e879sCJLGvR3merj+fAdPpVplXKQZv+ey6CgQ== dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-reduce-initial@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== +postcss-reduce-initial@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz#9d6369865b0f6f6f6b165a0ef5dc1a4856c7e946" + integrity sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw== dependencies: - browserslist "^4.0.0" + browserslist "^4.16.0" caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" -postcss-reduce-transforms@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== +postcss-reduce-transforms@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz#93c12f6a159474aa711d5269923e2383cedcf640" + integrity sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA== dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-selector-parser@^3.0.0: - version "3.1.2" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" - integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== - dependencies: - dot-prop "^5.2.0" - indexes-of "^1.0.1" - uniq "^1.0.1" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: version "6.0.4" @@ -23168,35 +23053,36 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector uniq "^1.0.1" util-deprecate "^1.0.2" -postcss-svgo@^4.0.2: - version "4.0.3" - resolved "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz#343a2cdbac9505d416243d496f724f38894c941e" - integrity sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw== +postcss-selector-parser@^6.0.5: + version "6.0.6" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" + integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" + cssesc "^3.0.0" + util-deprecate "^1.0.2" -postcss-unique-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== +postcss-svgo@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.3.tgz#d945185756e5dfaae07f9edb0d3cae7ff79f9b30" + integrity sha512-41XZUA1wNDAZrQ3XgWREL/M2zSw8LJPvb5ZWivljBsUQAGoEKMYm6okHsTjJxKYI4M75RQEH4KYlEM52VwdXVA== dependencies: - alphanum-sort "^1.0.0" - postcss "^7.0.0" - uniqs "^2.0.0" + postcss-value-parser "^4.1.0" + svgo "^2.7.0" -postcss-value-parser@^3.0.0: - version "3.3.1" - resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== +postcss-unique-selectors@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.2.tgz#5d6893daf534ae52626708e0d62250890108c0c1" + integrity sha512-w3zBVlrtZm7loQWRPVC0yjUwwpty7OM6DnEHkxcSQXO1bMS3RJ+JUS5LFMSDZHJcvGsRwhZinCWVqn8Kej4EDA== + dependencies: + alphanum-sort "^1.0.2" + postcss-selector-parser "^6.0.5" postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -"postcss@5 - 7", postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: +"postcss@5 - 7", postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: version "7.0.32" resolved "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== @@ -25072,11 +24958,6 @@ resolve-from@5.0.0, resolve-from@^5.0.0: resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -25188,16 +25069,6 @@ rfc4648@^1.3.0: resolved "https://registry.npmjs.org/rfc4648/-/rfc4648-1.4.0.tgz#c75b2856ad2e2d588b6ddb985d556f1f7f2a2abd" integrity sha512-3qIzGhHlMHA6PoT6+cdPKZ+ZqtxkIvg8DZGKA5z6PQ33/uuhoJ+Ws/D/J9rXW6gXodgH8QYlz2UCl+sdUDmNIg== -rgb-regex@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= - -rgba-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= - rifm@^0.7.0: version "0.7.0" resolved "https://registry.npmjs.org/rifm/-/rifm-0.7.0.tgz#debe951a9c83549ca6b33e5919f716044c2230be" @@ -25265,13 +25136,13 @@ rollup-plugin-peer-deps-external@^2.2.2: integrity sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g== rollup-plugin-postcss@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.0.tgz#2131fb6db0d5dce01a37235e4f6ad4523c681cea" - integrity sha512-OQzT+YspV01/6dxfyEw8lBO2px3hyL8Xn+k2QGctL7V/Yx2Z1QaMKdYVslP1mqv7RsKt6DROIlnbpmgJ3yxf6g== + version "4.0.2" + resolved "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz#15e9462f39475059b368ce0e49c800fa4b1f7050" + integrity sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w== dependencies: chalk "^4.1.0" concat-with-sourcemaps "^1.1.0" - cssnano "^4.1.10" + cssnano "^5.0.1" import-cwd "^3.0.0" p-queue "^6.6.2" pify "^5.0.0" @@ -26757,14 +26628,13 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -stylehacks@^4.0.0: - version "4.0.3" - resolved "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== +stylehacks@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.1.tgz#323ec554198520986806388c7fdaebc38d2c06fb" + integrity sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA== dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" + browserslist "^4.16.0" + postcss-selector-parser "^6.0.4" stylis@^4.0.6: version "4.0.7" @@ -26896,7 +26766,7 @@ svg-parser@^2.0.2: resolved "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== -svgo@^1.0.0, svgo@^1.2.2: +svgo@^1.2.2: version "1.3.2" resolved "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== @@ -26915,6 +26785,19 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" +svgo@^2.7.0: + version "2.8.0" + resolved "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" + integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== + dependencies: + "@trysound/sax" "0.2.0" + commander "^7.2.0" + css-select "^4.1.3" + css-tree "^1.1.3" + csso "^4.2.0" + picocolors "^1.0.0" + stable "^0.1.8" + swagger-client@3.16.1, swagger-client@^3.16.1: version "3.16.1" resolved "https://registry.npmjs.org/swagger-client/-/swagger-client-3.16.1.tgz#df86c9d407ab52c00cb356e714b0ec732bb3ad40" @@ -28072,11 +27955,6 @@ uniq@^1.0.1: resolved "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" @@ -28616,11 +28494,6 @@ vasync@^2.2.0: dependencies: verror "1.10.0" -vendors@^1.0.0: - version "1.0.4" - resolved "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" - integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== - verror@1.10.0, verror@^1.8.1: version "1.10.0" resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" From a3c5b2f70b038ebccc0c31d61b9e52856fe098f1 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 23 Nov 2021 16:33:29 +0100 Subject: [PATCH 112/138] core-plugin-api: Deprecate Plugin register and output Co-authored-by: blam Co-authored-by: Patrik Oldsberg Signed-off-by: Johan Haals --- packages/core-app-api/src/app/AppManager.tsx | 29 ++++++++++++------- .../core-plugin-api/src/plugin/Plugin.tsx | 23 ++++++++++++--- packages/core-plugin-api/src/plugin/types.ts | 23 ++++++++++++++- plugins/cost-insights/src/plugin.ts | 4 +-- 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/packages/core-app-api/src/app/AppManager.tsx b/packages/core-app-api/src/app/AppManager.tsx index 950f57bb7d..5903a8c874 100644 --- a/packages/core-app-api/src/app/AppManager.tsx +++ b/packages/core-app-api/src/app/AppManager.tsx @@ -272,17 +272,26 @@ export class AppManager implements BackstageApp { const featureFlagsApi = this.getApiHolder().get(featureFlagsApiRef)!; for (const plugin of this.plugins.values()) { - for (const output of plugin.output()) { - switch (output.type) { - case 'feature-flag': { - featureFlagsApi.registerFlag({ - name: output.name, - pluginId: plugin.getId(), - }); - break; + if ('getFeatureFlags' in plugin) { + for (const flag of plugin.getFeatureFlags()) { + featureFlagsApi.registerFlag({ + name: flag.name, + pluginId: plugin.getId(), + }); + } + } else { + for (const output of plugin.output()) { + switch (output.type) { + case 'feature-flag': { + featureFlagsApi.registerFlag({ + name: output.name, + pluginId: plugin.getId(), + }); + break; + } + default: + break; } - default: - break; } } } diff --git a/packages/core-plugin-api/src/plugin/Plugin.tsx b/packages/core-plugin-api/src/plugin/Plugin.tsx index 52ca0e76e3..0fb7574cd7 100644 --- a/packages/core-plugin-api/src/plugin/Plugin.tsx +++ b/packages/core-plugin-api/src/plugin/Plugin.tsx @@ -21,6 +21,7 @@ import { Extension, AnyRoutes, AnyExternalRoutes, + PluginFeatureFlagConfig, } from './types'; import { AnyApiFactory } from '../apis'; @@ -44,6 +45,14 @@ export class PluginImpl< return this.config.apis ?? []; } + getFeatureFlags(): Iterable { + const registeredFlags = this.output() + .filter(({ type }) => type === 'feature-flag') + .map(({ name }) => ({ name })); + + return registeredFlags; + } + get routes(): Routes { return this.config.routes ?? ({} as Routes); } @@ -56,11 +65,18 @@ export class PluginImpl< if (this.storedOutput) { return this.storedOutput; } - if (!this.config.register) { - return []; + const outputs = new Array(); + this.storedOutput = outputs; + + if (this.config.featureFlags) { + for (const flag of this.config.featureFlags) { + outputs.push({ type: 'feature-flag', name: flag.name }); + } } - const outputs = new Array(); + if (!this.config.register) { + return outputs; + } this.config.register({ featureFlags: { @@ -70,7 +86,6 @@ export class PluginImpl< }, }); - this.storedOutput = outputs; return this.storedOutput; } diff --git a/packages/core-plugin-api/src/plugin/types.ts b/packages/core-plugin-api/src/plugin/types.ts index aeb7037c51..c258b6f9fc 100644 --- a/packages/core-plugin-api/src/plugin/types.ts +++ b/packages/core-plugin-api/src/plugin/types.ts @@ -19,7 +19,7 @@ import { AnyApiFactory } from '../apis/system'; /** * Replace with using {@link RouteRef}s. - * + * @deprecated * @public */ export type FeatureFlagOutput = { @@ -31,6 +31,7 @@ export type FeatureFlagOutput = { * {@link FeatureFlagOutput} type. * * @public + * @deprecated Use {@link BackstagePlugin.getFeatureFlags} instead. */ export type PluginOutput = FeatureFlagOutput; @@ -71,13 +72,30 @@ export type BackstagePlugin< ExternalRoutes extends AnyExternalRoutes = {}, > = { getId(): string; + /** + * @deprecated use getFeatureFlags instead. + * */ output(): PluginOutput[]; getApis(): Iterable; + /** + * Returns all registered feature flags for this plugin. + */ + getFeatureFlags(): Iterable; provide(extension: Extension): T; routes: Routes; externalRoutes: ExternalRoutes; }; +/** + * Plugin feature flag configuration. + * + * @public + */ +export type PluginFeatureFlagConfig = { + /** Feature flag name */ + name: string; +}; + /** * Plugin descriptor type. * @@ -89,14 +107,17 @@ export type PluginConfig< > = { id: string; apis?: Iterable; + /** @deprecated use featureFlags property instead for defining feature flags */ register?(hooks: PluginHooks): void; routes?: Routes; externalRoutes?: ExternalRoutes; + featureFlags?: PluginFeatureFlagConfig[]; }; /** * Holds hooks registered by the plugin. * + * @deprecated - feature flags are now registered in plugin config under featureFlags * @public */ export type PluginHooks = { diff --git a/plugins/cost-insights/src/plugin.ts b/plugins/cost-insights/src/plugin.ts index 1714c5fbd5..a422098e08 100644 --- a/plugins/cost-insights/src/plugin.ts +++ b/plugins/cost-insights/src/plugin.ts @@ -34,9 +34,7 @@ export const unlabeledDataflowAlertRef = createRouteRef({ export const costInsightsPlugin = createPlugin({ id: 'cost-insights', - register({ featureFlags }) { - featureFlags.register('cost-insights-currencies'); - }, + featureFlags: [{ name: 'cost-insights-currencies' }], routes: { root: rootRouteRef, growthAlerts: projectGrowthAlertRef, From 950b36393cc6bf94ab7d568e8149ddebdce3ecb7 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 23 Nov 2021 16:49:33 +0100 Subject: [PATCH 113/138] core-plugin-api: Add tests and changesets Co-authored-by: blam Co-authored-by: Patrik Oldsberg Signed-off-by: Johan Haals --- .changeset/slow-olives-confess.md | 7 ++ .changeset/young-hats-shop.md | 5 ++ .../core-app-api/src/app/AppManager.test.tsx | 72 +++++++++++++++ .../src/plugin/Plugin.test.tsx | 89 +++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 .changeset/slow-olives-confess.md create mode 100644 .changeset/young-hats-shop.md create mode 100644 packages/core-plugin-api/src/plugin/Plugin.test.tsx diff --git a/.changeset/slow-olives-confess.md b/.changeset/slow-olives-confess.md new file mode 100644 index 0000000000..68b2539157 --- /dev/null +++ b/.changeset/slow-olives-confess.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-plugin-api': patch +--- + +Deprecated `register` option of `createPlugin` and the `outputs` methods of the plugin instance. + +Introduces the `featureFlags` property to define your feature flags instead. diff --git a/.changeset/young-hats-shop.md b/.changeset/young-hats-shop.md new file mode 100644 index 0000000000..4db46cf9d9 --- /dev/null +++ b/.changeset/young-hats-shop.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights': patch +--- + +Supply featureFlags using featureFlag config option. diff --git a/packages/core-app-api/src/app/AppManager.test.tsx b/packages/core-app-api/src/app/AppManager.test.tsx index 07401660e8..20872b26f0 100644 --- a/packages/core-app-api/src/app/AppManager.test.tsx +++ b/packages/core-app-api/src/app/AppManager.test.tsx @@ -349,6 +349,78 @@ describe('Integration Test', () => { }); }); + it('getFeatureFlags should return feature flags', async () => { + const storageFlags = new LocalStorageFeatureFlags(); + jest.spyOn(storageFlags, 'registerFlag'); + + const apis = [ + noOpAnalyticsApi, + createApiFactory({ + api: featureFlagsApiRef, + deps: { configApi: configApiRef }, + factory() { + return storageFlags; + }, + }), + ]; + + const app = new AppManager({ + apis, + defaultApis: [], + themes: [ + { + id: 'light', + title: 'Light Theme', + variant: 'light', + Provider: ({ children }) => <>{children}, + }, + ], + icons, + plugins: [ + createPlugin({ + id: 'test', + featureFlags: [ + { + name: 'foo', + }, + ], + register: p => p.featureFlags.register('name'), + }), + ], + components, + configLoader: async () => [], + bindRoutes: ({ bind }) => { + bind(plugin1.externalRoutes, { + extRouteRef1: plugin1RouteRef, + extRouteRef2: plugin2RouteRef, + }); + }, + }); + + const Provider = app.getProvider(); + const Router = app.getRouter(); + + await renderWithEffects( + + + + } /> + } /> + + + , + ); + + expect(storageFlags.registerFlag).toHaveBeenCalledWith({ + name: 'name', + pluginId: 'test', + }); + expect(storageFlags.registerFlag).toHaveBeenCalledWith({ + name: 'foo', + pluginId: 'test', + }); + }); + it('should track route changes via analytics api', async () => { const mockAnalyticsApi = new MockAnalyticsApi(); const apis = [createApiFactory(analyticsApiRef, mockAnalyticsApi)]; diff --git a/packages/core-plugin-api/src/plugin/Plugin.test.tsx b/packages/core-plugin-api/src/plugin/Plugin.test.tsx new file mode 100644 index 0000000000..d3758543a1 --- /dev/null +++ b/packages/core-plugin-api/src/plugin/Plugin.test.tsx @@ -0,0 +1,89 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createPlugin } from './Plugin'; + +describe('Plugin Feature Flag', () => { + it('should be able to register and receive feature flags', () => { + expect( + createPlugin({ + id: 'test', + featureFlags: [{ name: 'test' }], + }).getFeatureFlags(), + ).toEqual([{ name: 'test' }]); + + expect( + createPlugin({ + id: 'test', + register({ featureFlags }) { + featureFlags.register('blob'); + }, + }).getFeatureFlags(), + ).toEqual([{ name: 'blob' }]); + + expect( + createPlugin({ + id: 'test', + register({ featureFlags }) { + featureFlags.register('blob'); + }, + featureFlags: [{ name: 'test' }], + }).getFeatureFlags(), + ).toEqual([{ name: 'test' }, { name: 'blob' }]); + + expect( + createPlugin({ + id: 'test', + }).getFeatureFlags(), + ).toEqual([]); + + /* deprecated tests */ + + expect( + createPlugin({ + id: 'test', + featureFlags: [{ name: 'test' }], + }).output(), + ).toEqual([{ name: 'test', type: 'feature-flag' }]); + + expect( + createPlugin({ + id: 'test', + register({ featureFlags }) { + featureFlags.register('blob'); + }, + }).output(), + ).toEqual([{ name: 'blob', type: 'feature-flag' }]); + expect( + createPlugin({ + id: 'test', + register({ featureFlags }) { + featureFlags.register('blob'); + }, + featureFlags: [{ name: 'test' }], + }).output(), + ).toEqual([ + { name: 'test', type: 'feature-flag' }, + { name: 'blob', type: 'feature-flag' }, + ]); + + expect( + createPlugin({ + id: 'test', + }).output(), + ).toEqual([]); + }); +}); From 6de3b8fb24abadeb678e376fae3c7144cf3da954 Mon Sep 17 00:00:00 2001 From: jodybro Date: Tue, 23 Nov 2021 13:30:01 -0500 Subject: [PATCH 114/138] support v1 api for ingress object Signed-off-by: jodybro --- contrib/chart/backstage/templates/ingress.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contrib/chart/backstage/templates/ingress.yaml b/contrib/chart/backstage/templates/ingress.yaml index 7231afda13..9340467800 100644 --- a/contrib/chart/backstage/templates/ingress.yaml +++ b/contrib/chart/backstage/templates/ingress.yaml @@ -1,7 +1,13 @@ {{- $frontendUrl := urlParse .Values.appConfig.app.baseUrl}} {{- $backendUrl := urlParse .Values.appConfig.backend.baseUrl}} {{- $lighthouseUrl := urlParse .Values.appConfig.lighthouse.baseUrl}} + +{{/* Determine the api type for the ingress */}} +{{- if lt .Capabilities.KubeVersion.Minor "19" }} apiVersion: networking.k8s.io/v1beta1 +{{- else if ge .Capabilities.KubeVersion.Minor "19" }} +apiVersion: networking.k8s.io/v1 +{{- end }} kind: Ingress metadata: name: {{ include "backstage.fullname" . }}-ingress From f1ba6dfb1d7fa1dec651d9330a1ea2c17f1b5be1 Mon Sep 17 00:00:00 2001 From: goenning Date: Tue, 23 Nov 2021 19:03:46 +0000 Subject: [PATCH 115/138] fix comments, support onpremise and paging Signed-off-by: goenning --- .changeset/strong-seahorses-scream.md | 2 +- microsite/sidebars.json | 6 +- mkdocs.yml | 1 + .../AzureDevOpsDiscoveryProcessor.ts | 4 +- .../ingestion/processors/azure/azure.test.ts | 92 +++++++++++++++++++ .../src/ingestion/processors/azure/azure.ts | 55 ++++++----- 6 files changed, 136 insertions(+), 24 deletions(-) diff --git a/.changeset/strong-seahorses-scream.md b/.changeset/strong-seahorses-scream.md index 445ed65c81..bbd1d44378 100644 --- a/.changeset/strong-seahorses-scream.md +++ b/.changeset/strong-seahorses-scream.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-backend': minor +'@backstage/plugin-catalog-backend': patch --- Added Azure DevOps discovery processor diff --git a/microsite/sidebars.json b/microsite/sidebars.json index ec5c5d8d68..bc026ec196 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -124,7 +124,11 @@ { "type": "subcategory", "label": "Azure", - "ids": ["integrations/azure/locations", "integrations/azure/org"] + "ids": [ + "integrations/azure/locations", + "integrations/azure/discovery", + "integrations/azure/org" + ] }, { "type": "subcategory", diff --git a/mkdocs.yml b/mkdocs.yml index 8c7114abbc..08107f255d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -88,6 +88,7 @@ nav: - Discovery: 'integrations/aws-s3/discovery.md' - Azure: - Locations: 'integrations/azure/locations.md' + - Discovery: 'integrations/azure/discovery.md' - Org Data: 'integrations/azure/org.md' - Bitbucket: - Locations: 'integrations/bitbucket/locations.md' diff --git a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts index b86e3f9c82..58ee2155e9 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts @@ -85,7 +85,9 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { catalogPath, ); - this.logger.info(`Found ${files.length} files in Azure DevOps.`); + this.logger.debug( + `Found ${files.length} files in Azure DevOps from ${location.target}.`, + ); for (const file of files) { emit( diff --git a/plugins/catalog-backend/src/ingestion/processors/azure/azure.test.ts b/plugins/catalog-backend/src/ingestion/processors/azure/azure.test.ts index d9dfe5d1f4..67cc120bab 100644 --- a/plugins/catalog-backend/src/ingestion/processors/azure/azure.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/azure/azure.test.ts @@ -34,6 +34,7 @@ describe('azure', () => { expect(req.headers.get('Authorization')).toBe('Basic OkFCQw=='); expect(req.body).toEqual({ searchText: 'path:/catalog-info.yaml repo:*', + $skip: 0, $top: 1000, }); return res(ctx.json(response)); @@ -81,6 +82,7 @@ describe('azure', () => { expect(req.headers.get('Authorization')).toBe('Basic OkFCQw=='); expect(req.body).toEqual({ searchText: 'path:/catalog-info.yaml repo:*', + $skip: 0, $top: 1000, }); return res(ctx.json(response)); @@ -120,6 +122,7 @@ describe('azure', () => { expect(req.headers.get('Authorization')).toBe('Basic OkFCQw=='); expect(req.body).toEqual({ searchText: 'path:/catalog-info.yaml repo:backstage', + $skip: 0, $top: 1000, }); return res(ctx.json(response)); @@ -137,4 +140,93 @@ describe('azure', () => { ), ).resolves.toEqual(response.results); }); + + it('can search using onpremise api', async () => { + const response: CodeSearchResponse = { + count: 1, + results: [ + { + fileName: 'catalog-info.yaml', + path: '/catalog-info.yaml', + repository: { + name: 'backstage', + }, + }, + ], + }; + + server.use( + rest.post( + `https://azuredevops.mycompany.com/shopify/engineering/_apis/search/codesearchresults`, + (req, res, ctx) => { + expect(req.headers.get('Authorization')).toBe('Basic OkFCQw=='); + expect(req.body).toEqual({ + searchText: 'path:/catalog-info.yaml repo:*', + $skip: 0, + $top: 1000, + }); + return res(ctx.json(response)); + }, + ), + ); + + await expect( + codeSearch( + { host: 'azuredevops.mycompany.com', token: 'ABC' }, + 'shopify', + 'engineering', + '', + '/catalog-info.yaml', + ), + ).resolves.toEqual(response.results); + }); + + it('searches multiple pages if response contains many items', async () => { + const totalCount = 2401; + const generateItems = (count: number) => { + return Array.from(Array(count).keys()).map(_ => ({ + fileName: 'catalog-info.yaml', + path: '/catalog-info.yaml', + repository: { + name: 'backstage', + }, + })); + }; + + server.use( + rest.post( + `https://almsearch.dev.azure.com/shopify/engineering/_apis/search/codesearchresults`, + (req, res, ctx) => { + expect(req.headers.get('Authorization')).toBe('Basic OkFCQw=='); + expect(req.body).toMatchObject({ + searchText: 'path:/catalog-info.yaml repo:backstage', + $top: 1000, + }); + + const body = req.body as { $skip: number; $top: number }; + const countItemsToReturn = + body.$top + body.$skip > totalCount + ? totalCount - body.$skip + : body.$top; + + return res( + ctx.json({ + count: totalCount, + results: generateItems(countItemsToReturn), + }), + ); + }, + ), + ); + + await expect( + codeSearch( + { host: 'dev.azure.com', token: 'ABC' }, + 'shopify', + 'engineering', + 'backstage', + '/catalog-info.yaml', + ), + ).resolves.toHaveLength(totalCount); + }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/azure/azure.ts b/plugins/catalog-backend/src/ingestion/processors/azure/azure.ts index ec1b9ba0fb..0c7b17483a 100644 --- a/plugins/catalog-backend/src/ingestion/processors/azure/azure.ts +++ b/plugins/catalog-backend/src/ingestion/processors/azure/azure.ts @@ -33,6 +33,9 @@ export interface CodeSearchResultItem { }; } +const isCloud = (host: string) => host === 'dev.azure.com'; +const PAGE_SIZE = 1000; + // codeSearch returns all files that matches the given search path. export async function codeSearch( azureConfig: AzureIntegrationConfig, @@ -41,27 +44,37 @@ export async function codeSearch( repo: string, path: string, ): Promise { - // TODO: What's the search URL for onpremises DevOps? - const searchUrl = `https://almsearch.dev.azure.com/${org}/${project}/_apis/search/codesearchresults?api-version=6.0-preview.1`; - const opts = getAzureRequestOptions(azureConfig); - const response = await fetch(searchUrl, { - method: 'POST', - headers: { - ...opts.headers, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - searchText: `path:${path} repo:${repo || '*'}`, - $top: 1000, - }), - }); + const searchBaseUrl = isCloud(azureConfig.host) + ? 'https://almsearch.dev.azure.com' + : `https://${azureConfig.host}`; + const searchUrl = `${searchBaseUrl}/${org}/${project}/_apis/search/codesearchresults?api-version=6.0-preview.1`; - if (response.status !== 200) { - throw new Error( - `Azure DevOps search failed with response status ${response.status}`, - ); - } + let items: CodeSearchResultItem[] = []; + let hasMorePages = true; - const responseBody: CodeSearchResponse = await response.json(); - return responseBody.results; + do { + const response = await fetch(searchUrl, { + ...getAzureRequestOptions(azureConfig, { + 'Content-Type': 'application/json', + }), + method: 'POST', + body: JSON.stringify({ + searchText: `path:${path} repo:${repo || '*'}`, + $skip: items.length, + $top: PAGE_SIZE, + }), + }); + + if (response.status !== 200) { + throw new Error( + `Azure DevOps search failed with response status ${response.status}`, + ); + } + + const body: CodeSearchResponse = await response.json(); + items = [...items, ...body.results]; + hasMorePages = body.count > items.length; + } while (hasMorePages); + + return items; } From f803ac931e3cd6d0e29b7de32e9bd5eb81b40dc0 Mon Sep 17 00:00:00 2001 From: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> Date: Tue, 23 Nov 2021 21:41:06 +0100 Subject: [PATCH 116/138] add missing styles to Swagger (dark mode) Signed-off-by: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> --- .../OpenApiDefinitionWidget/OpenApiDefinition.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx index 4a74b238f7..8d0accb254 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx @@ -61,12 +61,13 @@ const useStyles = makeStyles(theme => ({ [`& .opblock .opblock-summary-operation-id, .opblock .opblock-summary-path, .opblock .opblock-summary-path__deprecated, - .opblock .opblock-section-header h4, + .opblock h4, + .opblock h5, + .opblock a, + .opblock li, .parameter__name, .response-col_status, .response-col_links, - .responses-inner h4, - .responses-inner h5, .opblock-section-header .btn, .tab li, .info li, @@ -89,6 +90,7 @@ const useStyles = makeStyles(theme => ({ color: theme.palette.text.disabled, }, [`& .opblock-description-wrapper p, + .opblock-description-wrapper li, .opblock-external-docs-wrapper p, .opblock-title_normal p, .response-control-media-type__accept-message, From c982fc12cbf0798caefdebd7c36e8b35b809598e Mon Sep 17 00:00:00 2001 From: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> Date: Tue, 23 Nov 2021 22:03:03 +0100 Subject: [PATCH 117/138] add changeset Signed-off-by: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> --- .changeset/yellow-apes-brush.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/yellow-apes-brush.md diff --git a/.changeset/yellow-apes-brush.md b/.changeset/yellow-apes-brush.md new file mode 100644 index 0000000000..06b33e97d1 --- /dev/null +++ b/.changeset/yellow-apes-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Adjusted some styles in the OpenAPI definition, for elements which were barely readable in dark mode. From 2c54173a3982928da5cc8ec13df71c82b6887a36 Mon Sep 17 00:00:00 2001 From: Morgan Martinet Date: Tue, 23 Nov 2021 18:01:30 -0500 Subject: [PATCH 118/138] apply code review recommandations use encodeURIComponent on dynamic parts ensure that we keep any dashboard path prefix when generating links move URL hash exception for SPAs into the standardFormatter Signed-off-by: Morgan Martinet --- .github/styles/vocab.txt | 2 +- .../clusterLinks/formatClusterLink.test.ts | 15 ------ .../utils/clusterLinks/formatClusterLink.ts | 5 +- .../clusterLinks/formatters/openshift.test.ts | 54 +++++++++++++------ .../clusterLinks/formatters/openshift.ts | 26 ++++++--- .../utils/clusterLinks/formatters/rancher.ts | 26 ++++++--- .../clusterLinks/formatters/standard.test.ts | 45 ++++++++++++++++ .../utils/clusterLinks/formatters/standard.ts | 14 +++-- 8 files changed, 130 insertions(+), 57 deletions(-) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 217342b448..4ec62923d8 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -189,7 +189,7 @@ oidc Okta onboarding Onboarding -Openshift +OpenShift orgs pagerduty pageview diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts b/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts index afc53d9509..31e07a0f14 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts @@ -78,21 +78,6 @@ describe('clusterLinks', () => { 'https://k8s.foo.com/#/service/bar/foobar?namespace=bar', ); }); - it('should return an url on the deployment properly url encoded', () => { - const url = formatClusterLink({ - dashboardUrl: 'https://k8s.foo.com/', - object: { - metadata: { - name: 'foobar', - namespace: 'bar bar', - }, - }, - kind: 'Deployment', - }); - expect(url).toBe( - 'https://k8s.foo.com/#/deployment/bar%20bar/foobar?namespace=bar+bar', - ); - }); }); describe('standard app', () => { diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts b/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts index 83e970248b..a8f83a9c76 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts @@ -40,8 +40,5 @@ export function formatClusterLink(options: FormatClusterLinkOptions) { object: options.object, kind: options.kind, }); - // Note that we can't rely on 'url.href' since it will put the search before the hash - // and this won't be properly recognized by SPAs such as Angular in the standard dashboard. - // Note also that pathname, hash and search will be properly url encoded. - return `${url.origin}${url.pathname}${url.hash}${url.search}`; + return url.toString(); } diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts b/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts index b6cd60b85c..f0b85cad49 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts @@ -15,11 +15,7 @@ */ import { openshiftFormatter } from './openshift'; -function formatUrl(url: URL) { - return url.toString(); -} - -describe('clusterLinks - Openshift formatter', () => { +describe('clusterLinks - OpenShift formatter', () => { it('should return an url on the workloads when there is a namespace only', () => { const url = openshiftFormatter({ dashboardUrl: new URL('https://k8s.foo.com'), @@ -30,7 +26,7 @@ describe('clusterLinks - Openshift formatter', () => { }, kind: 'foo', }); - expect(formatUrl(url)).toBe('https://k8s.foo.com/k8s/cluster/projects/bar'); + expect(url.href).toBe('https://k8s.foo.com/k8s/cluster/projects/bar'); }); it('should return an url on the workloads when the kind is not recognizeed', () => { const url = openshiftFormatter({ @@ -43,7 +39,7 @@ describe('clusterLinks - Openshift formatter', () => { }, kind: 'UnknownKind', }); - expect(formatUrl(url)).toBe('https://k8s.foo.com/k8s/cluster/projects/bar'); + expect(url.href).toBe('https://k8s.foo.com/k8s/cluster/projects/bar'); }); it('should return an url on the deployment', () => { const url = openshiftFormatter({ @@ -56,8 +52,36 @@ describe('clusterLinks - Openshift formatter', () => { }, kind: 'Deployment', }); - expect(formatUrl(url)).toBe( - 'https://k8s.foo.com/k8s/ns/bar/deployments/foobar', + expect(url.href).toBe('https://k8s.foo.com/k8s/ns/bar/deployments/foobar'); + }); + it('should return an url on the deployment and keep the path prefix 1', () => { + const url = openshiftFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/some/prefix/'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Deployment', + }); + expect(url.href).toBe( + 'https://k8s.foo.com/some/prefix/k8s/ns/bar/deployments/foobar', + ); + }); + it('should return an url on the deployment and keep the path prefix 2', () => { + const url = openshiftFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/some/prefix'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Deployment', + }); + expect(url.href).toBe( + 'https://k8s.foo.com/some/prefix/k8s/ns/bar/deployments/foobar', ); }); it('should return an url on the service', () => { @@ -71,9 +95,7 @@ describe('clusterLinks - Openshift formatter', () => { }, kind: 'Service', }); - expect(formatUrl(url)).toBe( - 'https://k8s.foo.com/k8s/ns/bar/services/foobar', - ); + expect(url.href).toBe('https://k8s.foo.com/k8s/ns/bar/services/foobar'); }); it('should return an url on the ingress', () => { const url = openshiftFormatter({ @@ -86,9 +108,7 @@ describe('clusterLinks - Openshift formatter', () => { }, kind: 'Ingress', }); - expect(formatUrl(url)).toBe( - 'https://k8s.foo.com/k8s/ns/bar/ingresses/foobar', - ); + expect(url.href).toBe('https://k8s.foo.com/k8s/ns/bar/ingresses/foobar'); }); it('should return an url on the deployment for a hpa', () => { const url = openshiftFormatter({ @@ -101,7 +121,7 @@ describe('clusterLinks - Openshift formatter', () => { }, kind: 'HorizontalPodAutoscaler', }); - expect(formatUrl(url)).toBe( + expect(url.href).toBe( 'https://k8s.foo.com/k8s/ns/bar/horizontalpodautoscalers/foobar', ); }); @@ -115,7 +135,7 @@ describe('clusterLinks - Openshift formatter', () => { }, kind: 'PersistentVolume', }); - expect(formatUrl(url)).toBe( + expect(url.href).toBe( 'https://k8s.foo.com/k8s/cluster/persistentvolumes/foobar', ); }); diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts b/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts index 4300212a03..6c20cd4720 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts @@ -24,21 +24,31 @@ const kindMappings: Record = { }; export function openshiftFormatter(options: ClusterLinksFormatterOptions): URL { - const result = new URL(options.dashboardUrl.href); - const name = options.object.metadata?.name; - const namespace = options.object.metadata?.namespace; + const basePath = new URL(options.dashboardUrl.href); + const name = encodeURIComponent(options.object.metadata?.name ?? ''); + const namespace = encodeURIComponent( + options.object.metadata?.namespace ?? '', + ); const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; + if (!basePath.pathname.endsWith('/')) { + // a dashboard url with a path should end with a slash otherwise + // the new combined URL will replace the last segment with the appended path! + // https://foobar.com/abc/def + k8s/cluster/projects/test --> https://foobar.com/abc/k8s/cluster/projects/test + // https://foobar.com/abc/def/ + k8s/cluster/projects/test --> https://foobar.com/abc/def/k8s/cluster/projects/test + basePath.pathname += '/'; + } + let path = ''; if (namespace) { if (name && validKind) { - result.pathname = `k8s/ns/${namespace}/${validKind}/${name}`; + path = `k8s/ns/${namespace}/${validKind}/${name}`; } else { - result.pathname = `k8s/cluster/projects/${namespace}`; + path = `k8s/cluster/projects/${namespace}`; } } else if (validKind) { - result.pathname = `k8s/cluster/${validKind}`; + path = `k8s/cluster/${validKind}`; if (name) { - result.pathname += `/${name}`; + path += `/${name}`; } } - return result; + return new URL(path, basePath); } diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/rancher.ts b/plugins/kubernetes/src/utils/clusterLinks/formatters/rancher.ts index a3a274496e..1ace39ec59 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatters/rancher.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatters/rancher.ts @@ -23,14 +23,24 @@ const kindMappings: Record = { }; export function rancherFormatter(options: ClusterLinksFormatterOptions): URL { - const result = new URL(options.dashboardUrl.href); - const name = options.object.metadata?.name; - const namespace = options.object.metadata?.namespace; + const basePath = new URL(options.dashboardUrl.href); + const name = encodeURIComponent(options.object.metadata?.name ?? ''); + const namespace = encodeURIComponent( + options.object.metadata?.namespace ?? '', + ); const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; - if (validKind && name && namespace) { - result.pathname += `explorer/${validKind}/${namespace}/${name}`; - } else if (namespace) { - result.pathname += 'explorer/workload'; + if (!basePath.pathname.endsWith('/')) { + // a dashboard url with a path should end with a slash otherwise + // the new combined URL will replace the last segment with the appended path! + // https://foobar.com/abc/def + explorer/service/test --> https://foobar.com/abc/explorer/service/test + // https://foobar.com/abc/def/ + explorer/service/test --> https://foobar.com/abc/def/explorer/service/test + basePath.pathname += '/'; } - return result; + let path = ''; + if (validKind && name && namespace) { + path = `explorer/${validKind}/${namespace}/${name}`; + } else if (namespace) { + path = 'explorer/workload'; + } + return new URL(path, basePath); } diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.test.ts b/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.test.ts index 76bbf5643d..0b3c21a627 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.test.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.test.ts @@ -67,6 +67,51 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar', ); }); + it('should return an url on the deployment with a prefix 1', () => { + const url = standardFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/some/prefix'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Deployment', + }); + expect(formatUrl(url)).toBe( + 'https://k8s.foo.com/some/prefix/#/deployment/bar/foobar?namespace=bar', + ); + }); + it('should return an url on the deployment with a prefix 2', () => { + const url = standardFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/some/prefix/'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Deployment', + }); + expect(formatUrl(url)).toBe( + 'https://k8s.foo.com/some/prefix/#/deployment/bar/foobar?namespace=bar', + ); + }); + it('should return an url on the deployment properly url encoded', () => { + const url = standardFormatter({ + dashboardUrl: new URL('https://k8s.foo.com/'), + object: { + metadata: { + name: 'foobar', + namespace: 'bar bar', + }, + }, + kind: 'Deployment', + }); + expect(formatUrl(url)).toBe( + 'https://k8s.foo.com/#/deployment/bar%20bar/foobar?namespace=bar%20bar', + ); + }); it('should return an url on the service', () => { const url = standardFormatter({ dashboardUrl: new URL('https://k8s.foo.com/'), diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.ts b/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.ts index fb26cf220d..e28c9fae2b 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.ts @@ -24,16 +24,22 @@ const kindMappings: Record = { export function standardFormatter(options: ClusterLinksFormatterOptions) { const result = new URL(options.dashboardUrl.href); - const name = options.object.metadata?.name; - const namespace = options.object.metadata?.namespace; + const name = encodeURIComponent(options.object.metadata?.name ?? ''); + const namespace = encodeURIComponent( + options.object.metadata?.namespace ?? '', + ); const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; - if (namespace) { - result.searchParams.set('namespace', namespace); + if (!result.pathname.endsWith('/')) { + result.pathname += '/'; } if (validKind && name && namespace) { result.hash = `/${validKind}/${namespace}/${name}`; } else if (namespace) { result.hash = '/workloads'; } + if (namespace) { + // Note that Angular SPA requires a hash and the query parameter should be part of it + result.hash += `?namespace=${namespace}`; + } return result; } From fb90b70de501da7e481deb9749e4ec560140c65d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Nov 2021 04:11:52 +0000 Subject: [PATCH 119/138] chore(deps-dev): bump @testing-library/cypress from 7.0.6 to 8.0.2 Bumps [@testing-library/cypress](https://github.com/kentcdodds/cypress-testing-library) from 7.0.6 to 8.0.2. - [Release notes](https://github.com/kentcdodds/cypress-testing-library/releases) - [Changelog](https://github.com/testing-library/cypress-testing-library/blob/main/CHANGELOG.md) - [Commits](https://github.com/kentcdodds/cypress-testing-library/compare/v7.0.6...v8.0.2) --- updated-dependencies: - dependency-name: "@testing-library/cypress" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- packages/app/package.json | 2 +- yarn.lock | 85 ++++++++++++++++++++++++++++++++------- 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/packages/app/package.json b/packages/app/package.json index 5b9e97d317..09141f7cf7 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -66,7 +66,7 @@ "devDependencies": { "@backstage/test-utils": "^0.1.22", "@rjsf/core": "^3.2.1", - "@testing-library/cypress": "^7.0.1", + "@testing-library/cypress": "^8.0.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/yarn.lock b/yarn.lock index ed2be71ddb..51bf649f1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2078,10 +2078,10 @@ core-js-pure "^3.16.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.15.4" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" - integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.6", "@babel/runtime@^7.14.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.16.3" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5" + integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== dependencies: regenerator-runtime "^0.13.4" @@ -3654,6 +3654,17 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@jest/types@^27.2.5": + version "27.2.5" + resolved "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz#420765c052605e75686982d24b061b4cbba22132" + integrity sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + "@josephg/resolvable@^1.0.0": version "1.0.1" resolved "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz#69bc4db754d79e1a2f17a650d3466e038d94a5eb" @@ -6651,13 +6662,13 @@ dependencies: defer-to-connect "^2.0.0" -"@testing-library/cypress@^7.0.1": - version "7.0.6" - resolved "https://registry.npmjs.org/@testing-library/cypress/-/cypress-7.0.6.tgz#5445dac4f4852c26901c356e9d3a69371bd20ccf" - integrity sha512-atnjqlkEt6spU4Mv7evvpA8fMXeRw7AN2uTKOR1dP6WBvBixVwAYMZY+1fMOaZULWAj9vGLCXXvmw++u3TxuCQ== +"@testing-library/cypress@^8.0.2": + version "8.0.2" + resolved "https://registry.npmjs.org/@testing-library/cypress/-/cypress-8.0.2.tgz#b13f0ff2424dec4368b6670dfbfb7e43af8eefc9" + integrity sha512-KVdm7n37sg/A4e3wKMD4zUl0NpzzVhx06V9Tf0hZHZ7nrZ4yFva6Zwg2EFF1VzHkEfN/ahUzRtT1qiW+vuWnJw== dependencies: - "@babel/runtime" "^7.12.5" - "@testing-library/dom" "^7.28.1" + "@babel/runtime" "^7.14.6" + "@testing-library/dom" "^8.1.0" "@testing-library/dom@^7.28.1": version "7.29.6" @@ -6673,6 +6684,20 @@ lz-string "^1.4.4" pretty-format "^26.6.2" +"@testing-library/dom@^8.1.0": + version "8.11.1" + resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.1.tgz#03fa2684aa09ade589b460db46b4c7be9fc69753" + integrity sha512-3KQDyx9r0RKYailW2MiYrSSKEfH0GTkI51UGEvJenvcoDoeRYs0PZpi2SXqtnMClQvCqdtTTpOfFETDTVADpAg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" + aria-query "^5.0.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.4.4" + pretty-format "^27.0.2" + "@testing-library/jest-dom@^5.10.1": version "5.14.1" resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.14.1.tgz#8501e16f1e55a55d675fe73eecee32cdaddb9766" @@ -8322,6 +8347,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yargs@^16.0.0": + version "16.0.4" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" + integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + dependencies: + "@types/yargs-parser" "*" + "@types/yarnpkg__lockfile@^1.1.4": version "1.1.4" resolved "https://registry.npmjs.org/@types/yarnpkg__lockfile/-/yarnpkg__lockfile-1.1.4.tgz#445251eb00bd9c1e751f82c7c6bf4f714edfd464" @@ -9016,7 +9048,7 @@ ansi-regex@^4.0.0, ansi-regex@^4.1.0: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== -ansi-regex@^5.0.0: +ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== @@ -9046,6 +9078,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: "@types/color-name" "^1.1.1" color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + ansi-to-html@^0.6.11: version "0.6.14" resolved "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.14.tgz#65fe6d08bba5dd9db33f44a20aec331e0010dad8" @@ -9367,6 +9404,11 @@ aria-query@^4.2.2: "@babel/runtime" "^7.10.2" "@babel/runtime-corejs3" "^7.10.2" +aria-query@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c" + integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg== + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -13126,6 +13168,11 @@ dom-accessibility-api@^0.5.4, dom-accessibility-api@^0.5.6: resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.6.tgz#3f5d43b52c7a3bd68b5fb63fa47b4e4c1fdf65a9" integrity sha512-DplGLZd8L1lN64jlT27N9TVSESFR5STaEJvX+thCby7fuCHonfPpAlodYc3vuUYbDuDec5w8AMP7oCM5TWFsqw== +dom-accessibility-api@^0.5.9: + version "0.5.10" + resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.10.tgz#caa6d08f60388d0bb4539dd75fe458a9a1d0014c" + integrity sha512-Xu9mD0UjrJisTmv7lmVSDMagQcU9R5hwAbxsaAE/35XPnPLJobbuREfV/rraiSaEj/UOvgrzQs66zyTWTlyd+g== + dom-converter@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -23233,6 +23280,16 @@ pretty-format@^26.0.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" +pretty-format@^27.0.2: + version "27.3.1" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz#7e9486365ccdd4a502061fa761d3ab9ca1b78df5" + integrity sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA== + dependencies: + "@jest/types" "^27.2.5" + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + pretty-hrtime@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" @@ -29142,9 +29199,9 @@ write-pkg@^4.0.0: write-json-file "^3.2.0" ws@7.4.5, ws@^7.4.6: - version "7.5.5" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== + version "7.5.6" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" + integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== ws@7.4.6: version "7.4.6" From b8f430eee03b66dd3d50bd3e745abf56a54022e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Nov 2021 04:13:08 +0000 Subject: [PATCH 120/138] chore(deps-dev): bump @storybook/addon-actions from 6.3.7 to 6.3.12 Bumps [@storybook/addon-actions](https://github.com/storybookjs/storybook/tree/HEAD/addons/actions) from 6.3.7 to 6.3.12. - [Release notes](https://github.com/storybookjs/storybook/releases) - [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md) - [Commits](https://github.com/storybookjs/storybook/commits/v6.3.12/addons/actions) --- updated-dependencies: - dependency-name: "@storybook/addon-actions" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 61 +++++++++++-------------------------------------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/yarn.lock b/yarn.lock index ed2be71ddb..86998a31d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5556,16 +5556,16 @@ util-deprecate "^1.0.2" "@storybook/addon-actions@^6.1.11": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.3.7.tgz#b25434972bef351aceb3f7ec6fd66e210f256aac" - integrity sha512-CEAmztbVt47Gw1o6Iw0VP20tuvISCEKk9CS/rCjHtb4ubby6+j/bkp3pkEUQIbyLdHiLWFMz0ZJdyA/U6T6jCw== + version "6.3.12" + resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.3.12.tgz#69eb5f8f780f1b00456051da6290d4b959ba24a0" + integrity sha512-mzuN4Ano4eyicwycM2PueGzzUCAEzt9/6vyptWEIVJu0sjK0J9KtBRlqFi1xGQxmCfimDR/n/vWBBkc7fp2uJA== dependencies: - "@storybook/addons" "6.3.7" - "@storybook/api" "6.3.7" - "@storybook/client-api" "6.3.7" - "@storybook/components" "6.3.7" - "@storybook/core-events" "6.3.7" - "@storybook/theming" "6.3.7" + "@storybook/addons" "6.3.12" + "@storybook/api" "6.3.12" + "@storybook/client-api" "6.3.12" + "@storybook/components" "6.3.12" + "@storybook/core-events" "6.3.12" + "@storybook/theming" "6.3.12" core-js "^3.8.2" fast-deep-equal "^3.1.3" global "^4.4.0" @@ -5841,19 +5841,6 @@ qs "^6.10.0" telejson "^5.3.2" -"@storybook/channel-postmessage@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.3.7.tgz#bd4edf84a29aa2cd4a22d26115c60194d289a840" - integrity sha512-Cmw8HRkeSF1yUFLfEIUIkUICyCXX8x5Ol/5QPbiW9HPE2hbZtYROCcg4bmWqdq59N0Tp9FQNSn+9ZygPgqQtNw== - dependencies: - "@storybook/channels" "6.3.7" - "@storybook/client-logger" "6.3.7" - "@storybook/core-events" "6.3.7" - core-js "^3.8.2" - global "^4.4.0" - qs "^6.10.0" - telejson "^5.3.2" - "@storybook/channels@6.3.11": version "6.3.11" resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.3.11.tgz#a14ce233367a9072bd1cffef3825f125c27bb0ae" @@ -5929,30 +5916,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.3.7.tgz#cb1dca05467d777bd09aadbbdd1dd22ca537ce14" - integrity sha512-8wOH19cMIwIIYhZy5O5Wl8JT1QOL5kNuamp9GPmg5ff4DtnG+/uUslskRvsnKyjPvl+WbIlZtBVWBiawVdd/yQ== - dependencies: - "@storybook/addons" "6.3.7" - "@storybook/channel-postmessage" "6.3.7" - "@storybook/channels" "6.3.7" - "@storybook/client-logger" "6.3.7" - "@storybook/core-events" "6.3.7" - "@storybook/csf" "0.0.1" - "@types/qs" "^6.9.5" - "@types/webpack-env" "^1.16.0" - core-js "^3.8.2" - global "^4.4.0" - lodash "^4.17.20" - memoizerific "^1.11.3" - qs "^6.10.0" - regenerator-runtime "^0.13.7" - stable "^0.1.8" - store2 "^2.12.0" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/client-logger@6.3.11": version "6.3.11" resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.3.11.tgz#d2e0e17f35ed4c5ee282d818b6db3a015ce6b833" @@ -29142,9 +29105,9 @@ write-pkg@^4.0.0: write-json-file "^3.2.0" ws@7.4.5, ws@^7.4.6: - version "7.5.5" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== + version "7.5.6" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" + integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== ws@7.4.6: version "7.4.6" From 88f5378397dfe3b626ee492d34b78a0f6d93ea4d Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 24 Nov 2021 09:36:40 +0100 Subject: [PATCH 121/138] Add export, update API report Signed-off-by: Johan Haals --- packages/core-plugin-api/api-report.md | 11 +++++++++-- packages/core-plugin-api/src/plugin/index.ts | 1 + packages/core-plugin-api/src/plugin/types.ts | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/core-plugin-api/api-report.md b/packages/core-plugin-api/api-report.md index 27f3480930..560071e1fa 100644 --- a/packages/core-plugin-api/api-report.md +++ b/packages/core-plugin-api/api-report.md @@ -258,6 +258,7 @@ export type BackstagePlugin< getId(): string; output(): PluginOutput[]; getApis(): Iterable; + getFeatureFlags(): Iterable; provide(extension: Extension): T; routes: Routes; externalRoutes: ExternalRoutes; @@ -463,7 +464,7 @@ export type FeatureFlag = { pluginId: string; }; -// @public +// @public @deprecated export type FeatureFlagOutput = { type: 'feature-flag'; name: string; @@ -682,14 +683,20 @@ export type PluginConfig< register?(hooks: PluginHooks): void; routes?: Routes; externalRoutes?: ExternalRoutes; + featureFlags?: PluginFeatureFlagConfig[]; }; // @public +export type PluginFeatureFlagConfig = { + name: string; +}; + +// @public @deprecated export type PluginHooks = { featureFlags: FeatureFlagsHooks; }; -// @public +// @public @deprecated export type PluginOutput = FeatureFlagOutput; // @public diff --git a/packages/core-plugin-api/src/plugin/index.ts b/packages/core-plugin-api/src/plugin/index.ts index d3272607ef..4f7609fd9c 100644 --- a/packages/core-plugin-api/src/plugin/index.ts +++ b/packages/core-plugin-api/src/plugin/index.ts @@ -25,4 +25,5 @@ export type { PluginConfig, PluginHooks, PluginOutput, + PluginFeatureFlagConfig, } from './types'; diff --git a/packages/core-plugin-api/src/plugin/types.ts b/packages/core-plugin-api/src/plugin/types.ts index c258b6f9fc..0f8d3404d8 100644 --- a/packages/core-plugin-api/src/plugin/types.ts +++ b/packages/core-plugin-api/src/plugin/types.ts @@ -19,7 +19,7 @@ import { AnyApiFactory } from '../apis/system'; /** * Replace with using {@link RouteRef}s. - * @deprecated + * @deprecated will be removed * @public */ export type FeatureFlagOutput = { From f658a341783ba4507b215c9dd77ffc3b75e90a02 Mon Sep 17 00:00:00 2001 From: Nicolas Arnold Date: Wed, 24 Nov 2021 09:31:12 +0000 Subject: [PATCH 122/138] Using stringEntityRef for comparision Signed-off-by: Nicolas Arnold --- .../src/service/DefaultLocationService.test.ts | 2 +- .../src/service/DefaultLocationService.ts | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultLocationService.test.ts b/plugins/catalog-backend/src/service/DefaultLocationService.test.ts index e2b82ad2c0..562bae4867 100644 --- a/plugins/catalog-backend/src/service/DefaultLocationService.test.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.test.ts @@ -196,7 +196,7 @@ describe('DefaultLocationServiceTest', () => { { type: 'url', target: 'https://backstage.io/catalog-info.yaml' }, true, ), - ).rejects.toThrowError('Duplicate nested entity: foo'); + ).rejects.toThrowError('Duplicate nested entity: location:default/foo'); }); it('should return exists false when the location does not exist beforehand', async () => { diff --git a/plugins/catalog-backend/src/service/DefaultLocationService.ts b/plugins/catalog-backend/src/service/DefaultLocationService.ts index d28112eda3..8dd2274842 100644 --- a/plugins/catalog-backend/src/service/DefaultLocationService.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.ts @@ -19,6 +19,7 @@ import { LocationSpec, LOCATION_ANNOTATION, ORIGIN_LOCATION_ANNOTATION, + stringifyEntityRef, } from '@backstage/catalog-model'; import { CatalogProcessingOrchestrator, @@ -69,13 +70,18 @@ export class DefaultLocationService implements LocationService { }); if (processed.ok) { - const { metadata, kind } = processed.completedEntity; if ( entities.some( - e => e.metadata.name === metadata.name && e.kind === kind, + e => + stringifyEntityRef(e) === + stringifyEntityRef(processed.completedEntity), ) ) { - throw new Error(`Duplicate nested entity: ${metadata.name}`); + throw new Error( + `Duplicate nested entity: ${stringifyEntityRef( + processed.completedEntity, + )}`, + ); } unprocessedEntities.push(...processed.deferredEntities); entities.push(processed.completedEntity); From 92405f32bb0cf4acd0d860b354fca411281f62ee Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 24 Nov 2021 13:55:28 +0100 Subject: [PATCH 123/138] bug: should check the children of the first parse, not the root. Signed-off-by: blam --- ...WorkflowRunner.test.ts => NunjucksWorkflowRunner.test.ts} | 0 .../src/scaffolder/tasks/NunjucksWorkflowRunner.ts | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) rename plugins/scaffolder-backend/src/scaffolder/tasks/{DefaultWorkflowRunner.test.ts => NunjucksWorkflowRunner.test.ts} (100%) diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DefaultWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/tasks/DefaultWorkflowRunner.test.ts rename to plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index c66d967103..1139ce41c5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -114,9 +114,10 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { private isSingleTemplateString(input: string) { const { parser, nodes } = require('nunjucks'); const parsed = parser.parse(input, {}, this.nunjucksOptions); + return ( parsed.children.length === 1 && - !(parsed.children[0] instanceof nodes.TemplateData) + !(parsed.children[0]?.children?.[0] instanceof nodes.TemplateData) ); } @@ -147,7 +148,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { return JSON.parse(templated); } } catch (ex) { - this.options.logger.error( + console.error( `Failed to parse template string: ${value} with error ${ex.message}`, ); } From 5fd0e077bc3e38cf98dfb172690b4fcdbab4a1d1 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 24 Nov 2021 14:01:26 +0100 Subject: [PATCH 124/138] chore: adding test for this bug Signed-off-by: blam --- .../tasks/NunjucksWorkflowRunner.test.ts | 25 +++++++++++++++++++ .../tasks/NunjucksWorkflowRunner.ts | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 1f7877791c..b2e2e85a6c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -270,6 +270,31 @@ describe('DefaultWorkflowRunner', () => { ); }); + it('should not try and parse something that is not parsable', async () => { + jest.spyOn(logger, 'error'); + const task = createMockTaskWithSpec({ + apiVersion: 'scaffolder.backstage.io/v1beta3', + steps: [ + { + id: 'test', + name: 'name', + action: 'jest-mock-action', + input: { + foo: 'bob', + }, + }, + ], + output: {}, + parameters: { + input: 'BACKSTAGE', + }, + }); + + await runner.execute(task); + + expect(logger.error).not.toHaveBeenCalled(); + }); + it('should keep the original types for the input and not parse things that arent meant to be parsed', async () => { const task = createMockTaskWithSpec({ apiVersion: 'scaffolder.backstage.io/v1beta3', diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 1139ce41c5..5b42eef459 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -148,7 +148,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { return JSON.parse(templated); } } catch (ex) { - console.error( + this.options.logger.error( `Failed to parse template string: ${value} with error ${ex.message}`, ); } From 4be343d2dd464fd8e21fe2ea7dc9f45e4261ced4 Mon Sep 17 00:00:00 2001 From: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> Date: Wed, 24 Nov 2021 14:03:00 +0100 Subject: [PATCH 125/138] add LogMeIn as an adopter Signed-off-by: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> --- ADOPTERS.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index 67aa8ec709..c4c84d11be 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -66,8 +66,9 @@ | [Palo Alto Networks](https://www.paloaltonetworks.com) | [Jeremy Guarini](https://github.com/jeremyguarini), [Brian Lomeland](https://github.com/bbbmmmlll), [Palo Alto Networks](https://github.com/PaloAltoNetworks) | Developer portal, service catalog, documentation and tooling | | [Signal Iduna Group](https://www.signal-iduna.de/) | [Jonas Thomsen](https://github.com/JoThomsen) | Developer Portal, documentation, monitoring, service catalog for our insurance ecosystem | | [Tradeshift](https://www.tradeshift.com/) | [Soren Mathiasen](https://github.com/sorenmat) | Developer Portal: documentation, monitoring, service templates, service catalog for our micro services | -| [Unity](https://unity.com) | [Ted Cordery](https://github.com/TeddyBallGame) | A centralized service catalog with documentation for our service engineers. | -| [PicPay](https://www.picpay.com) | [Luis Baroni](https://github.com/lcsbaroni), [Renata Poluceno](https://github.com/renatapoluceno), [PicPay](https://github.com/picpay) | Developer portal for building services throught templates, service catalog with ownership of services, documentation and metrics providing autonomy and visibility for all. | +| [Unity](https://unity.com) | [Ted Cordery](https://github.com/TeddyBallGame) | A centralized service catalog with documentation for our service engineers. | +| [PicPay](https://www.picpay.com) | [Luis Baroni](https://github.com/lcsbaroni), [Renata Poluceno](https://github.com/renatapoluceno), [PicPay](https://github.com/picpay) | Developer portal for building services throught templates, service catalog with ownership of services, documentation and metrics providing autonomy and visibility for all. | | [Epic Games](https://www.epicgames.com) | [Brian Jung](https://github.com/brian-at-epic), [Jeff Goldian](https://github.com/jeffgoldian-Epic) | Developer Portal: Service Catalog, Documentation, Software Templates and more making our internal teams' lives easier! | -| [Globo](https://globo.com) | [Carlos Gusmão](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. | -| [QBE](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly 🚀 | \ No newline at end of file +| [Globo](https://globo.com) | [Carlos Gusmão](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. | +| [QBE](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly 🚀 | +| [LogMeIn](https://www.logmein.com) | [Lorenzo Orsatti](https://github.com/lorsatti) | Improve onboarding experience of new developers. Discover faster and painlessly developer documentation, API definitions and team information. Provide useful dev metrics in a central place. Provide easy-to-use templates for new services. | From e634a47ce50236b65a73140f0c4b0c7fbd559c1f Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 24 Nov 2021 14:03:22 +0100 Subject: [PATCH 126/138] chore: added changeset Signed-off-by: blam --- .changeset/shiny-insects-remember.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/shiny-insects-remember.md diff --git a/.changeset/shiny-insects-remember.md b/.changeset/shiny-insects-remember.md new file mode 100644 index 0000000000..a26882b65d --- /dev/null +++ b/.changeset/shiny-insects-remember.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fix bug where there was error log lines written when failing to `JSON.parse` things that were not `JSON` values. From e99db76f6ad95174c7b4d75ed556b7cae88de24b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Oct 2021 14:48:41 +0000 Subject: [PATCH 127/138] build(deps): bump @gitbeaker/node from 30.3.0 to 34.4.1 Bumps [@gitbeaker/node](https://github.com/jdalrymple/gitbeaker) from 30.3.0 to 34.4.1. - [Release notes](https://github.com/jdalrymple/gitbeaker/releases) - [Changelog](https://github.com/jdalrymple/gitbeaker/blob/master/CHANGELOG.md) - [Commits](https://github.com/jdalrymple/gitbeaker/compare/30.3.0...34.4.1) --- updated-dependencies: - dependency-name: "@gitbeaker/node" dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- packages/backend/package.json | 2 +- plugins/scaffolder-backend/package.json | 2 +- yarn.lock | 47 +++++++++++++++++++++---- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index 4fb692f040..794f5ac1a6 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -52,7 +52,7 @@ "@backstage/plugin-tech-insights-node": "^0.1.0", "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.0", "@backstage/plugin-todo-backend": "^0.1.13", - "@gitbeaker/node": "^30.2.0", + "@gitbeaker/node": "^34.4.1", "@octokit/rest": "^18.5.3", "azure-devops-node-api": "^11.0.1", "dockerode": "^3.3.1", diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 374cfeffd6..01d0b793bf 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -41,7 +41,7 @@ "@backstage/plugin-scaffolder-backend-module-cookiecutter": "^0.1.4", "@backstage/types": "^0.1.1", "@gitbeaker/core": "^30.2.0", - "@gitbeaker/node": "^30.2.0", + "@gitbeaker/node": "^34.4.1", "@octokit/rest": "^18.5.3", "@octokit/webhooks": "^9.14.1", "@types/express": "^4.17.6", diff --git a/yarn.lock b/yarn.lock index 420fd4add8..ce88d83aa3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2879,7 +2879,7 @@ resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== -"@gitbeaker/core@^30.2.0", "@gitbeaker/core@^30.3.0": +"@gitbeaker/core@^30.2.0": version "30.3.0" resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-30.3.0.tgz#d005891d47cfacb41d4a3cc8bf3ee8c68c53d378" integrity sha512-j7GHsFo6AOuRmLaK4F4Kx967jTy6LFZh5vjmRxjlRvX0qlfl3NJKiQIl30fZz1rPXWdQLAq+kwl1i0BKrWhOpA== @@ -2890,13 +2890,25 @@ query-string "^7.0.0" xcase "^2.0.1" -"@gitbeaker/node@^30.2.0": - version "30.3.0" - resolved "https://registry.npmjs.org/@gitbeaker/node/-/node-30.3.0.tgz#ceebde08a13d3f655fa614a4ced56eb1f0a71ec1" - integrity sha512-Ythbadb1+yMO2hSgvp3nvaroHTkI4+mdLg1rdV3YNIF1n+kUYXQD2GY7wpAjH0KjAnBAmgxw/JsFmlfnRu3KAg== +"@gitbeaker/core@^34.4.1": + version "34.4.1" + resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-34.4.1.tgz#4458c7a607d5d3bd28202e897fab758fae78f747" + integrity sha512-M109vfwG9qaKH9oPouMRq8oM1ohJ8btCNmuxlfbj4OYbP2q8JhB5yO4xJeGiA0FdG/BWtrqEASQvJS3H4RNM3Q== dependencies: - "@gitbeaker/core" "^30.3.0" - "@gitbeaker/requester-utils" "^30.3.0" + "@gitbeaker/requester-utils" "^34.4.1" + form-data "^4.0.0" + li "^1.3.0" + mime-types "^2.1.32" + query-string "^7.0.0" + xcase "^2.0.1" + +"@gitbeaker/node@^34.4.1": + version "34.4.1" + resolved "https://registry.npmjs.org/@gitbeaker/node/-/node-34.4.1.tgz#872ebd0cae16343008a1f0ed937bd1c159f42007" + integrity sha512-0hXpZF3WU9WJgSD6rmj1oCwzQVf5cEw6HiXjwlkwQXv2hwRlZETL4M8JALInRD1ngMOoREe33eTNwyoRWmS2lA== + dependencies: + "@gitbeaker/core" "^34.4.1" + "@gitbeaker/requester-utils" "^34.4.1" delay "^5.0.0" got "^11.8.2" xcase "^2.0.1" @@ -2910,6 +2922,15 @@ query-string "^7.0.0" xcase "^2.0.1" +"@gitbeaker/requester-utils@^34.4.1": + version "34.4.1" + resolved "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-34.4.1.tgz#e5f1e9397de1cb5219640b3cf96d8cb7f41e3f14" + integrity sha512-YqRNzV5lwhLrIltgjfaYFCsdp/jHthbc4IEmKO1yZw5aAE7aJrtR/iXMxPy2JvnGODNgIhBSxHaXlCdLJWYIkA== + dependencies: + form-data "^4.0.0" + qs "^6.10.1" + xcase "^2.0.1" + "@google-cloud/common@^3.7.0": version "3.7.0" resolved "https://registry.npmjs.org/@google-cloud/common/-/common-3.7.0.tgz#ee3fba75aeaa614978aebf8740380670026592aa" @@ -20452,6 +20473,11 @@ mime-db@1.49.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== +mime-db@1.50.0: + version "1.50.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" + integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== + "mime-db@>= 1.43.0 < 2": version "1.48.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" @@ -20476,6 +20502,13 @@ mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, m dependencies: mime-db "1.49.0" +mime-types@^2.1.32: + version "2.1.33" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" + integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== + dependencies: + mime-db "1.50.0" + mime@1.6.0, mime@^1.4.1: version "1.6.0" resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" From 42ebbc18c0dc476baf1efa6322ce3b026a5a37c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 24 Nov 2021 14:21:45 +0100 Subject: [PATCH 128/138] get both gitbeaker packages bumped, and add changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/thirty-tigers-refuse.md | 6 ++ packages/backend/package.json | 2 +- .../packages/backend/package.json.hbs | 2 +- plugins/scaffolder-backend/package.json | 4 +- yarn.lock | 69 ++++++------------- 5 files changed, 31 insertions(+), 52 deletions(-) create mode 100644 .changeset/thirty-tigers-refuse.md diff --git a/.changeset/thirty-tigers-refuse.md b/.changeset/thirty-tigers-refuse.md new file mode 100644 index 0000000000..0797d36747 --- /dev/null +++ b/.changeset/thirty-tigers-refuse.md @@ -0,0 +1,6 @@ +--- +'@backstage/create-app': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +Bump gitbeaker to the latest version diff --git a/packages/backend/package.json b/packages/backend/package.json index 794f5ac1a6..1cef99c6a0 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -52,7 +52,7 @@ "@backstage/plugin-tech-insights-node": "^0.1.0", "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.0", "@backstage/plugin-todo-backend": "^0.1.13", - "@gitbeaker/node": "^34.4.1", + "@gitbeaker/node": "^34.6.0", "@octokit/rest": "^18.5.3", "azure-devops-node-api": "^11.0.1", "dockerode": "^3.3.1", diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs index 8f2de6a8ae..6f0726b0f8 100644 --- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs @@ -27,7 +27,7 @@ "@backstage/plugin-search-backend": "^{{version '@backstage/plugin-search-backend'}}", "@backstage/plugin-search-backend-node": "^{{version '@backstage/plugin-search-backend-node'}}", "@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}", - "@gitbeaker/node": "^30.2.0", + "@gitbeaker/node": "^34.6.0", "@octokit/rest": "^18.5.3", "dockerode": "^3.3.1", "express": "^4.17.1", diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 01d0b793bf..36ac76c95f 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -40,8 +40,8 @@ "@backstage/plugin-scaffolder-common": "^0.1.1", "@backstage/plugin-scaffolder-backend-module-cookiecutter": "^0.1.4", "@backstage/types": "^0.1.1", - "@gitbeaker/core": "^30.2.0", - "@gitbeaker/node": "^34.4.1", + "@gitbeaker/core": "^34.6.0", + "@gitbeaker/node": "^34.6.0", "@octokit/rest": "^18.5.3", "@octokit/webhooks": "^9.14.1", "@types/express": "^4.17.6", diff --git a/yarn.lock b/yarn.lock index ce88d83aa3..1e4d402072 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2879,53 +2879,33 @@ resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== -"@gitbeaker/core@^30.2.0": - version "30.3.0" - resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-30.3.0.tgz#d005891d47cfacb41d4a3cc8bf3ee8c68c53d378" - integrity sha512-j7GHsFo6AOuRmLaK4F4Kx967jTy6LFZh5vjmRxjlRvX0qlfl3NJKiQIl30fZz1rPXWdQLAq+kwl1i0BKrWhOpA== +"@gitbeaker/core@^34.6.0": + version "34.6.0" + resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-34.6.0.tgz#f774ea98ac079ba2edf495fdef738ac3f741178b" + integrity sha512-yKF+oxffPyzOnyuHCqLGJrBHhcFHuGHtcmqKhGKtnYPfqcNYA8rt4INAHaE5wMz4ILua9b4sB8p42fki+xn6WA== dependencies: - "@gitbeaker/requester-utils" "^30.3.0" + "@gitbeaker/requester-utils" "^34.6.0" form-data "^4.0.0" li "^1.3.0" + mime "^3.0.0" query-string "^7.0.0" xcase "^2.0.1" -"@gitbeaker/core@^34.4.1": - version "34.4.1" - resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-34.4.1.tgz#4458c7a607d5d3bd28202e897fab758fae78f747" - integrity sha512-M109vfwG9qaKH9oPouMRq8oM1ohJ8btCNmuxlfbj4OYbP2q8JhB5yO4xJeGiA0FdG/BWtrqEASQvJS3H4RNM3Q== +"@gitbeaker/node@^34.6.0": + version "34.6.0" + resolved "https://registry.npmjs.org/@gitbeaker/node/-/node-34.6.0.tgz#104f122433b65ceb45b0e645001d15cbcc9b1280" + integrity sha512-gVV4Wuev43Jbyoy1fszC885+bkvWH4zWiUhtIu0PSAm628j/OxO7idLIqUEMV0hDf6wm/PE/vOSP6PhjE0N+fA== dependencies: - "@gitbeaker/requester-utils" "^34.4.1" - form-data "^4.0.0" - li "^1.3.0" - mime-types "^2.1.32" - query-string "^7.0.0" - xcase "^2.0.1" - -"@gitbeaker/node@^34.4.1": - version "34.4.1" - resolved "https://registry.npmjs.org/@gitbeaker/node/-/node-34.4.1.tgz#872ebd0cae16343008a1f0ed937bd1c159f42007" - integrity sha512-0hXpZF3WU9WJgSD6rmj1oCwzQVf5cEw6HiXjwlkwQXv2hwRlZETL4M8JALInRD1ngMOoREe33eTNwyoRWmS2lA== - dependencies: - "@gitbeaker/core" "^34.4.1" - "@gitbeaker/requester-utils" "^34.4.1" + "@gitbeaker/core" "^34.6.0" + "@gitbeaker/requester-utils" "^34.6.0" delay "^5.0.0" got "^11.8.2" xcase "^2.0.1" -"@gitbeaker/requester-utils@^30.3.0": - version "30.3.0" - resolved "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-30.3.0.tgz#fbbaae20263ff90952da116d8782f74f47b29c81" - integrity sha512-b5vCaUqP2Jrqdpt5CkmFET4VFHwJYjnIovwZGYd5H0aKmiPw4NmeW1JtP+65J4xf0c4AOQQj6XSf7TZLuPNAqw== - dependencies: - form-data "^4.0.0" - query-string "^7.0.0" - xcase "^2.0.1" - -"@gitbeaker/requester-utils@^34.4.1": - version "34.4.1" - resolved "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-34.4.1.tgz#e5f1e9397de1cb5219640b3cf96d8cb7f41e3f14" - integrity sha512-YqRNzV5lwhLrIltgjfaYFCsdp/jHthbc4IEmKO1yZw5aAE7aJrtR/iXMxPy2JvnGODNgIhBSxHaXlCdLJWYIkA== +"@gitbeaker/requester-utils@^34.6.0": + version "34.6.0" + resolved "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-34.6.0.tgz#4489009b759ca6f9a83f244453f4f610f1ac7349" + integrity sha512-H8utxbSP1kEdX0KcyVYrTDTT0A3UcPwrIV1ahyufX9ZLybYSUsA56B8Wx5kJSbWGFT1ffu2f8H2YDMwNCKKsBg== dependencies: form-data "^4.0.0" qs "^6.10.1" @@ -20473,11 +20453,6 @@ mime-db@1.49.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== -mime-db@1.50.0: - version "1.50.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" - integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== - "mime-db@>= 1.43.0 < 2": version "1.48.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" @@ -20502,13 +20477,6 @@ mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, m dependencies: mime-db "1.49.0" -mime-types@^2.1.32: - version "2.1.33" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" - integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== - dependencies: - mime-db "1.50.0" - mime@1.6.0, mime@^1.4.1: version "1.6.0" resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -20519,6 +20487,11 @@ mime@^2.2.0, mime@^2.4.4, mime@^2.4.6: resolved "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" From b08dbb103552ad16064c0c84bad975311152320d Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Wed, 24 Nov 2021 14:18:11 +0000 Subject: [PATCH 129/138] permission-node: destructure options inside function to simplify api-report Signed-off-by: Mike Lewis --- plugins/permission-node/api-report.md | 6 +-- .../src/integration/createConditionExports.ts | 38 ++++++++++--------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index 95e1eb0711..e5fe9a7087 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -57,11 +57,7 @@ export type ConditionTransformer = ( export const createConditionExports: < TResource, TRules extends Record>, ->({ - pluginId, - resourceType, - rules, -}: { +>(options: { pluginId: string; resourceType: string; rules: TRules; diff --git a/plugins/permission-node/src/integration/createConditionExports.ts b/plugins/permission-node/src/integration/createConditionExports.ts index d7f8c675d2..d69064a56c 100644 --- a/plugins/permission-node/src/integration/createConditionExports.ts +++ b/plugins/permission-node/src/integration/createConditionExports.ts @@ -63,11 +63,7 @@ export type Conditions< export const createConditionExports = < TResource, TRules extends Record>, ->({ - pluginId, - resourceType, - rules, -}: { +>(options: { pluginId: string; resourceType: string; rules: TRules; @@ -78,17 +74,23 @@ export const createConditionExports = < resourceType: string; conditions: PermissionCriteria; }; -} => ({ - conditions: Object.entries(rules).reduce( - (acc, [key, rule]) => ({ - ...acc, - [key]: createConditionFactory(rule), +} => { + const { pluginId, resourceType, rules } = options; + + return { + conditions: Object.entries(rules).reduce( + (acc, [key, rule]) => ({ + ...acc, + [key]: createConditionFactory(rule), + }), + {} as Conditions, + ), + createConditions: ( + conditions: PermissionCriteria, + ) => ({ + pluginId, + resourceType, + conditions, }), - {} as Conditions, - ), - createConditions: (conditions: PermissionCriteria) => ({ - pluginId, - resourceType, - conditions, - }), -}); + }; +}; From f5a25ec8046dd40c05f258ae5f58a430b37a9039 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Wed, 24 Nov 2021 14:19:32 +0000 Subject: [PATCH 130/138] permission-node: fix typo in doc comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Mike Lewis --- .../permission-node/src/integration/createConditionFactory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/permission-node/src/integration/createConditionFactory.ts b/plugins/permission-node/src/integration/createConditionFactory.ts index 066233bf41..8ee94091e1 100644 --- a/plugins/permission-node/src/integration/createConditionFactory.ts +++ b/plugins/permission-node/src/integration/createConditionFactory.ts @@ -26,7 +26,7 @@ import { PermissionRule } from '../types'; * Plugin authors should generally use the {@link createConditionExports} in order to efficiently * create multiple condition factories. This helper should generally only be used to construct * condition factories for third-party rules that aren't part of the backend plugin with which - * they're intended to integrate with. + * they're intended to integrate. * * @public */ From aded9bbc22444e1da75c0d60947096e49d7e8154 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Wed, 24 Nov 2021 14:20:56 +0000 Subject: [PATCH 131/138] permission-node: set version to 0.0.0 before initial release Signed-off-by: Mike Lewis --- plugins/permission-node/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 4a9c837eb6..e22e2d2de4 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-node", "description": "Common permission and authorization utilities for backend plugins", - "version": "0.1.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", From 44b46644d996c82aa1aa611e539db3844661fe5d Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Wed, 24 Nov 2021 14:22:32 +0000 Subject: [PATCH 132/138] permission-node: add changeset for initial release Signed-off-by: Mike Lewis --- .changeset/heavy-tools-hang.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/heavy-tools-hang.md diff --git a/.changeset/heavy-tools-hang.md b/.changeset/heavy-tools-hang.md new file mode 100644 index 0000000000..91a843b0a7 --- /dev/null +++ b/.changeset/heavy-tools-hang.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-permission-node': patch +--- + +New package containing common permission and authorization utilities for backend plugins. For more information, see the [authorization PRFC](https://github.com/backstage/backstage/pull/7761). From 370da15e7b225de270c8fc90f6cb8b817a02c859 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Wed, 24 Nov 2021 14:30:21 +0000 Subject: [PATCH 133/138] permission-node: separate doc comment summaries with @remarks tag Signed-off-by: Mike Lewis --- plugins/permission-node/src/index.ts | 1 - .../src/integration/createConditionExports.ts | 6 +++++- .../src/integration/createConditionFactory.ts | 2 ++ .../src/integration/createPermissionIntegrationRouter.ts | 2 ++ plugins/permission-node/src/policy/types.ts | 9 +++++++++ plugins/permission-node/src/types.ts | 3 +++ 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/plugins/permission-node/src/index.ts b/plugins/permission-node/src/index.ts index 697c02ab22..39527bac71 100644 --- a/plugins/permission-node/src/index.ts +++ b/plugins/permission-node/src/index.ts @@ -19,7 +19,6 @@ * * @packageDocumentation */ - export * from './integration'; export * from './policy'; export * from './types'; diff --git a/plugins/permission-node/src/integration/createConditionExports.ts b/plugins/permission-node/src/integration/createConditionExports.ts index d69064a56c..30cff6628a 100644 --- a/plugins/permission-node/src/integration/createConditionExports.ts +++ b/plugins/permission-node/src/integration/createConditionExports.ts @@ -49,7 +49,11 @@ export type Conditions< /** * Creates the recommended condition-related exports for a given plugin based on the built-in - * {@link PermissionRule}s it supports. It returns a `conditions` object containing a + * {@link PermissionRule}s it supports. + * + * @remarks + * + * The function returns a `conditions` object containing a * {@link @backstage/plugin-permission-common#PermissionCondition} factory for each of the * supplied {@link PermissionRule}s, along with a `createConditions` function which builds the * wrapper object needed to enclose conditions when authoring {@link PermissionPolicy} implementations. diff --git a/plugins/permission-node/src/integration/createConditionFactory.ts b/plugins/permission-node/src/integration/createConditionFactory.ts index 8ee94091e1..84a8dc86a6 100644 --- a/plugins/permission-node/src/integration/createConditionFactory.ts +++ b/plugins/permission-node/src/integration/createConditionFactory.ts @@ -19,6 +19,8 @@ import { PermissionRule } from '../types'; /** * Creates a condition factory function for a given authorization rule and parameter types. * + * @remarks + * * For example, an isEntityOwner rule for catalog entities might take an array of entityRef strings. * The rule itself defines _how_ to check a given resource, whereas a condition also includes _what_ * to verify. diff --git a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts index 7757678128..99e282b144 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts @@ -97,6 +97,8 @@ const applyConditions = ( * conditional authorization for their resources should add the router created by this function * to their express app inside their `createRouter` implementation. * + * @remarks + * * To make this concrete, we can use the Backstage software catalog as an example. The catalog has * conditional rules around access to specific _entities_ in the catalog. The _type_ of resource is * captured here as `resourceType`, a string identifier (`catalog-entity` in this example) that can diff --git a/plugins/permission-node/src/policy/types.ts b/plugins/permission-node/src/policy/types.ts index 36186d5e57..44380bad26 100644 --- a/plugins/permission-node/src/policy/types.ts +++ b/plugins/permission-node/src/policy/types.ts @@ -25,9 +25,12 @@ import { BackstageIdentity } from '@backstage/plugin-auth-backend'; /** * An authorization request to be evaluated by the {@link PermissionPolicy}. * + * @remarks + * * This differs from {@link @backstage/permission-common#AuthorizeRequest} in that `resourceRef` * should never be provided. This forces policies to be written in a way that's compatible with * filtering collections of resources at data load time. + * * @public */ export type PolicyAuthorizeRequest = Omit; @@ -35,6 +38,8 @@ export type PolicyAuthorizeRequest = Omit; /** * A conditional result to an authorization request, returned by the {@link PermissionPolicy}. * + * @remarks + * * This indicates that the policy allows authorization for the request, given that the returned * conditions hold when evaluated. The conditions will be evaluated by the corresponding plugin * which knows about the referenced permission rules. @@ -54,6 +59,7 @@ export type ConditionalPolicyResult = { /** * The result of evaluating an authorization request with a {@link PermissionPolicy}. + * * @public */ export type PolicyResult = @@ -63,6 +69,8 @@ export type PolicyResult = /** * A policy to evaluate authorization requests for any permissioned action performed in Backstage. * + * @remarks + * * This takes as input a permission and an optional Backstage identity, and should return ALLOW if * the user is permitted to execute that action; otherwise DENY. For permissions relating to * resources, such a catalog entities, a conditional response can also be returned. This states @@ -71,6 +79,7 @@ export type PolicyResult = * Conditions are a rule, and parameters to evaluate against that rule. For example, the rule might * be `isOwner` and the parameters a collection of entityRefs; if one of the entityRefs matches * the `owner` field on a catalog entity, this would resolve to ALLOW. + * * @public */ export interface PermissionPolicy { diff --git a/plugins/permission-node/src/types.ts b/plugins/permission-node/src/types.ts index a4e95fbd61..678befc99c 100644 --- a/plugins/permission-node/src/types.ts +++ b/plugins/permission-node/src/types.ts @@ -20,6 +20,8 @@ import type { PermissionCriteria } from '@backstage/plugin-permission-common'; * A conditional rule that can be provided in an * {@link @backstage/permission-common#AuthorizeResult} response to an authorization request. * + * @remarks + * * Rules can either be evaluated against a resource loaded in memory, or used as filters when * loading a collection of resources from a data source. The `apply` and `toQuery` methods implement * these two concepts. @@ -27,6 +29,7 @@ import type { PermissionCriteria } from '@backstage/plugin-permission-common'; * The two operations should always have the same logical result. If they don’t, the effective * outcome of an authorization operation will sometimes differ depending on how the authorization * check was performed. + * * @public */ export type PermissionRule< From 5970c1ecc2dbb6746c220be4f8de2e43b3e6f7f2 Mon Sep 17 00:00:00 2001 From: Morgan Martinet Date: Wed, 24 Nov 2021 17:20:39 -0500 Subject: [PATCH 134/138] fix spelling of OpenShift Signed-off-by: Morgan Martinet --- .changeset/green-bags-hug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/green-bags-hug.md b/.changeset/green-bags-hug.md index fb6240321c..9d250062f7 100644 --- a/.changeset/green-bags-hug.md +++ b/.changeset/green-bags-hug.md @@ -2,4 +2,4 @@ '@backstage/plugin-kubernetes': patch --- -Implement support for formatting Openshift dashboard url links +Implement support for formatting OpenShift dashboard url links From c59edf0415b75df30a4f5dc4c0381e61ab3a7003 Mon Sep 17 00:00:00 2001 From: MrSecure Date: Wed, 24 Nov 2021 17:04:16 -0600 Subject: [PATCH 135/138] fix: inconsistent time units The stability document had mixed use of "two days" and "two weeks" ... with "two weeks" seeming to be the intended value. Signed-off-by: Mr. Secure --- docs/overview/stability-index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/overview/stability-index.md b/docs/overview/stability-index.md index a79bcd6e11..be02ba8f07 100644 --- a/docs/overview/stability-index.md +++ b/docs/overview/stability-index.md @@ -27,7 +27,7 @@ point building on top of the previous one: and the new APIs can be used in parallel. This deprecation must have been released for at least two weeks before the deprecated API is removed in a minor version bump. -- **3** - The time limit for the deprecation is 3 months instead of two days. +- **3** - The time limit for the deprecation is 3 months instead of two weeks. TL;DR: From ddb60aa7c4283d47f2d43201e029645ea98233f9 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Wed, 24 Nov 2021 23:37:11 +0000 Subject: [PATCH 136/138] permission-node: switch initial release changeset to minor Signed-off-by: Mike Lewis --- .changeset/heavy-tools-hang.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/heavy-tools-hang.md b/.changeset/heavy-tools-hang.md index 91a843b0a7..0c47202e46 100644 --- a/.changeset/heavy-tools-hang.md +++ b/.changeset/heavy-tools-hang.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-permission-node': patch +'@backstage/plugin-permission-node': minor --- New package containing common permission and authorization utilities for backend plugins. For more information, see the [authorization PRFC](https://github.com/backstage/backstage/pull/7761). From 58e197947a18e6168fd839e4aea5134f5f50a7ea Mon Sep 17 00:00:00 2001 From: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> Date: Thu, 25 Nov 2021 00:50:59 +0100 Subject: [PATCH 137/138] fix jenkins pagination Signed-off-by: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> --- .../src/components/BuildsPage/lib/CITable/CITable.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx index 39187fe859..b1eaf2c24c 100644 --- a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -205,6 +205,10 @@ export const CITableView = ({ onChangePageSize, total, }: Props) => { + const projectsInPage = projects?.slice( + page * pageSize, + Math.min(projects.length, (page + 1) * pageSize), + ); return ( retry(), }, ]} - data={projects ?? []} + data={projectsInPage ?? []} onPageChange={onChangePage} onRowsPerPageChange={onChangePageSize} title={ From ad433b346ffea0fcc29cc76fddeac1ada63e106e Mon Sep 17 00:00:00 2001 From: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> Date: Thu, 25 Nov 2021 00:54:41 +0100 Subject: [PATCH 138/138] add changeset Signed-off-by: Lorenzo Orsatti <49567430+lorsatti@users.noreply.github.com> --- .changeset/eleven-suns-type.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/eleven-suns-type.md diff --git a/.changeset/eleven-suns-type.md b/.changeset/eleven-suns-type.md new file mode 100644 index 0000000000..b16f26c968 --- /dev/null +++ b/.changeset/eleven-suns-type.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-jenkins': patch +--- + +Fix Jenkins project table pagination.