From a7d5efa4a92225d97e73bf2d7cf49c5d22c13710 Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Fri, 29 Sep 2023 18:13:01 -0400 Subject: [PATCH 001/348] Fix TechDocs page scroll. Move logic from scrollIntoAnchor transformer to a useEffect . Signed-off-by: Sydney Achinger --- .../TechDocsReaderPageContent.tsx | 18 ++- .../TechDocsReaderPageContent/dom.tsx | 2 - .../techdocs/src/reader/transformers/index.ts | 1 - .../transformers/scrollIntoAnchor.test.ts | 118 ------------------ .../reader/transformers/scrollIntoAnchor.ts | 37 ------ 5 files changed, 16 insertions(+), 160 deletions(-) delete mode 100644 plugins/techdocs/src/reader/transformers/scrollIntoAnchor.test.ts delete mode 100644 plugins/techdocs/src/reader/transformers/scrollIntoAnchor.ts diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx index 1e5459fc9d..ad25c5c81d 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx @@ -14,12 +14,14 @@ * limitations under the License. */ -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect } from 'react'; import { makeStyles, Grid } from '@material-ui/core'; import { TechDocsShadowDom, + useShadowDomStylesLoading, + useShadowRootElements, useTechDocsReaderPage, } from '@backstage/plugin-techdocs-react'; import { CompoundEntityRef } from '@backstage/catalog-model'; @@ -78,8 +80,20 @@ export const TechDocsReaderPageContent = withTechDocsReaderProvider( entityRef, setShadowRoot, } = useTechDocsReaderPage(); - const dom = useTechDocsReaderDom(entityRef); + const hash = window.location.hash; + const isStyleLoading = useShadowDomStylesLoading(dom); + const [hashElement] = useShadowRootElements([`[id="${hash.slice(1)}"]`]); + + useEffect(() => { + if (hashElement) { + if (!isStyleLoading) { + hashElement.scrollIntoView(); + } + } else { + document?.querySelector('header')?.scrollIntoView(); + } + }, [hashElement, isStyleLoading, dom]); const handleAppend = useCallback( (newShadowRoot: ShadowRoot) => { diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx index cc42c46b4e..29e6945fa7 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx @@ -39,7 +39,6 @@ import { removeMkdocsHeader, rewriteDocLinks, simplifyMkdocsFooter, - scrollIntoAnchor, scrollIntoNavigation, transform as transformer, copyToClipboard, @@ -167,7 +166,6 @@ export const useTechDocsReaderDom = ( const postRender = useCallback( async (transformedElement: Element) => transformer(transformedElement, [ - scrollIntoAnchor(), scrollIntoNavigation(), copyToClipboard(theme), addLinkClickListener({ diff --git a/plugins/techdocs/src/reader/transformers/index.ts b/plugins/techdocs/src/reader/transformers/index.ts index ca17261572..7df98f1f26 100644 --- a/plugins/techdocs/src/reader/transformers/index.ts +++ b/plugins/techdocs/src/reader/transformers/index.ts @@ -25,6 +25,5 @@ export * from './copyToClipboard'; export * from './removeMkdocsHeader'; export * from './simplifyMkdocsFooter'; export * from './onCssReady'; -export * from './scrollIntoAnchor'; export * from './scrollIntoNavigation'; export * from './transformer'; diff --git a/plugins/techdocs/src/reader/transformers/scrollIntoAnchor.test.ts b/plugins/techdocs/src/reader/transformers/scrollIntoAnchor.test.ts deleted file mode 100644 index e222c24a4c..0000000000 --- a/plugins/techdocs/src/reader/transformers/scrollIntoAnchor.test.ts +++ /dev/null @@ -1,118 +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 { scrollIntoAnchor } from '../transformers'; -import { createTestShadowDom } from '../../test-utils'; -import { Transformer } from './transformer'; -import mkdocsIndex from '../../test-utils/fixtures/mkdocs-index'; -import { SHADOW_DOM_STYLE_LOAD_EVENT } from '@backstage/plugin-techdocs-react'; - -describe('scrollIntoAnchor', () => { - const scrollIntoView = jest.fn(); - let querySelectorSpy: jest.SpyInstance; - let addEventListenerSpy: jest.SpyInstance; - let removeEventListenerSpy: jest.SpyInstance; - const applySpies: Transformer = dom => { - querySelectorSpy = jest.spyOn(dom, 'querySelector'); - querySelectorSpy.mockReturnValue({ scrollIntoView }); - addEventListenerSpy = jest.spyOn(dom, 'addEventListener'); - removeEventListenerSpy = jest.spyOn(dom, 'removeEventListener'); - return dom; - }; - - afterEach(() => { - jest.clearAllMocks(); - }); - - it('does nothing if there is no anchor element', async () => { - await createTestShadowDom(mkdocsIndex, { - preTransformers: [], - postTransformers: [applySpies, scrollIntoAnchor()], - }); - expect(querySelectorSpy).not.toHaveBeenCalled(); - expect(addEventListenerSpy).toHaveBeenCalled(); - expect(removeEventListenerSpy).toHaveBeenCalled(); - expect(addEventListenerSpy).toHaveBeenCalledWith( - SHADOW_DOM_STYLE_LOAD_EVENT, - expect.any(Function), - ); - expect(removeEventListenerSpy).toHaveBeenCalledTimes(1); - expect(removeEventListenerSpy).toHaveBeenCalledWith( - SHADOW_DOM_STYLE_LOAD_EVENT, - expect.any(Function), - ); - // check that the same function is passed to both addEventListener and removeEventListener - expect(addEventListenerSpy.mock.calls[0][1]).toBe( - removeEventListenerSpy.mock.calls[0][1], - ); - }); - - it('scroll to the hash anchor element', async () => { - window.location.hash = '#hash'; - await createTestShadowDom(mkdocsIndex, { - preTransformers: [], - postTransformers: [applySpies, scrollIntoAnchor()], - }); - expect(querySelectorSpy).toHaveBeenCalledWith( - expect.stringMatching('[id="hash"]'), - ); - expect(scrollIntoView).toHaveBeenCalledWith(); - expect(addEventListenerSpy).toHaveBeenCalledTimes(1); - expect(removeEventListenerSpy).toHaveBeenCalledTimes(1); - expect(addEventListenerSpy).toHaveBeenCalledWith( - SHADOW_DOM_STYLE_LOAD_EVENT, - expect.any(Function), - ); - expect(removeEventListenerSpy).toHaveBeenCalledTimes(1); - expect(removeEventListenerSpy).toHaveBeenCalledWith( - SHADOW_DOM_STYLE_LOAD_EVENT, - expect.any(Function), - ); - // check that the same function is passed to both addEventListener and removeEventListener - expect(addEventListenerSpy.mock.calls[0][1]).toBe( - removeEventListenerSpy.mock.calls[0][1], - ); - window.location.hash = ''; - }); - - it('works for anchor starting with number', async () => { - querySelectorSpy.mockReturnValue({ scrollIntoView }); - window.location.hash = '#1-hash'; - await createTestShadowDom(mkdocsIndex, { - preTransformers: [], - postTransformers: [applySpies, scrollIntoAnchor()], - }); - expect(querySelectorSpy).toHaveBeenCalledWith( - expect.stringMatching('[id="1-hash"]'), - ); - expect(scrollIntoView).toHaveBeenCalledWith(); - expect(addEventListenerSpy).toHaveBeenCalledTimes(1); - expect(addEventListenerSpy).toHaveBeenCalledWith( - SHADOW_DOM_STYLE_LOAD_EVENT, - expect.any(Function), - ); - expect(removeEventListenerSpy).toHaveBeenCalledTimes(1); - expect(removeEventListenerSpy).toHaveBeenCalledWith( - SHADOW_DOM_STYLE_LOAD_EVENT, - expect.any(Function), - ); - // check that the same function is passed to both addEventListener and removeEventListener - expect(addEventListenerSpy.mock.calls[0][1]).toBe( - removeEventListenerSpy.mock.calls[0][1], - ); - window.location.hash = ''; - }); -}); diff --git a/plugins/techdocs/src/reader/transformers/scrollIntoAnchor.ts b/plugins/techdocs/src/reader/transformers/scrollIntoAnchor.ts deleted file mode 100644 index 97a18b7241..0000000000 --- a/plugins/techdocs/src/reader/transformers/scrollIntoAnchor.ts +++ /dev/null @@ -1,37 +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 type { Transformer } from './transformer'; -import { SHADOW_DOM_STYLE_LOAD_EVENT } from '@backstage/plugin-techdocs-react'; - -export const scrollIntoAnchor = (): Transformer => { - return dom => { - dom.addEventListener( - SHADOW_DOM_STYLE_LOAD_EVENT, - function handleShadowDomStyleLoad() { - if (window.location.hash) { - const hash = window.location.hash.slice(1); - dom?.querySelector(`[id="${hash}"]`)?.scrollIntoView(); - } - dom.removeEventListener( - SHADOW_DOM_STYLE_LOAD_EVENT, - handleShadowDomStyleLoad, - ); - }, - ); - return dom; - }; -}; From c21a8b419a02b2ffff6e034a2efd0cbb64a6e7c8 Mon Sep 17 00:00:00 2001 From: David Weber Date: Sun, 1 Oct 2023 21:52:12 +0200 Subject: [PATCH 002/348] chore: add tips plugin to microsite Signed-off-by: David Weber --- microsite/data/plugins/tips.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 microsite/data/plugins/tips.yaml diff --git a/microsite/data/plugins/tips.yaml b/microsite/data/plugins/tips.yaml new file mode 100644 index 0000000000..93c57ab303 --- /dev/null +++ b/microsite/data/plugins/tips.yaml @@ -0,0 +1,10 @@ +--- +title: Tips +author: dweber019 +authorUrl: https://github.com/dweber019 +category: Discovery +description: The tips plugin will show the end user some helpful information for entities. +documentation: https://github.com/dweber019/backstage-plugin-tips +iconUrl: https://raw.githubusercontent.com/dweber019/backstage-plugin-tips/main/plugins/tips/docs/pluginIcon.png +npmPackageName: '@dweber019/backstage-plugin-tips' +addedDate: '2023-10-01' From c437253b7a00805b07fad9bac086560bb02edefa Mon Sep 17 00:00:00 2001 From: Hannes Jetter Date: Thu, 5 Oct 2023 22:32:26 +0200 Subject: [PATCH 003/348] Refactored TechDocsCollator; added entityTransformer functionality Signed-off-by: Hannes Jetter --- .changeset/red-beers-roll.md | 5 ++ docs/features/search/how-to-guides.md | 35 +++++++++--- .../DefaultTechDocsCollatorFactory.test.ts | 42 +++++++++++++- .../DefaultTechDocsCollatorFactory.ts | 20 +++---- .../TechDocsCollatorEntityTransformer.ts | 23 ++++++++ ...tTechDocsCollatorEntityTransformer.test.ts | 54 ++++++++++++++++++ ...efaultTechDocsCollatorEntityTransformer.ts | 55 +++++++++++++++++++ .../src/collators/index.ts | 4 ++ 8 files changed, 217 insertions(+), 21 deletions(-) create mode 100644 .changeset/red-beers-roll.md create mode 100644 plugins/search-backend-module-techdocs/src/collators/TechDocsCollatorEntityTransformer.ts create mode 100644 plugins/search-backend-module-techdocs/src/collators/defaultTechDocsCollatorEntityTransformer.test.ts create mode 100644 plugins/search-backend-module-techdocs/src/collators/defaultTechDocsCollatorEntityTransformer.ts diff --git a/.changeset/red-beers-roll.md b/.changeset/red-beers-roll.md new file mode 100644 index 0000000000..d5d2d36511 --- /dev/null +++ b/.changeset/red-beers-roll.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-techdocs': patch +--- + +The process of adding or modifying fields in the techdocs search index has been simplified. For more details, see [How to customize fields in the Software Catalog or TechDocs index](../docs/features/search/how-to-guides.md#how-to-customize-fields-in-the-software-catalog-or-techdocs-index). diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md index 382221d781..a5662999ae 100644 --- a/docs/features/search/how-to-guides.md +++ b/docs/features/search/how-to-guides.md @@ -114,18 +114,18 @@ of the `SearchType` component. > Check out the documentation around [integrating search into plugins](../../plugins/integrating-search-into-plugins.md#create-a-collator) for how to create your own collator. -## How to customize fields in the Software Catalog index +## How to customize fields in the Software Catalog or TechDocs index -Sometimes you will might want to have ability to control -which data passes to search index in catalog collator, or to customize data for specific kind. -You can easily do that by passing `entityTransformer` callback to `DefaultCatalogCollatorFactory`. -You can either just simply amend default behaviour, or even to write completely new document -(which should follow some required basic structure though). +Sometimes, you might want to have the ability to control which data passes into the search index +in the catalog collator or customize data for a specific kind. You can easily achieve this +by passing an `entityTransformer` callback to the `DefaultCatalogCollatorFactory`. This behavior +is also possible for the `DefaultTechDocsCollatorFactory`. You can either simply amend the default behavior +or even write an entirely new document (which should still follow some required basic structure). > `authorization` and `location` cannot be modified via a `entityTransformer`, `location` can be modified only through `locationTemplate`. ```ts title="packages/backend/src/plugins/search.ts" -const entityTransformer: CatalogCollatorEntityTransformer = ( +const catalogEntityTransformer: CatalogCollatorEntityTransformer = ( entity: Entity, ) => { if (entity.kind === 'SomeKind') { @@ -146,7 +146,26 @@ indexBuilder.addCollator({ discovery: env.discovery, tokenManager: env.tokenManager, /* highlight-add-next-line */ - entityTransformer, + entityTransformer: catalogEntityTransformer, + }), +}); + +const techDocsEntityTransformer: TechDocsCollatorEntityTransformer = ( + entity: Entity, +) => { + return { + // add more fields to the index + ...defaultTechDocsCollatorEntityTransformer(entity), + tags: entity.metadata.tags, + }; +}; + +indexBuilder.addCollator({ + collator: DefaultTechDocsCollatorFactory.fromConfig(env.config, { + discovery: env.discovery, + tokenManager: env.tokenManager, + /* highlight-add-next-line */ + entityTransformer: techDocsEntityTransformer, }), }); ``` diff --git a/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.test.ts b/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.test.ts index 319b8fb446..8f56a92096 100644 --- a/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.test.ts +++ b/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2023 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. @@ -26,6 +26,8 @@ import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { Readable } from 'stream'; import { DefaultTechDocsCollatorFactory } from './DefaultTechDocsCollatorFactory'; +import { defaultTechDocsCollatorEntityTransformer } from './defaultTechDocsCollatorEntityTransformer'; +import { TechDocsCollatorEntityTransformer } from './TechDocsCollatorEntityTransformer'; const logger = getVoidLogger(); @@ -66,6 +68,7 @@ const expectedEntities: Entity[] = [ annotations: { 'backstage.io/techdocs-ref': './', }, + tags: ['tag1', 'tag2'], }, spec: { type: 'dog', @@ -256,5 +259,42 @@ describe('DefaultTechDocsCollatorFactory', () => { }); }); }); + + it('should transform the entity using the entityTransformer function', async () => { + const entityTransformer: TechDocsCollatorEntityTransformer = ( + entity: Entity, + ) => { + return { + ...defaultTechDocsCollatorEntityTransformer(entity), + tags: entity.metadata.tags, + }; + }; + + factory = DefaultTechDocsCollatorFactory.fromConfig(config, { + ...options, + entityTransformer, + }); + + collator = await factory.getCollator(); + + const pipeline = TestPipeline.fromCollator(collator); + const { documents } = await pipeline.execute(); + const entity = expectedEntities[0]; + documents.forEach((document, idx) => { + expect(document).toMatchObject({ + title: mockSearchDocIndex.docs[idx].title, + location: `/docs/default/component/${entity.metadata.name}/${mockSearchDocIndex.docs[idx].location}`, + text: mockSearchDocIndex.docs[idx].text, + namespace: 'default', + entityTitle: entity!.metadata.title, + componentType: entity!.spec!.type, + lifecycle: entity!.spec!.lifecycle, + owner: '', + kind: entity.kind.toLocaleLowerCase('en-US'), + name: entity.metadata.name, + tags: entity.metadata.tags, + }); + }); + }); }); }); diff --git a/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts b/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts index 051dc93189..b76fedbdf9 100644 --- a/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts +++ b/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2023 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. @@ -39,6 +39,8 @@ import fetch from 'node-fetch'; import pLimit from 'p-limit'; import { Readable } from 'stream'; import { Logger } from 'winston'; +import { TechDocsCollatorEntityTransformer } from './TechDocsCollatorEntityTransformer'; +import { defaultTechDocsCollatorEntityTransformer } from './defaultTechDocsCollatorEntityTransformer'; interface MkSearchIndexDoc { title: string; @@ -59,6 +61,7 @@ export type TechDocsCollatorFactoryOptions = { catalogClient?: CatalogApi; parallelismLimit?: number; legacyPathCasing?: boolean; + entityTransformer?: TechDocsCollatorEntityTransformer; }; type EntityInfo = { @@ -85,6 +88,7 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { private readonly tokenManager: TokenManager; private readonly parallelismLimit: number; private readonly legacyPathCasing: boolean; + private entityTransformer: TechDocsCollatorEntityTransformer; private constructor(options: TechDocsCollatorFactoryOptions) { this.discovery = options.discovery; @@ -97,6 +101,8 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { this.parallelismLimit = options.parallelismLimit ?? 10; this.legacyPathCasing = options.legacyPathCasing ?? false; this.tokenManager = options.tokenManager; + this.entityTransformer = + options.entityTransformer ?? defaultTechDocsCollatorEntityTransformer; } static fromConfig(config: Config, options: TechDocsCollatorFactoryOptions) { @@ -142,17 +148,6 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { 'metadata.annotations.backstage.io/techdocs-ref': CATALOG_FILTER_EXISTS, }, - fields: [ - 'kind', - 'namespace', - 'metadata.annotations', - 'metadata.name', - 'metadata.title', - 'metadata.namespace', - 'spec.type', - 'spec.lifecycle', - 'relations', - ], limit: batchSize, offset: entitiesRetrieved, }, @@ -204,6 +199,7 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { ]); return searchIndex.docs.map((doc: MkSearchIndexDoc) => ({ + ...this.entityTransformer(entity), title: unescape(doc.title), text: unescape(doc.text || ''), location: this.applyArgsToFormat( diff --git a/plugins/search-backend-module-techdocs/src/collators/TechDocsCollatorEntityTransformer.ts b/plugins/search-backend-module-techdocs/src/collators/TechDocsCollatorEntityTransformer.ts new file mode 100644 index 0000000000..142199e3dc --- /dev/null +++ b/plugins/search-backend-module-techdocs/src/collators/TechDocsCollatorEntityTransformer.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2023 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 { Entity } from '@backstage/catalog-model'; +import { TechDocsDocument } from '@backstage/plugin-techdocs-node'; + +/** @public */ +export type TechDocsCollatorEntityTransformer = ( + entity: Entity, +) => Omit; diff --git a/plugins/search-backend-module-techdocs/src/collators/defaultTechDocsCollatorEntityTransformer.test.ts b/plugins/search-backend-module-techdocs/src/collators/defaultTechDocsCollatorEntityTransformer.test.ts new file mode 100644 index 0000000000..fe8f61dbe8 --- /dev/null +++ b/plugins/search-backend-module-techdocs/src/collators/defaultTechDocsCollatorEntityTransformer.test.ts @@ -0,0 +1,54 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { defaultTechDocsCollatorEntityTransformer } from './defaultTechDocsCollatorEntityTransformer'; + +describe('defaultTechDocsCollatorEntityTransformer', () => { + it('should transform the entity with the correct properties', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test-component', + description: 'A test component', + annotations: { + 'backstage.io/techdocs-ref': 'docs', + }, + }, + spec: { + type: 'service', + owner: 'test@example.com', + }, + }; + + const transformedEntity = defaultTechDocsCollatorEntityTransformer(entity); + + expect(transformedEntity).toEqual({ + kind: entity.kind, + namespace: entity.metadata.namespace || 'default', + annotations: entity.metadata.annotations || '', + name: entity.metadata.name || '', + title: entity.metadata.title || '', + text: 'A test component', + componentType: entity.spec?.type?.toString() || 'other', + type: entity.spec?.type?.toString() || 'other', + lifecycle: (entity.spec?.lifecycle as string) || '', + owner: (entity.spec?.owner as string) || '', + path: '', + }); + }); +}); diff --git a/plugins/search-backend-module-techdocs/src/collators/defaultTechDocsCollatorEntityTransformer.ts b/plugins/search-backend-module-techdocs/src/collators/defaultTechDocsCollatorEntityTransformer.ts new file mode 100644 index 0000000000..cc0b16b2fa --- /dev/null +++ b/plugins/search-backend-module-techdocs/src/collators/defaultTechDocsCollatorEntityTransformer.ts @@ -0,0 +1,55 @@ +/* + * Copyright 2023 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 { Entity, isGroupEntity, isUserEntity } from '@backstage/catalog-model'; +import { TechDocsCollatorEntityTransformer } from './TechDocsCollatorEntityTransformer'; + +const getDocumentText = (entity: Entity): string => { + const documentTexts: string[] = []; + documentTexts.push(entity.metadata.description || ''); + + if (isUserEntity(entity) || isGroupEntity(entity)) { + if (entity.spec?.profile?.displayName) { + documentTexts.push(entity.spec.profile.displayName); + } + } + + if (isUserEntity(entity)) { + if (entity.spec?.profile?.email) { + documentTexts.push(entity.spec.profile.email); + } + } + + return documentTexts.join(' : '); +}; + +/** @public */ +export const defaultTechDocsCollatorEntityTransformer: TechDocsCollatorEntityTransformer = + (entity: Entity) => { + return { + kind: entity.kind, + namespace: entity.metadata.namespace || 'default', + annotations: entity.metadata.annotations || '', + name: entity.metadata.name || '', + title: entity.metadata.title || '', + text: getDocumentText(entity), + componentType: entity.spec?.type?.toString() || 'other', + type: entity.spec?.type?.toString() || 'other', + lifecycle: (entity.spec?.lifecycle as string) || '', + owner: (entity.spec?.owner as string) || '', + path: '', + }; + }; diff --git a/plugins/search-backend-module-techdocs/src/collators/index.ts b/plugins/search-backend-module-techdocs/src/collators/index.ts index 8c5fd122f1..94be458e33 100644 --- a/plugins/search-backend-module-techdocs/src/collators/index.ts +++ b/plugins/search-backend-module-techdocs/src/collators/index.ts @@ -17,3 +17,7 @@ export { DefaultTechDocsCollatorFactory } from './DefaultTechDocsCollatorFactory'; export type { TechDocsCollatorFactoryOptions } from './DefaultTechDocsCollatorFactory'; + +export { defaultTechDocsCollatorEntityTransformer } from './defaultTechDocsCollatorEntityTransformer'; + +export type { TechDocsCollatorEntityTransformer } from './TechDocsCollatorEntityTransformer'; From 033fedd516ea0656881c5c0041f49afb40cd90d3 Mon Sep 17 00:00:00 2001 From: Hannes Jetter Date: Fri, 6 Oct 2023 03:00:17 +0200 Subject: [PATCH 004/348] api-report.md changes Signed-off-by: Hannes Jetter --- plugins/search-backend-module-techdocs/api-report.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/search-backend-module-techdocs/api-report.md b/plugins/search-backend-module-techdocs/api-report.md index 9f72b1c487..592cf5065a 100644 --- a/plugins/search-backend-module-techdocs/api-report.md +++ b/plugins/search-backend-module-techdocs/api-report.md @@ -8,12 +8,17 @@ import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; +import { Entity } from '@backstage/catalog-model'; import { Logger } from 'winston'; import { Permission } from '@backstage/plugin-permission-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Readable } from 'stream'; +import { TechDocsDocument } from '@backstage/plugin-techdocs-node'; import { TokenManager } from '@backstage/backend-common'; +// @public (undocumented) +export const defaultTechDocsCollatorEntityTransformer: TechDocsCollatorEntityTransformer; + // @public export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { // (undocumented) @@ -29,6 +34,11 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { readonly visibilityPermission: Permission; } +// @public (undocumented) +export type TechDocsCollatorEntityTransformer = ( + entity: Entity, +) => Omit; + // @public export type TechDocsCollatorFactoryOptions = { discovery: PluginEndpointDiscovery; @@ -38,5 +48,6 @@ export type TechDocsCollatorFactoryOptions = { catalogClient?: CatalogApi; parallelismLimit?: number; legacyPathCasing?: boolean; + entityTransformer?: TechDocsCollatorEntityTransformer; }; ``` From 75e728ec557f07650872a504ba2d31b862b98385 Mon Sep 17 00:00:00 2001 From: David Weber Date: Sun, 8 Oct 2023 01:32:56 +0200 Subject: [PATCH 005/348] chore: add tips plugin to microsite Signed-off-by: David Weber --- microsite/data/plugins/tips.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/data/plugins/tips.yaml b/microsite/data/plugins/tips.yaml index 93c57ab303..e58ad0fb46 100644 --- a/microsite/data/plugins/tips.yaml +++ b/microsite/data/plugins/tips.yaml @@ -7,4 +7,4 @@ description: The tips plugin will show the end user some helpful information for documentation: https://github.com/dweber019/backstage-plugin-tips iconUrl: https://raw.githubusercontent.com/dweber019/backstage-plugin-tips/main/plugins/tips/docs/pluginIcon.png npmPackageName: '@dweber019/backstage-plugin-tips' -addedDate: '2023-10-01' +addedDate: '2023-10-08' From b73020637ee9fae7c12ba8c44a69f29979129a9c Mon Sep 17 00:00:00 2001 From: StepSecurity Bot Date: Thu, 21 Sep 2023 16:45:27 +0000 Subject: [PATCH 006/348] [StepSecurity] Apply security best practices Signed-off-by: StepSecurity Bot --- .github/dependabot.yml | 1291 +++++++++++++++++ .github/workflows/automate_area-labels.yml | 13 +- .../workflows/automate_changeset_feedback.yml | 9 +- .github/workflows/automate_merge_message.yml | 9 +- .github/workflows/automate_stale.yml | 13 +- .github/workflows/ci-noop.yml | 13 + .github/workflows/ci.yml | 33 +- .github/workflows/cron.yml | 7 +- .github/workflows/dependency-review.yml | 27 + .github/workflows/deploy_docker-image.yml | 17 +- .github/workflows/deploy_microsite.yml | 16 +- .github/workflows/deploy_nightly.yml | 13 +- .github/workflows/deploy_packages.yml | 28 +- .github/workflows/issue.yaml | 7 +- .../workflows/pr-review-comment-trigger.yaml | 10 +- .github/workflows/pr-review-comment.yaml | 9 +- .github/workflows/pr.yaml | 7 +- .github/workflows/scorecard.yml | 5 + .github/workflows/sync_code-formatting.yml | 13 +- .../workflows/sync_dependabot-changesets.yml | 9 +- .github/workflows/sync_release-manifest.yml | 13 +- .../workflows/sync_renovate-changesets.yml | 9 +- .github/workflows/sync_snyk-github-issues.yml | 13 +- .github/workflows/sync_snyk-monitor.yml | 19 +- .github/workflows/sync_version-packages.yml | 11 +- .github/workflows/uffizzi-build.yml | 35 +- .github/workflows/uffizzi-preview.yaml | 9 +- .../workflows/verify_accessibility-noop.yml | 8 + .github/workflows/verify_accessibility.yml | 11 +- .github/workflows/verify_codeql.yml | 20 +- .github/workflows/verify_docs-quality.yml | 9 +- .../workflows/verify_e2e-kubernetes-noop.yml | 8 + .github/workflows/verify_e2e-kubernetes.yml | 13 +- .github/workflows/verify_e2e-linux-noop.yml | 8 + .github/workflows/verify_e2e-linux.yml | 11 +- .github/workflows/verify_e2e-techdocs.yml | 12 +- .github/workflows/verify_e2e-windows-noop.yml | 8 + .github/workflows/verify_e2e-windows.yml | 15 +- .github/workflows/verify_fossa.yml | 10 +- .github/workflows/verify_microsite-noop.yml | 8 + .github/workflows/verify_microsite.yml | 12 +- .github/workflows/verify_storybook-noop.yml | 8 + .github/workflows/verify_storybook.yml | 13 +- .github/workflows/verify_windows.yml | 12 +- .pre-commit-config.yaml | 18 + 45 files changed, 1752 insertions(+), 110 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 .pre-commit-config.yaml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..253e5b3230 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,1291 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + + - package-ecosystem: docker + directory: /contrib/.devcontainer + schedule: + interval: daily + + - package-ecosystem: docker + directory: /contrib/docker/devops + schedule: + interval: daily + + - package-ecosystem: npm + directory: /cypress + schedule: + interval: daily + + - package-ecosystem: npm + directory: /microsite + schedule: + interval: daily + + - package-ecosystem: npm + directory: / + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/app-defaults + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/app-next-example-plugin + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/app-next + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/app + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-app-api + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-defaults + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-dev-utils + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-next + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-openapi-utils + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-plugin-api + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-plugin-manager + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-tasks + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend-test-utils + schedule: + interval: daily + + - package-ecosystem: docker + directory: /packages/backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/catalog-client + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/catalog-model + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/cli-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/cli-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/cli/asset-types + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/cli + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/codemods + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/config-loader + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/config + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/core-app-api + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/core-components + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/core-plugin-api + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/create-app + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/create-app/templates/default-app/examples/template/content + schedule: + interval: daily + + - package-ecosystem: docker + directory: /packages/create-app/templates/default-app/packages/backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/create-app/templates/default-app + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/dev-utils + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/e2e-test + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/errors + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/eslint-plugin + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/eslint-plugin/src/__fixtures__/monorepo + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/frontend-app-api + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/frontend-plugin-api + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/integration-aws-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/integration-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/integration + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/release-manifests + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/repo-tools + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/techdocs-cli-embedded-app + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/techdocs-cli + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/test-utils + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/theme + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/types + schedule: + interval: daily + + - package-ecosystem: npm + directory: /packages/version-bridge + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/adr-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/adr-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/adr + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/airbrake-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/airbrake + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/allure + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/analytics-module-ga + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/analytics-module-ga4 + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/analytics-module-newrelic-browser + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/apache-airflow + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/api-docs-module-protoc-gen-doc + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/api-docs + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/apollo-explorer + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/app-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/app-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/auth-backend-module-gcp-iap-provider + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/auth-backend-module-github-provider + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/auth-backend-module-gitlab-provider + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/auth-backend-module-google-provider + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/auth-backend-module-oauth2-provider + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/auth-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/auth-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/azure-devops-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/azure-devops-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/azure-devops + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/azure-sites-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/azure-sites-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/azure-sites + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/badges-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/badges + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/bazaar-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/bazaar + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/bitbucket-cloud-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/bitrise + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-aws + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-azure + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-bitbucket-cloud + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-bitbucket-server + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-bitbucket + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-gcp + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-gerrit + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-github + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-gitlab + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-incremental-ingestion + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-ldap + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-msgraph + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-openapi + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-puppetdb + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-scaffolder-entity-model + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend-module-unprocessed + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-customized + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-graph + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-graphql + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-import + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog-unprocessed-entities + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/catalog + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/cicd-statistics-module-gitlab + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/cicd-statistics + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/circleci + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/cloudbuild + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/code-climate + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/code-coverage-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/code-coverage + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/codescene + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/config-schema + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/cost-insights-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/cost-insights + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/devtools-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/devtools-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/devtools + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/dynatrace + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/entity-feedback-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/entity-feedback-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/entity-feedback + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/entity-validation + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/events-backend-module-aws-sqs + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/events-backend-module-azure + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/events-backend-module-bitbucket-cloud + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/events-backend-module-gerrit + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/events-backend-module-github + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/events-backend-module-gitlab + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/events-backend-test-utils + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/events-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/events-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/example-todo-list-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/example-todo-list-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/example-todo-list + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/explore-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/explore-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/explore-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/explore + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/firehydrant + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/fossa + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/gcalendar + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/gcp-projects + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/git-release-manager + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/github-actions + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/github-deployments + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/github-issues + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/github-pull-requests-board + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/gitops-profiles + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/gocd + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/graphiql + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/graphql-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/graphql-voyager + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/home-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/home + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/ilert + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/jenkins-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/jenkins-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/jenkins + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/kafka-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/kafka + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/kubernetes-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/kubernetes-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/kubernetes + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/lighthouse-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/lighthouse-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/lighthouse + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/linguist-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/linguist-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/linguist + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/microsoft-calendar + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/newrelic-dashboard + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/newrelic + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/nomad-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/nomad + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/octopus-deploy + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/opencost + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/org-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/org + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/pagerduty + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/periskop-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/periskop + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/permission-backend-module-policy-allow-all + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/permission-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/permission-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/permission-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/permission-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/playlist-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/playlist-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/playlist + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/proxy-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/puppetdb + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/rollbar-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/rollbar + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-backend-module-confluence-to-markdown + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-backend-module-cookiecutter + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-backend-module-gitlab + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-backend-module-rails + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-backend-module-sentry + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-backend-module-yeoman + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/scaffolder + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search-backend-module-catalog + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search-backend-module-elasticsearch + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search-backend-module-explore + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search-backend-module-pg + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search-backend-module-techdocs + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search-backend-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/search + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/sentry + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/shortcuts + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/sonarqube-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/sonarqube-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/sonarqube + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/splunk-on-call + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/stack-overflow-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/stack-overflow + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/stackstorm + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/tech-insights-backend-module-jsonfc + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/tech-insights-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/tech-insights-common + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/tech-insights-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/tech-insights + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/tech-radar + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/techdocs-addons-test-utils + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/techdocs-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/techdocs-module-addons-contrib + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/techdocs-node + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/techdocs-react + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/techdocs + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/todo-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/todo + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/user-settings-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/user-settings + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/vault-backend + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/vault + schedule: + interval: daily + + - package-ecosystem: npm + directory: /plugins/xcmetrics + schedule: + interval: daily + + - package-ecosystem: npm + directory: /storybook + schedule: + interval: daily diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml index 3d616506e1..c7a147470c 100644 --- a/.github/workflows/automate_area-labels.yml +++ b/.github/workflows/automate_area-labels.yml @@ -2,11 +2,22 @@ name: Automate area labels on: - pull_request_target +permissions: + contents: read + jobs: triage: + permissions: + contents: read # for actions/labeler to determine modified files + pull-requests: write # for actions/labeler to add labels to PRs runs-on: ubuntu-latest steps: - - uses: actions/labeler@v4 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0 with: repo-token: '${{ secrets.GITHUB_TOKEN }}' sync-labels: true diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index 9cadf12b4f..9d67c9ef12 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -22,14 +22,19 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.pull_request.user.login != 'backstage-service' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: # Fetch the commit that's merged into the base rather than the target ref # This will let us diff only the contents of the PR, without fetching more history ref: 'refs/pull/${{ github.event.pull_request.number }}/merge' - name: fetch base run: git fetch --depth 1 origin ${{ github.base_ref }} - - uses: backstage/actions/changeset-feedback@v0.6.4 + - uses: backstage/actions/changeset-feedback@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 name: Generate feedback with: diff-ref: 'origin/master' diff --git a/.github/workflows/automate_merge_message.yml b/.github/workflows/automate_merge_message.yml index 9fed796aa5..1ae172e8e4 100644 --- a/.github/workflows/automate_merge_message.yml +++ b/.github/workflows/automate_merge_message.yml @@ -23,7 +23,12 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: ref: '${{ github.event.pull_request.merge_commit_sha }}' @@ -39,7 +44,7 @@ jobs: node generate.js ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} > message.txt - name: Post Message - uses: actions/github-script@v6 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 env: ISSUE_NUMBER: ${{ github.event.pull_request.number }} with: diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml index 452ecc48d6..a7a0041a9a 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -4,11 +4,22 @@ on: schedule: - cron: '*/10 * * * *' # run every 10 minutes as it also removes labels. +permissions: + contents: read + jobs: stale: + permissions: + issues: write # for actions/stale to close stale issues + pull-requests: write # for actions/stale to close stale PRs runs-on: ubuntu-latest steps: - - uses: actions/stale@v7 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/stale@6f05e4244c9a0b2ed3401882b05d701dd0a7289b # v7.0.0 id: stale with: stale-issue-message: > diff --git a/.github/workflows/ci-noop.yml b/.github/workflows/ci-noop.yml index 16bf11dd1a..bafe59e83a 100644 --- a/.github/workflows/ci-noop.yml +++ b/.github/workflows/ci-noop.yml @@ -7,6 +7,9 @@ on: paths: - 'microsite/**' +permissions: + contents: read + jobs: # The verify jobs runs all the verification that doesn't require a # diff towards master, since it takes some time to fetch that. @@ -19,6 +22,11 @@ jobs: name: Verify ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP test-noop: @@ -30,4 +38,9 @@ jobs: name: Test ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12c19075a6..3234242223 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,16 +26,21 @@ jobs: name: Install ${{ matrix.node-version }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -57,16 +62,21 @@ jobs: name: Verify ${{ matrix.node-version }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -186,18 +196,23 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: fetch branch master run: git fetch origin master - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index ef8906818f..50395b9f5c 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -8,7 +8,12 @@ jobs: cron: runs-on: ubuntu-latest steps: - - uses: backstage/actions/cron@v0.6.4 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: backstage/actions/cron@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000000..9bfe6712e5 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,27 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, +# PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - name: 'Checkout Repository' + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - name: 'Dependency Review' + uses: actions/dependency-review-action@0efb1d1d84fc9633afcdaad14c485cbbc90ef46c # v2.5.1 diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 231b81598e..1e602bce60 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -13,20 +13,25 @@ jobs: node-version: [18.x] steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: path: backstage ref: v${{ github.event.client_payload.version }} - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -40,17 +45,17 @@ jobs: working-directory: ./example-app - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0 - name: Build and push - uses: docker/build-push-action@v4 + uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4.2.1 with: context: './example-app' file: ./example-app/packages/backend/Dockerfile diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index dddb2de4af..75976456c0 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -4,8 +4,13 @@ on: branches: - master +permissions: + contents: read + jobs: deploy-microsite-and-storybook: + permissions: + contents: write # for JamesIves/github-pages-deploy-action to push changes in repo runs-on: ubuntu-latest env: @@ -18,10 +23,15 @@ jobs: cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth @@ -56,7 +66,7 @@ jobs: run: ls microsite/build && ls microsite/build/storybook - name: Deploy both microsite and storybook to gh-pages - uses: JamesIves/github-pages-deploy-action@v4.4.3 + uses: JamesIves/github-pages-deploy-action@a1ea191d508feb8485aceba848389d49f80ca2dc # v4.4.3 with: branch: gh-pages folder: microsite/build diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index e48a6b97ab..d5fe9f5a64 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -14,15 +14,20 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v18.x @@ -59,7 +64,7 @@ jobs: - name: Discord notification if: ${{ failure() }} - uses: Ilshidur/action-discord@0.3.2 + uses: Ilshidur/action-discord@0c4b27844ba47cb1c7bee539c8eead5284ce9fa9 # 0.3.2 env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} with: diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index 2329101eb0..b420ebf690 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -60,15 +60,20 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -112,7 +117,7 @@ jobs: - name: Discord notification if: ${{ failure() }} - uses: Ilshidur/action-discord@0.3.2 + uses: Ilshidur/action-discord@0c4b27844ba47cb1c7bee539c8eead5284ce9fa9 # 0.3.2 env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} with: @@ -137,15 +142,20 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -185,7 +195,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} - name: Dispatch repository event - uses: peter-evans/repository-dispatch@v2 + uses: peter-evans/repository-dispatch@bf47d102fdb849e755b0b0023ea3e81a44b6f570 # v2.1.2 with: token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} event-type: release-published @@ -193,7 +203,7 @@ jobs: # Notify everyone about this great new release :D - name: Discord notification - uses: Ilshidur/action-discord@0.3.2 + uses: Ilshidur/action-discord@0c4b27844ba47cb1c7bee539c8eead5284ce9fa9 # 0.3.2 env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }} TAG_NAME: ${{ steps.create_tag.outputs.tag_name }} diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 89595db189..b456c1dae4 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -9,5 +9,10 @@ jobs: if: github.repository == 'backstage/backstage' steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Issue sync - uses: backstage/actions/issue-sync@v0.6.4 + uses: backstage/actions/issue-sync@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml index 67e4c5abba..7ae7122154 100644 --- a/.github/workflows/pr-review-comment-trigger.yaml +++ b/.github/workflows/pr-review-comment-trigger.yaml @@ -7,6 +7,9 @@ on: types: - created +permissions: + contents: read + jobs: trigger: runs-on: ubuntu-latest @@ -16,13 +19,18 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.comment.user.id == github.event.pull_request.user.id steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Save PR number env: PR_NUMBER: ${{ github.event.pull_request.number }} run: | mkdir -p ./pr echo $PR_NUMBER > ./pr/pr_number - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: pr_number-${{ github.event.pull_request.number }} path: pr/ diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index 0930c75ddd..1f26643bab 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -16,9 +16,14 @@ jobs: steps: # Inspired by https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Read PR Number id: pr-number - uses: actions/github-script@v6 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -35,7 +40,7 @@ jobs: const prNumber = artifact.name.slice('pr_number-'.length) core.setOutput('pr-number', prNumber); - - uses: backstage/actions/re-review@v0.6.4 + - uses: backstage/actions/re-review@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index a92effbd14..4993e93dbb 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -17,8 +17,13 @@ jobs: # Avoid running on issue comments if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: PR sync - uses: backstage/actions/pr-sync@v0.6.4 + uses: backstage/actions/pr-sync@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 99b391660a..f245240c99 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -28,6 +28,11 @@ jobs: id-token: write steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: 'Checkout code' uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index 6471b265bc..f3afec592d 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -9,23 +9,28 @@ jobs: name: Autofix Markdown files using Prettier runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: # Fetch changes to previous commit - required for 'only_changed' in Prettier action fetch-depth: 0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: Run Prettier on ADOPTERS.md - uses: creyD/prettier_action@v4.3 + uses: creyD/prettier_action@31355f8eef017f8aeba2e0bc09d8502b13dbbad1 # v4.3 with: # Modifies commit only if prettier autofixed the ADOPTERS.md prettier_options: --config docs/prettier.config.js --write ADOPTERS.md diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml index d5f6f9a36c..0c732f28d1 100644 --- a/.github/workflows/sync_dependabot-changesets.yml +++ b/.github/workflows/sync_dependabot-changesets.yml @@ -10,8 +10,13 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage' steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -21,7 +26,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@v6 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: script: | const { promises: fs } = require('fs'); diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index df8d3909f4..dcb13d58c5 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -8,7 +8,12 @@ jobs: runs-on: ubuntu-latest steps: # Setup node & install deps before checkout, keeping install quick - - uses: actions/setup-node@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: 18.x - name: Install dependencies @@ -16,7 +21,7 @@ jobs: run: npm install semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1 - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: path: backstage # 'v' prefix is added here for the tag, we keep it out of the manifest logic @@ -24,7 +29,7 @@ jobs: # Checkout backstage/versions into /backstage/versions, which is where store the output - name: Checkout versions - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: repository: backstage/versions path: backstage/versions @@ -48,7 +53,7 @@ jobs: git push - name: Dispatch update-helper update - uses: actions/github-script@v6 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} # TODO(Rugvip): Remove the create-app dispatch once we've been on the release version for a while diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml index cd67fa9954..f29fdaa6b7 100644 --- a/.github/workflows/sync_renovate-changesets.yml +++ b/.github/workflows/sync_renovate-changesets.yml @@ -10,8 +10,13 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage' steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -21,7 +26,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@v6 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: script: | const { promises: fs } = require("fs"); diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 6b55609bd5..5b8c56da43 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -11,20 +11,25 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v18.x - name: Create Snyk report - uses: snyk/actions/node@master + uses: snyk/actions/node@299cde98a08ff8b1c2bfde1e5a067bce67a6d2b8 # master continue-on-error: true # Snyk CLI exits with error when vulnerabilities are found with: args: > diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index 8bfa90d726..dbeccb52fc 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -14,13 +14,24 @@ on: # ignore policies in the .snyk files and then have them show up in the snyk web # UI, and also automatically adds any new packages that are created. +permissions: + contents: read + jobs: sync: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Monitor and Synchronize Snyk Policies - uses: snyk/actions/node@master + uses: snyk/actions/node@299cde98a08ff8b1c2bfde1e5a067bce67a6d2b8 # master with: command: monitor args: > @@ -35,7 +46,7 @@ jobs: # Above we run the `monitor` command, this runs the `test` command which is # the one that generates the SARIF report that we can upload to GitHub. - name: Create Snyk report - uses: snyk/actions/node@master + uses: snyk/actions/node@299cde98a08ff8b1c2bfde1e5a067bce67a6d2b8 # master continue-on-error: true # To make sure that SARIF upload gets called with: args: > @@ -47,6 +58,6 @@ jobs: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} NODE_OPTIONS: --max-old-space-size=7168 - name: Upload Snyk report - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 with: sarif_file: snyk.sarif diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml index 127c11791d..a77050318b 100644 --- a/.github/workflows/sync_version-packages.yml +++ b/.github/workflows/sync_version-packages.yml @@ -13,7 +13,12 @@ jobs: name: Create Changeset PR runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: fetch-depth: 20000 fetch-tags: true @@ -21,7 +26,7 @@ jobs: - name: Install Dependencies run: yarn --immutable - name: Create Release Pull Request - uses: backstage/changesets-action@v2 + uses: backstage/changesets-action@99063c276a7f12e024cb310e7a05a3a5b89449f8 # v2.1.0 with: # Calls out to `changeset version`, but also runs prettier version: yarn release @@ -31,7 +36,7 @@ jobs: - name: Discord notification if: ${{ failure() }} - uses: Ilshidur/action-discord@0.3.2 + uses: Ilshidur/action-discord@0c4b27844ba47cb1c7bee539c8eead5284ce9fa9 # 0.3.2 env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} with: diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index 1bcd5ebcd8..b2d3667f4d 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -19,17 +19,22 @@ jobs: outputs: tags: ${{ steps.meta.outputs.tags }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: setup-node - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: linux-v18 @@ -46,7 +51,7 @@ jobs: yarn workspace example-backend build - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0 - name: Generate UUID image name id: uuid @@ -54,13 +59,13 @@ jobs: - name: Docker metadata id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4.6.0 with: images: registry.uffizzi.com/${{ env.UUID_TAG_APP }} tags: type=raw,value=60d - name: Build Image - uses: docker/build-push-action@v4 + uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4.2.1 with: context: . file: packages/backend/Dockerfile @@ -76,8 +81,13 @@ jobs: outputs: compose-file-cache-key: ${{ steps.hash.outputs.hash }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout git repo - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Render Compose File run: | BACKSTAGE_IMAGE=$(echo ${{ needs.build-backstage.outputs.tags }}) @@ -86,13 +96,13 @@ jobs: envsubst '$BACKSTAGE_IMAGE $GITHUB_SHA' < .github/uffizzi/docker-compose.uffizzi.yml > docker-compose.rendered.yml cat docker-compose.rendered.yml - name: Upload Rendered Compose File as Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: preview-spec path: docker-compose.rendered.yml retention-days: 2 - name: Upload PR Event as Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: preview-spec path: ${{ github.event_path }} @@ -104,8 +114,13 @@ jobs: if: ${{ github.event.action == 'closed' }} steps: # If this PR is closing, we will not render a compose file nor pass it to the next workflow. + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Upload PR Event as Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: preview-spec path: ${{ github.event_path }} diff --git a/.github/workflows/uffizzi-preview.yaml b/.github/workflows/uffizzi-preview.yaml index 87c1eaa02f..bf43bbdb4c 100644 --- a/.github/workflows/uffizzi-preview.yaml +++ b/.github/workflows/uffizzi-preview.yaml @@ -17,9 +17,14 @@ jobs: git-ref: ${{ env.GIT_REF }} pr-number: ${{ env.PR_NUMBER }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: 'Download artifacts' # Fetch output (zip archive) from the workflow run that triggered this workflow. - uses: actions/github-script@v6 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: script: | let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ @@ -59,7 +64,7 @@ jobs: - name: Cache Rendered Compose File if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }} - uses: actions/cache@v3 + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 with: path: docker-compose.rendered.yml key: ${{ env.COMPOSE_FILE_HASH }} diff --git a/.github/workflows/verify_accessibility-noop.yml b/.github/workflows/verify_accessibility-noop.yml index bde483eece..e2b1860b28 100644 --- a/.github/workflows/verify_accessibility-noop.yml +++ b/.github/workflows/verify_accessibility-noop.yml @@ -17,9 +17,17 @@ on: - 'plugins/search/src/**' - 'plugins/search-react/src/**' +permissions: + contents: read + jobs: noop: name: Accessibility runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index 32ded3bd3a..7d8753b3bd 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -19,13 +19,18 @@ jobs: name: Accessibility runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Use Node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: 18.x - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v18.x - name: run Lighthouse CI diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index f3417ac582..8ea2e8fcd8 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -19,8 +19,15 @@ on: schedule: - cron: '0 8 * * 6' +permissions: + contents: read + jobs: analyze: + permissions: + actions: read # for github/codeql-action/init to get workflow details + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/autobuild to send a status report name: Analyze runs-on: ubuntu-latest @@ -34,8 +41,13 @@ jobs: # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -43,7 +55,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -54,7 +66,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -68,4 +80,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml index dc1d942e32..1760b2a186 100644 --- a/.github/workflows/verify_docs-quality.yml +++ b/.github/workflows/verify_docs-quality.yml @@ -11,7 +11,12 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 # Vale does not support file excludes, so we use the script to generate a list of files instead # The action also does not allow args or a local config file to be passed in, so the files array @@ -21,7 +26,7 @@ jobs: run: echo "args=$(node scripts/check-docs-quality.js --ci-args)" >> $GITHUB_OUTPUT - name: documentation quality check - uses: errata-ai/vale-action@v2.0.1 + uses: errata-ai/vale-action@c4213d4de3d5f718b8497bd86161531c78992084 # v2.0.1 with: # This also contains --config=.github/vale/config.ini ... :/ files: '${{ steps.generate.outputs.args }}' diff --git a/.github/workflows/verify_e2e-kubernetes-noop.yml b/.github/workflows/verify_e2e-kubernetes-noop.yml index bedf357079..5c52968820 100644 --- a/.github/workflows/verify_e2e-kubernetes-noop.yml +++ b/.github/workflows/verify_e2e-kubernetes-noop.yml @@ -9,6 +9,9 @@ on: - '.github/workflows/verify_e2e-kubernetes.yml' - 'packages/backend-common/src/**' +permissions: + contents: read + jobs: verify: runs-on: ubuntu-latest @@ -19,4 +22,9 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index 0c78c1f933..237ce4977b 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -21,21 +21,26 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: bootstrap kind - uses: helm/kind-action@v1.8.0 + uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0 - name: kubernetes test working-directory: packages/backend-common diff --git a/.github/workflows/verify_e2e-linux-noop.yml b/.github/workflows/verify_e2e-linux-noop.yml index 1384b83378..27e08c7055 100644 --- a/.github/workflows/verify_e2e-linux-noop.yml +++ b/.github/workflows/verify_e2e-linux-noop.yml @@ -14,6 +14,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: noop: runs-on: ubuntu-latest @@ -24,4 +27,9 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 61ce55e385..9c684b9ea3 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -39,7 +39,12 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Configure Git run: | @@ -47,12 +52,12 @@ jobs: git config --global user.name 'GitHub e2e user' - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index fd5c4f0956..a7116d9bf8 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -12,6 +12,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: verify: runs-on: ubuntu-latest @@ -26,8 +29,13 @@ jobs: name: Techdocs steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: '3.9' diff --git a/.github/workflows/verify_e2e-windows-noop.yml b/.github/workflows/verify_e2e-windows-noop.yml index f042c350c2..e4b8556f58 100644 --- a/.github/workflows/verify_e2e-windows-noop.yml +++ b/.github/workflows/verify_e2e-windows-noop.yml @@ -11,6 +11,9 @@ on: - 'packages/e2e-test/**' - 'packages/create-app/**' +permissions: + contents: read + jobs: noop: runs-on: windows-2019 @@ -21,4 +24,9 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index b1decefd10..016ea04b95 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -32,12 +32,17 @@ jobs: steps: # In order to have the create-app template function as if it was downloaded from NPM # we need to make sure we checkout files with LF line endings only + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Set git to use LF run: | git config --global core.autocrlf false git config --global core.eol lf - - uses: actions/checkout@v3 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Configure Git run: | @@ -45,18 +50,18 @@ jobs: git config --global user.name 'GitHub e2e user' - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: setup python - uses: actions/setup-python@v4 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: '3.10' - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.3.1 + uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1 - name: Setup gyp env run: | @@ -70,7 +75,7 @@ jobs: npm prefix -g | % {npm config set node_gyp "$_\node_modules\node-gyp\bin\node-gyp.js"} - name: setup chrome - uses: browser-actions/setup-chrome@latest + uses: browser-actions/setup-chrome@803ef6dfb4fdf22089c9563225d95e4a515820a0 # latest - name: yarn install uses: backstage/actions/yarn-install@v0.6.4 diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml index 8c6b25d2e4..5174845467 100644 --- a/.github/workflows/verify_fossa.yml +++ b/.github/workflows/verify_fossa.yml @@ -5,13 +5,21 @@ on: pull_request: branches: [master] +permissions: + contents: read + jobs: analyze: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Install Fossa run: "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | bash" diff --git a/.github/workflows/verify_microsite-noop.yml b/.github/workflows/verify_microsite-noop.yml index cca7e512c5..8c329a0f27 100644 --- a/.github/workflows/verify_microsite-noop.yml +++ b/.github/workflows/verify_microsite-noop.yml @@ -11,10 +11,18 @@ on: - 'mkdocs.yml' - 'docs/**' +permissions: + contents: read + jobs: noop: runs-on: ubuntu-latest name: Microsite steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index d219d0ea74..e14799f378 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -9,6 +9,9 @@ on: - 'mkdocs.yml' - 'docs/**' +permissions: + contents: read + jobs: build-microsite: runs-on: ubuntu-latest @@ -20,10 +23,15 @@ jobs: name: Microsite steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: 18.x diff --git a/.github/workflows/verify_storybook-noop.yml b/.github/workflows/verify_storybook-noop.yml index c1f16e4fbd..aee4623d5a 100644 --- a/.github/workflows/verify_storybook-noop.yml +++ b/.github/workflows/verify_storybook-noop.yml @@ -18,10 +18,18 @@ on: - 'packages/core-components/src/**' - '**/*.stories.tsx' +permissions: + contents: read + jobs: noop: runs-on: ubuntu-latest name: Storybook steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index bcb0cfe178..3d1bcbf34e 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -27,17 +27,22 @@ jobs: name: Storybook steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: fetch-depth: 0 # Required to retrieve git history - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: storybook yarn install @@ -46,7 +51,7 @@ jobs: - run: yarn build-storybook - - uses: chromaui/action@v1 + - uses: chromaui/action@807600692d28833b717c155e15ed20905cdc865c # v1 with: token: ${{ secrets.GITHUB_TOKEN }} # projectToken intentionally shared to allow collaborators to run Chromatic on forks diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index 312c662b5a..309c2be7ab 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -7,6 +7,9 @@ on: paths: - '.github/workflows/verify_windows.yml' +permissions: + contents: read + jobs: build: runs-on: windows-2022 @@ -25,10 +28,15 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..723e338d33 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,18 @@ +repos: +- repo: https://github.com/gitleaks/gitleaks + rev: v8.16.3 + hooks: + - id: gitleaks +- repo: https://github.com/jumanjihouse/pre-commit-hooks + rev: 3.0.0 + hooks: + - id: shellcheck +- repo: https://github.com/pre-commit/mirrors-eslint + rev: v8.38.0 + hooks: + - id: eslint +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace From 753630068a34a5d23d0ef462b51c61b024d36d11 Mon Sep 17 00:00:00 2001 From: NishkarshRaj Date: Thu, 21 Sep 2023 22:43:12 +0530 Subject: [PATCH 007/348] bump Signed-off-by: NishkarshRaj --- .github/dependabot.yml | 1291 ----------------- .github/workflows/automate_area-labels.yml | 6 +- .../workflows/automate_changeset_feedback.yml | 4 +- .github/workflows/automate_merge_message.yml | 4 +- .github/workflows/automate_stale.yml | 6 +- .github/workflows/ci.yml | 18 +- .github/workflows/cron.yml | 2 +- .github/workflows/dependency-review.yml | 27 - .github/workflows/deploy_docker-image.yml | 12 +- .github/workflows/deploy_microsite.yml | 6 +- .github/workflows/deploy_packages.yml | 12 +- .github/workflows/issue.yaml | 2 +- .../workflows/pr-review-comment-trigger.yaml | 2 +- .github/workflows/pr-review-comment.yaml | 4 +- .github/workflows/pr.yaml | 2 +- .github/workflows/scorecard.yml | 4 +- .github/workflows/sync_code-formatting.yml | 4 +- .../workflows/sync_dependabot-changesets.yml | 4 +- .github/workflows/sync_release-manifest.yml | 8 +- .../workflows/sync_renovate-changesets.yml | 4 +- .github/workflows/sync_snyk-github-issues.yml | 6 +- .github/workflows/sync_snyk-monitor.yml | 8 +- .github/workflows/sync_version-packages.yml | 4 +- .github/workflows/uffizzi-build.yml | 14 +- .github/workflows/uffizzi-preview.yaml | 4 +- .github/workflows/verify_accessibility.yml | 6 +- .github/workflows/verify_codeql.yml | 14 +- .github/workflows/verify_docs-quality.yml | 2 +- .github/workflows/verify_e2e-kubernetes.yml | 6 +- .github/workflows/verify_e2e-linux.yml | 6 +- .github/workflows/verify_e2e-techdocs.yml | 4 +- .github/workflows/verify_e2e-windows.yml | 8 +- .github/workflows/verify_fossa.yml | 2 +- .github/workflows/verify_microsite.yml | 4 +- .github/workflows/verify_storybook.yml | 6 +- .github/workflows/verify_windows.yml | 4 +- .pre-commit-config.yaml | 18 - 37 files changed, 101 insertions(+), 1437 deletions(-) delete mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/dependency-review.yml delete mode 100644 .pre-commit-config.yaml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 253e5b3230..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,1291 +0,0 @@ -version: 2 -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: daily - - - package-ecosystem: docker - directory: /contrib/.devcontainer - schedule: - interval: daily - - - package-ecosystem: docker - directory: /contrib/docker/devops - schedule: - interval: daily - - - package-ecosystem: npm - directory: /cypress - schedule: - interval: daily - - - package-ecosystem: npm - directory: /microsite - schedule: - interval: daily - - - package-ecosystem: npm - directory: / - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/app-defaults - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/app-next-example-plugin - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/app-next - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/app - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-app-api - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-defaults - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-dev-utils - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-next - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-openapi-utils - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-plugin-api - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-plugin-manager - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-tasks - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend-test-utils - schedule: - interval: daily - - - package-ecosystem: docker - directory: /packages/backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/catalog-client - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/catalog-model - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/cli-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/cli-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/cli/asset-types - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/cli - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/codemods - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/config-loader - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/config - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/core-app-api - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/core-components - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/core-plugin-api - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/create-app - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/create-app/templates/default-app/examples/template/content - schedule: - interval: daily - - - package-ecosystem: docker - directory: /packages/create-app/templates/default-app/packages/backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/create-app/templates/default-app - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/dev-utils - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/e2e-test - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/errors - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/eslint-plugin - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/eslint-plugin/src/__fixtures__/monorepo - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/frontend-app-api - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/frontend-plugin-api - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/integration-aws-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/integration-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/integration - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/release-manifests - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/repo-tools - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/techdocs-cli-embedded-app - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/techdocs-cli - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/test-utils - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/theme - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/types - schedule: - interval: daily - - - package-ecosystem: npm - directory: /packages/version-bridge - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/adr-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/adr-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/adr - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/airbrake-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/airbrake - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/allure - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/analytics-module-ga - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/analytics-module-ga4 - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/analytics-module-newrelic-browser - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/apache-airflow - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/api-docs-module-protoc-gen-doc - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/api-docs - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/apollo-explorer - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/app-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/app-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/auth-backend-module-gcp-iap-provider - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/auth-backend-module-github-provider - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/auth-backend-module-gitlab-provider - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/auth-backend-module-google-provider - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/auth-backend-module-oauth2-provider - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/auth-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/auth-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/azure-devops-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/azure-devops-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/azure-devops - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/azure-sites-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/azure-sites-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/azure-sites - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/badges-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/badges - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/bazaar-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/bazaar - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/bitbucket-cloud-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/bitrise - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-aws - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-azure - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-bitbucket-cloud - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-bitbucket-server - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-bitbucket - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-gcp - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-gerrit - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-github - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-gitlab - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-incremental-ingestion - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-ldap - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-msgraph - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-openapi - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-puppetdb - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-scaffolder-entity-model - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend-module-unprocessed - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-customized - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-graph - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-graphql - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-import - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog-unprocessed-entities - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/catalog - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/cicd-statistics-module-gitlab - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/cicd-statistics - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/circleci - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/cloudbuild - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/code-climate - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/code-coverage-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/code-coverage - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/codescene - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/config-schema - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/cost-insights-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/cost-insights - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/devtools-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/devtools-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/devtools - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/dynatrace - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/entity-feedback-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/entity-feedback-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/entity-feedback - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/entity-validation - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/events-backend-module-aws-sqs - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/events-backend-module-azure - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/events-backend-module-bitbucket-cloud - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/events-backend-module-gerrit - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/events-backend-module-github - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/events-backend-module-gitlab - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/events-backend-test-utils - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/events-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/events-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/example-todo-list-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/example-todo-list-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/example-todo-list - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/explore-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/explore-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/explore-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/explore - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/firehydrant - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/fossa - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/gcalendar - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/gcp-projects - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/git-release-manager - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/github-actions - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/github-deployments - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/github-issues - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/github-pull-requests-board - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/gitops-profiles - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/gocd - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/graphiql - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/graphql-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/graphql-voyager - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/home-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/home - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/ilert - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/jenkins-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/jenkins-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/jenkins - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/kafka-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/kafka - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/kubernetes-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/kubernetes-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/kubernetes - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/lighthouse-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/lighthouse-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/lighthouse - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/linguist-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/linguist-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/linguist - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/microsoft-calendar - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/newrelic-dashboard - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/newrelic - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/nomad-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/nomad - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/octopus-deploy - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/opencost - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/org-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/org - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/pagerduty - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/periskop-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/periskop - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/permission-backend-module-policy-allow-all - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/permission-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/permission-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/permission-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/permission-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/playlist-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/playlist-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/playlist - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/proxy-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/puppetdb - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/rollbar-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/rollbar - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-backend-module-confluence-to-markdown - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-backend-module-cookiecutter - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-backend-module-gitlab - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-backend-module-rails - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-backend-module-sentry - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-backend-module-yeoman - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/scaffolder - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search-backend-module-catalog - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search-backend-module-elasticsearch - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search-backend-module-explore - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search-backend-module-pg - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search-backend-module-techdocs - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search-backend-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/search - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/sentry - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/shortcuts - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/sonarqube-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/sonarqube-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/sonarqube - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/splunk-on-call - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/stack-overflow-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/stack-overflow - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/stackstorm - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/tech-insights-backend-module-jsonfc - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/tech-insights-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/tech-insights-common - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/tech-insights-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/tech-insights - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/tech-radar - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/techdocs-addons-test-utils - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/techdocs-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/techdocs-module-addons-contrib - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/techdocs-node - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/techdocs-react - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/techdocs - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/todo-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/todo - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/user-settings-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/user-settings - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/vault-backend - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/vault - schedule: - interval: daily - - - package-ecosystem: npm - directory: /plugins/xcmetrics - schedule: - interval: daily - - - package-ecosystem: npm - directory: /storybook - schedule: - interval: daily diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml index c7a147470c..dfb60c9243 100644 --- a/.github/workflows/automate_area-labels.yml +++ b/.github/workflows/automate_area-labels.yml @@ -8,8 +8,8 @@ permissions: jobs: triage: permissions: - contents: read # for actions/labeler to determine modified files - pull-requests: write # for actions/labeler to add labels to PRs + contents: read # for actions/labeler to determine modified files + pull-requests: write # for actions/labeler to add labels to PRs runs-on: ubuntu-latest steps: - name: Harden Runner @@ -17,7 +17,7 @@ jobs: with: egress-policy: audit - - uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0 + - uses: actions/labeler@v4.3.0 with: repo-token: '${{ secrets.GITHUB_TOKEN }}' sync-labels: true diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index 9d67c9ef12..483d59dc8c 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -27,14 +27,14 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 with: # Fetch the commit that's merged into the base rather than the target ref # This will let us diff only the contents of the PR, without fetching more history ref: 'refs/pull/${{ github.event.pull_request.number }}/merge' - name: fetch base run: git fetch --depth 1 origin ${{ github.base_ref }} - - uses: backstage/actions/changeset-feedback@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + - uses: backstage/actions/changeset-feedback@v0.6.4 name: Generate feedback with: diff-ref: 'origin/master' diff --git a/.github/workflows/automate_merge_message.yml b/.github/workflows/automate_merge_message.yml index 1ae172e8e4..4cbf6c69a2 100644 --- a/.github/workflows/automate_merge_message.yml +++ b/.github/workflows/automate_merge_message.yml @@ -28,7 +28,7 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 with: ref: '${{ github.event.pull_request.merge_commit_sha }}' @@ -44,7 +44,7 @@ jobs: node generate.js ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} > message.txt - name: Post Message - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@v6.4.1 env: ISSUE_NUMBER: ${{ github.event.pull_request.number }} with: diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml index a7a0041a9a..40ebdf8a3e 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -10,8 +10,8 @@ permissions: jobs: stale: permissions: - issues: write # for actions/stale to close stale issues - pull-requests: write # for actions/stale to close stale PRs + issues: write # for actions/stale to close stale issues + pull-requests: write # for actions/stale to close stale PRs runs-on: ubuntu-latest steps: - name: Harden Runner @@ -19,7 +19,7 @@ jobs: with: egress-policy: audit - - uses: actions/stale@6f05e4244c9a0b2ed3401882b05d701dd0a7289b # v7.0.0 + - uses: actions/stale@v7.0.0 id: stale with: stale-issue-message: > diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3234242223..b08a28d786 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,16 +31,16 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -67,16 +67,16 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -201,18 +201,18 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: fetch branch master run: git fetch origin master - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 50395b9f5c..2874be512c 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -13,7 +13,7 @@ jobs: with: egress-policy: audit - - uses: backstage/actions/cron@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + - uses: backstage/actions/cron@v0.6.4 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml deleted file mode 100644 index 9bfe6712e5..0000000000 --- a/.github/workflows/dependency-review.yml +++ /dev/null @@ -1,27 +0,0 @@ -# Dependency Review Action -# -# This Action will scan dependency manifest files that change as part of a Pull Request, -# surfacing known-vulnerable versions of the packages declared or updated in the PR. -# Once installed, if the workflow run is marked as required, -# PRs introducing known-vulnerable packages will be blocked from merging. -# -# Source repository: https://github.com/actions/dependency-review-action -name: 'Dependency Review' -on: [pull_request] - -permissions: - contents: read - -jobs: - dependency-review: - runs-on: ubuntu-latest - steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit - - - name: 'Checkout Repository' - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - - name: 'Dependency Review' - uses: actions/dependency-review-action@0efb1d1d84fc9633afcdaad14c485cbbc90ef46c # v2.5.1 diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 1e602bce60..30e7badcd0 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -19,19 +19,19 @@ jobs: egress-policy: audit - name: checkout - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 with: path: backstage ref: v${{ github.event.client_payload.version }} - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -45,17 +45,17 @@ jobs: working-directory: ./example-app - name: Login to GitHub Container Registry - uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0 + uses: docker/login-action@v2.2.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0 + uses: docker/setup-buildx-action@v2.10.0 - name: Build and push - uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4.2.1 + uses: docker/build-push-action@v4.2.1 with: context: './example-app' file: ./example-app/packages/backend/Dockerfile diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index 75976456c0..f614db31ca 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -10,7 +10,7 @@ permissions: jobs: deploy-microsite-and-storybook: permissions: - contents: write # for JamesIves/github-pages-deploy-action to push changes in repo + contents: write # for JamesIves/github-pages-deploy-action to push changes in repo runs-on: ubuntu-latest env: @@ -28,10 +28,10 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index b420ebf690..a8a4315191 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -65,15 +65,15 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -147,15 +147,15 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index b456c1dae4..1c1c028f20 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -15,4 +15,4 @@ jobs: egress-policy: audit - name: Issue sync - uses: backstage/actions/issue-sync@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/issue-sync@v0.6.4 diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml index 7ae7122154..784dc6cf79 100644 --- a/.github/workflows/pr-review-comment-trigger.yaml +++ b/.github/workflows/pr-review-comment-trigger.yaml @@ -30,7 +30,7 @@ jobs: run: | mkdir -p ./pr echo $PR_NUMBER > ./pr/pr_number - - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + - uses: actions/upload-artifact@v3.1.3 with: name: pr_number-${{ github.event.pull_request.number }} path: pr/ diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index 1f26643bab..e557c85d51 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -23,7 +23,7 @@ jobs: - name: Read PR Number id: pr-number - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@v6.4.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -40,7 +40,7 @@ jobs: const prNumber = artifact.name.slice('pr_number-'.length) core.setOutput('pr-number', prNumber); - - uses: backstage/actions/re-review@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + - uses: backstage/actions/re-review@v0.6.4 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 4993e93dbb..8c99f105a9 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -23,7 +23,7 @@ jobs: egress-policy: audit - name: PR sync - uses: backstage/actions/pr-sync@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/pr-sync@v0.6.4 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index f245240c99..3a1e2b1501 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -34,7 +34,7 @@ jobs: egress-policy: audit - name: 'Checkout code' - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 with: persist-credentials: false @@ -58,7 +58,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: 'Upload artifact' - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@v3.1.3 with: name: SARIF file path: results.sarif diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index f3afec592d..fa8d91f25a 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -20,12 +20,12 @@ jobs: fetch-depth: 0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml index 0c732f28d1..2ac6d7f0d0 100644 --- a/.github/workflows/sync_dependabot-changesets.yml +++ b/.github/workflows/sync_dependabot-changesets.yml @@ -16,7 +16,7 @@ jobs: egress-policy: audit - name: Checkout - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -26,7 +26,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@v6.4.1 with: script: | const { promises: fs } = require('fs'); diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index dcb13d58c5..a3f6bc232f 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -13,7 +13,7 @@ jobs: with: egress-policy: audit - - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + - uses: actions/setup-node@v3.8.1 with: node-version: 18.x - name: Install dependencies @@ -21,7 +21,7 @@ jobs: run: npm install semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1 - name: Checkout - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 with: path: backstage # 'v' prefix is added here for the tag, we keep it out of the manifest logic @@ -29,7 +29,7 @@ jobs: # Checkout backstage/versions into /backstage/versions, which is where store the output - name: Checkout versions - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 with: repository: backstage/versions path: backstage/versions @@ -53,7 +53,7 @@ jobs: git push - name: Dispatch update-helper update - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@v6.4.1 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} # TODO(Rugvip): Remove the create-app dispatch once we've been on the release version for a while diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml index f29fdaa6b7..738abcf773 100644 --- a/.github/workflows/sync_renovate-changesets.yml +++ b/.github/workflows/sync_renovate-changesets.yml @@ -16,7 +16,7 @@ jobs: egress-policy: audit - name: Checkout - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -26,7 +26,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@v6.4.1 with: script: | const { promises: fs } = require("fs"); diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 5b8c56da43..690e2fb76e 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -16,15 +16,15 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v18.x diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index dbeccb52fc..c74c303076 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -20,8 +20,8 @@ permissions: jobs: sync: permissions: - contents: read # for actions/checkout to fetch code - security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results runs-on: ubuntu-latest steps: - name: Harden Runner @@ -29,7 +29,7 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@ v3.6.0 - name: Monitor and Synchronize Snyk Policies uses: snyk/actions/node@299cde98a08ff8b1c2bfde1e5a067bce67a6d2b8 # master with: @@ -58,6 +58,6 @@ jobs: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} NODE_OPTIONS: --max-old-space-size=7168 - name: Upload Snyk report - uses: github/codeql-action/upload-sarif@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 + uses: github/codeql-action/upload-sarif@v2.21.8 with: sarif_file: snyk.sarif diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml index a77050318b..929fb9cc89 100644 --- a/.github/workflows/sync_version-packages.yml +++ b/.github/workflows/sync_version-packages.yml @@ -18,7 +18,7 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 with: fetch-depth: 20000 fetch-tags: true @@ -26,7 +26,7 @@ jobs: - name: Install Dependencies run: yarn --immutable - name: Create Release Pull Request - uses: backstage/changesets-action@99063c276a7f12e024cb310e7a05a3a5b89449f8 # v2.1.0 + uses: backstage/changesets-action@v2.1.0 with: # Calls out to `changeset version`, but also runs prettier version: yarn release diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index b2d3667f4d..a58eba7055 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -25,16 +25,16 @@ jobs: egress-policy: audit - name: checkout - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 - name: setup-node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: linux-v18 @@ -87,7 +87,7 @@ jobs: egress-policy: audit - name: Checkout git repo - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 - name: Render Compose File run: | BACKSTAGE_IMAGE=$(echo ${{ needs.build-backstage.outputs.tags }}) @@ -96,13 +96,13 @@ jobs: envsubst '$BACKSTAGE_IMAGE $GITHUB_SHA' < .github/uffizzi/docker-compose.uffizzi.yml > docker-compose.rendered.yml cat docker-compose.rendered.yml - name: Upload Rendered Compose File as Artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@v3.1.3 with: name: preview-spec path: docker-compose.rendered.yml retention-days: 2 - name: Upload PR Event as Artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@v3.1.3 with: name: preview-spec path: ${{ github.event_path }} @@ -120,7 +120,7 @@ jobs: egress-policy: audit - name: Upload PR Event as Artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@v3.1.3 with: name: preview-spec path: ${{ github.event_path }} diff --git a/.github/workflows/uffizzi-preview.yaml b/.github/workflows/uffizzi-preview.yaml index bf43bbdb4c..deebf356bf 100644 --- a/.github/workflows/uffizzi-preview.yaml +++ b/.github/workflows/uffizzi-preview.yaml @@ -24,7 +24,7 @@ jobs: - name: 'Download artifacts' # Fetch output (zip archive) from the workflow run that triggered this workflow. - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@v6.4.1 with: script: | let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ @@ -64,7 +64,7 @@ jobs: - name: Cache Rendered Compose File if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }} - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + uses: actions/cache@v3.3.2 with: path: docker-compose.rendered.yml key: ${{ env.COMPOSE_FILE_HASH }} diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index 7d8753b3bd..d53f3834d2 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -24,13 +24,13 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: Use Node.js 18.x - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v18.x - name: run Lighthouse CI diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index 8ea2e8fcd8..666bd5f0f4 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -25,9 +25,9 @@ permissions: jobs: analyze: permissions: - actions: read # for github/codeql-action/init to get workflow details - contents: read # for actions/checkout to fetch code - security-events: write # for github/codeql-action/autobuild to send a status report + actions: read # for github/codeql-action/init to get workflow details + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/autobuild to send a status report name: Analyze runs-on: ubuntu-latest @@ -47,7 +47,7 @@ jobs: egress-policy: audit - name: Checkout repository - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -55,7 +55,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 + uses: github/codeql-action/init@v2.21.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -66,7 +66,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 + uses: github/codeql-action/autobuild@v2.21.8 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -80,4 +80,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 + uses: github/codeql-action/analyze@v2.21.8 diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml index 1760b2a186..ce457a234f 100644 --- a/.github/workflows/verify_docs-quality.yml +++ b/.github/workflows/verify_docs-quality.yml @@ -16,7 +16,7 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 # Vale does not support file excludes, so we use the script to generate a list of files instead # The action also does not allow args or a local config file to be passed in, so the files array diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index 237ce4977b..cddd6589d7 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -26,16 +26,16 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 9c684b9ea3..744a5d7e74 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -44,7 +44,7 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: Configure Git run: | @@ -52,12 +52,12 @@ jobs: git config --global user.name 'GitHub e2e user' - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index a7116d9bf8..94f08a491f 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -34,8 +34,8 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + - uses: actions/checkout@v3.6.0 + - uses: actions/setup-python@v4.7.0 with: python-version: '3.9' diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index 016ea04b95..3ecb33a2da 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -42,7 +42,7 @@ jobs: git config --global core.autocrlf false git config --global core.eol lf - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: Configure Git run: | @@ -50,18 +50,18 @@ jobs: git config --global user.name 'GitHub e2e user' - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: setup python - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + uses: actions/setup-python@v4.7.0 with: python-version: '3.10' - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1 + uses: microsoft/setup-msbuild@v1.3.1 - name: Setup gyp env run: | diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml index 5174845467..393bcf9631 100644 --- a/.github/workflows/verify_fossa.yml +++ b/.github/workflows/verify_fossa.yml @@ -19,7 +19,7 @@ jobs: egress-policy: audit - name: Checkout - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 - name: Install Fossa run: "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | bash" diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index e14799f378..f0705bedc7 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -28,10 +28,10 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index 3d1bcbf34e..f0354df296 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -32,17 +32,17 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 with: fetch-depth: 0 # Required to retrieve git history - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.4 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: storybook yarn install diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index 309c2be7ab..f2c61938d8 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -33,10 +33,10 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 723e338d33..0000000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,18 +0,0 @@ -repos: -- repo: https://github.com/gitleaks/gitleaks - rev: v8.16.3 - hooks: - - id: gitleaks -- repo: https://github.com/jumanjihouse/pre-commit-hooks - rev: 3.0.0 - hooks: - - id: shellcheck -- repo: https://github.com/pre-commit/mirrors-eslint - rev: v8.38.0 - hooks: - - id: eslint -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: end-of-file-fixer - - id: trailing-whitespace From 2c92c6ef4093133cb20c07fdb65f102b0a368751 Mon Sep 17 00:00:00 2001 From: NishkarshRaj Date: Fri, 29 Sep 2023 02:05:27 +0530 Subject: [PATCH 008/348] Harden Runner just fails for 1 workflow: Verify Windows Signed-off-by: NishkarshRaj --- .github/workflows/verify_windows.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index f2c61938d8..d220df5406 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -28,11 +28,6 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit - - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} From b4d24e9d2e090bbdc1ad7ec4daeeb8c5ab47da2b Mon Sep 17 00:00:00 2001 From: NishkarshRaj Date: Fri, 29 Sep 2023 02:27:25 +0530 Subject: [PATCH 009/348] Disable Harden Runners to validate if they are culprit for broken workflows Signed-off-by: NishkarshRaj --- .github/workflows/automate_area-labels.yml | 8 +++---- .../workflows/automate_changeset_feedback.yml | 8 +++---- .github/workflows/automate_merge_message.yml | 8 +++---- .github/workflows/automate_stale.yml | 8 +++---- .github/workflows/ci-noop.yml | 16 ++++++------- .github/workflows/ci.yml | 24 +++++++++---------- .github/workflows/cron.yml | 8 +++---- .github/workflows/deploy_docker-image.yml | 8 +++---- .github/workflows/deploy_microsite.yml | 8 +++---- .github/workflows/deploy_nightly.yml | 8 +++---- .github/workflows/deploy_packages.yml | 16 ++++++------- .github/workflows/issue.yaml | 8 +++---- .../workflows/pr-review-comment-trigger.yaml | 8 +++---- .github/workflows/pr-review-comment.yaml | 8 +++---- .github/workflows/pr.yaml | 8 +++---- .github/workflows/scorecard.yml | 8 +++---- .github/workflows/sync_code-formatting.yml | 8 +++---- .../workflows/sync_dependabot-changesets.yml | 8 +++---- .github/workflows/sync_release-manifest.yml | 8 +++---- .../workflows/sync_renovate-changesets.yml | 8 +++---- .github/workflows/sync_snyk-github-issues.yml | 8 +++---- .github/workflows/sync_snyk-monitor.yml | 10 ++++---- .github/workflows/uffizzi-build.yml | 24 +++++++++---------- .github/workflows/uffizzi-preview.yaml | 8 +++---- .../workflows/verify_accessibility-noop.yml | 8 +++---- .github/workflows/verify_accessibility.yml | 8 +++---- .github/workflows/verify_codeql.yml | 8 +++---- .github/workflows/verify_docs-quality.yml | 8 +++---- .../workflows/verify_e2e-kubernetes-noop.yml | 8 +++---- .github/workflows/verify_e2e-kubernetes.yml | 8 +++---- .github/workflows/verify_e2e-linux-noop.yml | 8 +++---- .github/workflows/verify_e2e-linux.yml | 8 +++---- .github/workflows/verify_e2e-techdocs.yml | 8 +++---- .github/workflows/verify_e2e-windows-noop.yml | 8 +++---- .github/workflows/verify_e2e-windows.yml | 8 +++---- .github/workflows/verify_fossa.yml | 8 +++---- .github/workflows/verify_microsite-noop.yml | 8 +++---- .github/workflows/verify_microsite.yml | 8 +++---- .github/workflows/verify_storybook-noop.yml | 8 +++---- .github/workflows/verify_storybook.yml | 8 +++---- .github/workflows/verify_windows.yml | 5 ++++ 41 files changed, 190 insertions(+), 185 deletions(-) diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml index dfb60c9243..47b3dfe42b 100644 --- a/.github/workflows/automate_area-labels.yml +++ b/.github/workflows/automate_area-labels.yml @@ -12,10 +12,10 @@ jobs: pull-requests: write # for actions/labeler to add labels to PRs runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/labeler@v4.3.0 with: diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index 483d59dc8c..8dab48c2a3 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -22,10 +22,10 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.pull_request.user.login != 'backstage-service' runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 with: diff --git a/.github/workflows/automate_merge_message.yml b/.github/workflows/automate_merge_message.yml index 4cbf6c69a2..f5b26b5db3 100644 --- a/.github/workflows/automate_merge_message.yml +++ b/.github/workflows/automate_merge_message.yml @@ -23,10 +23,10 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 with: diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml index 40ebdf8a3e..6cca838722 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -14,10 +14,10 @@ jobs: pull-requests: write # for actions/stale to close stale PRs runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/stale@v7.0.0 id: stale diff --git a/.github/workflows/ci-noop.yml b/.github/workflows/ci-noop.yml index bafe59e83a..d04770ea15 100644 --- a/.github/workflows/ci-noop.yml +++ b/.github/workflows/ci-noop.yml @@ -22,10 +22,10 @@ jobs: name: Verify ${{ matrix.node-version }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - run: echo NOOP @@ -38,9 +38,9 @@ jobs: name: Test ${{ matrix.node-version }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b08a28d786..f63a34c8a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,10 +26,10 @@ jobs: name: Install ${{ matrix.node-version }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 @@ -62,10 +62,10 @@ jobs: name: Verify ${{ matrix.node-version }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 @@ -196,10 +196,10 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 - name: fetch branch master diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 2874be512c..28cd7cc26e 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -8,10 +8,10 @@ jobs: cron: runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: backstage/actions/cron@v0.6.4 with: diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 30e7badcd0..34d18465ed 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -13,10 +13,10 @@ jobs: node-version: [18.x] steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: checkout uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index f614db31ca..cf11cff115 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -23,10 +23,10 @@ jobs: cancel-in-progress: true steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index d5fe9f5a64..89dc085b61 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -14,10 +14,10 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index a8a4315191..7abe55594c 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -60,10 +60,10 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 @@ -142,10 +142,10 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 1c1c028f20..72873cd358 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -9,10 +9,10 @@ jobs: if: github.repository == 'backstage/backstage' steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Issue sync uses: backstage/actions/issue-sync@v0.6.4 diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml index 784dc6cf79..f106dd819a 100644 --- a/.github/workflows/pr-review-comment-trigger.yaml +++ b/.github/workflows/pr-review-comment-trigger.yaml @@ -19,10 +19,10 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.comment.user.id == github.event.pull_request.user.id steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Save PR number env: diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index e557c85d51..ade9e51ab5 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -16,10 +16,10 @@ jobs: steps: # Inspired by https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Read PR Number id: pr-number diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 8c99f105a9..ddf5d57d4d 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -17,10 +17,10 @@ jobs: # Avoid running on issue comments if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: PR sync uses: backstage/actions/pr-sync@v0.6.4 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 3a1e2b1501..d052eb2db4 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -28,10 +28,10 @@ jobs: id-token: write steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: 'Checkout code' uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index fa8d91f25a..b7c41dbcc0 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -9,10 +9,10 @@ jobs: name: Autofix Markdown files using Prettier runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml index 2ac6d7f0d0..52a91afedf 100644 --- a/.github/workflows/sync_dependabot-changesets.yml +++ b/.github/workflows/sync_dependabot-changesets.yml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage' steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Checkout uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index a3f6bc232f..906f234afa 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -8,10 +8,10 @@ jobs: runs-on: ubuntu-latest steps: # Setup node & install deps before checkout, keeping install quick - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/setup-node@v3.8.1 with: diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml index 738abcf773..afbbaa4fa2 100644 --- a/.github/workflows/sync_renovate-changesets.yml +++ b/.github/workflows/sync_renovate-changesets.yml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage' steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Checkout uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 690e2fb76e..25e3b659a4 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -11,10 +11,10 @@ jobs: runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index c74c303076..a902e108eb 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -24,12 +24,12 @@ jobs: security-events: write # for github/codeql-action/upload-sarif to upload SARIF results runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - - uses: actions/checkout@ v3.6.0 + - uses: actions/checkout@v3.6.0 - name: Monitor and Synchronize Snyk Policies uses: snyk/actions/node@299cde98a08ff8b1c2bfde1e5a067bce67a6d2b8 # master with: diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index a58eba7055..3930d87687 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -19,10 +19,10 @@ jobs: outputs: tags: ${{ steps.meta.outputs.tags }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: checkout uses: actions/checkout@v3.6.0 @@ -81,10 +81,10 @@ jobs: outputs: compose-file-cache-key: ${{ steps.hash.outputs.hash }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Checkout git repo uses: actions/checkout@v3.6.0 @@ -114,10 +114,10 @@ jobs: if: ${{ github.event.action == 'closed' }} steps: # If this PR is closing, we will not render a compose file nor pass it to the next workflow. - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Upload PR Event as Artifact uses: actions/upload-artifact@v3.1.3 diff --git a/.github/workflows/uffizzi-preview.yaml b/.github/workflows/uffizzi-preview.yaml index deebf356bf..82f8b8b859 100644 --- a/.github/workflows/uffizzi-preview.yaml +++ b/.github/workflows/uffizzi-preview.yaml @@ -17,10 +17,10 @@ jobs: git-ref: ${{ env.GIT_REF }} pr-number: ${{ env.PR_NUMBER }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: 'Download artifacts' # Fetch output (zip archive) from the workflow run that triggered this workflow. diff --git a/.github/workflows/verify_accessibility-noop.yml b/.github/workflows/verify_accessibility-noop.yml index e2b1860b28..5a7228e408 100644 --- a/.github/workflows/verify_accessibility-noop.yml +++ b/.github/workflows/verify_accessibility-noop.yml @@ -25,9 +25,9 @@ jobs: name: Accessibility runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index d53f3834d2..5e4ac62943 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -19,10 +19,10 @@ jobs: name: Accessibility runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 - name: Use Node.js 18.x diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index 666bd5f0f4..6523937c8d 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -41,10 +41,10 @@ jobs: # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Checkout repository uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml index ce457a234f..35e9fb1c85 100644 --- a/.github/workflows/verify_docs-quality.yml +++ b/.github/workflows/verify_docs-quality.yml @@ -11,10 +11,10 @@ jobs: runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_e2e-kubernetes-noop.yml b/.github/workflows/verify_e2e-kubernetes-noop.yml index 5c52968820..6038e7194a 100644 --- a/.github/workflows/verify_e2e-kubernetes-noop.yml +++ b/.github/workflows/verify_e2e-kubernetes-noop.yml @@ -22,9 +22,9 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index cddd6589d7..e602e6b0d9 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -21,10 +21,10 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_e2e-linux-noop.yml b/.github/workflows/verify_e2e-linux-noop.yml index 27e08c7055..deb21168dc 100644 --- a/.github/workflows/verify_e2e-linux-noop.yml +++ b/.github/workflows/verify_e2e-linux-noop.yml @@ -27,9 +27,9 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 744a5d7e74..53cfa7be50 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -39,10 +39,10 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index 94f08a491f..e1368bbce5 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -29,10 +29,10 @@ jobs: name: Techdocs steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 - uses: actions/setup-python@v4.7.0 diff --git a/.github/workflows/verify_e2e-windows-noop.yml b/.github/workflows/verify_e2e-windows-noop.yml index e4b8556f58..74971df3a6 100644 --- a/.github/workflows/verify_e2e-windows-noop.yml +++ b/.github/workflows/verify_e2e-windows-noop.yml @@ -24,9 +24,9 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index 3ecb33a2da..368c4ad645 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -32,10 +32,10 @@ jobs: steps: # In order to have the create-app template function as if it was downloaded from NPM # we need to make sure we checkout files with LF line endings only - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Set git to use LF run: | diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml index 393bcf9631..82c0d71aa6 100644 --- a/.github/workflows/verify_fossa.yml +++ b/.github/workflows/verify_fossa.yml @@ -13,10 +13,10 @@ jobs: runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - name: Checkout uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_microsite-noop.yml b/.github/workflows/verify_microsite-noop.yml index 8c329a0f27..9597ef3f8b 100644 --- a/.github/workflows/verify_microsite-noop.yml +++ b/.github/workflows/verify_microsite-noop.yml @@ -20,9 +20,9 @@ jobs: name: Microsite steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index f0705bedc7..d5867f69ee 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -23,10 +23,10 @@ jobs: name: Microsite steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_storybook-noop.yml b/.github/workflows/verify_storybook-noop.yml index aee4623d5a..97fe6171c1 100644 --- a/.github/workflows/verify_storybook-noop.yml +++ b/.github/workflows/verify_storybook-noop.yml @@ -27,9 +27,9 @@ jobs: name: Storybook steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index f0354df296..dfe6856c38 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -27,10 +27,10 @@ jobs: name: Storybook steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit - uses: actions/checkout@v3.6.0 with: diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index d220df5406..153d8d76a5 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -28,6 +28,11 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} From 595ed3b48e7a2f67aca4e967463cba15da7242a5 Mon Sep 17 00:00:00 2001 From: NishkarshRaj Date: Mon, 9 Oct 2023 15:48:02 +0530 Subject: [PATCH 010/348] PR Ready for Review Signed-off-by: NishkarshRaj --- .github/workflows/automate_area-labels.yml | 8 +++--- .../workflows/automate_changeset_feedback.yml | 8 +++--- .github/workflows/automate_merge_message.yml | 8 +++--- .github/workflows/automate_stale.yml | 8 +++--- .github/workflows/ci-noop.yml | 8 +++--- .github/workflows/ci.yml | 24 ++++++++--------- .github/workflows/cron.yml | 8 +++--- .github/workflows/deploy_docker-image.yml | 8 +++--- .github/workflows/deploy_microsite.yml | 8 +++--- .github/workflows/deploy_nightly.yml | 8 +++--- .github/workflows/deploy_packages.yml | 16 ++++++------ .github/workflows/issue.yaml | 8 +++--- .../workflows/pr-review-comment-trigger.yaml | 8 +++--- .github/workflows/pr-review-comment.yaml | 8 +++--- .github/workflows/pr.yaml | 8 +++--- .github/workflows/scorecard.yml | 8 +++--- .github/workflows/sync_code-formatting.yml | 8 +++--- .../workflows/sync_dependabot-changesets.yml | 8 +++--- .github/workflows/sync_release-manifest.yml | 10 +++---- .../workflows/sync_renovate-changesets.yml | 8 +++--- .github/workflows/sync_snyk-github-issues.yml | 8 +++--- .github/workflows/sync_snyk-monitor.yml | 8 +++--- .github/workflows/uffizzi-build.yml | 26 +++++++++---------- .github/workflows/uffizzi-preview.yaml | 8 +++--- .../workflows/verify_accessibility-noop.yml | 8 +++--- .github/workflows/verify_accessibility.yml | 8 +++--- .github/workflows/verify_codeql.yml | 8 +++--- .github/workflows/verify_docs-quality.yml | 8 +++--- .../workflows/verify_e2e-kubernetes-noop.yml | 8 +++--- .github/workflows/verify_e2e-kubernetes.yml | 8 +++--- .github/workflows/verify_e2e-linux-noop.yml | 8 +++--- .github/workflows/verify_e2e-linux.yml | 8 +++--- .github/workflows/verify_e2e-techdocs.yml | 8 +++--- .github/workflows/verify_e2e-windows-noop.yml | 8 +++--- .github/workflows/verify_e2e-windows.yml | 10 +++---- .github/workflows/verify_fossa.yml | 8 +++--- .github/workflows/verify_microsite-noop.yml | 8 +++--- .github/workflows/verify_microsite.yml | 8 +++--- .github/workflows/verify_storybook-noop.yml | 8 +++--- .github/workflows/verify_storybook.yml | 8 +++--- .github/workflows/verify_windows.yml | 8 +++--- 41 files changed, 187 insertions(+), 187 deletions(-) diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml index 47b3dfe42b..dfb60c9243 100644 --- a/.github/workflows/automate_area-labels.yml +++ b/.github/workflows/automate_area-labels.yml @@ -12,10 +12,10 @@ jobs: pull-requests: write # for actions/labeler to add labels to PRs runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/labeler@v4.3.0 with: diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index 8dab48c2a3..483d59dc8c 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -22,10 +22,10 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.pull_request.user.login != 'backstage-service' runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 with: diff --git a/.github/workflows/automate_merge_message.yml b/.github/workflows/automate_merge_message.yml index f5b26b5db3..4cbf6c69a2 100644 --- a/.github/workflows/automate_merge_message.yml +++ b/.github/workflows/automate_merge_message.yml @@ -23,10 +23,10 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 with: diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml index 6cca838722..40ebdf8a3e 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -14,10 +14,10 @@ jobs: pull-requests: write # for actions/stale to close stale PRs runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/stale@v7.0.0 id: stale diff --git a/.github/workflows/ci-noop.yml b/.github/workflows/ci-noop.yml index d04770ea15..7234e945e3 100644 --- a/.github/workflows/ci-noop.yml +++ b/.github/workflows/ci-noop.yml @@ -38,9 +38,9 @@ jobs: name: Test ${{ matrix.node-version }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f63a34c8a1..b08a28d786 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,10 +26,10 @@ jobs: name: Install ${{ matrix.node-version }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 @@ -62,10 +62,10 @@ jobs: name: Verify ${{ matrix.node-version }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 @@ -196,10 +196,10 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 - name: fetch branch master diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 28cd7cc26e..2874be512c 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -8,10 +8,10 @@ jobs: cron: runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: backstage/actions/cron@v0.6.4 with: diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 34d18465ed..30e7badcd0 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -13,10 +13,10 @@ jobs: node-version: [18.x] steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: checkout uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index cf11cff115..f614db31ca 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -23,10 +23,10 @@ jobs: cancel-in-progress: true steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index 89dc085b61..d5fe9f5a64 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -14,10 +14,10 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index 7abe55594c..a8a4315191 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -60,10 +60,10 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 @@ -142,10 +142,10 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 72873cd358..1c1c028f20 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -9,10 +9,10 @@ jobs: if: github.repository == 'backstage/backstage' steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: Issue sync uses: backstage/actions/issue-sync@v0.6.4 diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml index f106dd819a..784dc6cf79 100644 --- a/.github/workflows/pr-review-comment-trigger.yaml +++ b/.github/workflows/pr-review-comment-trigger.yaml @@ -19,10 +19,10 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.comment.user.id == github.event.pull_request.user.id steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: Save PR number env: diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index ade9e51ab5..e557c85d51 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -16,10 +16,10 @@ jobs: steps: # Inspired by https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: Read PR Number id: pr-number diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index ddf5d57d4d..8c99f105a9 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -17,10 +17,10 @@ jobs: # Avoid running on issue comments if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: PR sync uses: backstage/actions/pr-sync@v0.6.4 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 06f8eafac5..f4486e2910 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -28,10 +28,10 @@ jobs: id-token: write steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: 'Checkout code' uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index b7c41dbcc0..fa8d91f25a 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -9,10 +9,10 @@ jobs: name: Autofix Markdown files using Prettier runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml index 52a91afedf..2ac6d7f0d0 100644 --- a/.github/workflows/sync_dependabot-changesets.yml +++ b/.github/workflows/sync_dependabot-changesets.yml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage' steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: Checkout uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index 906f234afa..46d5d5382a 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -7,12 +7,12 @@ jobs: create-new-version: runs-on: ubuntu-latest steps: - # Setup node & install deps before checkout, keeping install quick - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + # Setup node & install deps before checkout, keeping install quick - uses: actions/setup-node@v3.8.1 with: node-version: 18.x diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml index afbbaa4fa2..738abcf773 100644 --- a/.github/workflows/sync_renovate-changesets.yml +++ b/.github/workflows/sync_renovate-changesets.yml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage' steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: Checkout uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 25e3b659a4..690e2fb76e 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -11,10 +11,10 @@ jobs: runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index a902e108eb..6450b1bd51 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -24,10 +24,10 @@ jobs: security-events: write # for github/codeql-action/upload-sarif to upload SARIF results runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 - name: Monitor and Synchronize Snyk Policies diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index 3930d87687..3107b87b8f 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -19,10 +19,10 @@ jobs: outputs: tags: ${{ steps.meta.outputs.tags }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: checkout uses: actions/checkout@v3.6.0 @@ -81,10 +81,10 @@ jobs: outputs: compose-file-cache-key: ${{ steps.hash.outputs.hash }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: Checkout git repo uses: actions/checkout@v3.6.0 @@ -113,12 +113,12 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.action == 'closed' }} steps: - # If this PR is closing, we will not render a compose file nor pass it to the next workflow. - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + # If this PR is closing, we will not render a compose file nor pass it to the next workflow. - name: Upload PR Event as Artifact uses: actions/upload-artifact@v3.1.3 with: diff --git a/.github/workflows/uffizzi-preview.yaml b/.github/workflows/uffizzi-preview.yaml index 82f8b8b859..deebf356bf 100644 --- a/.github/workflows/uffizzi-preview.yaml +++ b/.github/workflows/uffizzi-preview.yaml @@ -17,10 +17,10 @@ jobs: git-ref: ${{ env.GIT_REF }} pr-number: ${{ env.PR_NUMBER }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: 'Download artifacts' # Fetch output (zip archive) from the workflow run that triggered this workflow. diff --git a/.github/workflows/verify_accessibility-noop.yml b/.github/workflows/verify_accessibility-noop.yml index 5a7228e408..e2b1860b28 100644 --- a/.github/workflows/verify_accessibility-noop.yml +++ b/.github/workflows/verify_accessibility-noop.yml @@ -25,9 +25,9 @@ jobs: name: Accessibility runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index 5e4ac62943..d53f3834d2 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -19,10 +19,10 @@ jobs: name: Accessibility runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 - name: Use Node.js 18.x diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index 6523937c8d..666bd5f0f4 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -41,10 +41,10 @@ jobs: # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: Checkout repository uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml index 35e9fb1c85..ce457a234f 100644 --- a/.github/workflows/verify_docs-quality.yml +++ b/.github/workflows/verify_docs-quality.yml @@ -11,10 +11,10 @@ jobs: runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_e2e-kubernetes-noop.yml b/.github/workflows/verify_e2e-kubernetes-noop.yml index 6038e7194a..5c52968820 100644 --- a/.github/workflows/verify_e2e-kubernetes-noop.yml +++ b/.github/workflows/verify_e2e-kubernetes-noop.yml @@ -22,9 +22,9 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index e602e6b0d9..cddd6589d7 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -21,10 +21,10 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_e2e-linux-noop.yml b/.github/workflows/verify_e2e-linux-noop.yml index deb21168dc..27e08c7055 100644 --- a/.github/workflows/verify_e2e-linux-noop.yml +++ b/.github/workflows/verify_e2e-linux-noop.yml @@ -27,9 +27,9 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 53cfa7be50..744a5d7e74 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -39,10 +39,10 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index e1368bbce5..94f08a491f 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -29,10 +29,10 @@ jobs: name: Techdocs steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 - uses: actions/setup-python@v4.7.0 diff --git a/.github/workflows/verify_e2e-windows-noop.yml b/.github/workflows/verify_e2e-windows-noop.yml index 74971df3a6..e4b8556f58 100644 --- a/.github/workflows/verify_e2e-windows-noop.yml +++ b/.github/workflows/verify_e2e-windows-noop.yml @@ -24,9 +24,9 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index 368c4ad645..1385983c24 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -30,13 +30,13 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + # In order to have the create-app template function as if it was downloaded from NPM # we need to make sure we checkout files with LF line endings only - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit - - name: Set git to use LF run: | git config --global core.autocrlf false diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml index 82c0d71aa6..393bcf9631 100644 --- a/.github/workflows/verify_fossa.yml +++ b/.github/workflows/verify_fossa.yml @@ -13,10 +13,10 @@ jobs: runs-on: ubuntu-latest steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - name: Checkout uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_microsite-noop.yml b/.github/workflows/verify_microsite-noop.yml index 9597ef3f8b..8c329a0f27 100644 --- a/.github/workflows/verify_microsite-noop.yml +++ b/.github/workflows/verify_microsite-noop.yml @@ -20,9 +20,9 @@ jobs: name: Microsite steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index d5867f69ee..f0705bedc7 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -23,10 +23,10 @@ jobs: name: Microsite steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 diff --git a/.github/workflows/verify_storybook-noop.yml b/.github/workflows/verify_storybook-noop.yml index 97fe6171c1..aee4623d5a 100644 --- a/.github/workflows/verify_storybook-noop.yml +++ b/.github/workflows/verify_storybook-noop.yml @@ -27,9 +27,9 @@ jobs: name: Storybook steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - run: echo NOOP diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index dfe6856c38..f0354df296 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -27,10 +27,10 @@ jobs: name: Storybook steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 with: diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index 153d8d76a5..f2c61938d8 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -28,10 +28,10 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - # - name: Harden Runner - # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - # with: - # egress-policy: audit + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit - uses: actions/checkout@v3.6.0 From 99d4936f6c220fca7990bd40423ca6052eddf13c Mon Sep 17 00:00:00 2001 From: parmar-abhinav Date: Tue, 10 Oct 2023 23:11:21 +0530 Subject: [PATCH 011/348] Add examples for github:webhook scaffolder actions Signed-off-by: parmar-abhinav --- .changeset/sweet-countries-share.md | 5 + .../github/githubWebhook.examples.test.ts | 209 ++++++++++++++++++ .../builtin/github/githubWebhook.examples.ts | 120 ++++++++++ .../actions/builtin/github/githubWebhook.ts | 2 + 4 files changed, 336 insertions(+) create mode 100644 .changeset/sweet-countries-share.md create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.test.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.ts diff --git a/.changeset/sweet-countries-share.md b/.changeset/sweet-countries-share.md new file mode 100644 index 0000000000..e1327a74b8 --- /dev/null +++ b/.changeset/sweet-countries-share.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Add examples for `github:webhook` scaffolder action & improve related tests diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.test.ts new file mode 100644 index 0000000000..ce1fe76c53 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.test.ts @@ -0,0 +1,209 @@ +/* + * Copyright 2023 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 { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { + DefaultGithubCredentialsProvider, + GithubCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; +import { PassThrough } from 'stream'; +import { createGithubWebhookAction } from './githubWebhook'; +import yaml from 'yaml'; +import { examples } from './githubWebhook.examples'; + +const mockOctokit = { + rest: { + repos: { + createWebhook: jest.fn(), + }, + }, +}; +jest.mock('octokit', () => ({ + Octokit: class { + constructor() { + return mockOctokit; + } + }, +})); + +describe('github:webhook examples', () => { + const config = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + }); + + const defaultWebhookSecret = 'aafdfdivierernfdk23f'; + const integrations = ScmIntegrations.fromConfig(config); + let githubCredentialsProvider: GithubCredentialsProvider; + let action: TemplateAction; + + const mockContext = { + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.resetAllMocks(); + githubCredentialsProvider = + DefaultGithubCredentialsProvider.fromIntegrations(integrations); + action = createGithubWebhookAction({ + integrations, + defaultWebhookSecret, + githubCredentialsProvider, + }); + }); + + it('Create a GitHub webhook for a repository', async () => { + const input = yaml.parse(examples[0].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect(mockOctokit.rest.repos.createWebhook).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + config: { + url: input.webhookUrl, + content_type: input.contentType, + secret: input.webhookSecret, + insecure_ssl: '0', + }, + events: input.events, + active: input.active, + }); + }); + + it('Create a GitHub webhook with minimal configuration', async () => { + const input = yaml.parse(examples[1].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect(mockOctokit.rest.repos.createWebhook).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + config: { + url: 'https://example.com/my-webhook', + content_type: 'form', + secret: defaultWebhookSecret, + insecure_ssl: '0', + }, + events: ['push'], + active: true, + }); + }); + + it('Create a GitHub webhook with custom events', async () => { + const input = yaml.parse(examples[2].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect(mockOctokit.rest.repos.createWebhook).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + config: { + url: 'https://example.com/my-webhook', + content_type: 'form', + secret: defaultWebhookSecret, + insecure_ssl: '0', + }, + events: ['push', 'pull_request'], + active: true, + }); + }); + + it('Create a GitHub webhook with JSON content type', async () => { + const input = yaml.parse(examples[3].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect(mockOctokit.rest.repos.createWebhook).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + config: { + url: 'https://example.com/my-webhook', + content_type: 'json', + secret: defaultWebhookSecret, + insecure_ssl: '0', + }, + events: ['push'], + active: true, + }); + }); + + it('Create a GitHub webhook with insecure SSL', async () => { + const input = yaml.parse(examples[4].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect(mockOctokit.rest.repos.createWebhook).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + config: { + url: 'https://example.com/my-webhook', + content_type: 'form', + secret: defaultWebhookSecret, + insecure_ssl: '1', + }, + events: ['push'], + active: true, + }); + }); + + it('Create an inactive GitHub webhook', async () => { + const input = yaml.parse(examples[5].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect(mockOctokit.rest.repos.createWebhook).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + config: { + url: 'https://example.com/my-webhook', + content_type: 'form', + secret: defaultWebhookSecret, + insecure_ssl: '0', + }, + events: ['push'], + active: false, + }); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.ts new file mode 100644 index 0000000000..b6d4a8f80e --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.ts @@ -0,0 +1,120 @@ +/* + * Copyright 2023 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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: 'Create a GitHub webhook for a repository', + example: yaml.stringify({ + steps: [ + { + action: 'github:webhook', + name: 'Create GitHub Webhook', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + webhookUrl: 'https://example.com/my-webhook', + webhookSecret: 'mysecret', + events: ['push'], + active: true, + contentType: 'json', + insecureSsl: false, + token: 'my-github-token', + }, + }, + ], + }), + }, + { + description: 'Create a GitHub webhook with minimal configuration', + example: yaml.stringify({ + steps: [ + { + action: 'github:webhook', + name: 'Create GitHub Webhook', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + webhookUrl: 'https://example.com/my-webhook', + }, + }, + ], + }), + }, + { + description: 'Create a GitHub webhook with custom events', + example: yaml.stringify({ + steps: [ + { + action: 'github:webhook', + name: 'Create GitHub Webhook', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + webhookUrl: 'https://example.com/my-webhook', + events: ['push', 'pull_request'], + }, + }, + ], + }), + }, + { + description: 'Create a GitHub webhook with JSON content type', + example: yaml.stringify({ + steps: [ + { + action: 'github:webhook', + name: 'Create GitHub Webhook', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + webhookUrl: 'https://example.com/my-webhook', + contentType: 'json', + }, + }, + ], + }), + }, + { + description: 'Create a GitHub webhook with insecure SSL', + example: yaml.stringify({ + steps: [ + { + action: 'github:webhook', + name: 'Create GitHub Webhook', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + webhookUrl: 'https://example.com/my-webhook', + insecureSsl: true, + }, + }, + ], + }), + }, + { + description: 'Create an inactive GitHub webhook', + example: yaml.stringify({ + steps: [ + { + action: 'github:webhook', + name: 'Create GitHub Webhook', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + webhookUrl: 'https://example.com/my-webhook', + active: false, + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts index 4d487befc7..5589c951a5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts @@ -24,6 +24,7 @@ import { assertError, InputError } from '@backstage/errors'; import { Octokit } from 'octokit'; import { getOctokitOptions } from './helpers'; import { parseRepoUrl } from '../publish/util'; +import { examples } from './githubWebhook.examples'; /** * Creates new action that creates a webhook for a repository on GitHub. @@ -51,6 +52,7 @@ export function createGithubWebhookAction(options: { }>({ id: 'github:webhook', description: 'Creates webhook for a repository on GitHub.', + examples, schema: { input: { type: 'object', From 90646b4c028e9a998a992cd399fe11f7300bd3e5 Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Wed, 11 Oct 2023 11:48:45 +0200 Subject: [PATCH 012/348] Added wrapper around fetching users from gitlab group to make it fail gracefully Signed-off-by: Jasper Boeijenga --- .../src/lib/client.ts | 12 +++----- .../src/lib/types.ts | 6 +++- .../GitlabOrgDiscoveryEntityProvider.ts | 29 ++++++++++--------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index 722f079a21..c4cdd444cb 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -13,18 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import fetch from 'node-fetch'; import { getGitLabRequestOptions, GitLabIntegrationConfig, } from '@backstage/integration'; +import fetch from 'node-fetch'; import { Logger } from 'winston'; + import { - GitLabGroup, GitLabDescendantGroupsResponse, + GitLabGroup, GitLabGroupMembersResponse, GitLabUser, + PagedResponse, } from './types'; export type CommonListOptions = { @@ -44,11 +45,6 @@ interface UserListOptions extends CommonListOptions { exclude_internal?: boolean | undefined; } -export type PagedResponse = { - items: T[]; - nextPage?: number; -}; - export class GitLabClient { private readonly config: GitLabIntegrationConfig; private readonly logger: Logger; diff --git a/plugins/catalog-backend-module-gitlab/src/lib/types.ts b/plugins/catalog-backend-module-gitlab/src/lib/types.ts index 946317a11a..fa2eb73da6 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/types.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/types.ts @@ -13,9 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { TaskScheduleDefinition } from '@backstage/backend-tasks'; +export type PagedResponse = { + items: T[]; + nextPage?: number; +}; + export type GitlabGroupDescription = { id: number; web_url: string; diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts index 732f9f9fac..54373791ff 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts @@ -13,31 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { PluginTaskScheduler, TaskRunner } from '@backstage/backend-tasks'; +import { + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, + Entity, + GroupEntity, + UserEntity, +} from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { GitLabIntegration, ScmIntegrations } from '@backstage/integration'; import { EntityProvider, EntityProviderConnection, } from '@backstage/plugin-catalog-node'; +import { merge } from 'lodash'; import * as uuid from 'uuid'; import { Logger } from 'winston'; + import { GitLabClient, GitlabProviderConfig, paginated, readGitlabConfigs, } from '../lib'; -import { GitLabGroup, GitLabUser } from '../lib/types'; -import { - ANNOTATION_LOCATION, - ANNOTATION_ORIGIN_LOCATION, - Entity, - UserEntity, - GroupEntity, -} from '@backstage/catalog-model'; -import { merge } from 'lodash'; +import { GitLabGroup, GitLabUser, PagedResponse } from '../lib/types'; type Result = { scanned: number; @@ -245,9 +245,12 @@ export class GitlabOrgDiscoveryEntityProvider implements EntityProvider { groupRes.scanned++; groupRes.matches.push(group); - const groupUsers = await client.getGroupMembers(group.full_path, [ - 'DIRECT', - ]); + let groupUsers: PagedResponse = { items: [] }; + try { + groupUsers = await client.getGroupMembers(group.full_path, ['DIRECT']); + } catch { + logger.error(`Failed fetching user for group: ${group.full_path}`); + } for (const groupUser of groupUsers.items) { const user = idMappedUser[groupUser.id]; From d732f176101f3f097bca4ef2fe05342e7cef7091 Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Wed, 11 Oct 2023 11:57:07 +0200 Subject: [PATCH 013/348] Added changeset Signed-off-by: Jasper Boeijenga --- .changeset/fresh-schools-thank.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fresh-schools-thank.md diff --git a/.changeset/fresh-schools-thank.md b/.changeset/fresh-schools-thank.md new file mode 100644 index 0000000000..a5ab99587b --- /dev/null +++ b/.changeset/fresh-schools-thank.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-gitlab': patch +--- + +Added try catch arround fetching gitlab group users to prevent refresh from failing completely while only a select number of groups might not be able to load correctly. From ee87bef45634b3d2daa08edc5a762fc373d86e4a Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Wed, 11 Oct 2023 12:43:41 +0200 Subject: [PATCH 014/348] Correct spelling in changeset Signed-off-by: Jasper Boeijenga --- .changeset/fresh-schools-thank.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/fresh-schools-thank.md b/.changeset/fresh-schools-thank.md index a5ab99587b..1e32f82051 100644 --- a/.changeset/fresh-schools-thank.md +++ b/.changeset/fresh-schools-thank.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-backend-module-gitlab': patch --- -Added try catch arround fetching gitlab group users to prevent refresh from failing completely while only a select number of groups might not be able to load correctly. +Added try catch around fetching gitlab group users to prevent refresh from failing completely while only a select number of groups might not be able to load correctly. From 0920fd02ac4701b00d36ffcfbcb08447e5d0d9f6 Mon Sep 17 00:00:00 2001 From: parmar-abhinav Date: Wed, 11 Oct 2023 16:22:39 +0530 Subject: [PATCH 015/348] Add examples for github:environment:create scaffolder action Signed-off-by: parmar-abhinav --- .changeset/long-turkeys-argue.md | 5 + .../github/gitHubEnvironment.examples.ts | 99 +++++++ .../github/githubEnvironment.examples.test.ts | 260 ++++++++++++++++++ .../builtin/github/githubEnvironment.ts | 2 + 4 files changed, 366 insertions(+) create mode 100644 .changeset/long-turkeys-argue.md create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/gitHubEnvironment.examples.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts diff --git a/.changeset/long-turkeys-argue.md b/.changeset/long-turkeys-argue.md new file mode 100644 index 0000000000..f051d42478 --- /dev/null +++ b/.changeset/long-turkeys-argue.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Add examples for `github:environment:create` scaffolder action & improve related tests diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/gitHubEnvironment.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/gitHubEnvironment.examples.ts new file mode 100644 index 0000000000..606424bef0 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/gitHubEnvironment.examples.ts @@ -0,0 +1,99 @@ +/* + * Copyright 2023 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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: + 'Create a GitHub Environment (No Policies, No Variables, No Secrets)', + example: yaml.stringify({ + steps: [ + { + action: 'github:environment:create', + name: 'Create Environment', + input: { + repoUrl: 'github.com?repo=repository&owner=owner', + name: 'envname', + }, + }, + ], + }), + }, + { + description: 'Create a GitHub Environment with Protected Branch Policy', + example: yaml.stringify({ + steps: [ + { + action: 'github:environment:create', + name: 'Create Environment', + input: { + repoUrl: 'github.com?repo=repository&owner=owner', + name: 'envname', + deploymentBranchPolicy: { + protected_branches: true, + custom_branch_policies: false, + }, + }, + }, + ], + }), + }, + { + description: 'Create a GitHub Environment with Custom Branch Policies', + example: yaml.stringify({ + steps: [ + { + action: 'github:environment:create', + name: 'Create Environment', + input: { + repoUrl: 'github.com?repo=repository&owner=owner', + name: 'envname', + deploymentBranchPolicy: { + protected_branches: false, + custom_branch_policies: true, + }, + customBranchPolicyNames: ['main', '*.*.*'], + }, + }, + ], + }), + }, + { + description: + 'Create a GitHub Environment with Environment Variables and Secrets', + example: yaml.stringify({ + steps: [ + { + action: 'github:environment:create', + name: 'Create Environment', + input: { + repoUrl: 'github.com?repo=repository&owner=owner', + name: 'envname', + environmentVariables: { + key1: 'val1', + key2: 'val2', + }, + secrets: { + secret1: 'supersecret1', + secret2: 'supersecret2', + }, + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts new file mode 100644 index 0000000000..5e3da2fcec --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts @@ -0,0 +1,260 @@ +/* + * Copyright 2023 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 { PassThrough } from 'stream'; +import { createGithubEnvironmentAction } from './githubEnvironment'; +import { getVoidLogger } from '@backstage/backend-common'; +import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { ConfigReader } from '@backstage/config'; +import { ScmIntegrations } from '@backstage/integration'; +import yaml from 'yaml'; +import { examples } from './gitHubEnvironment.examples'; + +const mockOctokit = { + rest: { + actions: { + getRepoPublicKey: jest.fn(), + createEnvironmentVariable: jest.fn(), + createOrUpdateEnvironmentSecret: jest.fn(), + }, + repos: { + createDeploymentBranchPolicy: jest.fn(), + createOrUpdateEnvironment: jest.fn(), + get: jest.fn(), + }, + }, +}; +jest.mock('octokit', () => ({ + Octokit: class { + constructor() { + return mockOctokit; + } + }, +})); + +const publicKey = '2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvvcCU='; + +describe('github:environment:create examples', () => { + const config = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + let action: TemplateAction; + + const mockContext = { + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + mockOctokit.rest.actions.getRepoPublicKey.mockResolvedValue({ + data: { + key: publicKey, + key_id: 'keyid', + }, + }); + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + id: 'repoid', + }, + }); + + action = createGithubEnvironmentAction({ + integrations, + }); + }); + + afterEach(jest.resetAllMocks); + + it('Create a GitHub Environment (No Policies, No Variables, No Secrets)', async () => { + const input = yaml.parse(examples[0].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect( + mockOctokit.rest.repos.createOrUpdateEnvironment, + ).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repository', + environment_name: 'envname', + deployment_branch_policy: null, + }); + expect( + mockOctokit.rest.repos.createDeploymentBranchPolicy, + ).not.toHaveBeenCalled(); + expect( + mockOctokit.rest.actions.createEnvironmentVariable, + ).not.toHaveBeenCalled(); + expect(mockOctokit.rest.actions.getRepoPublicKey).not.toHaveBeenCalled(); + expect( + mockOctokit.rest.actions.createOrUpdateEnvironmentSecret, + ).not.toHaveBeenCalled(); + }); + + it('Create a GitHub Environment with Protected Branch Policy', async () => { + const input = yaml.parse(examples[1].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect( + mockOctokit.rest.repos.createOrUpdateEnvironment, + ).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repository', + environment_name: 'envname', + deployment_branch_policy: { + protected_branches: true, + custom_branch_policies: false, + }, + }); + + expect( + mockOctokit.rest.repos.createDeploymentBranchPolicy, + ).not.toHaveBeenCalled(); + expect( + mockOctokit.rest.actions.createEnvironmentVariable, + ).not.toHaveBeenCalled(); + expect(mockOctokit.rest.actions.getRepoPublicKey).not.toHaveBeenCalled(); + expect( + mockOctokit.rest.actions.createOrUpdateEnvironmentSecret, + ).not.toHaveBeenCalled(); + }); + + it('Create a GitHub Environment with Custom Branch Policies', async () => { + const input = yaml.parse(examples[2].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect( + mockOctokit.rest.repos.createOrUpdateEnvironment, + ).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repository', + environment_name: 'envname', + deployment_branch_policy: { + protected_branches: false, + custom_branch_policies: true, + }, + }); + + expect( + mockOctokit.rest.repos.createDeploymentBranchPolicy, + ).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repository', + environment_name: 'envname', + name: 'main', + }); + + expect( + mockOctokit.rest.repos.createDeploymentBranchPolicy, + ).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repository', + environment_name: 'envname', + name: '*.*.*', + }); + + expect( + mockOctokit.rest.actions.createEnvironmentVariable, + ).not.toHaveBeenCalled(); + + expect( + mockOctokit.rest.actions.createOrUpdateEnvironmentSecret, + ).not.toHaveBeenCalled(); + }); + + it('Create a GitHub Environment with Environment Variables and Secrets', async () => { + const input = yaml.parse(examples[3].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect( + mockOctokit.rest.repos.createOrUpdateEnvironment, + ).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repository', + environment_name: 'envname', + deployment_branch_policy: null, + }); + + expect( + mockOctokit.rest.repos.createDeploymentBranchPolicy, + ).not.toHaveBeenCalled(); + + expect( + mockOctokit.rest.actions.createEnvironmentVariable, + ).toHaveBeenCalledTimes(2); + expect( + mockOctokit.rest.actions.createEnvironmentVariable, + ).toHaveBeenCalledWith({ + repository_id: 'repoid', + environment_name: 'envname', + name: 'key1', + value: 'val1', + }); + expect( + mockOctokit.rest.actions.createEnvironmentVariable, + ).toHaveBeenCalledWith({ + repository_id: 'repoid', + environment_name: 'envname', + name: 'key2', + value: 'val2', + }); + + expect( + mockOctokit.rest.actions.createOrUpdateEnvironmentSecret, + ).toHaveBeenCalledTimes(2); + expect( + mockOctokit.rest.actions.createOrUpdateEnvironmentSecret, + ).toHaveBeenCalledWith({ + repository_id: 'repoid', + environment_name: 'envname', + secret_name: 'secret1', + key_id: 'keyid', + encrypted_value: expect.any(String), + }); + expect( + mockOctokit.rest.actions.createOrUpdateEnvironmentSecret, + ).toHaveBeenCalledWith({ + repository_id: 'repoid', + environment_name: 'envname', + secret_name: 'secret2', + key_id: 'keyid', + encrypted_value: expect.any(String), + }); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts index 04b33ed259..874798e4df 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts @@ -21,6 +21,7 @@ import { parseRepoUrl } from '../publish/util'; import { getOctokitOptions } from './helpers'; import { Octokit } from 'octokit'; import Sodium from 'libsodium-wrappers'; +import { examples } from './gitHubEnvironment.examples'; /** * Creates an `github:environment:create` Scaffolder action that creates a Github Environment. @@ -47,6 +48,7 @@ export function createGithubEnvironmentAction(options: { }>({ id: 'github:environment:create', description: 'Creates Deployment Environments', + examples, schema: { input: { type: 'object', From 1150a8cdeca6d79335f72e13f24b39f50a1872ae Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Wed, 11 Oct 2023 13:00:35 +0200 Subject: [PATCH 016/348] Add group in the error message from the graphQL query Signed-off-by: Jasper Boeijenga --- plugins/catalog-backend-module-gitlab/src/lib/client.ts | 6 +++++- .../src/providers/GitlabOrgDiscoveryEntityProvider.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index c4cdd444cb..5447dec9d4 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -236,7 +236,11 @@ export class GitLabClient { }, ).then(r => r.json()); if (response.errors) { - throw new Error(`GraphQL errors: ${JSON.stringify(response.errors)}`); + throw new Error( + `GraphQL errors: ${JSON.stringify( + response.errors, + )}, for group: ${groupPath}`, + ); } if (!response.data.group?.groupMembers?.nodes) { diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts index 54373791ff..6dbb0d162b 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts @@ -249,7 +249,7 @@ export class GitlabOrgDiscoveryEntityProvider implements EntityProvider { try { groupUsers = await client.getGroupMembers(group.full_path, ['DIRECT']); } catch { - logger.error(`Failed fetching user for group: ${group.full_path}`); + logger.error(`Failed fetching users for group: ${group.full_path}`); } for (const groupUser of groupUsers.items) { From a40a23776804eb448b89ac57bfe44571563a8ff8 Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Wed, 11 Oct 2023 14:12:02 +0200 Subject: [PATCH 017/348] Applied PR suggestions Signed-off-by: Jasper Boeijenga --- plugins/catalog-backend-module-gitlab/src/lib/client.ts | 6 +----- .../src/providers/GitlabOrgDiscoveryEntityProvider.ts | 6 ++++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index 5447dec9d4..c4cdd444cb 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -236,11 +236,7 @@ export class GitLabClient { }, ).then(r => r.json()); if (response.errors) { - throw new Error( - `GraphQL errors: ${JSON.stringify( - response.errors, - )}, for group: ${groupPath}`, - ); + throw new Error(`GraphQL errors: ${JSON.stringify(response.errors)}`); } if (!response.data.group?.groupMembers?.nodes) { diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts index 6dbb0d162b..affa8a41cf 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts @@ -248,8 +248,10 @@ export class GitlabOrgDiscoveryEntityProvider implements EntityProvider { let groupUsers: PagedResponse = { items: [] }; try { groupUsers = await client.getGroupMembers(group.full_path, ['DIRECT']); - } catch { - logger.error(`Failed fetching users for group: ${group.full_path}`); + } catch (e) { + logger.error( + `Failed fetching users for group '${group.full_path}': ${e}`, + ); } for (const groupUser of groupUsers.items) { From dd0350379b4cbd21794fcb4e883bfad1b8a13c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 12 Oct 2023 09:56:03 +0200 Subject: [PATCH 018/348] stop using `useHotMemoize` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/hungry-radios-play.md | 5 ++++ .../src/service/standaloneServer.ts | 29 +++++++------------ .../src/service/standaloneServer.ts | 23 +++++++-------- .../src/service/standaloneServer.ts | 27 +++++++---------- .../src/service/standaloneServer.ts | 19 +++++------- .../src/service/standaloneServer.ts | 27 +++++++---------- .../src/service/standaloneServer.ts | 19 +++++------- .../src/service/standaloneServer.ts | 27 +++++++---------- .../src/service/standaloneServer.ts | 19 +++++------- plugins/user-settings-backend/package.json | 1 + .../src/service/standaloneServer.ts | 26 +++++++++-------- yarn.lock | 1 + 12 files changed, 100 insertions(+), 123 deletions(-) create mode 100644 .changeset/hungry-radios-play.md diff --git a/.changeset/hungry-radios-play.md b/.changeset/hungry-radios-play.md new file mode 100644 index 0000000000..ce7f524f4a --- /dev/null +++ b/.changeset/hungry-radios-play.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings-backend': patch +--- + +Added dependency on `@backstage/config` diff --git a/plugins/auth-backend/src/service/standaloneServer.ts b/plugins/auth-backend/src/service/standaloneServer.ts index 0c311d5949..834305553b 100644 --- a/plugins/auth-backend/src/service/standaloneServer.ts +++ b/plugins/auth-backend/src/service/standaloneServer.ts @@ -19,12 +19,12 @@ import { loadBackendConfig, ServerTokenManager, HostDiscovery, - useHotMemoize, + DatabaseManager, } from '@backstage/backend-common'; import { Server } from 'http'; -import Knex from 'knex'; import { LoggerService } from '@backstage/backend-plugin-api'; import { createRouter } from './router'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { logger: LoggerService; @@ -37,27 +37,20 @@ export async function startStandaloneServer( const config = await loadBackendConfig({ logger, argv: process.argv }); const discovery = HostDiscovery.fromConfig(config); - const database = useHotMemoize(module, () => { - const knex = Knex({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { - resource.run('PRAGMA foreign_keys = ON', () => {}); - }); - return knex; - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('auth'); logger.debug('Starting application server...'); const router = await createRouter({ logger, config, - database: { - async getClient() { - return database; - }, - }, + database, discovery, tokenManager: ServerTokenManager.noop(), }); diff --git a/plugins/badges-backend/src/service/standaloneServer.ts b/plugins/badges-backend/src/service/standaloneServer.ts index 75185c4aef..661d218edb 100644 --- a/plugins/badges-backend/src/service/standaloneServer.ts +++ b/plugins/badges-backend/src/service/standaloneServer.ts @@ -21,12 +21,12 @@ import { loadBackendConfig, ServerTokenManager, HostDiscovery, - useHotMemoize, + DatabaseManager, } from '@backstage/backend-common'; import { createRouter } from './router'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { DatabaseBadgesStore } from '../database/badgesStore'; -import Knex from 'knex'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { port: number; @@ -40,13 +40,14 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'badges-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); const discovery = HostDiscovery.fromConfig(config); - const database = useHotMemoize(module, () => { - return Knex({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('badges'); logger.debug('Creating application...'); @@ -70,9 +71,7 @@ export async function startStandaloneServer( tokenManager, logger, identity, - badgeStore: await DatabaseBadgesStore.create({ - database: { getClient: async () => database }, - }), + badgeStore: await DatabaseBadgesStore.create({ database }), }); let service = createServiceBuilder(module) diff --git a/plugins/bazaar-backend/src/service/standaloneServer.ts b/plugins/bazaar-backend/src/service/standaloneServer.ts index a50e350f39..c222777aae 100644 --- a/plugins/bazaar-backend/src/service/standaloneServer.ts +++ b/plugins/bazaar-backend/src/service/standaloneServer.ts @@ -15,15 +15,15 @@ */ import { + DatabaseManager, createServiceBuilder, loadBackendConfig, - useHotMemoize, } from '@backstage/backend-common'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; -import knexFactory from 'knex'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { port: number; @@ -37,23 +37,18 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'bazaar-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const db = useHotMemoize(module, () => { - const knex = knexFactory({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - - knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { - resource.run('PRAGMA foreign_keys = ON', () => {}); - }); - - return knex; - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('bazaar'); const router = await createRouter({ logger, - database: { getClient: async () => db }, + database, config: config, identity: {} as IdentityApi, }); diff --git a/plugins/catalog-backend/src/service/standaloneServer.ts b/plugins/catalog-backend/src/service/standaloneServer.ts index cff4fa1f94..995a607ab5 100644 --- a/plugins/catalog-backend/src/service/standaloneServer.ts +++ b/plugins/catalog-backend/src/service/standaloneServer.ts @@ -21,7 +21,6 @@ import { ServerTokenManager, HostDiscovery, UrlReaders, - useHotMemoize, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; @@ -43,16 +42,14 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'catalog-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); const reader = UrlReaders.default({ logger, config }); - const database = useHotMemoize(module, () => { - const manager = DatabaseManager.fromConfig( - new ConfigReader({ - backend: { - database: { client: 'better-sqlite3', connection: ':memory:' }, - }, - }), - ); - return manager.forPlugin('catalog'); - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('catalog'); const discovery = HostDiscovery.fromConfig(config); const tokenManager = ServerTokenManager.fromConfig(config, { logger, diff --git a/plugins/code-coverage-backend/src/service/standaloneServer.ts b/plugins/code-coverage-backend/src/service/standaloneServer.ts index 23eaf981c1..a2207b86d9 100644 --- a/plugins/code-coverage-backend/src/service/standaloneServer.ts +++ b/plugins/code-coverage-backend/src/service/standaloneServer.ts @@ -16,17 +16,17 @@ import { createServiceBuilder, + DatabaseManager, HostDiscovery, loadBackendConfig, UrlReaders, - useHotMemoize, } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model'; import { Server } from 'http'; -import knexFactory from 'knex'; import { Logger } from 'winston'; import { createRouter } from './router'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { port: number; @@ -40,19 +40,14 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'code-coverage-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const db = useHotMemoize(module, () => { - const knex = knexFactory({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - - knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { - resource.run('PRAGMA foreign_keys = ON', () => {}); - }); - - return knex; - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('code-coverage'); const catalogApi = { async getEntityByRef(entityRef: string | CompoundEntityRef) { @@ -69,7 +64,7 @@ export async function startStandaloneServer( logger.debug('Starting application server...'); const router = await createRouter({ - database: { getClient: async () => db }, + database, config, discovery: HostDiscovery.fromConfig(config), urlReader: UrlReaders.default({ logger, config }), diff --git a/plugins/entity-feedback-backend/src/service/standaloneServer.ts b/plugins/entity-feedback-backend/src/service/standaloneServer.ts index f230cc1463..27c48ebb1e 100644 --- a/plugins/entity-feedback-backend/src/service/standaloneServer.ts +++ b/plugins/entity-feedback-backend/src/service/standaloneServer.ts @@ -19,7 +19,6 @@ import { DatabaseManager, loadBackendConfig, HostDiscovery, - useHotMemoize, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; @@ -40,16 +39,14 @@ export async function startStandaloneServer( const config = await loadBackendConfig({ logger, argv: process.argv }); const discovery = HostDiscovery.fromConfig(config); - const database = useHotMemoize(module, () => { - const manager = DatabaseManager.fromConfig( - new ConfigReader({ - backend: { - database: { client: 'better-sqlite3', connection: ':memory:' }, - }, - }), - ); - return manager.forPlugin('entity-feedback'); - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('entity-feedback'); const identity = DefaultIdentityClient.create({ discovery, diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts index 61f75d4827..518efed6a0 100644 --- a/plugins/linguist-backend/src/service/standaloneServer.ts +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -19,14 +19,14 @@ import { loadBackendConfig, HostDiscovery, UrlReaders, - useHotMemoize, ServerTokenManager, + DatabaseManager, } from '@backstage/backend-common'; import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; -import knexFactory from 'knex'; import { TaskScheduleDefinition } from '@backstage/backend-tasks'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { port: number; @@ -39,19 +39,14 @@ export async function startStandaloneServer( ): Promise { const logger = options.logger.child({ service: 'linguist-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const db = useHotMemoize(module, () => { - const knex = knexFactory({ - client: 'sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - - knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { - resource.run('PRAGMA foreign_keys = ON', () => {}); - }); - - return knex; - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('linguist'); const schedule: TaskScheduleDefinition = { frequency: { minutes: 2 }, @@ -63,7 +58,7 @@ export async function startStandaloneServer( const router = await createRouter( { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, { - database: { getClient: async () => db }, + database, discovery: HostDiscovery.fromConfig(config), reader: UrlReaders.default({ logger, config }), logger, diff --git a/plugins/playlist-backend/src/service/standaloneServer.ts b/plugins/playlist-backend/src/service/standaloneServer.ts index 02a375229c..26a601822a 100644 --- a/plugins/playlist-backend/src/service/standaloneServer.ts +++ b/plugins/playlist-backend/src/service/standaloneServer.ts @@ -20,7 +20,6 @@ import { loadBackendConfig, ServerTokenManager, HostDiscovery, - useHotMemoize, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; @@ -42,16 +41,14 @@ export async function startStandaloneServer( const config = await loadBackendConfig({ logger, argv: process.argv }); const discovery = HostDiscovery.fromConfig(config); - const database = useHotMemoize(module, () => { - const manager = DatabaseManager.fromConfig( - new ConfigReader({ - backend: { - database: { client: 'better-sqlite3', connection: ':memory:' }, - }, - }), - ); - return manager.forPlugin('playlist'); - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('playlist'); const identity = DefaultIdentityClient.create({ discovery, diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index eb1d08bbe2..991b388767 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -33,6 +33,7 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", + "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/types": "workspace:^", diff --git a/plugins/user-settings-backend/src/service/standaloneServer.ts b/plugins/user-settings-backend/src/service/standaloneServer.ts index 6dd8c7f72d..48a640636f 100644 --- a/plugins/user-settings-backend/src/service/standaloneServer.ts +++ b/plugins/user-settings-backend/src/service/standaloneServer.ts @@ -14,10 +14,13 @@ * limitations under the License. */ -import { createServiceBuilder, useHotMemoize } from '@backstage/backend-common'; +import { + createServiceBuilder, + DatabaseManager, +} from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Server } from 'http'; -import Knex from 'knex'; import { Logger } from 'winston'; import { DatabaseUserSettingsStore } from '../database/DatabaseUserSettingsStore'; import { createRouterInternal } from './router'; @@ -33,13 +36,14 @@ export async function startStandaloneServer( ): Promise { const logger = options.logger.child({ service: 'storage-backend' }); - const database = useHotMemoize(module, () => { - return Knex({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('user-settings'); logger.debug('Starting application server...'); @@ -58,9 +62,7 @@ export async function startStandaloneServer( }; const router = await createRouterInternal({ - userSettingsStore: await DatabaseUserSettingsStore.create({ - database: { getClient: async () => database }, - }), + userSettingsStore: await DatabaseUserSettingsStore.create({ database }), identity: identityMock, }); diff --git a/yarn.lock b/yarn.lock index 27a712861c..24f5950a5b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9948,6 +9948,7 @@ __metadata: "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/types": "workspace:^" From 2e0cef42ab49c32140f40f915c75b5ec1367959e Mon Sep 17 00:00:00 2001 From: Federico Morreale Date: Thu, 12 Oct 2023 17:06:45 +0200 Subject: [PATCH 019/348] fix: add missing required property in template schema Signed-off-by: Federico Morreale --- .changeset/fifty-taxis-allow.md | 5 +++++ plugins/scaffolder-common/src/Template.v1beta3.schema.json | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/fifty-taxis-allow.md diff --git a/.changeset/fifty-taxis-allow.md b/.changeset/fifty-taxis-allow.md new file mode 100644 index 0000000000..1b818f45e7 --- /dev/null +++ b/.changeset/fifty-taxis-allow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-common': patch +--- + +Add missing required property `type` in `Template.v1beta3.schema.json` schema diff --git a/plugins/scaffolder-common/src/Template.v1beta3.schema.json b/plugins/scaffolder-common/src/Template.v1beta3.schema.json index 1de68205b2..d4be9b7538 100644 --- a/plugins/scaffolder-common/src/Template.v1beta3.schema.json +++ b/plugins/scaffolder-common/src/Template.v1beta3.schema.json @@ -14,6 +14,7 @@ }, "spec": { "owner": "artist-relations-team", + "type": "website", "parameters": { "required": ["name", "description", "repoUrl"], "backstage:permissions": { From 30d601f15260bfd62e733c2d9efe414c56c31670 Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 10 Oct 2023 18:05:23 -0400 Subject: [PATCH 020/348] extractInitials without Regex lookbehind Signed-off-by: Taras Mankovski --- .../src/components/Avatar/util.test.ts | 2 +- .../core-components/src/components/Avatar/utils.ts | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/core-components/src/components/Avatar/util.test.ts b/packages/core-components/src/components/Avatar/util.test.ts index 6581df8b9a..70ed360bc3 100644 --- a/packages/core-components/src/components/Avatar/util.test.ts +++ b/packages/core-components/src/components/Avatar/util.test.ts @@ -36,6 +36,6 @@ describe('extractInitials', () => { }); it('limit the initials to two letters', async () => { - expect(extractInitials('John Jonathan Doe')).toEqual('JJ'); + expect(extractInitials('John Jonathan Doe')).toEqual('JD'); }); }); diff --git a/packages/core-components/src/components/Avatar/utils.ts b/packages/core-components/src/components/Avatar/utils.ts index 79627d5996..ad587e0e8e 100644 --- a/packages/core-components/src/components/Avatar/utils.ts +++ b/packages/core-components/src/components/Avatar/utils.ts @@ -27,9 +27,11 @@ export function stringToColor(str: string) { return color; } -export function extractInitials(value: string) { - return value - .match(/(? 1 ? names[names.length - 1] : ''; + return firstName && lastName + ? `${firstName.charAt(0)}${lastName.charAt(0)}` + : firstName.charAt(0); } From 7bdc1b0a12da6ba43141b442e9e8d7b9b0da437a Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 10 Oct 2023 18:10:59 -0400 Subject: [PATCH 021/348] Added changeset Signed-off-by: Taras Mankovski --- .changeset/ninety-numbers-study.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/ninety-numbers-study.md diff --git a/.changeset/ninety-numbers-study.md b/.changeset/ninety-numbers-study.md new file mode 100644 index 0000000000..e77131fab9 --- /dev/null +++ b/.changeset/ninety-numbers-study.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-components': patch +--- + +Fixed compatibility with Safari <16.3 by eliminating RegEx lookbehind in `extractInitials`. + +This PR also changed how initials are generated resulting in _John Jonathan Doe_ => _JD_ instead of _JJ_. From bdd6f9487afd0bd8eef37aaed31340ccc6ae82ca Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Fri, 13 Oct 2023 10:14:17 -0400 Subject: [PATCH 022/348] Added lookbehind to accepted vale words Signed-off-by: Taras Mankovski --- .github/vale/Vocab/Backstage/accept.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index e6c0aa9632..1a028d1387 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -455,3 +455,4 @@ Pulumi Lightsail PR rebasing +lookbehind From a1c0ffd533c2cb528b7da68c084b513742e0287b Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Fri, 13 Oct 2023 15:58:23 -0400 Subject: [PATCH 023/348] Added trim, test and removed unnecessary async Signed-off-by: Taras Mankovski --- .../src/components/Avatar/util.test.ts | 14 +++++++++----- .../core-components/src/components/Avatar/utils.ts | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/core-components/src/components/Avatar/util.test.ts b/packages/core-components/src/components/Avatar/util.test.ts index 70ed360bc3..98d0bd2550 100644 --- a/packages/core-components/src/components/Avatar/util.test.ts +++ b/packages/core-components/src/components/Avatar/util.test.ts @@ -17,25 +17,29 @@ import { extractInitials, stringToColor } from './utils'; describe('stringToColor', () => { - it('extract color', async () => { + it('extract color', () => { expect(stringToColor('Jenny Doe')).toEqual('#7809fa'); }); }); describe('extractInitials', () => { - it('extract initials', async () => { + it('extract initials', () => { expect(extractInitials('Jenny Doe')).toEqual('JD'); }); - it('extract unicode initials', async () => { + it('extract unicode initials', () => { expect(extractInitials('Petr Čech')).toEqual('PČ'); }); - it('extract single letter for short name', async () => { + it('extract single letter for short name', () => { expect(extractInitials('Doe')).toEqual('D'); }); - it('limit the initials to two letters', async () => { + it('limit the initials to two letters', () => { expect(extractInitials('John Jonathan Doe')).toEqual('JD'); }); + + it('removes spaces from beginning or the end', () => { + expect(extractInitials(' John Jonathan Doe ')).toEqual('JD'); + }); }); diff --git a/packages/core-components/src/components/Avatar/utils.ts b/packages/core-components/src/components/Avatar/utils.ts index ad587e0e8e..65e2be6afa 100644 --- a/packages/core-components/src/components/Avatar/utils.ts +++ b/packages/core-components/src/components/Avatar/utils.ts @@ -28,7 +28,7 @@ export function stringToColor(str: string) { } export function extractInitials(name: string) { - const names = name.split(' '); + const names = name.trim().split(' '); const firstName = names[0] ?? ''; const lastName = names.length > 1 ? names[names.length - 1] : ''; return firstName && lastName From 7187f2953edce88e2e485a1784e3b0de66929c51 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Oct 2023 17:33:44 +0200 Subject: [PATCH 024/348] cli: update package detection filtering logic to only consider package name Signed-off-by: Patrik Oldsberg --- .changeset/twelve-mirrors-brush.md | 5 ++ .../cli/src/lib/bundler/packageDetection.ts | 83 +++++++++++-------- 2 files changed, 55 insertions(+), 33 deletions(-) create mode 100644 .changeset/twelve-mirrors-brush.md diff --git a/.changeset/twelve-mirrors-brush.md b/.changeset/twelve-mirrors-brush.md new file mode 100644 index 0000000000..90725b5ec4 --- /dev/null +++ b/.changeset/twelve-mirrors-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +The experimental package discovery will now always use the package name for include and exclude filtering, rather than the full module id. Entries pointing to a subpath export will now instead have an `export` field specifying the subpath that the import is from. diff --git a/packages/cli/src/lib/bundler/packageDetection.ts b/packages/cli/src/lib/bundler/packageDetection.ts index 10686f7c86..2095fe23e7 100644 --- a/packages/cli/src/lib/bundler/packageDetection.ts +++ b/packages/cli/src/lib/bundler/packageDetection.ts @@ -15,7 +15,7 @@ */ import { BackstagePackageJson } from '@backstage/cli-node'; -import { Config } from '@backstage/config'; +import { Config, ConfigReader } from '@backstage/config'; import chokidar from 'chokidar'; import fs from 'fs-extra'; import { join as joinPath, resolve as resolvePath } from 'path'; @@ -45,9 +45,19 @@ function readPackageDetectionConfig( return {}; } + if (typeof packages !== 'object' || Array.isArray(packages)) { + throw new Error( + "Invalid config at 'app.experimental.packages', expected object", + ); + } + const packagesConfig = new ConfigReader( + packages, + 'app.experimental.packages', + ); + return { - include: config.getOptionalStringArray('app.experimental.packages.include'), - exclude: config.getOptionalStringArray('app.experimental.packages.exclude'), + include: packagesConfig.getOptionalStringArray('include'), + exclude: packagesConfig.getOptionalStringArray('exclude'), }; } @@ -59,40 +69,47 @@ async function detectPackages( resolvePath(targetPath, 'package.json'), ); - return Object.keys(pkg.dependencies ?? {}) - .flatMap(depName => { - const depPackageJson: BackstagePackageJson = require(require.resolve( - `${depName}/package.json`, - { paths: [targetPath] }, - )); - if ( - ['frontend-plugin', 'frontend-plugin-module'].includes( - depPackageJson.backstage?.role ?? '', - ) - ) { - // Include alpha entry point if available. If there's no default export it will be ignored - const exp = depPackageJson.exports; - if (exp && typeof exp === 'object' && './alpha' in exp) { - return [depName, `${depName}/alpha`]; - } - return [depName]; - } + return Object.keys(pkg.dependencies ?? {}).flatMap(depName => { + if (exclude?.includes(depName)) { return []; - }) - .filter(name => { - if (exclude?.includes(name)) { - return false; + } + if (include && !include.includes(depName)) { + return []; + } + + const depPackageJson: BackstagePackageJson = require(require.resolve( + `${depName}/package.json`, + { paths: [targetPath] }, + )); + if ( + ['frontend-plugin', 'frontend-plugin-module'].includes( + depPackageJson.backstage?.role ?? '', + ) + ) { + // Include alpha entry point if available. If there's no default export it will be ignored + const exp = depPackageJson.exports; + if (exp && typeof exp === 'object' && './alpha' in exp) { + return [ + { name: depName, import: depName }, + { name: depName, export: './alpha', import: `${depName}/alpha` }, + ]; } - if (include && !include.includes(name)) { - return false; - } - return true; - }); + return [{ name: depName, import: depName }]; + } + return []; + }); } -async function writeDetectedPackagesModule(packageNames: string[]) { - const requirePackageScript = packageNames - ?.map(pkg => `{ name: '${pkg}', default: require('${pkg}').default }`) +async function writeDetectedPackagesModule( + pkgs: { name: string; export?: string; import: string }[], +) { + const requirePackageScript = pkgs + ?.map( + pkg => + `{ name: ${JSON.stringify(pkg.name)}, export: ${JSON.stringify( + pkg.export, + )}, default: require('${pkg.import}').default }`, + ) .join(','); await fs.writeFile( From f78ac58f8893432f84bb62ff17972e87d981fb68 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Oct 2023 17:35:15 +0200 Subject: [PATCH 025/348] frontend-app-api: apply package detection filters at runtime Signed-off-by: Patrik Oldsberg --- .changeset/chilled-sloths-rest.md | 5 ++ packages/frontend-app-api/config.d.ts | 8 +++ .../frontend-app-api/src/wiring/createApp.tsx | 4 +- .../src/wiring/discovery.test.ts | 27 +++++---- .../frontend-app-api/src/wiring/discovery.ts | 59 +++++++++++++++++-- 5 files changed, 84 insertions(+), 19 deletions(-) create mode 100644 .changeset/chilled-sloths-rest.md diff --git a/.changeset/chilled-sloths-rest.md b/.changeset/chilled-sloths-rest.md new file mode 100644 index 0000000000..1cad0be99f --- /dev/null +++ b/.changeset/chilled-sloths-rest.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Filters for discovered packages are now also applied at runtime. This makes it possible to disable packages through the `app.experimental.packages` config at runtime. diff --git a/packages/frontend-app-api/config.d.ts b/packages/frontend-app-api/config.d.ts index 81c24d1185..5f5f877d3e 100644 --- a/packages/frontend-app-api/config.d.ts +++ b/packages/frontend-app-api/config.d.ts @@ -16,6 +16,14 @@ export interface Config { app?: { + experimental?: { + /** + * @visibility frontend + * @deepVisibility frontend + */ + packages?: 'all' | { include?: string[]; exclude?: string[] }; + }; + /** * @deepVisibility frontend */ diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index f262ecde72..4b7e4985f3 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -116,7 +116,7 @@ export interface ExtensionTree { export function createExtensionTree(options: { config: Config; }): ExtensionTree { - const features = getAvailableFeatures(); + const features = getAvailableFeatures(options.config); const { instances } = createInstances({ features, config: options.config, @@ -286,7 +286,7 @@ export function createApp(options: { overrideBaseUrlConfigs(defaultConfigLoaderSync()), ); - const discoveredFeatures = getAvailableFeatures(); + const discoveredFeatures = getAvailableFeatures(config); const loadedFeatures = (await options.featureLoader?.({ config })) ?? []; const allFeatures = Array.from( new Set([ diff --git a/packages/frontend-app-api/src/wiring/discovery.test.ts b/packages/frontend-app-api/src/wiring/discovery.test.ts index 54294bbd45..6008ce6746 100644 --- a/packages/frontend-app-api/src/wiring/discovery.test.ts +++ b/packages/frontend-app-api/src/wiring/discovery.test.ts @@ -16,24 +16,29 @@ import { createPlugin } from '@backstage/frontend-plugin-api'; import { getAvailableFeatures } from './discovery'; +import { ConfigReader } from '@backstage/config'; const globalSpy = jest.fn(); Object.defineProperty(global, '__@backstage/discovered__', { get: globalSpy, }); +const config = new ConfigReader({ + app: { experimental: { packages: 'all' } }, +}); + describe('getAvailableFeatures', () => { afterEach(jest.resetAllMocks); it('should discover nothing with undefined global', () => { - expect(getAvailableFeatures()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); }); it('should discover nothing with empty global', () => { globalSpy.mockReturnValue({ modules: [], }); - expect(getAvailableFeatures()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); }); it('should discover a plugin', () => { @@ -41,24 +46,24 @@ describe('getAvailableFeatures', () => { globalSpy.mockReturnValue({ modules: [{ default: testPlugin }], }); - expect(getAvailableFeatures()).toEqual([testPlugin]); + expect(getAvailableFeatures(config)).toEqual([testPlugin]); }); it('should ignore garbage', () => { globalSpy.mockReturnValueOnce({ modules: [{ default: null }] }); - expect(getAvailableFeatures()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: undefined }] }); - expect(getAvailableFeatures()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: Symbol() }] }); - expect(getAvailableFeatures()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: () => {} }] }); - expect(getAvailableFeatures()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: 0 }] }); - expect(getAvailableFeatures()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: false }] }); - expect(getAvailableFeatures()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: true }] }); - expect(getAvailableFeatures()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); }); it('should discover multiple plugins', () => { @@ -72,7 +77,7 @@ describe('getAvailableFeatures', () => { { default: test3Plugin }, ], }); - expect(getAvailableFeatures()).toEqual([ + expect(getAvailableFeatures(config)).toEqual([ test1Plugin, test2Plugin, test3Plugin, diff --git a/packages/frontend-app-api/src/wiring/discovery.ts b/packages/frontend-app-api/src/wiring/discovery.ts index 14786c93d9..1181992d53 100644 --- a/packages/frontend-app-api/src/wiring/discovery.ts +++ b/packages/frontend-app-api/src/wiring/discovery.ts @@ -14,28 +14,75 @@ * limitations under the License. */ +import { Config, ConfigReader } from '@backstage/config'; import { BackstagePlugin, ExtensionOverrides, } from '@backstage/frontend-plugin-api'; interface DiscoveryGlobal { - modules: Array<{ name: string; default: unknown }>; + modules: Array<{ name: string; export?: string; default: unknown }>; +} + +function readPackageDetectionConfig(config: Config) { + const packages = config.getOptional('app.experimental.packages'); + if (packages === undefined || packages === null) { + return undefined; + } + + if (typeof packages === 'string') { + if (packages !== 'all') { + throw new Error( + `Invalid app.experimental.packages mode, got '${packages}', expected 'all'`, + ); + } + return {}; + } + + if (typeof packages !== 'object' || Array.isArray(packages)) { + throw new Error( + "Invalid config at 'app.experimental.packages', expected object", + ); + } + const packagesConfig = new ConfigReader( + packages, + 'app.experimental.packages', + ); + + return { + include: packagesConfig.getOptionalStringArray('include'), + exclude: packagesConfig.getOptionalStringArray('exclude'), + }; } /** * @public */ -export function getAvailableFeatures(): ( - | BackstagePlugin - | ExtensionOverrides -)[] { +export function getAvailableFeatures( + config: Config, +): (BackstagePlugin | ExtensionOverrides)[] { const discovered = ( window as { '__@backstage/discovered__'?: DiscoveryGlobal } )['__@backstage/discovered__']; + const detection = readPackageDetectionConfig(config); + if (!detection) { + return []; + } + return ( - discovered?.modules.map(m => m.default).filter(isBackstageFeature) ?? [] + discovered?.modules + .filter(({ name }) => { + if (detection.exclude?.includes(name)) { + return false; + } + if (detection.include && !detection.include.includes(name)) { + return false; + } + return true; + }) + .map(m => m.default) + .filter(isBackstageFeature) ?? [] ); } From d0566f5184ffd7a08017cdf33b9a50855546b9f6 Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Mon, 16 Oct 2023 15:52:41 -0400 Subject: [PATCH 026/348] Add mock for Element.scrollIntoView to fix tests. Signed-off-by: Sydney Achinger --- .../TechDocsReaderPage/TechDocsReaderPage.test.tsx | 2 ++ .../TechDocsReaderPageContent/TechDocsReaderPageContent.tsx | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx index e11b7b6e81..c9339171e3 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx @@ -91,6 +91,8 @@ const configApi = new MockConfigApi({ }, }); +Element.prototype.scrollIntoView = jest.fn(); + const Wrapper = ({ children }: { children: React.ReactNode }) => { return ( { - if (hashElement) { - if (!isStyleLoading) { - hashElement.scrollIntoView(); - } + if (hashElement && !isStyleLoading) { + hashElement.scrollIntoView(); } else { document?.querySelector('header')?.scrollIntoView(); } From 2daffe3f7d88cfda2c5716f05cbd9f3b3105e978 Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Mon, 16 Oct 2023 16:40:00 -0400 Subject: [PATCH 027/348] Add mock for Element.scrollIntoView to fix tests. Signed-off-by: Sydney Achinger --- packages/app-defaults/src/setupTests.ts | 2 ++ .../components/TechDocsReaderPage/TechDocsReaderPage.test.tsx | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app-defaults/src/setupTests.ts b/packages/app-defaults/src/setupTests.ts index 963c0f188b..5f1220066f 100644 --- a/packages/app-defaults/src/setupTests.ts +++ b/packages/app-defaults/src/setupTests.ts @@ -15,3 +15,5 @@ */ import '@testing-library/jest-dom'; + +Element.prototype.scroll = jest.fn(); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx index c9339171e3..e11b7b6e81 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx @@ -91,8 +91,6 @@ const configApi = new MockConfigApi({ }, }); -Element.prototype.scrollIntoView = jest.fn(); - const Wrapper = ({ children }: { children: React.ReactNode }) => { return ( Date: Mon, 16 Oct 2023 21:24:05 +0000 Subject: [PATCH 028/348] build(deps): bump @babel/traverse from 7.23.0 to 7.23.2 in /microsite Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.23.0 to 7.23.2. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse) --- updated-dependencies: - dependency-name: "@babel/traverse" dependency-type: indirect ... Signed-off-by: dependabot[bot] --- microsite/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 835727014c..8147655315 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -1614,8 +1614,8 @@ __metadata: linkType: hard "@babel/traverse@npm:^7.22.8, @babel/traverse@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/traverse@npm:7.23.0" + version: 7.23.2 + resolution: "@babel/traverse@npm:7.23.2" dependencies: "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.23.0 @@ -1627,7 +1627,7 @@ __metadata: "@babel/types": ^7.23.0 debug: ^4.1.0 globals: ^11.1.0 - checksum: 0b17fae53269e1af2cd3edba00892bc2975ad5df9eea7b84815dab07dfec2928c451066d51bc65b4be61d8499e77db7e547ce69ef2a7b0eca3f96269cb43a0b0 + checksum: 26a1eea0dde41ab99dde8b9773a013a0dc50324e5110a049f5d634e721ff08afffd54940b3974a20308d7952085ac769689369e9127dea655f868c0f6e1ab35d languageName: node linkType: hard From 4a8c49b21e7581ea46b7bc8065736818e276f9ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 22:15:01 +0000 Subject: [PATCH 029/348] build(deps): bump undici from 5.25.4 to 5.26.3 Bumps [undici](https://github.com/nodejs/undici) from 5.25.4 to 5.26.3. - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/commits/v5.26.3) --- updated-dependencies: - dependency-name: undici dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4a2d73dd4d..49c1603c65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -41554,11 +41554,11 @@ __metadata: linkType: hard "undici@npm:^5.12.0, undici@npm:^5.24.0, undici@npm:^5.8.0": - version: 5.25.4 - resolution: "undici@npm:5.25.4" + version: 5.26.3 + resolution: "undici@npm:5.26.3" dependencies: "@fastify/busboy": ^2.0.0 - checksum: 654da161687de893127a685be61a19cb5bae42f4595c316ebf633929d871ac3bcd33edcb74156cea90655dfcd100bfe9b53a4f4749d52fc6ad2232f49a6ca8ab + checksum: aaa9aadb712cf80e1a9cea2377e4842670105e00abbc184a21770ea5a8b77e4e2eadc200eac62442e74a1cd3b16a840c6f73b112b9e886bd3c1a125eb22e4f21 languageName: node linkType: hard From b732b92b368b0fda0686408743bfb50bd4f50d0a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 10:40:22 +0200 Subject: [PATCH 030/348] docs/publishing: remove link to pre.json Signed-off-by: Patrik Oldsberg --- docs/publishing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/publishing.md b/docs/publishing.md index 2424bc1352..f8964278b5 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -40,7 +40,7 @@ Congratulations on the release! There should be now a post in the [`#announcemen Additional steps for the main line release - [Switch Release Mode](#switching-release-modes) to exit pre-release mode. This can be done at any time after the last Next Line Release. - - Check [`.changeset/pre.json`](https://github.com/backstage/backstage/blob/master/.changeset/pre.json) if the `mode` is set to `exit`. If you encounter `mode: "pre"` it indicates a next line release. + - Check `.changeset/pre.json` if the `mode` is set to `exit`. If you encounter `mode: "pre"` it indicates a next line release. - Check [`Version Packages` Pull Request](https://github.com/backstage/backstage/pulls?q=is%3Aopen+is%3Apr+in%3Atitle+%22Version+Packages) - Check for mentions of "major" & "breaking" and if they are expected in the current release - Verify the version we are shipping is correct From 8cdb8c2e40f24a59a2fc1aacdf60b8712446e0f8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 17 Oct 2023 08:54:50 +0000 Subject: [PATCH 031/348] Version Packages --- .changeset/angry-badgers-beg.md | 5 - .changeset/angry-clocks-exercise.md | 5 - .changeset/big-spies-beam.md | 5 - .changeset/breezy-dryers-thank.md | 10 - .changeset/calm-carpets-kiss.md | 5 - .changeset/calm-scissors-rescue.md | 5 - .changeset/chatty-papayas-care.md | 5 - .changeset/chilled-sloths-rest.md | 5 - .changeset/clean-forks-love.md | 5 - .changeset/cold-bees-jam.md | 6 - .changeset/cold-seas-repeat.md | 5 - .changeset/create-app-1696937840.md | 5 - .changeset/dirty-doors-wave.md | 5 - .changeset/dull-bugs-build.md | 6 - .changeset/dull-dolls-explode.md | 5 - .changeset/dull-experts-kiss.md | 5 - .changeset/dull-laws-camp.md | 7 - .changeset/early-toes-develop.md | 11 - .changeset/eight-melons-cough.md | 5 - .changeset/eight-spiders-fold.md | 7 - .changeset/eight-suns-tan.md | 5 - .changeset/eighty-actors-type.md | 5 - .changeset/eleven-hounds-invent.md | 5 - .changeset/empty-clocks-argue.md | 5 - .changeset/empty-schools-check.md | 6 - .changeset/fair-frogs-enjoy.md | 5 - .changeset/five-hornets-provide.md | 5 - .changeset/five-spiders-listen.md | 5 - .changeset/flat-pandas-tan.md | 5 - .changeset/flat-rules-rush.md | 19 - .changeset/four-jars-protect.md | 5 - .changeset/four-onions-clap.md | 5 - .changeset/four-pans-sin.md | 5 - .changeset/fresh-badgers-study.md | 5 - .changeset/fresh-kangaroos-tap.md | 5 - .changeset/fuzzy-pillows-remain.md | 5 - .changeset/gentle-elephants-fold.md | 20 - .changeset/gentle-spies-deny.md | 14 - .changeset/great-walls-brake.md | 5 - .changeset/happy-books-smoke.md | 5 - .changeset/healthy-laws-divide.md | 5 - .changeset/healthy-shirts-fold.md | 6 - .changeset/heavy-forks-tie.md | 5 - .changeset/heavy-ladybugs-leave.md | 5 - .changeset/heavy-plants-doubt.md | 5 - .changeset/itchy-bobcats-fly.md | 5 - .changeset/itchy-monkeys-reply.md | 5 - .changeset/itchy-rabbits-exist.md | 7 - .changeset/khaki-tools-tease.md | 11 - .changeset/large-balloons-brush.md | 5 - .changeset/large-comics-knock.md | 5 - .changeset/late-papayas-push.md | 5 - .changeset/lazy-doors-wink.md | 5 - .changeset/lemon-cups-wait.md | 5 - .changeset/lemon-masks-greet.md | 5 - .changeset/light-squids-deny.md | 6 - .changeset/little-ligers-cheat.md | 5 - .changeset/long-flies-battle.md | 5 - .changeset/long-owls-complain.md | 5 - .changeset/loud-hotels-hunt.md | 22 - .changeset/lovely-coins-occur.md | 5 - .changeset/lovely-fans-sniff.md | 5 - .changeset/many-impalas-wait.md | 5 - .changeset/many-pianos-bow.md | 5 - .changeset/many-swans-eat.md | 5 - .changeset/mean-dancers-burn.md | 7 - .changeset/metal-peas-beam.md | 5 - .changeset/modern-owls-mate.md | 5 - .changeset/moody-lobsters-rescue.md | 5 - .changeset/nasty-needles-hear.md | 5 - .changeset/nervous-hounds-sleep.md | 5 - .changeset/nice-clocks-smash.md | 5 - .changeset/nice-dancers-explain.md | 5 - .changeset/nice-ghosts-build.md | 6 - .changeset/nine-flies-move.md | 6 - .changeset/nine-garlics-attend.md | 5 - .changeset/odd-pants-sleep.md | 7 - .changeset/olive-cars-rescue.md | 5 - .changeset/olive-geese-rest.md | 5 - .changeset/olive-islands-sneeze.md | 6 - .changeset/orange-cycles-wait.md | 5 - .changeset/perfect-cobras-bake.md | 9 - .changeset/perfect-pumas-protect.md | 5 - .changeset/perfect-shrimps-attend.md | 5 - .changeset/plenty-llamas-double.md | 5 - .changeset/plenty-toys-cheer.md | 6 - .changeset/polite-cooks-perform.md | 5 - .changeset/polite-donuts-fail.md | 5 - .changeset/polite-trainers-grin.md | 5 - .changeset/popular-bikes-do.md | 5 - .changeset/popular-dots-design.md | 5 - .changeset/pre.json | 390 -- .changeset/pretty-apes-sneeze.md | 5 - .changeset/pretty-steaks-serve.md | 5 - .changeset/pretty-swans-worry.md | 5 - .changeset/purple-chefs-wait.md | 5 - .changeset/purple-forks-fetch.md | 5 - .changeset/quick-weeks-explode.md | 5 - .changeset/rare-glasses-play.md | 5 - .changeset/rare-pants-reply.md | 5 - .changeset/red-baboons-warn.md | 5 - .changeset/red-bees-try.md | 5 - .changeset/red-geese-clean.md | 8 - .changeset/renovate-0a0b7ba.md | 8 - .changeset/renovate-2633beb.md | 104 - .changeset/renovate-37d5549.md | 86 - .changeset/renovate-7d08f6a.md | 5 - .changeset/renovate-a1c52e8.md | 5 - .changeset/renovate-a6a783f.md | 6 - .changeset/renovate-c204e0d.md | 5 - .changeset/rotten-rings-confess.md | 9 - .changeset/serious-pants-lie.md | 21 - .changeset/serious-penguins-tease.md | 5 - .changeset/serious-ravens-serve.md | 5 - .changeset/shaggy-beers-collect.md | 6 - .changeset/shiny-birds-melt.md | 5 - .changeset/short-ears-rescue.md | 5 - .changeset/short-terms-check.md | 5 - .changeset/shy-clouds-reflect.md | 5 - .changeset/shy-seas-sip.md | 5 - .changeset/silent-years-bake.md | 11 - .changeset/silent-years-marry.md | 8 - .changeset/silly-chefs-allow.md | 5 - .changeset/silly-swans-invent.md | 5 - .changeset/six-weeks-raise.md | 5 - .changeset/slow-cameras-grab.md | 5 - .changeset/slow-dodos-remember.md | 8 - .changeset/small-avocados-live.md | 5 - .changeset/small-books-deliver.md | 5 - .changeset/small-pugs-build.md | 7 - .changeset/smooth-rings-mate.md | 5 - .changeset/spicy-chairs-film.md | 7 - .changeset/spicy-poets-sell.md | 5 - .changeset/spotty-badgers-wash.md | 5 - .changeset/stale-eagles-reply.md | 6 - .changeset/stale-stingrays-explode.md | 5 - .changeset/strange-dodos-film.md | 5 - .changeset/strong-falcons-tickle.md | 5 - .changeset/stupid-drinks-trade.md | 5 - .changeset/stupid-eagles-shave.md | 5 - .changeset/sweet-buckets-fry.md | 5 - .changeset/swift-kings-add.md | 5 - .changeset/swift-steaks-fetch.md | 6 - .changeset/tall-dragons-jump.md | 5 - .changeset/tame-trainers-visit.md | 5 - .changeset/tasty-avocados-hope.md | 5 - .changeset/tasty-doors-switch.md | 5 - .changeset/ten-seals-wait.md | 5 - .changeset/tender-experts-yell.md | 5 - .changeset/tender-pears-work.md | 5 - .changeset/thick-dolphins-boil.md | 5 - .changeset/thirty-coins-sneeze.md | 5 - .changeset/tiny-garlics-cheer.md | 5 - .changeset/tiny-suns-deny.md | 5 - .changeset/twelve-clouds-design.md | 9 - .changeset/twelve-days-walk.md | 5 - .changeset/twelve-mirrors-brush.md | 5 - .changeset/twelve-snakes-sell.md | 5 - .changeset/twenty-bags-sin.md | 5 - .changeset/twenty-carrots-smile.md | 5 - .changeset/twenty-masks-exist.md | 5 - .changeset/two-dingos-dream.md | 7 - .changeset/two-terms-play.md | 5 - .changeset/unlucky-experts-breathe.md | 5 - .changeset/violet-apes-beam.md | 5 - .changeset/violet-beers-cross.md | 5 - .changeset/warm-drinks-argue.md | 5 - .changeset/wet-cows-brake.md | 5 - .changeset/wet-olives-wave.md | 5 - .changeset/wet-timers-chew.md | 5 - .changeset/wicked-rings-flash.md | 5 - .changeset/wild-geese-occur.md | 5 - .changeset/wild-jobs-greet.md | 5 - .changeset/wild-queens-grab.md | 5 - .changeset/wild-toys-arrive.md | 5 - .changeset/yellow-numbers-own.md | 11 - .changeset/yellow-rings-invent.md | 5 - .changeset/young-ducks-heal.md | 5 - .changeset/young-toes-knock.md | 5 - docs/releases/v1.19.0-changelog.md | 3632 +++++++++++++++++ package.json | 2 +- packages/app-defaults/CHANGELOG.md | 13 + packages/app-defaults/package.json | 2 +- packages/app-next-example-plugin/CHANGELOG.md | 8 + packages/app-next-example-plugin/package.json | 2 +- packages/app-next/CHANGELOG.md | 77 + packages/app-next/package.json | 2 +- packages/app/CHANGELOG.md | 77 + packages/app/package.json | 2 +- packages/backend-app-api/CHANGELOG.md | 19 + packages/backend-app-api/package.json | 2 +- packages/backend-common/CHANGELOG.md | 25 + packages/backend-common/package.json | 2 +- packages/backend-defaults/CHANGELOG.md | 9 + packages/backend-defaults/package.json | 2 +- packages/backend-dev-utils/CHANGELOG.md | 6 + packages/backend-dev-utils/package.json | 2 +- packages/backend-next/CHANGELOG.md | 39 + packages/backend-next/package.json | 2 +- packages/backend-openapi-utils/CHANGELOG.md | 12 + packages/backend-openapi-utils/package.json | 2 +- packages/backend-plugin-api/CHANGELOG.md | 11 + packages/backend-plugin-api/package.json | 2 +- packages/backend-plugin-manager/CHANGELOG.md | 23 + packages/backend-plugin-manager/package.json | 2 +- packages/backend-tasks/CHANGELOG.md | 18 + packages/backend-tasks/package.json | 2 +- packages/backend-test-utils/CHANGELOG.md | 16 + packages/backend-test-utils/package.json | 2 +- packages/backend/CHANGELOG.md | 59 + packages/backend/package.json | 2 +- packages/catalog-client/CHANGELOG.md | 8 + packages/catalog-client/package.json | 2 +- packages/catalog-model/CHANGELOG.md | 9 + packages/catalog-model/package.json | 2 +- packages/cli-common/CHANGELOG.md | 6 + packages/cli-common/package.json | 2 +- packages/cli-node/CHANGELOG.md | 9 + packages/cli-node/package.json | 2 +- packages/cli/CHANGELOG.md | 55 + packages/cli/package.json | 2 +- packages/codemods/CHANGELOG.md | 8 + packages/codemods/package.json | 2 +- packages/config-loader/CHANGELOG.md | 14 + packages/config-loader/package.json | 2 +- packages/config/CHANGELOG.md | 8 + packages/config/package.json | 2 +- packages/core-app-api/CHANGELOG.md | 20 + packages/core-app-api/package.json | 2 +- packages/core-components/CHANGELOG.md | 22 + packages/core-components/package.json | 2 +- packages/core-plugin-api/CHANGELOG.md | 16 + packages/core-plugin-api/package.json | 2 +- packages/create-app/CHANGELOG.md | 35 + packages/create-app/package.json | 2 +- packages/dev-utils/CHANGELOG.md | 18 + packages/dev-utils/package.json | 2 +- packages/e2e-test-utils/CHANGELOG.md | 6 + packages/e2e-test-utils/package.json | 2 +- packages/e2e-test/CHANGELOG.md | 9 + packages/e2e-test/package.json | 2 +- packages/errors/CHANGELOG.md | 8 + packages/errors/package.json | 2 +- packages/frontend-app-api/CHANGELOG.md | 34 + packages/frontend-app-api/package.json | 2 +- packages/frontend-plugin-api/CHANGELOG.md | 18 + packages/frontend-plugin-api/package.json | 2 +- packages/integration-aws-node/CHANGELOG.md | 8 + packages/integration-aws-node/package.json | 2 +- packages/integration-react/CHANGELOG.md | 12 + packages/integration-react/package.json | 2 +- packages/integration/CHANGELOG.md | 9 + packages/integration/package.json | 2 +- packages/repo-tools/CHANGELOG.md | 11 + packages/repo-tools/package.json | 2 +- .../techdocs-cli-embedded-app/CHANGELOG.md | 19 + .../techdocs-cli-embedded-app/package.json | 2 +- packages/techdocs-cli/CHANGELOG.md | 17 + packages/techdocs-cli/package.json | 2 +- packages/test-utils/CHANGELOG.md | 16 + packages/test-utils/package.json | 2 +- packages/theme/CHANGELOG.md | 6 + packages/theme/package.json | 2 +- packages/version-bridge/CHANGELOG.md | 6 + packages/version-bridge/package.json | 2 +- plugins/adr-backend/CHANGELOG.md | 15 + plugins/adr-backend/package.json | 2 +- plugins/adr-common/CHANGELOG.md | 9 + plugins/adr-common/package.json | 2 +- plugins/adr/CHANGELOG.md | 20 + plugins/adr/package.json | 2 +- plugins/airbrake-backend/CHANGELOG.md | 9 + plugins/airbrake-backend/package.json | 2 +- plugins/airbrake/CHANGELOG.md | 15 + plugins/airbrake/package.json | 2 +- plugins/allure/CHANGELOG.md | 13 + plugins/allure/package.json | 2 +- plugins/analytics-module-ga/CHANGELOG.md | 13 + plugins/analytics-module-ga/package.json | 2 +- plugins/analytics-module-ga4/CHANGELOG.md | 12 + plugins/analytics-module-ga4/package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- plugins/apache-airflow/CHANGELOG.md | 10 + plugins/apache-airflow/package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- plugins/api-docs/CHANGELOG.md | 16 + plugins/api-docs/package.json | 2 +- plugins/apollo-explorer/CHANGELOG.md | 11 + plugins/apollo-explorer/package.json | 2 +- plugins/app-backend/CHANGELOG.md | 12 + plugins/app-backend/package.json | 2 +- plugins/app-node/CHANGELOG.md | 7 + plugins/app-node/package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- plugins/auth-backend/CHANGELOG.md | 23 + plugins/auth-backend/package.json | 2 +- plugins/auth-node/CHANGELOG.md | 20 + plugins/auth-node/package.json | 2 +- plugins/azure-devops-backend/CHANGELOG.md | 10 + plugins/azure-devops-backend/package.json | 2 +- plugins/azure-devops/CHANGELOG.md | 15 + plugins/azure-devops/package.json | 2 +- plugins/azure-sites-backend/CHANGELOG.md | 9 + plugins/azure-sites-backend/package.json | 2 +- plugins/azure-sites/CHANGELOG.md | 14 + plugins/azure-sites/package.json | 2 +- plugins/badges-backend/CHANGELOG.md | 14 + plugins/badges-backend/package.json | 2 +- plugins/badges/CHANGELOG.md | 13 + plugins/badges/package.json | 2 +- plugins/bazaar-backend/CHANGELOG.md | 11 + plugins/bazaar-backend/package.json | 2 +- plugins/bazaar/CHANGELOG.md | 16 + plugins/bazaar/package.json | 2 +- plugins/bitbucket-cloud-common/CHANGELOG.md | 7 + plugins/bitbucket-cloud-common/package.json | 2 +- plugins/bitrise/CHANGELOG.md | 13 + plugins/bitrise/package.json | 2 +- .../catalog-backend-module-aws/CHANGELOG.md | 23 + .../catalog-backend-module-aws/package.json | 2 +- .../catalog-backend-module-azure/CHANGELOG.md | 17 + .../catalog-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 18 + .../package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../catalog-backend-module-gcp/CHANGELOG.md | 12 + .../catalog-backend-module-gcp/package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../CHANGELOG.md | 22 + .../package.json | 2 +- .../CHANGELOG.md | 32 + .../package.json | 2 +- .../CHANGELOG.md | 17 + .../package.json | 2 +- .../catalog-backend-module-ldap/CHANGELOG.md | 14 + .../catalog-backend-module-ldap/package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/catalog-backend/CHANGELOG.md | 31 + plugins/catalog-backend/package.json | 2 +- plugins/catalog-common/CHANGELOG.md | 9 + plugins/catalog-common/package.json | 2 +- plugins/catalog-graph/CHANGELOG.md | 15 + plugins/catalog-graph/package.json | 2 +- plugins/catalog-graphql/CHANGELOG.md | 13 + plugins/catalog-graphql/package.json | 2 +- plugins/catalog-import/CHANGELOG.md | 19 + plugins/catalog-import/package.json | 2 +- plugins/catalog-node/CHANGELOG.md | 13 + plugins/catalog-node/package.json | 2 +- plugins/catalog-react/CHANGELOG.md | 23 + plugins/catalog-react/package.json | 2 +- .../catalog-unprocessed-entities/CHANGELOG.md | 12 + .../catalog-unprocessed-entities/package.json | 2 +- plugins/catalog/CHANGELOG.md | 47 + plugins/catalog/package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/cicd-statistics/CHANGELOG.md | 10 + plugins/cicd-statistics/package.json | 2 +- plugins/circleci/CHANGELOG.md | 13 + plugins/circleci/package.json | 2 +- plugins/cloudbuild/CHANGELOG.md | 13 + plugins/cloudbuild/package.json | 2 +- plugins/code-climate/CHANGELOG.md | 13 + plugins/code-climate/package.json | 2 +- plugins/code-coverage-backend/CHANGELOG.md | 14 + plugins/code-coverage-backend/package.json | 2 +- plugins/code-coverage/CHANGELOG.md | 18 + plugins/code-coverage/package.json | 2 +- plugins/codescene/CHANGELOG.md | 14 + plugins/codescene/package.json | 2 +- plugins/config-schema/CHANGELOG.md | 14 + plugins/config-schema/package.json | 2 +- plugins/cost-insights/CHANGELOG.md | 17 + plugins/cost-insights/package.json | 2 +- plugins/devtools-backend/CHANGELOG.md | 17 + plugins/devtools-backend/package.json | 2 +- plugins/devtools-common/CHANGELOG.md | 8 + plugins/devtools-common/package.json | 2 +- plugins/devtools/CHANGELOG.md | 14 + plugins/devtools/package.json | 2 +- plugins/dynatrace/CHANGELOG.md | 13 + plugins/dynatrace/package.json | 2 +- plugins/entity-feedback-backend/CHANGELOG.md | 13 + plugins/entity-feedback-backend/package.json | 2 +- plugins/entity-feedback/CHANGELOG.md | 16 + plugins/entity-feedback/package.json | 2 +- plugins/entity-validation/CHANGELOG.md | 16 + plugins/entity-validation/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../events-backend-module-azure/CHANGELOG.md | 8 + .../events-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../events-backend-module-gerrit/CHANGELOG.md | 8 + .../events-backend-module-gerrit/package.json | 2 +- .../events-backend-module-github/CHANGELOG.md | 9 + .../events-backend-module-github/package.json | 2 +- .../events-backend-module-gitlab/CHANGELOG.md | 9 + .../events-backend-module-gitlab/package.json | 2 +- .../events-backend-test-utils/CHANGELOG.md | 7 + .../events-backend-test-utils/package.json | 2 +- plugins/events-backend/CHANGELOG.md | 10 + plugins/events-backend/package.json | 2 +- plugins/events-node/CHANGELOG.md | 7 + plugins/events-node/package.json | 2 +- .../example-todo-list-backend/CHANGELOG.md | 11 + .../example-todo-list-backend/package.json | 2 +- plugins/example-todo-list-common/CHANGELOG.md | 7 + plugins/example-todo-list-common/package.json | 2 +- plugins/example-todo-list/CHANGELOG.md | 9 + plugins/example-todo-list/package.json | 2 +- plugins/explore-backend/CHANGELOG.md | 12 + plugins/explore-backend/package.json | 2 +- plugins/explore-react/CHANGELOG.md | 10 + plugins/explore-react/package.json | 2 +- plugins/explore/CHANGELOG.md | 20 + plugins/explore/package.json | 2 +- plugins/firehydrant/CHANGELOG.md | 13 + plugins/firehydrant/package.json | 2 +- plugins/fossa/CHANGELOG.md | 14 + plugins/fossa/package.json | 2 +- plugins/gcalendar/CHANGELOG.md | 12 + plugins/gcalendar/package.json | 2 +- plugins/gcp-projects/CHANGELOG.md | 11 + plugins/gcp-projects/package.json | 2 +- plugins/git-release-manager/CHANGELOG.md | 12 + plugins/git-release-manager/package.json | 2 +- plugins/github-actions/CHANGELOG.md | 15 + plugins/github-actions/package.json | 2 +- plugins/github-deployments/CHANGELOG.md | 16 + plugins/github-deployments/package.json | 2 +- plugins/github-issues/CHANGELOG.md | 16 + plugins/github-issues/package.json | 2 +- .../github-pull-requests-board/CHANGELOG.md | 14 + .../github-pull-requests-board/package.json | 2 +- plugins/gitops-profiles/CHANGELOG.md | 12 + plugins/gitops-profiles/package.json | 2 +- plugins/gocd/CHANGELOG.md | 14 + plugins/gocd/package.json | 2 +- plugins/graphiql/CHANGELOG.md | 14 + plugins/graphiql/package.json | 2 +- plugins/graphql-backend/CHANGELOG.md | 13 + plugins/graphql-backend/package.json | 2 +- plugins/graphql-voyager/CHANGELOG.md | 11 + plugins/graphql-voyager/package.json | 2 +- plugins/home-react/CHANGELOG.md | 10 + plugins/home-react/package.json | 2 +- plugins/home/CHANGELOG.md | 18 + plugins/home/package.json | 2 +- plugins/ilert/CHANGELOG.md | 16 + plugins/ilert/package.json | 2 +- plugins/jenkins-backend/CHANGELOG.md | 25 + plugins/jenkins-backend/package.json | 2 +- plugins/jenkins-common/CHANGELOG.md | 8 + plugins/jenkins-common/package.json | 2 +- plugins/jenkins/CHANGELOG.md | 23 + plugins/jenkins/package.json | 2 +- plugins/kafka-backend/CHANGELOG.md | 11 + plugins/kafka-backend/package.json | 2 +- plugins/kafka/CHANGELOG.md | 14 + plugins/kafka/package.json | 2 +- plugins/kubernetes-backend/CHANGELOG.md | 31 + plugins/kubernetes-backend/package.json | 2 +- plugins/kubernetes-cluster/CHANGELOG.md | 18 + plugins/kubernetes-cluster/package.json | 2 +- plugins/kubernetes-common/CHANGELOG.md | 17 + plugins/kubernetes-common/package.json | 2 +- plugins/kubernetes-node/CHANGELOG.md | 13 + plugins/kubernetes-node/package.json | 2 +- plugins/kubernetes-react/CHANGELOG.md | 20 + plugins/kubernetes-react/package.json | 2 +- plugins/kubernetes/CHANGELOG.md | 26 + plugins/kubernetes/package.json | 2 +- plugins/lighthouse-backend/CHANGELOG.md | 15 + plugins/lighthouse-backend/package.json | 2 +- plugins/lighthouse-common/CHANGELOG.md | 7 + plugins/lighthouse-common/package.json | 2 +- plugins/lighthouse/CHANGELOG.md | 15 + plugins/lighthouse/package.json | 2 +- plugins/linguist-backend/CHANGELOG.md | 17 + plugins/linguist-backend/package.json | 2 +- plugins/linguist/CHANGELOG.md | 15 + plugins/linguist/package.json | 2 +- plugins/microsoft-calendar/CHANGELOG.md | 12 + plugins/microsoft-calendar/package.json | 2 +- plugins/newrelic-dashboard/CHANGELOG.md | 24 + plugins/newrelic-dashboard/package.json | 2 +- plugins/newrelic/CHANGELOG.md | 12 + plugins/newrelic/package.json | 2 +- plugins/nomad-backend/CHANGELOG.md | 11 + plugins/nomad-backend/package.json | 2 +- plugins/nomad/CHANGELOG.md | 13 + plugins/nomad/package.json | 2 +- plugins/octopus-deploy/CHANGELOG.md | 13 + plugins/octopus-deploy/package.json | 2 +- plugins/opencost/CHANGELOG.md | 11 + plugins/opencost/package.json | 2 +- plugins/org-react/CHANGELOG.md | 14 + plugins/org-react/package.json | 2 +- plugins/org/CHANGELOG.md | 15 + plugins/org/package.json | 2 +- plugins/pagerduty/CHANGELOG.md | 16 + plugins/pagerduty/package.json | 2 +- plugins/periskop-backend/CHANGELOG.md | 9 + plugins/periskop-backend/package.json | 2 +- plugins/periskop/CHANGELOG.md | 14 + plugins/periskop/package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- plugins/permission-backend/CHANGELOG.md | 13 + plugins/permission-backend/package.json | 2 +- plugins/permission-common/CHANGELOG.md | 9 + plugins/permission-common/package.json | 2 +- plugins/permission-node/CHANGELOG.md | 12 + plugins/permission-node/package.json | 2 +- plugins/permission-react/CHANGELOG.md | 10 + plugins/permission-react/package.json | 2 +- plugins/playlist-backend/CHANGELOG.md | 17 + plugins/playlist-backend/package.json | 2 +- plugins/playlist-common/CHANGELOG.md | 7 + plugins/playlist-common/package.json | 2 +- plugins/playlist/CHANGELOG.md | 20 + plugins/playlist/package.json | 2 +- plugins/proxy-backend/CHANGELOG.md | 9 + plugins/proxy-backend/package.json | 2 +- plugins/puppetdb/CHANGELOG.md | 13 + plugins/puppetdb/package.json | 2 +- plugins/rollbar-backend/CHANGELOG.md | 9 + plugins/rollbar-backend/package.json | 2 +- plugins/rollbar/CHANGELOG.md | 13 + plugins/rollbar/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/scaffolder-backend/CHANGELOG.md | 38 + plugins/scaffolder-backend/package.json | 2 +- plugins/scaffolder-common/CHANGELOG.md | 9 + plugins/scaffolder-common/package.json | 2 +- plugins/scaffolder-node/CHANGELOG.md | 13 + plugins/scaffolder-node/package.json | 2 +- plugins/scaffolder-react/CHANGELOG.md | 18 + plugins/scaffolder-react/package.json | 2 +- plugins/scaffolder/CHANGELOG.md | 27 + plugins/scaffolder/package.json | 2 +- .../CHANGELOG.md | 18 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- plugins/search-backend-module-pg/CHANGELOG.md | 11 + plugins/search-backend-module-pg/package.json | 2 +- .../CHANGELOG.md | 18 + .../package.json | 2 +- plugins/search-backend-node/CHANGELOG.md | 13 + plugins/search-backend-node/package.json | 2 +- plugins/search-backend/CHANGELOG.md | 18 + plugins/search-backend/package.json | 2 +- plugins/search-common/CHANGELOG.md | 8 + plugins/search-common/package.json | 2 +- plugins/search-react/CHANGELOG.md | 19 + plugins/search-react/package.json | 2 +- plugins/search/CHANGELOG.md | 22 + plugins/search/package.json | 2 +- plugins/sentry/CHANGELOG.md | 13 + plugins/sentry/package.json | 2 +- plugins/shortcuts/CHANGELOG.md | 12 + plugins/shortcuts/package.json | 2 +- plugins/sonarqube-backend/CHANGELOG.md | 11 + plugins/sonarqube-backend/package.json | 2 +- plugins/sonarqube-react/CHANGELOG.md | 8 + plugins/sonarqube-react/package.json | 2 +- plugins/sonarqube/CHANGELOG.md | 14 + plugins/sonarqube/package.json | 2 +- plugins/splunk-on-call/CHANGELOG.md | 13 + plugins/splunk-on-call/package.json | 2 +- plugins/stack-overflow-backend/CHANGELOG.md | 9 + plugins/stack-overflow-backend/package.json | 2 +- plugins/stack-overflow/CHANGELOG.md | 15 + plugins/stack-overflow/package.json | 2 +- plugins/stackstorm/CHANGELOG.md | 12 + plugins/stackstorm/package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- plugins/tech-insights-backend/CHANGELOG.md | 16 + plugins/tech-insights-backend/package.json | 2 +- plugins/tech-insights-node/CHANGELOG.md | 11 + plugins/tech-insights-node/package.json | 2 +- plugins/tech-insights/CHANGELOG.md | 17 + plugins/tech-insights/package.json | 2 +- plugins/tech-radar/CHANGELOG.md | 14 + plugins/tech-radar/package.json | 2 +- .../techdocs-addons-test-utils/CHANGELOG.md | 18 + .../techdocs-addons-test-utils/package.json | 2 +- plugins/techdocs-backend/CHANGELOG.md | 27 + plugins/techdocs-backend/package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- plugins/techdocs-node/CHANGELOG.md | 24 + plugins/techdocs-node/package.json | 2 +- plugins/techdocs-react/CHANGELOG.md | 12 + plugins/techdocs-react/package.json | 2 +- plugins/techdocs/CHANGELOG.md | 30 + plugins/techdocs/package.json | 2 +- plugins/todo-backend/CHANGELOG.md | 15 + plugins/todo-backend/package.json | 2 +- plugins/todo/CHANGELOG.md | 14 + plugins/todo/package.json | 2 +- plugins/user-settings-backend/CHANGELOG.md | 12 + plugins/user-settings-backend/package.json | 2 +- plugins/user-settings/CHANGELOG.md | 18 + plugins/user-settings/package.json | 2 +- plugins/vault-backend/CHANGELOG.md | 10 + plugins/vault-backend/package.json | 2 +- plugins/vault/CHANGELOG.md | 14 + plugins/vault/package.json | 2 +- plugins/xcmetrics/CHANGELOG.md | 12 + plugins/xcmetrics/package.json | 2 +- yarn.lock | 412 +- 660 files changed, 7546 insertions(+), 2202 deletions(-) delete mode 100644 .changeset/angry-badgers-beg.md delete mode 100644 .changeset/angry-clocks-exercise.md delete mode 100644 .changeset/big-spies-beam.md delete mode 100644 .changeset/breezy-dryers-thank.md delete mode 100644 .changeset/calm-carpets-kiss.md delete mode 100644 .changeset/calm-scissors-rescue.md delete mode 100644 .changeset/chatty-papayas-care.md delete mode 100644 .changeset/chilled-sloths-rest.md delete mode 100644 .changeset/clean-forks-love.md delete mode 100644 .changeset/cold-bees-jam.md delete mode 100644 .changeset/cold-seas-repeat.md delete mode 100644 .changeset/create-app-1696937840.md delete mode 100644 .changeset/dirty-doors-wave.md delete mode 100644 .changeset/dull-bugs-build.md delete mode 100644 .changeset/dull-dolls-explode.md delete mode 100644 .changeset/dull-experts-kiss.md delete mode 100644 .changeset/dull-laws-camp.md delete mode 100644 .changeset/early-toes-develop.md delete mode 100644 .changeset/eight-melons-cough.md delete mode 100644 .changeset/eight-spiders-fold.md delete mode 100644 .changeset/eight-suns-tan.md delete mode 100644 .changeset/eighty-actors-type.md delete mode 100644 .changeset/eleven-hounds-invent.md delete mode 100644 .changeset/empty-clocks-argue.md delete mode 100644 .changeset/empty-schools-check.md delete mode 100644 .changeset/fair-frogs-enjoy.md delete mode 100644 .changeset/five-hornets-provide.md delete mode 100644 .changeset/five-spiders-listen.md delete mode 100644 .changeset/flat-pandas-tan.md delete mode 100644 .changeset/flat-rules-rush.md delete mode 100644 .changeset/four-jars-protect.md delete mode 100644 .changeset/four-onions-clap.md delete mode 100644 .changeset/four-pans-sin.md delete mode 100644 .changeset/fresh-badgers-study.md delete mode 100644 .changeset/fresh-kangaroos-tap.md delete mode 100644 .changeset/fuzzy-pillows-remain.md delete mode 100644 .changeset/gentle-elephants-fold.md delete mode 100644 .changeset/gentle-spies-deny.md delete mode 100644 .changeset/great-walls-brake.md delete mode 100644 .changeset/happy-books-smoke.md delete mode 100644 .changeset/healthy-laws-divide.md delete mode 100644 .changeset/healthy-shirts-fold.md delete mode 100644 .changeset/heavy-forks-tie.md delete mode 100644 .changeset/heavy-ladybugs-leave.md delete mode 100644 .changeset/heavy-plants-doubt.md delete mode 100644 .changeset/itchy-bobcats-fly.md delete mode 100644 .changeset/itchy-monkeys-reply.md delete mode 100644 .changeset/itchy-rabbits-exist.md delete mode 100644 .changeset/khaki-tools-tease.md delete mode 100644 .changeset/large-balloons-brush.md delete mode 100644 .changeset/large-comics-knock.md delete mode 100644 .changeset/late-papayas-push.md delete mode 100644 .changeset/lazy-doors-wink.md delete mode 100644 .changeset/lemon-cups-wait.md delete mode 100644 .changeset/lemon-masks-greet.md delete mode 100644 .changeset/light-squids-deny.md delete mode 100644 .changeset/little-ligers-cheat.md delete mode 100644 .changeset/long-flies-battle.md delete mode 100644 .changeset/long-owls-complain.md delete mode 100644 .changeset/loud-hotels-hunt.md delete mode 100644 .changeset/lovely-coins-occur.md delete mode 100644 .changeset/lovely-fans-sniff.md delete mode 100644 .changeset/many-impalas-wait.md delete mode 100644 .changeset/many-pianos-bow.md delete mode 100644 .changeset/many-swans-eat.md delete mode 100644 .changeset/mean-dancers-burn.md delete mode 100644 .changeset/metal-peas-beam.md delete mode 100644 .changeset/modern-owls-mate.md delete mode 100644 .changeset/moody-lobsters-rescue.md delete mode 100644 .changeset/nasty-needles-hear.md delete mode 100644 .changeset/nervous-hounds-sleep.md delete mode 100644 .changeset/nice-clocks-smash.md delete mode 100644 .changeset/nice-dancers-explain.md delete mode 100644 .changeset/nice-ghosts-build.md delete mode 100644 .changeset/nine-flies-move.md delete mode 100644 .changeset/nine-garlics-attend.md delete mode 100644 .changeset/odd-pants-sleep.md delete mode 100644 .changeset/olive-cars-rescue.md delete mode 100644 .changeset/olive-geese-rest.md delete mode 100644 .changeset/olive-islands-sneeze.md delete mode 100644 .changeset/orange-cycles-wait.md delete mode 100644 .changeset/perfect-cobras-bake.md delete mode 100644 .changeset/perfect-pumas-protect.md delete mode 100644 .changeset/perfect-shrimps-attend.md delete mode 100644 .changeset/plenty-llamas-double.md delete mode 100644 .changeset/plenty-toys-cheer.md delete mode 100644 .changeset/polite-cooks-perform.md delete mode 100644 .changeset/polite-donuts-fail.md delete mode 100644 .changeset/polite-trainers-grin.md delete mode 100644 .changeset/popular-bikes-do.md delete mode 100644 .changeset/popular-dots-design.md delete mode 100644 .changeset/pre.json delete mode 100644 .changeset/pretty-apes-sneeze.md delete mode 100644 .changeset/pretty-steaks-serve.md delete mode 100644 .changeset/pretty-swans-worry.md delete mode 100644 .changeset/purple-chefs-wait.md delete mode 100644 .changeset/purple-forks-fetch.md delete mode 100644 .changeset/quick-weeks-explode.md delete mode 100644 .changeset/rare-glasses-play.md delete mode 100644 .changeset/rare-pants-reply.md delete mode 100644 .changeset/red-baboons-warn.md delete mode 100644 .changeset/red-bees-try.md delete mode 100644 .changeset/red-geese-clean.md delete mode 100644 .changeset/renovate-0a0b7ba.md delete mode 100644 .changeset/renovate-2633beb.md delete mode 100644 .changeset/renovate-37d5549.md delete mode 100644 .changeset/renovate-7d08f6a.md delete mode 100644 .changeset/renovate-a1c52e8.md delete mode 100644 .changeset/renovate-a6a783f.md delete mode 100644 .changeset/renovate-c204e0d.md delete mode 100644 .changeset/rotten-rings-confess.md delete mode 100644 .changeset/serious-pants-lie.md delete mode 100644 .changeset/serious-penguins-tease.md delete mode 100644 .changeset/serious-ravens-serve.md delete mode 100644 .changeset/shaggy-beers-collect.md delete mode 100644 .changeset/shiny-birds-melt.md delete mode 100644 .changeset/short-ears-rescue.md delete mode 100644 .changeset/short-terms-check.md delete mode 100644 .changeset/shy-clouds-reflect.md delete mode 100644 .changeset/shy-seas-sip.md delete mode 100644 .changeset/silent-years-bake.md delete mode 100644 .changeset/silent-years-marry.md delete mode 100644 .changeset/silly-chefs-allow.md delete mode 100644 .changeset/silly-swans-invent.md delete mode 100644 .changeset/six-weeks-raise.md delete mode 100644 .changeset/slow-cameras-grab.md delete mode 100644 .changeset/slow-dodos-remember.md delete mode 100644 .changeset/small-avocados-live.md delete mode 100644 .changeset/small-books-deliver.md delete mode 100644 .changeset/small-pugs-build.md delete mode 100644 .changeset/smooth-rings-mate.md delete mode 100644 .changeset/spicy-chairs-film.md delete mode 100644 .changeset/spicy-poets-sell.md delete mode 100644 .changeset/spotty-badgers-wash.md delete mode 100644 .changeset/stale-eagles-reply.md delete mode 100644 .changeset/stale-stingrays-explode.md delete mode 100644 .changeset/strange-dodos-film.md delete mode 100644 .changeset/strong-falcons-tickle.md delete mode 100644 .changeset/stupid-drinks-trade.md delete mode 100644 .changeset/stupid-eagles-shave.md delete mode 100644 .changeset/sweet-buckets-fry.md delete mode 100644 .changeset/swift-kings-add.md delete mode 100644 .changeset/swift-steaks-fetch.md delete mode 100644 .changeset/tall-dragons-jump.md delete mode 100644 .changeset/tame-trainers-visit.md delete mode 100644 .changeset/tasty-avocados-hope.md delete mode 100644 .changeset/tasty-doors-switch.md delete mode 100644 .changeset/ten-seals-wait.md delete mode 100644 .changeset/tender-experts-yell.md delete mode 100644 .changeset/tender-pears-work.md delete mode 100644 .changeset/thick-dolphins-boil.md delete mode 100644 .changeset/thirty-coins-sneeze.md delete mode 100644 .changeset/tiny-garlics-cheer.md delete mode 100644 .changeset/tiny-suns-deny.md delete mode 100644 .changeset/twelve-clouds-design.md delete mode 100644 .changeset/twelve-days-walk.md delete mode 100644 .changeset/twelve-mirrors-brush.md delete mode 100644 .changeset/twelve-snakes-sell.md delete mode 100644 .changeset/twenty-bags-sin.md delete mode 100644 .changeset/twenty-carrots-smile.md delete mode 100644 .changeset/twenty-masks-exist.md delete mode 100644 .changeset/two-dingos-dream.md delete mode 100644 .changeset/two-terms-play.md delete mode 100644 .changeset/unlucky-experts-breathe.md delete mode 100644 .changeset/violet-apes-beam.md delete mode 100644 .changeset/violet-beers-cross.md delete mode 100644 .changeset/warm-drinks-argue.md delete mode 100644 .changeset/wet-cows-brake.md delete mode 100644 .changeset/wet-olives-wave.md delete mode 100644 .changeset/wet-timers-chew.md delete mode 100644 .changeset/wicked-rings-flash.md delete mode 100644 .changeset/wild-geese-occur.md delete mode 100644 .changeset/wild-jobs-greet.md delete mode 100644 .changeset/wild-queens-grab.md delete mode 100644 .changeset/wild-toys-arrive.md delete mode 100644 .changeset/yellow-numbers-own.md delete mode 100644 .changeset/yellow-rings-invent.md delete mode 100644 .changeset/young-ducks-heal.md delete mode 100644 .changeset/young-toes-knock.md create mode 100644 docs/releases/v1.19.0-changelog.md create mode 100644 plugins/auth-backend-module-pinniped-provider/CHANGELOG.md diff --git a/.changeset/angry-badgers-beg.md b/.changeset/angry-badgers-beg.md deleted file mode 100644 index 38952aef98..0000000000 --- a/.changeset/angry-badgers-beg.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Internal update for removal of experimental plugin configuration API. diff --git a/.changeset/angry-clocks-exercise.md b/.changeset/angry-clocks-exercise.md deleted file mode 100644 index e7eb6ae1d9..0000000000 --- a/.changeset/angry-clocks-exercise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-nomad-backend': patch ---- - -Added support for the [new backend system](https://backstage.io/docs/backend-system/) diff --git a/.changeset/big-spies-beam.md b/.changeset/big-spies-beam.md deleted file mode 100644 index e5f0ad3eff..0000000000 --- a/.changeset/big-spies-beam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Removed duplicate `apple-touch-icon` link from `packages/app/public/index.html` that linked to nonexistent icon. diff --git a/.changeset/breezy-dryers-thank.md b/.changeset/breezy-dryers-thank.md deleted file mode 100644 index 7a742db1bf..0000000000 --- a/.changeset/breezy-dryers-thank.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/backend-tasks': patch ---- - -Instrument `backend-tasks` with some counters and histograms for duration. - -`backend_tasks.task.runs.count`: Counter with the total number of times a task has been run. -`backend_tasks.task.runs.duration`: Histogram with the run durations for each task. - -Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping. diff --git a/.changeset/calm-carpets-kiss.md b/.changeset/calm-carpets-kiss.md deleted file mode 100644 index b946e4d9c6..0000000000 --- a/.changeset/calm-carpets-kiss.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. diff --git a/.changeset/calm-scissors-rescue.md b/.changeset/calm-scissors-rescue.md deleted file mode 100644 index 4a5318d240..0000000000 --- a/.changeset/calm-scissors-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Create unique temp directory for each `create-app` execution. diff --git a/.changeset/chatty-papayas-care.md b/.changeset/chatty-papayas-care.md deleted file mode 100644 index 9f29e94a85..0000000000 --- a/.changeset/chatty-papayas-care.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-pagerduty': patch ---- - -Minor fix to avoid usage of deprecated prop diff --git a/.changeset/chilled-sloths-rest.md b/.changeset/chilled-sloths-rest.md deleted file mode 100644 index 1cad0be99f..0000000000 --- a/.changeset/chilled-sloths-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Filters for discovered packages are now also applied at runtime. This makes it possible to disable packages through the `app.experimental.packages` config at runtime. diff --git a/.changeset/clean-forks-love.md b/.changeset/clean-forks-love.md deleted file mode 100644 index f81fe3066b..0000000000 --- a/.changeset/clean-forks-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-sonarqube-backend': patch ---- - -Added support for the [new backend system](https://backstage.io/docs/backend-system/) diff --git a/.changeset/cold-bees-jam.md b/.changeset/cold-bees-jam.md deleted file mode 100644 index 3c6e652d2b..0000000000 --- a/.changeset/cold-bees-jam.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Fixed the display of OwnershipCard with aggregated relations by loading relations when getting children of entity. -This allows the already existing recursive method to work properly when children of entity have children themselves. diff --git a/.changeset/cold-seas-repeat.md b/.changeset/cold-seas-repeat.md deleted file mode 100644 index 0072c4327d..0000000000 --- a/.changeset/cold-seas-repeat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-code-coverage': patch ---- - -Fixed the coverage history statistics to compare newest with oldest record diff --git a/.changeset/create-app-1696937840.md b/.changeset/create-app-1696937840.md deleted file mode 100644 index b50d431d4b..0000000000 --- a/.changeset/create-app-1696937840.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Bumped create-app version. diff --git a/.changeset/dirty-doors-wave.md b/.changeset/dirty-doors-wave.md deleted file mode 100644 index aad6e8f414..0000000000 --- a/.changeset/dirty-doors-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Add examples for `github:issues:label` scaffolder action & improve related tests diff --git a/.changeset/dull-bugs-build.md b/.changeset/dull-bugs-build.md deleted file mode 100644 index 7acfe2a8a2..0000000000 --- a/.changeset/dull-bugs-build.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-search-backend-module-elasticsearch': patch -'@backstage/integration': patch ---- - -Ensure that all relevant config fields are properly marked as secret diff --git a/.changeset/dull-dolls-explode.md b/.changeset/dull-dolls-explode.md deleted file mode 100644 index 10088e0818..0000000000 --- a/.changeset/dull-dolls-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-playlist-backend': patch ---- - -Added support to the playlist plugin for the new backend diff --git a/.changeset/dull-experts-kiss.md b/.changeset/dull-experts-kiss.md deleted file mode 100644 index eaea346e49..0000000000 --- a/.changeset/dull-experts-kiss.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-react': patch ---- - -Fixed an issue causing `EntityPage` to show an error for entities containing special characters diff --git a/.changeset/dull-laws-camp.md b/.changeset/dull-laws-camp.md deleted file mode 100644 index 9a9c7436c5..0000000000 --- a/.changeset/dull-laws-camp.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Change base node image from node:18-bullseye-slim to node:18-bookworm-slim due to Docker build error on bullseye. - -You can apply these change to your own `Dockerfile` by replacing `node:18-bullseye-slim` with `node:18-bookworm-slim` diff --git a/.changeset/early-toes-develop.md b/.changeset/early-toes-develop.md deleted file mode 100644 index 3262ff0b98..0000000000 --- a/.changeset/early-toes-develop.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': minor -'@backstage/plugin-techdocs-node': minor ---- - -Allow prepared directory clean up for custom preparers - -When using custom preparer for TechDocs, the `preparedDir` might -end up taking disk space. This requires all custom preparers to -implement a new method `shouldCleanPreparedDirectory` which indicates -whether the prepared directory should be cleaned after generation. diff --git a/.changeset/eight-melons-cough.md b/.changeset/eight-melons-cough.md deleted file mode 100644 index 23d7b901f1..0000000000 --- a/.changeset/eight-melons-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Create an experimental `CatalogSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. diff --git a/.changeset/eight-spiders-fold.md b/.changeset/eight-spiders-fold.md deleted file mode 100644 index e4d35cd11d..0000000000 --- a/.changeset/eight-spiders-fold.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/cli': minor ---- - -Update typescript-eslint to 6.7.x, adding compatibility with TypeScript 5.2. - -This includes a major update on typescript-eslint, you can see the details in the [release notes](https://typescript-eslint.io/blog/announcing-typescript-eslint-v6/). diff --git a/.changeset/eight-suns-tan.md b/.changeset/eight-suns-tan.md deleted file mode 100644 index 4b8634a9e1..0000000000 --- a/.changeset/eight-suns-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': minor ---- - -Extension attachment point is now configured via `attachTo: { id, input }` instead of `at: 'id/input'`. diff --git a/.changeset/eighty-actors-type.md b/.changeset/eighty-actors-type.md deleted file mode 100644 index 5c55a7b0c6..0000000000 --- a/.changeset/eighty-actors-type.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/test-utils': patch ---- - -Removed the alpha `MockPluginProvider` export since the plugin configuration API has been removed. diff --git a/.changeset/eleven-hounds-invent.md b/.changeset/eleven-hounds-invent.md deleted file mode 100644 index ba863ebc28..0000000000 --- a/.changeset/eleven-hounds-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -In frontend builds and tests `process.env.HAS_REACT_DOM_CLIENT` will now be defined if `react-dom/client` is present, i.e. if using React 18. This allows for conditional imports of `react-dom/client`. diff --git a/.changeset/empty-clocks-argue.md b/.changeset/empty-clocks-argue.md deleted file mode 100644 index e3c5985f8a..0000000000 --- a/.changeset/empty-clocks-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Fixed bug in `AppRouter` to determine the correct `signOutTargetUrl` if `app.baseUrl` contains a `basePath` diff --git a/.changeset/empty-schools-check.md b/.changeset/empty-schools-check.md deleted file mode 100644 index c69bbaabb3..0000000000 --- a/.changeset/empty-schools-check.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/frontend-plugin-api': minor -'@backstage/frontend-app-api': minor ---- - -Removed support for the new `useRouteRef`. diff --git a/.changeset/fair-frogs-enjoy.md b/.changeset/fair-frogs-enjoy.md deleted file mode 100644 index 12eb57489e..0000000000 --- a/.changeset/fair-frogs-enjoy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Create an experimental `TechDocsSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. diff --git a/.changeset/five-hornets-provide.md b/.changeset/five-hornets-provide.md deleted file mode 100644 index a422c5fbc8..0000000000 --- a/.changeset/five-hornets-provide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -The app will now reject any extensions that attach to nonexistent inputs. diff --git a/.changeset/five-spiders-listen.md b/.changeset/five-spiders-listen.md deleted file mode 100644 index a7968964e2..0000000000 --- a/.changeset/five-spiders-listen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -Fixed bug in oidc refresh handler, if token endpoints response on refresh request does not contain a scope, the requested scope is used. diff --git a/.changeset/flat-pandas-tan.md b/.changeset/flat-pandas-tan.md deleted file mode 100644 index dfe7965bec..0000000000 --- a/.changeset/flat-pandas-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Added `createMockDirectory()` to help out with file system mocking in tests. diff --git a/.changeset/flat-rules-rush.md b/.changeset/flat-rules-rush.md deleted file mode 100644 index a95772bb6f..0000000000 --- a/.changeset/flat-rules-rush.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-gitlab': patch ---- - -fix: use REST API to get root group memberships for GitLab SaaS users listing - -This API is the only one that shows `email` field for enterprise users and -allows to filter out bot users not using a license using the `is_using_seat` -field. - -We also added the annotation `gitlab.com/saml-external-uid` taking the value -of `group_saml_identity.extern_uid` of the `groups/:group-id/members` endpoint -response. This is useful in case you want to create a `SignInResolver` that -references the user with the id of your identity provider (e.g. OneLogin). - -ref: - -https://docs.gitlab.com/ee/user/enterprise_user/#get-users-email-addresses-through-the-api -https://docs.gitlab.com/ee/api/members.html#limitations diff --git a/.changeset/four-jars-protect.md b/.changeset/four-jars-protect.md deleted file mode 100644 index 8469839856..0000000000 --- a/.changeset/four-jars-protect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-rollbar-backend': patch ---- - -ensure rollbar token is hidden diff --git a/.changeset/four-onions-clap.md b/.changeset/four-onions-clap.md deleted file mode 100644 index 44d0cf9ae7..0000000000 --- a/.changeset/four-onions-clap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fix for the new backend `start` command to make it work on Windows. diff --git a/.changeset/four-pans-sin.md b/.changeset/four-pans-sin.md deleted file mode 100644 index 46d31c242c..0000000000 --- a/.changeset/four-pans-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Marked the `LocationEntityProcessor` as deprecated, as it is no longer used internally since way back and can even be harmful at this point. diff --git a/.changeset/fresh-badgers-study.md b/.changeset/fresh-badgers-study.md deleted file mode 100644 index 4c9e7ee627..0000000000 --- a/.changeset/fresh-badgers-study.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Wrap entire app in ``, enabling support for using translations outside plugins. diff --git a/.changeset/fresh-kangaroos-tap.md b/.changeset/fresh-kangaroos-tap.md deleted file mode 100644 index 5ac4d184eb..0000000000 --- a/.changeset/fresh-kangaroos-tap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-plugin-api': minor ---- - -Removed the exprimental plugin configuration API. The `__experimentalReconfigure()` from the plugin options as well as the `__experimentalConfigure()` method on plugin instances have both been removed. diff --git a/.changeset/fuzzy-pillows-remain.md b/.changeset/fuzzy-pillows-remain.md deleted file mode 100644 index 59e3dd7896..0000000000 --- a/.changeset/fuzzy-pillows-remain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Improved `DocsTable` to display pagination controls dynamically, appearing only when needed. diff --git a/.changeset/gentle-elephants-fold.md b/.changeset/gentle-elephants-fold.md deleted file mode 100644 index 480ee41e7a..0000000000 --- a/.changeset/gentle-elephants-fold.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@backstage/plugin-catalog': minor ---- - -The catalog plugin no longer implements the experimental reconfiguration API. The create button title can now instead be configured using the new experimental internationalization API, via the `catalogTranslationRef` exported at `/alpha`. For example: - -```ts -import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'; - -const app = createApp({ - __experimentalTranslations: { - resources: [ - createTranslationMessages({ - ref: catalogTranslationRef, - catalog_page_create_button_title: 'Create Software', - }), - ], - }, -}); -``` diff --git a/.changeset/gentle-spies-deny.md b/.changeset/gentle-spies-deny.md deleted file mode 100644 index f2d0ea7d79..0000000000 --- a/.changeset/gentle-spies-deny.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-bitbucket-server': patch -'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch -'@backstage/plugin-catalog-backend-module-puppetdb': patch -'@backstage/plugin-catalog-backend-module-msgraph': patch -'@backstage/plugin-catalog-backend-module-gerrit': patch -'@backstage/plugin-catalog-backend-module-github': patch -'@backstage/plugin-catalog-backend-module-gitlab': patch -'@backstage/plugin-catalog-backend-module-azure': patch -'@backstage/plugin-catalog-backend-module-ldap': patch -'@backstage/plugin-catalog-backend-module-aws': patch ---- - -Make sure to include the error message when ingestion fails diff --git a/.changeset/great-walls-brake.md b/.changeset/great-walls-brake.md deleted file mode 100644 index dd71c81a07..0000000000 --- a/.changeset/great-walls-brake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. diff --git a/.changeset/happy-books-smoke.md b/.changeset/happy-books-smoke.md deleted file mode 100644 index 68ea19ea5e..0000000000 --- a/.changeset/happy-books-smoke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-home': patch ---- - -Adds Top/Recently Visited components to homepage diff --git a/.changeset/healthy-laws-divide.md b/.changeset/healthy-laws-divide.md deleted file mode 100644 index 4ab29e6426..0000000000 --- a/.changeset/healthy-laws-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Implement `toString()` and `toJSON()` for extension instances. diff --git a/.changeset/healthy-shirts-fold.md b/.changeset/healthy-shirts-fold.md deleted file mode 100644 index f2ac0a9e83..0000000000 --- a/.changeset/healthy-shirts-fold.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-catalog': patch -'@backstage/plugin-techdocs': patch ---- - -The `spec.lifecycle' field in entities will now always be rendered as a string. diff --git a/.changeset/heavy-forks-tie.md b/.changeset/heavy-forks-tie.md deleted file mode 100644 index f5af5975b7..0000000000 --- a/.changeset/heavy-forks-tie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-node': patch ---- - -Added docs to `processingResult` diff --git a/.changeset/heavy-ladybugs-leave.md b/.changeset/heavy-ladybugs-leave.md deleted file mode 100644 index 5af2324260..0000000000 --- a/.changeset/heavy-ladybugs-leave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-newrelic': patch ---- - -Fixed sorting and searching in the NewRelic table. diff --git a/.changeset/heavy-plants-doubt.md b/.changeset/heavy-plants-doubt.md deleted file mode 100644 index 3988a16752..0000000000 --- a/.changeset/heavy-plants-doubt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-user-settings': patch ---- - -Added experimental support for declarative integration via the `/alpha` subpath. diff --git a/.changeset/itchy-bobcats-fly.md b/.changeset/itchy-bobcats-fly.md deleted file mode 100644 index e91d944478..0000000000 --- a/.changeset/itchy-bobcats-fly.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository diff --git a/.changeset/itchy-monkeys-reply.md b/.changeset/itchy-monkeys-reply.md deleted file mode 100644 index 3773fe3ff8..0000000000 --- a/.changeset/itchy-monkeys-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-dev-utils': patch ---- - -Fix an issue where early IPC responses would be lost. diff --git a/.changeset/itchy-rabbits-exist.md b/.changeset/itchy-rabbits-exist.md deleted file mode 100644 index 6a16ac5648..0000000000 --- a/.changeset/itchy-rabbits-exist.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/cli': minor ---- - -**BREAKING** The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior set `LEGACY_BACKEND_START`, which is recommended if you haven't migrated to the new backend system. - -This new command is no longer based on Webpack, but instead uses Node.js loaders to transpile on the fly. Rather than hot reloading modules the entire backend is now restarted on change, but the SQLite database state is still maintained across restarts via a parent process. diff --git a/.changeset/khaki-tools-tease.md b/.changeset/khaki-tools-tease.md deleted file mode 100644 index e4383c9e33..0000000000 --- a/.changeset/khaki-tools-tease.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': minor ---- - -Updated `publish:gitlab` action properties to support additional Gitlab project settings: - -- general project settings provided by gitlab project create API (new `settings` property) -- branch level settings to create additional branches and make them protected (new `branches` property) -- project level environment variables settings (new `projectVariables` property) - -Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. diff --git a/.changeset/large-balloons-brush.md b/.changeset/large-balloons-brush.md deleted file mode 100644 index 0dcada12bf..0000000000 --- a/.changeset/large-balloons-brush.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-node': minor ---- - -**BREAKING**: The recently introduced `ProxyAuthenticator.initialize()` method is no longer `async` to match the way the OAuth equivalent is implemented. diff --git a/.changeset/large-comics-knock.md b/.changeset/large-comics-knock.md deleted file mode 100644 index 860172579e..0000000000 --- a/.changeset/large-comics-knock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -fixed issue related template editor fails with multiple templates per file. diff --git a/.changeset/late-papayas-push.md b/.changeset/late-papayas-push.md deleted file mode 100644 index 07422e1b1b..0000000000 --- a/.changeset/late-papayas-push.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Add support for `SidebarGroup` on the sidebar item extension. diff --git a/.changeset/lazy-doors-wink.md b/.changeset/lazy-doors-wink.md deleted file mode 100644 index aafbb3500e..0000000000 --- a/.changeset/lazy-doors-wink.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': minor ---- - -Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. diff --git a/.changeset/lemon-cups-wait.md b/.changeset/lemon-cups-wait.md deleted file mode 100644 index 4dd08c21b0..0000000000 --- a/.changeset/lemon-cups-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': minor ---- - -include owner chip in catalog search result item diff --git a/.changeset/lemon-masks-greet.md b/.changeset/lemon-masks-greet.md deleted file mode 100644 index 79c7b7e92b..0000000000 --- a/.changeset/lemon-masks-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -The `TabbedLayout` component will now also navigate when clicking the active tab, which allows for navigation back from any sub routes. diff --git a/.changeset/light-squids-deny.md b/.changeset/light-squids-deny.md deleted file mode 100644 index 07a124bed3..0000000000 --- a/.changeset/light-squids-deny.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-catalog-graphql': minor -'@backstage/plugin-graphql-backend': minor ---- - -This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. diff --git a/.changeset/little-ligers-cheat.md b/.changeset/little-ligers-cheat.md deleted file mode 100644 index 30b4238c59..0000000000 --- a/.changeset/little-ligers-cheat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Make entity picker more reliable with only one available entity diff --git a/.changeset/long-flies-battle.md b/.changeset/long-flies-battle.md deleted file mode 100644 index d143658004..0000000000 --- a/.changeset/long-flies-battle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-entity-feedback': patch ---- - -Added tooltip to like dislike buttons diff --git a/.changeset/long-owls-complain.md b/.changeset/long-owls-complain.md deleted file mode 100644 index f96b0f0987..0000000000 --- a/.changeset/long-owls-complain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Fixed an issue preventing the routing system to match subroutes diff --git a/.changeset/loud-hotels-hunt.md b/.changeset/loud-hotels-hunt.md deleted file mode 100644 index b977d2c1d9..0000000000 --- a/.changeset/loud-hotels-hunt.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch -'@backstage/plugin-catalog-backend-module-github': patch -'@backstage/plugin-catalog-backend-module-gitlab': patch -'@backstage/plugin-analytics-module-ga': patch -'@backstage/integration-react': patch -'@backstage/core-components': patch -'@backstage/core-plugin-api': patch -'@backstage/backend-common': patch -'@backstage/plugin-catalog-backend': patch -'@backstage/plugin-cicd-statistics': patch -'@backstage/catalog-model': patch -'@backstage/config-loader': patch -'@backstage/plugin-catalog-react': patch -'@backstage/integration': patch -'@backstage/plugin-tech-radar': patch -'@backstage/errors': patch -'@backstage/plugin-catalog': patch -'@backstage/plugin-ilert': patch ---- - -Removed some unused dependencies diff --git a/.changeset/lovely-coins-occur.md b/.changeset/lovely-coins-occur.md deleted file mode 100644 index 34a6774388..0000000000 --- a/.changeset/lovely-coins-occur.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Fixes a bug where eagerly deleted entities did not properly trigger re-stitching of entities that they had relations to. diff --git a/.changeset/lovely-fans-sniff.md b/.changeset/lovely-fans-sniff.md deleted file mode 100644 index af8aebb89b..0000000000 --- a/.changeset/lovely-fans-sniff.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-radar': patch ---- - -Added experimental support for the declarative integration. diff --git a/.changeset/many-impalas-wait.md b/.changeset/many-impalas-wait.md deleted file mode 100644 index 843adf66a1..0000000000 --- a/.changeset/many-impalas-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Plugins can now be assigned `routes` and `externalRoutes` when created. diff --git a/.changeset/many-pianos-bow.md b/.changeset/many-pianos-bow.md deleted file mode 100644 index 6c4e3be47f..0000000000 --- a/.changeset/many-pianos-bow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-adr': patch ---- - -Fix icon alignment in `AdrSearchResultListItem` diff --git a/.changeset/many-swans-eat.md b/.changeset/many-swans-eat.md deleted file mode 100644 index 86580d7cfe..0000000000 --- a/.changeset/many-swans-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-badges-backend': patch ---- - -Make sure the default badge factory is used if nothing is defined diff --git a/.changeset/mean-dancers-burn.md b/.changeset/mean-dancers-burn.md deleted file mode 100644 index a51ca7b8de..0000000000 --- a/.changeset/mean-dancers-burn.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/core-app-api': patch -'@backstage/app-defaults': patch -'@backstage/test-utils': patch ---- - -Add missing resource and template app icons diff --git a/.changeset/metal-peas-beam.md b/.changeset/metal-peas-beam.md deleted file mode 100644 index a4ebdeb69a..0000000000 --- a/.changeset/metal-peas-beam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Display log visibility button on the template panel diff --git a/.changeset/modern-owls-mate.md b/.changeset/modern-owls-mate.md deleted file mode 100644 index bed33c6bbc..0000000000 --- a/.changeset/modern-owls-mate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': minor ---- - -Added experimental support for declarative integration via the `/alpha` subpath. diff --git a/.changeset/moody-lobsters-rescue.md b/.changeset/moody-lobsters-rescue.md deleted file mode 100644 index c739e995c5..0000000000 --- a/.changeset/moody-lobsters-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Bump `cypress` to fix the end-to-end tests diff --git a/.changeset/nasty-needles-hear.md b/.changeset/nasty-needles-hear.md deleted file mode 100644 index 32a9d0dfb7..0000000000 --- a/.changeset/nasty-needles-hear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. diff --git a/.changeset/nervous-hounds-sleep.md b/.changeset/nervous-hounds-sleep.md deleted file mode 100644 index 530ff348f7..0000000000 --- a/.changeset/nervous-hounds-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Make themes configurable through extensions, and switched default themes to use extensions instead. diff --git a/.changeset/nice-clocks-smash.md b/.changeset/nice-clocks-smash.md deleted file mode 100644 index 8a289370e5..0000000000 --- a/.changeset/nice-clocks-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-insights-backend': patch ---- - -Increase the maximum allowed length of an entity filter for tech insights fact schemas. diff --git a/.changeset/nice-dancers-explain.md b/.changeset/nice-dancers-explain.md deleted file mode 100644 index 5e54a66c05..0000000000 --- a/.changeset/nice-dancers-explain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend-module-github-provider': patch ---- - -Fixed a bug where the GitHub authenticator did not properly persist granted OAuth scopes. diff --git a/.changeset/nice-ghosts-build.md b/.changeset/nice-ghosts-build.md deleted file mode 100644 index abdad08c3b..0000000000 --- a/.changeset/nice-ghosts-build.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-kubernetes-node': minor -'@backstage/plugin-kubernetes-backend': patch ---- - -A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. diff --git a/.changeset/nine-flies-move.md b/.changeset/nine-flies-move.md deleted file mode 100644 index 0e7bca2836..0000000000 --- a/.changeset/nine-flies-move.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@techdocs/cli': minor -'@backstage/plugin-techdocs-node': minor ---- - -Add possibility to use a mkdocs config file with a different name than `mkdocs. with the serve command using the `--mkdocs-config-file-name` argument diff --git a/.changeset/nine-garlics-attend.md b/.changeset/nine-garlics-attend.md deleted file mode 100644 index a9cdac4a32..0000000000 --- a/.changeset/nine-garlics-attend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-tasks': patch ---- - -Fix bug where backend tasks that are defined with HumanDuration are immediately triggered on application startup diff --git a/.changeset/odd-pants-sleep.md b/.changeset/odd-pants-sleep.md deleted file mode 100644 index ad0b95d973..0000000000 --- a/.changeset/odd-pants-sleep.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-codescene': patch -'@backstage/plugin-graphiql': patch -'@backstage/plugin-ilert': patch ---- - -Internal refactor to avoid using the deprecated `.icon.svg` extension. diff --git a/.changeset/olive-cars-rescue.md b/.changeset/olive-cars-rescue.md deleted file mode 100644 index fd6c8fe331..0000000000 --- a/.changeset/olive-cars-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Create an experimental search plugin that is compatible with the declarative integration system, it is exported from `/alpha` subpath. diff --git a/.changeset/olive-geese-rest.md b/.changeset/olive-geese-rest.md deleted file mode 100644 index 547fb828d8..0000000000 --- a/.changeset/olive-geese-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-jenkins-backend': patch ---- - -Added support for the [new backend system](https://backstage.io/docs/backend-system/) diff --git a/.changeset/olive-islands-sneeze.md b/.changeset/olive-islands-sneeze.md deleted file mode 100644 index b44f071acc..0000000000 --- a/.changeset/olive-islands-sneeze.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-github': patch -'@backstage/cli': patch ---- - -Request slightly smaller pages of data from GitHub diff --git a/.changeset/orange-cycles-wait.md b/.changeset/orange-cycles-wait.md deleted file mode 100644 index 5e71b69e80..0000000000 --- a/.changeset/orange-cycles-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Added the `bindRoutes` option to `createApp`. diff --git a/.changeset/perfect-cobras-bake.md b/.changeset/perfect-cobras-bake.md deleted file mode 100644 index bf66c12e83..0000000000 --- a/.changeset/perfect-cobras-bake.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-jenkins-backend': minor -'@backstage/plugin-jenkins': minor ---- - -Added JobRunTable Component. -Added new Route and extended Api to get buildJobs. -Actions column has a new icon button, clicking on which takes us to page where we -can see all the job runs. diff --git a/.changeset/perfect-pumas-protect.md b/.changeset/perfect-pumas-protect.md deleted file mode 100644 index 7d6bf8d6d7..0000000000 --- a/.changeset/perfect-pumas-protect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-code-coverage-backend': patch ---- - -Added option to set body size limit diff --git a/.changeset/perfect-shrimps-attend.md b/.changeset/perfect-shrimps-attend.md deleted file mode 100644 index b530d0e2a2..0000000000 --- a/.changeset/perfect-shrimps-attend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Fixed overflowing messages in `WarningPanel`. diff --git a/.changeset/plenty-llamas-double.md b/.changeset/plenty-llamas-double.md deleted file mode 100644 index b2691a2f17..0000000000 --- a/.changeset/plenty-llamas-double.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-node': patch ---- - -Fix for persisted scopes not being properly restored on sign-in. diff --git a/.changeset/plenty-toys-cheer.md b/.changeset/plenty-toys-cheer.md deleted file mode 100644 index 3c16002632..0000000000 --- a/.changeset/plenty-toys-cheer.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-search-react': patch -'@backstage/plugin-graphiql': patch ---- - -Updated `/alpha` exports to use new `attachTo` option. diff --git a/.changeset/polite-cooks-perform.md b/.changeset/polite-cooks-perform.md deleted file mode 100644 index 40766c84a3..0000000000 --- a/.changeset/polite-cooks-perform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': minor ---- - -The `createApp` config option has been replaced by a new `configLoader` option. There is now also a `pluginLoader` option that can be used to dynamically load plugins into the app. diff --git a/.changeset/polite-donuts-fail.md b/.changeset/polite-donuts-fail.md deleted file mode 100644 index 9c03faaf44..0000000000 --- a/.changeset/polite-donuts-fail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Internal refactors, laying the foundation for later introducing deferred stitching (see #18062). diff --git a/.changeset/polite-trainers-grin.md b/.changeset/polite-trainers-grin.md deleted file mode 100644 index 878596702d..0000000000 --- a/.changeset/polite-trainers-grin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-github': patch ---- - -Make `defaultUserTransformer` resolve to `UserEntity` instead of `Entity` diff --git a/.changeset/popular-bikes-do.md b/.changeset/popular-bikes-do.md deleted file mode 100644 index b1cc5c2cdd..0000000000 --- a/.changeset/popular-bikes-do.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-code-coverage': patch ---- - -The warning for missing code coverage will now render the entity as a reference. diff --git a/.changeset/popular-dots-design.md b/.changeset/popular-dots-design.md deleted file mode 100644 index c333ce0105..0000000000 --- a/.changeset/popular-dots-design.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Changed SupportButton menuitems to support text wrap diff --git a/.changeset/pre.json b/.changeset/pre.json deleted file mode 100644 index 85d6e9d017..0000000000 --- a/.changeset/pre.json +++ /dev/null @@ -1,390 +0,0 @@ -{ - "mode": "exit", - "tag": "next", - "initialVersions": { - "example-app": "0.2.87", - "@backstage/app-defaults": "1.4.3", - "example-app-next": "0.0.1", - "app-next-example-plugin": "0.0.1", - "example-backend": "0.2.87", - "@backstage/backend-app-api": "0.5.3", - "@backstage/backend-common": "0.19.5", - "@backstage/backend-defaults": "0.2.3", - "@backstage/backend-dev-utils": "0.1.1", - "example-backend-next": "0.0.15", - "@backstage/backend-openapi-utils": "0.0.4", - "@backstage/backend-plugin-api": "0.6.3", - "@backstage/backend-plugin-manager": "0.0.1", - "@backstage/backend-tasks": "0.5.8", - "@backstage/backend-test-utils": "0.2.3", - "@backstage/catalog-client": "1.4.4", - "@backstage/catalog-model": "1.4.2", - "@backstage/cli": "0.22.13", - "@backstage/cli-common": "0.1.12", - "@backstage/cli-node": "0.1.4", - "@backstage/codemods": "0.1.45", - "@backstage/config": "1.1.0", - "@backstage/config-loader": "1.5.0", - "@backstage/core-app-api": "1.10.0", - "@backstage/core-components": "0.13.5", - "@backstage/core-plugin-api": "1.6.0", - "@backstage/create-app": "0.5.5", - "@backstage/dev-utils": "1.0.21", - "e2e-test": "0.2.7", - "@backstage/errors": "1.2.2", - "@backstage/eslint-plugin": "0.1.3", - "@backstage/frontend-app-api": "0.1.0", - "@backstage/frontend-plugin-api": "0.1.0", - "@backstage/integration": "1.7.0", - "@backstage/integration-aws-node": "0.1.6", - "@backstage/integration-react": "1.1.19", - "@backstage/release-manifests": "0.0.10", - "@backstage/repo-tools": "0.3.4", - "@techdocs/cli": "1.5.0", - "techdocs-cli-embedded-app": "0.2.86", - "@backstage/test-utils": "1.4.3", - "@backstage/theme": "0.4.2", - "@backstage/types": "1.1.1", - "@backstage/version-bridge": "1.0.5", - "@backstage/plugin-adr": "0.6.7", - "@backstage/plugin-adr-backend": "0.4.0", - "@backstage/plugin-adr-common": "0.2.15", - "@backstage/plugin-airbrake": "0.3.24", - "@backstage/plugin-airbrake-backend": "0.3.0", - "@backstage/plugin-allure": "0.1.40", - "@backstage/plugin-analytics-module-ga": "0.1.33", - "@backstage/plugin-analytics-module-ga4": "0.1.4", - "@backstage/plugin-analytics-module-newrelic-browser": "0.0.2", - "@backstage/plugin-apache-airflow": "0.2.15", - "@backstage/plugin-api-docs": "0.9.11", - "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.3", - "@backstage/plugin-apollo-explorer": "0.1.15", - "@backstage/plugin-app-backend": "0.3.51", - "@backstage/plugin-app-node": "0.1.3", - "@backstage/plugin-auth-backend": "0.19.0", - "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.1.0", - "@backstage/plugin-auth-backend-module-github-provider": "0.1.0", - "@backstage/plugin-auth-backend-module-gitlab-provider": "0.1.0", - "@backstage/plugin-auth-backend-module-google-provider": "0.1.0", - "@backstage/plugin-auth-backend-module-oauth2-provider": "0.1.0", - "@backstage/plugin-auth-node": "0.3.0", - "@backstage/plugin-azure-devops": "0.3.6", - "@backstage/plugin-azure-devops-backend": "0.4.0", - "@backstage/plugin-azure-devops-common": "0.3.1", - "@backstage/plugin-azure-sites": "0.1.13", - "@backstage/plugin-azure-sites-backend": "0.1.13", - "@backstage/plugin-azure-sites-common": "0.1.1", - "@backstage/plugin-badges": "0.2.48", - "@backstage/plugin-badges-backend": "0.3.0", - "@backstage/plugin-bazaar": "0.2.16", - "@backstage/plugin-bazaar-backend": "0.3.0", - "@backstage/plugin-bitbucket-cloud-common": "0.2.12", - "@backstage/plugin-bitrise": "0.1.51", - "@backstage/plugin-catalog": "1.13.0", - "@backstage/plugin-catalog-backend": "1.13.0", - "@backstage/plugin-catalog-backend-module-aws": "0.2.6", - "@backstage/plugin-catalog-backend-module-azure": "0.1.22", - "@backstage/plugin-catalog-backend-module-bitbucket": "0.2.18", - "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.18", - "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.16", - "@backstage/plugin-catalog-backend-module-gcp": "0.1.3", - "@backstage/plugin-catalog-backend-module-gerrit": "0.1.19", - "@backstage/plugin-catalog-backend-module-github": "0.4.0", - "@backstage/plugin-catalog-backend-module-gitlab": "0.3.0", - "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.4.6", - "@backstage/plugin-catalog-backend-module-ldap": "0.5.18", - "@backstage/plugin-catalog-backend-module-msgraph": "0.5.10", - "@backstage/plugin-catalog-backend-module-openapi": "0.1.19", - "@backstage/plugin-catalog-backend-module-puppetdb": "0.1.8", - "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.1.0", - "@backstage/plugin-catalog-backend-module-unprocessed": "0.3.0", - "@backstage/plugin-catalog-common": "1.0.16", - "@internal/plugin-catalog-customized": "0.0.14", - "@backstage/plugin-catalog-graph": "0.2.36", - "@backstage/plugin-catalog-graphql": "0.3.23", - "@backstage/plugin-catalog-import": "0.10.0", - "@backstage/plugin-catalog-node": "1.4.4", - "@backstage/plugin-catalog-react": "1.8.4", - "@backstage/plugin-catalog-unprocessed-entities": "0.1.3", - "@backstage/plugin-cicd-statistics": "0.1.26", - "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.20", - "@backstage/plugin-circleci": "0.3.24", - "@backstage/plugin-cloudbuild": "0.3.24", - "@backstage/plugin-code-climate": "0.1.24", - "@backstage/plugin-code-coverage": "0.2.17", - "@backstage/plugin-code-coverage-backend": "0.2.17", - "@backstage/plugin-codescene": "0.1.17", - "@backstage/plugin-config-schema": "0.1.45", - "@backstage/plugin-cost-insights": "0.12.13", - "@backstage/plugin-cost-insights-common": "0.1.2", - "@backstage/plugin-devtools": "0.1.4", - "@backstage/plugin-devtools-backend": "0.2.0", - "@backstage/plugin-devtools-common": "0.1.4", - "@backstage/plugin-dynatrace": "7.0.4", - "@backstage/plugin-entity-feedback": "0.2.7", - "@backstage/plugin-entity-feedback-backend": "0.2.0", - "@backstage/plugin-entity-feedback-common": "0.1.3", - "@backstage/plugin-entity-validation": "0.1.9", - "@backstage/plugin-events-backend": "0.2.12", - "@backstage/plugin-events-backend-module-aws-sqs": "0.2.6", - "@backstage/plugin-events-backend-module-azure": "0.1.13", - "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.13", - "@backstage/plugin-events-backend-module-gerrit": "0.1.13", - "@backstage/plugin-events-backend-module-github": "0.1.13", - "@backstage/plugin-events-backend-module-gitlab": "0.1.13", - "@backstage/plugin-events-backend-test-utils": "0.1.13", - "@backstage/plugin-events-node": "0.2.12", - "@internal/plugin-todo-list": "1.0.17", - "@internal/plugin-todo-list-backend": "1.0.17", - "@internal/plugin-todo-list-common": "1.0.13", - "@backstage/plugin-explore": "0.4.10", - "@backstage/plugin-explore-backend": "0.0.13", - "@backstage/plugin-explore-common": "0.0.2", - "@backstage/plugin-explore-react": "0.0.31", - "@backstage/plugin-firehydrant": "0.2.8", - "@backstage/plugin-fossa": "0.2.56", - "@backstage/plugin-gcalendar": "0.3.18", - "@backstage/plugin-gcp-projects": "0.3.41", - "@backstage/plugin-git-release-manager": "0.3.37", - "@backstage/plugin-github-actions": "0.6.5", - "@backstage/plugin-github-deployments": "0.1.55", - "@backstage/plugin-github-issues": "0.2.13", - "@backstage/plugin-github-pull-requests-board": "0.1.18", - "@backstage/plugin-gitops-profiles": "0.3.40", - "@backstage/plugin-gocd": "0.1.30", - "@backstage/plugin-graphiql": "0.2.54", - "@backstage/plugin-graphql-backend": "0.1.41", - "@backstage/plugin-graphql-voyager": "0.1.7", - "@backstage/plugin-home": "0.5.8", - "@backstage/plugin-home-react": "0.1.3", - "@backstage/plugin-ilert": "0.2.13", - "@backstage/plugin-jenkins": "0.8.6", - "@backstage/plugin-jenkins-backend": "0.2.6", - "@backstage/plugin-jenkins-common": "0.1.19", - "@backstage/plugin-kafka": "0.3.24", - "@backstage/plugin-kafka-backend": "0.3.0", - "@backstage/plugin-kubernetes": "0.10.3", - "@backstage/plugin-kubernetes-backend": "0.12.0", - "@backstage/plugin-kubernetes-common": "0.6.6", - "@backstage/plugin-lighthouse": "0.4.9", - "@backstage/plugin-lighthouse-backend": "0.3.0", - "@backstage/plugin-lighthouse-common": "0.1.3", - "@backstage/plugin-linguist": "0.1.9", - "@backstage/plugin-linguist-backend": "0.5.0", - "@backstage/plugin-linguist-common": "0.1.2", - "@backstage/plugin-microsoft-calendar": "0.1.7", - "@backstage/plugin-newrelic": "0.3.40", - "@backstage/plugin-newrelic-dashboard": "0.2.17", - "@backstage/plugin-nomad": "0.1.5", - "@backstage/plugin-nomad-backend": "0.1.5", - "@backstage/plugin-octopus-deploy": "0.2.6", - "@backstage/plugin-opencost": "0.2.0", - "@backstage/plugin-org": "0.6.14", - "@backstage/plugin-org-react": "0.1.13", - "@backstage/plugin-pagerduty": "0.6.5", - "@backstage/plugin-periskop": "0.1.22", - "@backstage/plugin-periskop-backend": "0.2.0", - "@backstage/plugin-permission-backend": "0.5.26", - "@backstage/plugin-permission-backend-module-allow-all-policy": "0.1.0", - "@backstage/plugin-permission-common": "0.7.8", - "@backstage/plugin-permission-node": "0.7.14", - "@backstage/plugin-permission-react": "0.4.15", - "@backstage/plugin-playlist": "0.1.16", - "@backstage/plugin-playlist-backend": "0.3.7", - "@backstage/plugin-playlist-common": "0.1.10", - "@backstage/plugin-proxy-backend": "0.4.0", - "@backstage/plugin-puppetdb": "0.1.7", - "@backstage/plugin-rollbar": "0.4.24", - "@backstage/plugin-rollbar-backend": "0.1.48", - "@backstage/plugin-scaffolder": "1.15.0", - "@backstage/plugin-scaffolder-backend": "1.17.0", - "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.2.4", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.27", - "@backstage/plugin-scaffolder-backend-module-gitlab": "0.2.6", - "@backstage/plugin-scaffolder-backend-module-rails": "0.4.20", - "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.11", - "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.24", - "@backstage/plugin-scaffolder-common": "1.4.1", - "@backstage/plugin-scaffolder-node": "0.2.3", - "@backstage/plugin-scaffolder-react": "1.5.5", - "@backstage/plugin-search": "1.4.0", - "@backstage/plugin-search-backend": "1.4.3", - "@backstage/plugin-search-backend-module-catalog": "0.1.7", - "@backstage/plugin-search-backend-module-elasticsearch": "1.3.6", - "@backstage/plugin-search-backend-module-explore": "0.1.7", - "@backstage/plugin-search-backend-module-pg": "0.5.12", - "@backstage/plugin-search-backend-module-techdocs": "0.1.7", - "@backstage/plugin-search-backend-node": "1.2.7", - "@backstage/plugin-search-common": "1.2.6", - "@backstage/plugin-search-react": "1.7.0", - "@backstage/plugin-sentry": "0.5.9", - "@backstage/plugin-shortcuts": "0.3.14", - "@backstage/plugin-sonarqube": "0.7.5", - "@backstage/plugin-sonarqube-backend": "0.2.5", - "@backstage/plugin-sonarqube-react": "0.1.8", - "@backstage/plugin-splunk-on-call": "0.4.13", - "@backstage/plugin-stack-overflow": "0.1.20", - "@backstage/plugin-stack-overflow-backend": "0.2.7", - "@backstage/plugin-stackstorm": "0.1.6", - "@backstage/plugin-tech-insights": "0.3.16", - "@backstage/plugin-tech-insights-backend": "0.5.17", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.35", - "@backstage/plugin-tech-insights-common": "0.2.12", - "@backstage/plugin-tech-insights-node": "0.4.9", - "@backstage/plugin-tech-radar": "0.6.8", - "@backstage/plugin-techdocs": "1.7.0", - "@backstage/plugin-techdocs-addons-test-utils": "1.0.21", - "@backstage/plugin-techdocs-backend": "1.7.0", - "@backstage/plugin-techdocs-module-addons-contrib": "1.1.0", - "@backstage/plugin-techdocs-node": "1.8.0", - "@backstage/plugin-techdocs-react": "1.1.11", - "@backstage/plugin-todo": "0.2.27", - "@backstage/plugin-todo-backend": "0.3.1", - "@backstage/plugin-user-settings": "0.7.10", - "@backstage/plugin-user-settings-backend": "0.2.1", - "@backstage/plugin-vault": "0.1.19", - "@backstage/plugin-vault-backend": "0.3.8", - "@backstage/plugin-xcmetrics": "0.2.43", - "@backstage/e2e-test-utils": "0.0.0", - "@backstage/plugin-kubernetes-react": "0.0.0", - "@backstage/plugin-auth-backend-module-microsoft-provider": "0.0.0", - "@backstage/plugin-catalog-backend-module-github-org": "0.0.0", - "@backstage/plugin-kubernetes-cluster": "0.0.0", - "@backstage/plugin-kubernetes-node": "0.0.0" - }, - "changesets": [ - "angry-badgers-beg", - "angry-clocks-exercise", - "big-spies-beam", - "breezy-dryers-thank", - "calm-carpets-kiss", - "calm-scissors-rescue", - "chatty-papayas-care", - "clean-forks-love", - "cold-bees-jam", - "cold-seas-repeat", - "create-app-1696937840", - "dirty-doors-wave", - "dull-bugs-build", - "dull-dolls-explode", - "dull-experts-kiss", - "dull-laws-camp", - "early-toes-develop", - "eight-melons-cough", - "eight-spiders-fold", - "eight-suns-tan", - "eighty-actors-type", - "empty-schools-check", - "fair-frogs-enjoy", - "flat-pandas-tan", - "flat-rules-rush", - "four-jars-protect", - "four-onions-clap", - "four-pans-sin", - "fresh-badgers-study", - "fresh-kangaroos-tap", - "fuzzy-pillows-remain", - "gentle-elephants-fold", - "gentle-spies-deny", - "great-walls-brake", - "happy-books-smoke", - "healthy-laws-divide", - "heavy-forks-tie", - "heavy-ladybugs-leave", - "itchy-bobcats-fly", - "itchy-monkeys-reply", - "itchy-rabbits-exist", - "khaki-tools-tease", - "large-balloons-brush", - "large-comics-knock", - "late-papayas-push", - "lazy-doors-wink", - "lemon-cups-wait", - "lemon-masks-greet", - "little-ligers-cheat", - "loud-hotels-hunt", - "lovely-coins-occur", - "lovely-fans-sniff", - "many-pianos-bow", - "many-swans-eat", - "mean-dancers-burn", - "metal-peas-beam", - "moody-lobsters-rescue", - "nasty-needles-hear", - "nervous-hounds-sleep", - "nice-clocks-smash", - "nice-dancers-explain", - "nice-ghosts-build", - "nine-flies-move", - "nine-garlics-attend", - "odd-pants-sleep", - "olive-cars-rescue", - "olive-geese-rest", - "perfect-pumas-protect", - "perfect-shrimps-attend", - "plenty-llamas-double", - "plenty-toys-cheer", - "polite-cooks-perform", - "polite-donuts-fail", - "polite-trainers-grin", - "popular-dots-design", - "pretty-apes-sneeze", - "pretty-steaks-serve", - "purple-chefs-wait", - "purple-forks-fetch", - "quick-weeks-explode", - "rare-pants-reply", - "red-bees-try", - "red-geese-clean", - "renovate-7d08f6a", - "renovate-a1c52e8", - "rotten-rings-confess", - "serious-pants-lie", - "serious-penguins-tease", - "short-terms-check", - "shy-clouds-reflect", - "shy-seas-sip", - "silent-years-bake", - "silly-swans-invent", - "six-weeks-raise", - "slow-dodos-remember", - "small-books-deliver", - "small-pugs-build", - "smooth-rings-mate", - "spicy-chairs-film", - "spicy-poets-sell", - "spotty-badgers-wash", - "stale-eagles-reply", - "stale-stingrays-explode", - "strange-dodos-film", - "strong-falcons-tickle", - "stupid-drinks-trade", - "stupid-eagles-shave", - "swift-steaks-fetch", - "tame-trainers-visit", - "tasty-avocados-hope", - "tasty-doors-switch", - "ten-seals-wait", - "tender-pears-work", - "thirty-coins-sneeze", - "tiny-garlics-cheer", - "twelve-clouds-design", - "twelve-days-walk", - "twenty-bags-sin", - "twenty-carrots-smile", - "two-dingos-dream", - "two-terms-play", - "unlucky-experts-breathe", - "violet-apes-beam", - "violet-beers-cross", - "warm-drinks-argue", - "wet-olives-wave", - "wet-timers-chew", - "wicked-rings-flash", - "wild-jobs-greet", - "wild-queens-grab", - "yellow-numbers-own", - "yellow-rings-invent", - "young-toes-knock" - ] -} diff --git a/.changeset/pretty-apes-sneeze.md b/.changeset/pretty-apes-sneeze.md deleted file mode 100644 index a1008dc951..0000000000 --- a/.changeset/pretty-apes-sneeze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-user-settings': patch ---- - -Fixed a bug where the theme icons would not be colored according to their active state. diff --git a/.changeset/pretty-steaks-serve.md b/.changeset/pretty-steaks-serve.md deleted file mode 100644 index 8ec78e0aea..0000000000 --- a/.changeset/pretty-steaks-serve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Added a template for creating `node-library` packages with `yarn new`. diff --git a/.changeset/pretty-swans-worry.md b/.changeset/pretty-swans-worry.md deleted file mode 100644 index 621ae98fe5..0000000000 --- a/.changeset/pretty-swans-worry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Fixed the type declaration of `DependencyGraphProps`, the `defs` prop now expects `JSX.Element`s. diff --git a/.changeset/purple-chefs-wait.md b/.changeset/purple-chefs-wait.md deleted file mode 100644 index 9a8b1f9799..0000000000 --- a/.changeset/purple-chefs-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Adding `requestInterceptor` option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI. diff --git a/.changeset/purple-forks-fetch.md b/.changeset/purple-forks-fetch.md deleted file mode 100644 index 022fc32e71..0000000000 --- a/.changeset/purple-forks-fetch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Register default api implementations when creating declarative integrated apps. diff --git a/.changeset/quick-weeks-explode.md b/.changeset/quick-weeks-explode.md deleted file mode 100644 index fcc88263ec..0000000000 --- a/.changeset/quick-weeks-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Remove third type parameter used for `MockInstance`, in order to be compatible with older versions of `@types/jest`. diff --git a/.changeset/rare-glasses-play.md b/.changeset/rare-glasses-play.md deleted file mode 100644 index 7613f6f1bc..0000000000 --- a/.changeset/rare-glasses-play.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes-react': patch ---- - -Handle mixed decimals and bigint when calculating k8s resource usage diff --git a/.changeset/rare-pants-reply.md b/.changeset/rare-pants-reply.md deleted file mode 100644 index d37192048c..0000000000 --- a/.changeset/rare-pants-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend-module-gcp-iap-provider': minor ---- - -**BREAKING** `gcpIapAuthenticator.initialize()` is no longer `async` diff --git a/.changeset/red-baboons-warn.md b/.changeset/red-baboons-warn.md deleted file mode 100644 index 80b7cd3cad..0000000000 --- a/.changeset/red-baboons-warn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/dev-utils': patch ---- - -Moving development `dependencies` to `devDependencies` diff --git a/.changeset/red-bees-try.md b/.changeset/red-bees-try.md deleted file mode 100644 index de7eacfe14..0000000000 --- a/.changeset/red-bees-try.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows. diff --git a/.changeset/red-geese-clean.md b/.changeset/red-geese-clean.md deleted file mode 100644 index b4fc9c0808..0000000000 --- a/.changeset/red-geese-clean.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/backend-openapi-utils': patch ---- - -Adds new public utility types for common OpenAPI values, like request and response shapes and parameters available on an endpoint. - -**deprecated** `internal` namespace -The internal namespace will continue to be exported but now uses OpenAPI format for path parameters. You should use the new utility types. diff --git a/.changeset/renovate-0a0b7ba.md b/.changeset/renovate-0a0b7ba.md deleted file mode 100644 index dd43bcc8fa..0000000000 --- a/.changeset/renovate-0a0b7ba.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-kubernetes-common': patch -'@backstage/plugin-kubernetes': patch ---- - -Updated dependency `@kubernetes/client-node` to `0.19.0`. diff --git a/.changeset/renovate-2633beb.md b/.changeset/renovate-2633beb.md deleted file mode 100644 index ff4c574c85..0000000000 --- a/.changeset/renovate-2633beb.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -'@backstage/app-defaults': patch -'@backstage/core-app-api': patch -'@backstage/core-components': patch -'@backstage/core-plugin-api': patch -'@backstage/dev-utils': patch -'@backstage/frontend-app-api': patch -'@backstage/frontend-plugin-api': patch -'@backstage/integration-react': patch -'@backstage/test-utils': patch -'@backstage/version-bridge': patch -'@backstage/plugin-adr': patch -'@backstage/plugin-airbrake': patch -'@backstage/plugin-allure': patch -'@backstage/plugin-analytics-module-ga': patch -'@backstage/plugin-analytics-module-ga4': patch -'@backstage/plugin-analytics-module-newrelic-browser': patch -'@backstage/plugin-apache-airflow': patch -'@backstage/plugin-api-docs-module-protoc-gen-doc': patch -'@backstage/plugin-api-docs': patch -'@backstage/plugin-apollo-explorer': patch -'@backstage/plugin-azure-devops': patch -'@backstage/plugin-azure-sites': patch -'@backstage/plugin-badges': patch -'@backstage/plugin-bazaar': patch -'@backstage/plugin-bitrise': patch -'@backstage/plugin-catalog-graph': patch -'@backstage/plugin-catalog-import': patch -'@backstage/plugin-catalog-react': patch -'@backstage/plugin-catalog-unprocessed-entities': patch -'@backstage/plugin-catalog': patch -'@backstage/plugin-circleci': patch -'@backstage/plugin-cloudbuild': patch -'@backstage/plugin-code-climate': patch -'@backstage/plugin-code-coverage': patch -'@backstage/plugin-codescene': patch -'@backstage/plugin-config-schema': patch -'@backstage/plugin-cost-insights': patch -'@backstage/plugin-devtools': patch -'@backstage/plugin-dynatrace': patch -'@backstage/plugin-entity-feedback': patch -'@backstage/plugin-entity-validation': patch -'@backstage/plugin-explore-react': patch -'@backstage/plugin-explore': patch -'@backstage/plugin-firehydrant': patch -'@backstage/plugin-fossa': patch -'@backstage/plugin-gcalendar': patch -'@backstage/plugin-gcp-projects': patch -'@backstage/plugin-git-release-manager': patch -'@backstage/plugin-github-actions': patch -'@backstage/plugin-github-deployments': patch -'@backstage/plugin-github-issues': patch -'@backstage/plugin-github-pull-requests-board': patch -'@backstage/plugin-gitops-profiles': patch -'@backstage/plugin-gocd': patch -'@backstage/plugin-graphiql': patch -'@backstage/plugin-graphql-voyager': patch -'@backstage/plugin-home-react': patch -'@backstage/plugin-home': patch -'@backstage/plugin-ilert': patch -'@backstage/plugin-jenkins': patch -'@backstage/plugin-kafka': patch -'@backstage/plugin-kubernetes-cluster': patch -'@backstage/plugin-kubernetes-react': patch -'@backstage/plugin-kubernetes': patch -'@backstage/plugin-lighthouse': patch -'@backstage/plugin-linguist': patch -'@backstage/plugin-microsoft-calendar': patch -'@backstage/plugin-newrelic-dashboard': patch -'@backstage/plugin-newrelic': patch -'@backstage/plugin-nomad': patch -'@backstage/plugin-octopus-deploy': patch -'@backstage/plugin-opencost': patch -'@backstage/plugin-org-react': patch -'@backstage/plugin-org': patch -'@backstage/plugin-pagerduty': patch -'@backstage/plugin-periskop': patch -'@backstage/plugin-permission-react': patch -'@backstage/plugin-playlist': patch -'@backstage/plugin-puppetdb': patch -'@backstage/plugin-rollbar': patch -'@backstage/plugin-scaffolder-react': patch -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-search-react': patch -'@backstage/plugin-search': patch -'@backstage/plugin-sentry': patch -'@backstage/plugin-shortcuts': patch -'@backstage/plugin-sonarqube': patch -'@backstage/plugin-splunk-on-call': patch -'@backstage/plugin-stack-overflow': patch -'@backstage/plugin-stackstorm': patch -'@backstage/plugin-tech-insights': patch -'@backstage/plugin-tech-radar': patch -'@backstage/plugin-techdocs-addons-test-utils': patch -'@backstage/plugin-techdocs-module-addons-contrib': patch -'@backstage/plugin-techdocs-react': patch -'@backstage/plugin-techdocs': patch -'@backstage/plugin-todo': patch -'@backstage/plugin-user-settings': patch -'@backstage/plugin-vault': patch -'@backstage/plugin-xcmetrics': patch ---- - -Updated dependency `@testing-library/jest-dom` to `^6.0.0`. diff --git a/.changeset/renovate-37d5549.md b/.changeset/renovate-37d5549.md deleted file mode 100644 index 4aae56e839..0000000000 --- a/.changeset/renovate-37d5549.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -'@backstage/core-app-api': patch -'@backstage/core-components': patch -'@backstage/core-plugin-api': patch -'@backstage/dev-utils': patch -'@backstage/integration-react': patch -'@backstage/plugin-adr': patch -'@backstage/plugin-airbrake': patch -'@backstage/plugin-allure': patch -'@backstage/plugin-analytics-module-ga': patch -'@backstage/plugin-analytics-module-ga4': patch -'@backstage/plugin-apache-airflow': patch -'@backstage/plugin-api-docs': patch -'@backstage/plugin-apollo-explorer': patch -'@backstage/plugin-azure-devops': patch -'@backstage/plugin-azure-sites': patch -'@backstage/plugin-bitrise': patch -'@backstage/plugin-catalog-graph': patch -'@backstage/plugin-catalog-import': patch -'@backstage/plugin-catalog-react': patch -'@backstage/plugin-catalog': patch -'@backstage/plugin-circleci': patch -'@backstage/plugin-cloudbuild': patch -'@backstage/plugin-code-climate': patch -'@backstage/plugin-code-coverage': patch -'@backstage/plugin-codescene': patch -'@backstage/plugin-config-schema': patch -'@backstage/plugin-cost-insights': patch -'@backstage/plugin-dynatrace': patch -'@backstage/plugin-entity-feedback': patch -'@backstage/plugin-entity-validation': patch -'@backstage/plugin-explore-react': patch -'@backstage/plugin-explore': patch -'@backstage/plugin-firehydrant': patch -'@backstage/plugin-fossa': patch -'@backstage/plugin-gcalendar': patch -'@backstage/plugin-gcp-projects': patch -'@backstage/plugin-git-release-manager': patch -'@backstage/plugin-github-actions': patch -'@backstage/plugin-github-deployments': patch -'@backstage/plugin-github-issues': patch -'@backstage/plugin-github-pull-requests-board': patch -'@backstage/plugin-gitops-profiles': patch -'@backstage/plugin-gocd': patch -'@backstage/plugin-graphiql': patch -'@backstage/plugin-graphql-voyager': patch -'@backstage/plugin-home-react': patch -'@backstage/plugin-home': patch -'@backstage/plugin-ilert': patch -'@backstage/plugin-jenkins': patch -'@backstage/plugin-kafka': patch -'@backstage/plugin-kubernetes-cluster': patch -'@backstage/plugin-kubernetes': patch -'@backstage/plugin-lighthouse': patch -'@backstage/plugin-linguist': patch -'@backstage/plugin-microsoft-calendar': patch -'@backstage/plugin-newrelic': patch -'@backstage/plugin-octopus-deploy': patch -'@backstage/plugin-org-react': patch -'@backstage/plugin-org': patch -'@backstage/plugin-pagerduty': patch -'@backstage/plugin-periskop': patch -'@backstage/plugin-playlist': patch -'@backstage/plugin-rollbar': patch -'@backstage/plugin-scaffolder-react': patch -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-search-react': patch -'@backstage/plugin-search': patch -'@backstage/plugin-sentry': patch -'@backstage/plugin-shortcuts': patch -'@backstage/plugin-sonarqube': patch -'@backstage/plugin-splunk-on-call': patch -'@backstage/plugin-stack-overflow': patch -'@backstage/plugin-stackstorm': patch -'@backstage/plugin-tech-insights': patch -'@backstage/plugin-tech-radar': patch -'@backstage/plugin-techdocs-addons-test-utils': patch -'@backstage/plugin-techdocs-module-addons-contrib': patch -'@backstage/plugin-techdocs': patch -'@backstage/plugin-todo': patch -'@backstage/plugin-user-settings': patch -'@backstage/plugin-vault': patch -'@backstage/plugin-xcmetrics': patch ---- - -Updated dependency `@testing-library/dom` to `^9.0.0`. diff --git a/.changeset/renovate-7d08f6a.md b/.changeset/renovate-7d08f6a.md deleted file mode 100644 index 4e8111f1b3..0000000000 --- a/.changeset/renovate-7d08f6a.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/config-loader': patch ---- - -Updated dependency `typescript-json-schema` to `^0.61.0`. diff --git a/.changeset/renovate-a1c52e8.md b/.changeset/renovate-a1c52e8.md deleted file mode 100644 index c11c866b68..0000000000 --- a/.changeset/renovate-a1c52e8.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -Updated dependency `@types/pluralize` to `^0.0.31`. diff --git a/.changeset/renovate-a6a783f.md b/.changeset/renovate-a6a783f.md deleted file mode 100644 index a4c6188ee6..0000000000 --- a/.changeset/renovate-a6a783f.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-kubernetes': patch ---- - -Updated dependency `xterm-addon-attach` to `^0.9.0`. -Updated dependency `xterm-addon-fit` to `^0.8.0`. diff --git a/.changeset/renovate-c204e0d.md b/.changeset/renovate-c204e0d.md deleted file mode 100644 index 1f3e366540..0000000000 --- a/.changeset/renovate-c204e0d.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Updated dependency `@typescript-eslint/eslint-plugin` to `6.7.5`. diff --git a/.changeset/rotten-rings-confess.md b/.changeset/rotten-rings-confess.md deleted file mode 100644 index 8948a90347..0000000000 --- a/.changeset/rotten-rings-confess.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-newrelic-dashboard': minor ---- - -Changes in `newrelic-dashboard` plugin: - -- Make DashboardSnapshotList component public -- Settle discrepancies in the exported API -- Deprecate DashboardSnapshotComponent diff --git a/.changeset/serious-pants-lie.md b/.changeset/serious-pants-lie.md deleted file mode 100644 index e67f01dd53..0000000000 --- a/.changeset/serious-pants-lie.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Support for the `.icon.svg` extension has been deprecated and will be removed in the future. The implementation of this extension is too tied to a particular version of MUI and the SVGO, and it makes it harder to evolve the build system. We may introduce the ability to reintroduce this kind of functionality in the future through configuration for use in internal plugins, but for now we're forced to remove it. - -To migrate existing code, rename the `.icon.svg` file to `.tsx` and replace the `` element with `` from MUI and add necessary imports. For example: - -```tsx -import React from 'react'; -import SvgIcon from '@material-ui/core/SvgIcon'; -import { IconComponent } from '@backstage/core-plugin-api'; - -export const CodeSceneIcon = (props: SvgIconProps) => ( - - - - - -); -``` diff --git a/.changeset/serious-penguins-tease.md b/.changeset/serious-penguins-tease.md deleted file mode 100644 index aa6aba7208..0000000000 --- a/.changeset/serious-penguins-tease.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Updated to import `HostDiscovery` from `@backstage/backend-app-api`. diff --git a/.changeset/serious-ravens-serve.md b/.changeset/serious-ravens-serve.md deleted file mode 100644 index 66cbd795c0..0000000000 --- a/.changeset/serious-ravens-serve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -The scaffolder-module template now recommends usage of `createMockDirectory` instead of `mock-fs`. diff --git a/.changeset/shaggy-beers-collect.md b/.changeset/shaggy-beers-collect.md deleted file mode 100644 index 471368d6f2..0000000000 --- a/.changeset/shaggy-beers-collect.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/dev-utils': patch -'@backstage/plugin-techdocs': patch ---- - -Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. diff --git a/.changeset/shiny-birds-melt.md b/.changeset/shiny-birds-melt.md deleted file mode 100644 index 16591b6d2f..0000000000 --- a/.changeset/shiny-birds-melt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Fixed a bug in `TranslationApi` implementation where in some cases it wouldn't notify subscribers of language changes. diff --git a/.changeset/short-ears-rescue.md b/.changeset/short-ears-rescue.md deleted file mode 100644 index 41968f3da4..0000000000 --- a/.changeset/short-ears-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend-module-pinniped-provider': minor ---- - -Add new Pinniped auth module and authenticator to be used alongside the new Pinniped auth provider. diff --git a/.changeset/short-terms-check.md b/.changeset/short-terms-check.md deleted file mode 100644 index 69d85fcb9c..0000000000 --- a/.changeset/short-terms-check.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Removed `mock-fs` dev dependency. diff --git a/.changeset/shy-clouds-reflect.md b/.changeset/shy-clouds-reflect.md deleted file mode 100644 index 2861bad9f3..0000000000 --- a/.changeset/shy-clouds-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/config-loader': patch ---- - -The `FileConfigSource` will now retry file reading after a short delay if it reads an empty file. This is to avoid flakiness during watch mode where change events can trigger before the file content has been written. diff --git a/.changeset/shy-seas-sip.md b/.changeset/shy-seas-sip.md deleted file mode 100644 index dfbc4ff0e0..0000000000 --- a/.changeset/shy-seas-sip.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-gitlab': patch ---- - -Make sure the archived projects are skipped with the Gitlab API diff --git a/.changeset/silent-years-bake.md b/.changeset/silent-years-bake.md deleted file mode 100644 index 4f50c37c31..0000000000 --- a/.changeset/silent-years-bake.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-rails': patch -'@techdocs/cli': patch -'@backstage/cli': patch -'@backstage/cli-common': patch -'@backstage/create-app': patch -'@backstage/codemods': patch -'@backstage/repo-tools': patch ---- - -Bumped dev dependencies `@types/node` and `mock-fs`. diff --git a/.changeset/silent-years-marry.md b/.changeset/silent-years-marry.md deleted file mode 100644 index 6053261784..0000000000 --- a/.changeset/silent-years-marry.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': minor ---- - -**BREAKING** Allow passing undefined `labelSelector` to `KubernetesFetcher` - -`KubernetesFetch` no longer auto-adds `labelSelector` when empty string was passed. -This is only applicable if you have custom ObjectProvider implementation, as build-in `KubernetesFanOutHandler` already does this diff --git a/.changeset/silly-chefs-allow.md b/.changeset/silly-chefs-allow.md deleted file mode 100644 index 6a1ff5dc09..0000000000 --- a/.changeset/silly-chefs-allow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Added `createExtensionOverrides` which can be used to install a collection of extensions in an app that will replace any existing ones. diff --git a/.changeset/silly-swans-invent.md b/.changeset/silly-swans-invent.md deleted file mode 100644 index 68b094aba7..0000000000 --- a/.changeset/silly-swans-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Added `createThemeExtension` and `coreExtensionData.theme`. diff --git a/.changeset/six-weeks-raise.md b/.changeset/six-weeks-raise.md deleted file mode 100644 index 319555afa4..0000000000 --- a/.changeset/six-weeks-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -Moved `HostDiscovery` from `@backstage/backend-common`. diff --git a/.changeset/slow-cameras-grab.md b/.changeset/slow-cameras-grab.md deleted file mode 100644 index d2ffaac73d..0000000000 --- a/.changeset/slow-cameras-grab.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': minor ---- - -The hidden `'root'` extension has been removed and has instead been made an input of the `'core'` extension. The checks for rejecting configuration of the `'root'` extension to rejects configuration of the `'core'` extension instead. diff --git a/.changeset/slow-dodos-remember.md b/.changeset/slow-dodos-remember.md deleted file mode 100644 index fcc49e3f45..0000000000 --- a/.changeset/slow-dodos-remember.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-kubernetes-cluster': patch -'@backstage/plugin-kubernetes-react': patch -'@backstage/plugin-kubernetes': patch ---- - -Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage diff --git a/.changeset/small-avocados-live.md b/.changeset/small-avocados-live.md deleted file mode 100644 index ddb01a9dfa..0000000000 --- a/.changeset/small-avocados-live.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Adds the optional flag for useRedisSets for the Redis cache to the config. diff --git a/.changeset/small-books-deliver.md b/.changeset/small-books-deliver.md deleted file mode 100644 index 0d09f7ae1c..0000000000 --- a/.changeset/small-books-deliver.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Updates for `at` -> `attachTo` refactor. diff --git a/.changeset/small-pugs-build.md b/.changeset/small-pugs-build.md deleted file mode 100644 index 68e11cd967..0000000000 --- a/.changeset/small-pugs-build.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Bump Docker base images to `node:18-bookworm-slim` to fix node compatibility issues raised during image build. - -You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bookworm-slim` diff --git a/.changeset/smooth-rings-mate.md b/.changeset/smooth-rings-mate.md deleted file mode 100644 index f46ef2cb5c..0000000000 --- a/.changeset/smooth-rings-mate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/theme': patch ---- - -Added support for string `fontSize` values (e.g. `"2.5rem"`) in themes in addition to numbers. Also added an optional `fontFamily` prop for header typography variants to allow further customization. diff --git a/.changeset/spicy-chairs-film.md b/.changeset/spicy-chairs-film.md deleted file mode 100644 index 475d786330..0000000000 --- a/.changeset/spicy-chairs-film.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-kubernetes-common': minor -'@backstage/plugin-kubernetes-react': minor -'@backstage/plugin-kubernetes': minor ---- - -Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet diff --git a/.changeset/spicy-poets-sell.md b/.changeset/spicy-poets-sell.md deleted file mode 100644 index 4bebd71344..0000000000 --- a/.changeset/spicy-poets-sell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-jenkins': patch ---- - -Extend EntityJenkinsContent to receive columns as prop diff --git a/.changeset/spotty-badgers-wash.md b/.changeset/spotty-badgers-wash.md deleted file mode 100644 index 1ce9c66aee..0000000000 --- a/.changeset/spotty-badgers-wash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Instrumenting some missing metrics with `OpenTelemetry` diff --git a/.changeset/stale-eagles-reply.md b/.changeset/stale-eagles-reply.md deleted file mode 100644 index 4584355a59..0000000000 --- a/.changeset/stale-eagles-reply.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/config-loader': patch -'@backstage/backend-app-api': patch ---- - -Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. diff --git a/.changeset/stale-stingrays-explode.md b/.changeset/stale-stingrays-explode.md deleted file mode 100644 index b8b66b8398..0000000000 --- a/.changeset/stale-stingrays-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-node': patch ---- - -Fixed cookie persisted scope not returned in OAuth refresh handler response. diff --git a/.changeset/strange-dodos-film.md b/.changeset/strange-dodos-film.md deleted file mode 100644 index 78b9119a2b..0000000000 --- a/.changeset/strange-dodos-film.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-github-org': minor ---- - -Added `catalogModuleGithubOrgEntityProvider` to ingest users and teams from multiple Github organizations. diff --git a/.changeset/strong-falcons-tickle.md b/.changeset/strong-falcons-tickle.md deleted file mode 100644 index d6fa0eb565..0000000000 --- a/.changeset/strong-falcons-tickle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-adr': patch ---- - -Create an experimental `AdrSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. diff --git a/.changeset/stupid-drinks-trade.md b/.changeset/stupid-drinks-trade.md deleted file mode 100644 index a9eeacec8a..0000000000 --- a/.changeset/stupid-drinks-trade.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Add kind column by default to TechDocsTable diff --git a/.changeset/stupid-eagles-shave.md b/.changeset/stupid-eagles-shave.md deleted file mode 100644 index 9bd88290ee..0000000000 --- a/.changeset/stupid-eagles-shave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-code-coverage': patch ---- - -Updated layout to improve contrasts and consistency with other plugins diff --git a/.changeset/sweet-buckets-fry.md b/.changeset/sweet-buckets-fry.md deleted file mode 100644 index 8f17617645..0000000000 --- a/.changeset/sweet-buckets-fry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-react': patch ---- - -The `spec.type` field in entities will now always be rendered as a string. diff --git a/.changeset/swift-kings-add.md b/.changeset/swift-kings-add.md deleted file mode 100644 index 9e9c158eec..0000000000 --- a/.changeset/swift-kings-add.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-newrelic-dashboard': patch ---- - -Fix the styles for NewRelicDashboard, add more responsiveness diff --git a/.changeset/swift-steaks-fetch.md b/.changeset/swift-steaks-fetch.md deleted file mode 100644 index 80b23e7658..0000000000 --- a/.changeset/swift-steaks-fetch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-auth-backend-module-microsoft-provider': minor -'@backstage/plugin-auth-backend': patch ---- - -Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. diff --git a/.changeset/tall-dragons-jump.md b/.changeset/tall-dragons-jump.md deleted file mode 100644 index 2c35eb3fd2..0000000000 --- a/.changeset/tall-dragons-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fixed recursive reloading issues of the backend, caused by unwanted watched files. diff --git a/.changeset/tame-trainers-visit.md b/.changeset/tame-trainers-visit.md deleted file mode 100644 index 5315f3e1d5..0000000000 --- a/.changeset/tame-trainers-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-github': patch ---- - -Removed `catalogModuleGithubOrgEntityProvider`. Import from `@backstage/plugin-catalog-backend-module-github-org` instead. diff --git a/.changeset/tasty-avocados-hope.md b/.changeset/tasty-avocados-hope.md deleted file mode 100644 index 0772b55683..0000000000 --- a/.changeset/tasty-avocados-hope.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Migrate catalog api to declarative integration system, it is exported from `/alpha` subpath. diff --git a/.changeset/tasty-doors-switch.md b/.changeset/tasty-doors-switch.md deleted file mode 100644 index e35bf9cfa4..0000000000 --- a/.changeset/tasty-doors-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Explicitly set `exports: 'named'` for CJS builds, ensuring that they have e.g. `exports["default"] = catalogPlugin;` diff --git a/.changeset/ten-seals-wait.md b/.changeset/ten-seals-wait.md deleted file mode 100644 index 780422449c..0000000000 --- a/.changeset/ten-seals-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -The experimental plugin configuration has been removed. The trend line can now instead be hidden by setting `costInsights.hideTrendLine` to `true` in the configuration. diff --git a/.changeset/tender-experts-yell.md b/.changeset/tender-experts-yell.md deleted file mode 100644 index a4d321073b..0000000000 --- a/.changeset/tender-experts-yell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': minor ---- - -Added support for installing `ExtensionOverrides` via `createApp` options. As part of this change the `plugins` option has been renamed to `features`, and the `pluginLoader` has been renamed to `featureLoader`. diff --git a/.changeset/tender-pears-work.md b/.changeset/tender-pears-work.md deleted file mode 100644 index 7770e4c087..0000000000 --- a/.changeset/tender-pears-work.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -`RepoUrlPickerRepoName` now correctly handles value changes in allowed repos. diff --git a/.changeset/thick-dolphins-boil.md b/.changeset/thick-dolphins-boil.md deleted file mode 100644 index dd562e620c..0000000000 --- a/.changeset/thick-dolphins-boil.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-import': patch ---- - -The `app.title` configuration is now properly required to be a string. diff --git a/.changeset/thirty-coins-sneeze.md b/.changeset/thirty-coins-sneeze.md deleted file mode 100644 index 58a93065b8..0000000000 --- a/.changeset/thirty-coins-sneeze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/e2e-test-utils': minor ---- - -Initial release. diff --git a/.changeset/tiny-garlics-cheer.md b/.changeset/tiny-garlics-cheer.md deleted file mode 100644 index 992ed7f007..0000000000 --- a/.changeset/tiny-garlics-cheer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@techdocs/cli': patch ---- - -Restructured tests. diff --git a/.changeset/tiny-suns-deny.md b/.changeset/tiny-suns-deny.md deleted file mode 100644 index b00830c75c..0000000000 --- a/.changeset/tiny-suns-deny.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Bump dev dependencies `lerna@7.3.0` on the template diff --git a/.changeset/twelve-clouds-design.md b/.changeset/twelve-clouds-design.md deleted file mode 100644 index d71d6caec0..0000000000 --- a/.changeset/twelve-clouds-design.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -The E2E test setup based on Cypress has been replaced with one based on [Playwright](https://playwright.dev/). Migrating existing apps is not required as this is a standalone setup, only do so if you also want to switch from Cypress to Playwright. - -The scripts to run the E2E tests have been removed from `packages/app/package.json`, as they are now instead run from the root. Instead, a new script has been added to the root `package.json`, `yarn test:e2e`, which runs the E2E tests in development mode, unless `CI` is set in the environment. - -The Playwright setup uses utilities from the new `@backstage/e2e-test-utils` package to find and include all packages in the monorepo that have an `e2e-tests` folder. diff --git a/.changeset/twelve-days-walk.md b/.changeset/twelve-days-walk.md deleted file mode 100644 index 0b2d261c1a..0000000000 --- a/.changeset/twelve-days-walk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': minor ---- - -URL encode some well known unsafe characters in `RouteResolver` (and therefore `useRouteRef`) diff --git a/.changeset/twelve-mirrors-brush.md b/.changeset/twelve-mirrors-brush.md deleted file mode 100644 index 90725b5ec4..0000000000 --- a/.changeset/twelve-mirrors-brush.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -The experimental package discovery will now always use the package name for include and exclude filtering, rather than the full module id. Entries pointing to a subpath export will now instead have an `export` field specifying the subpath that the import is from. diff --git a/.changeset/twelve-snakes-sell.md b/.changeset/twelve-snakes-sell.md deleted file mode 100644 index 7f91b2910f..0000000000 --- a/.changeset/twelve-snakes-sell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend': patch ---- - -Set the default length limit to search query to 100. To override it, define `search.maxTermLength` in the config file. diff --git a/.changeset/twenty-bags-sin.md b/.changeset/twenty-bags-sin.md deleted file mode 100644 index 797fd5bfef..0000000000 --- a/.changeset/twenty-bags-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-insights': patch ---- - -Export `ScorecardInfo` and `ScorecardsList` components to be able to use manually queried check results directly. diff --git a/.changeset/twenty-carrots-smile.md b/.changeset/twenty-carrots-smile.md deleted file mode 100644 index 873af7dcd3..0000000000 --- a/.changeset/twenty-carrots-smile.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Add examples for `publish:Azure` scaffolder action. diff --git a/.changeset/twenty-masks-exist.md b/.changeset/twenty-masks-exist.md deleted file mode 100644 index 7e78cf0dec..0000000000 --- a/.changeset/twenty-masks-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-aws': minor ---- - -AwsEksClusterProcessor supports Entity callback function and passes in region when initialize EKS cluster diff --git a/.changeset/two-dingos-dream.md b/.changeset/two-dingos-dream.md deleted file mode 100644 index 9ebefacc69..0000000000 --- a/.changeset/two-dingos-dream.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-kubernetes-react': patch -'@backstage/plugin-kubernetes-common': patch ---- - -The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies diff --git a/.changeset/two-terms-play.md b/.changeset/two-terms-play.md deleted file mode 100644 index 6c7edc01db..0000000000 --- a/.changeset/two-terms-play.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-issues': patch ---- - -Filters out entities that belonged to a different github instance other than the one configured by the plugin diff --git a/.changeset/unlucky-experts-breathe.md b/.changeset/unlucky-experts-breathe.md deleted file mode 100644 index 018b1826d2..0000000000 --- a/.changeset/unlucky-experts-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Added support for the existing routing system. diff --git a/.changeset/violet-apes-beam.md b/.changeset/violet-apes-beam.md deleted file mode 100644 index 544dcf72b2..0000000000 --- a/.changeset/violet-apes-beam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-newrelic-dashboard': patch ---- - -Fixed React Warning: "Each child in a list should have a unique 'key' prop" during the rendering of `EntityNewRelicDashboardCard` diff --git a/.changeset/violet-beers-cross.md b/.changeset/violet-beers-cross.md deleted file mode 100644 index bdbb9da64e..0000000000 --- a/.changeset/violet-beers-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Change overlay header colors in the mobile menu to use navigation color from the theme diff --git a/.changeset/warm-drinks-argue.md b/.changeset/warm-drinks-argue.md deleted file mode 100644 index 5bd4fa63f1..0000000000 --- a/.changeset/warm-drinks-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-explore': patch ---- - -Create an experimental `ExploreSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. diff --git a/.changeset/wet-cows-brake.md b/.changeset/wet-cows-brake.md deleted file mode 100644 index 9e694d8452..0000000000 --- a/.changeset/wet-cows-brake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-react': patch ---- - -The filter options passed to `SearchResultGroupLayout` are now always explicitly rendered as strings by default. diff --git a/.changeset/wet-olives-wave.md b/.changeset/wet-olives-wave.md deleted file mode 100644 index 5b35e0ad90..0000000000 --- a/.changeset/wet-olives-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -added aria-label on api definition button for better a11y. diff --git a/.changeset/wet-timers-chew.md b/.changeset/wet-timers-chew.md deleted file mode 100644 index 3be6368331..0000000000 --- a/.changeset/wet-timers-chew.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -The `useHotCleanup` and `useHotMemoize` helpers are now deprecated, since hot module reloads for backend are being phased out. diff --git a/.changeset/wicked-rings-flash.md b/.changeset/wicked-rings-flash.md deleted file mode 100644 index b872c0c71f..0000000000 --- a/.changeset/wicked-rings-flash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-react': patch ---- - -Create `createSearchResultListItem` alpha version that only supports declarative integration. diff --git a/.changeset/wild-geese-occur.md b/.changeset/wild-geese-occur.md deleted file mode 100644 index b97620e7f5..0000000000 --- a/.changeset/wild-geese-occur.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Minor internal code cleanup. diff --git a/.changeset/wild-jobs-greet.md b/.changeset/wild-jobs-greet.md deleted file mode 100644 index fdbe6d56ac..0000000000 --- a/.changeset/wild-jobs-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Prevents root extension override and duplicated plugin extensions. diff --git a/.changeset/wild-queens-grab.md b/.changeset/wild-queens-grab.md deleted file mode 100644 index 287dc0482e..0000000000 --- a/.changeset/wild-queens-grab.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-playlist': patch ---- - -Updated Playlist read me with additional screenshots diff --git a/.changeset/wild-toys-arrive.md b/.changeset/wild-toys-arrive.md deleted file mode 100644 index 4aad036a96..0000000000 --- a/.changeset/wild-toys-arrive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-newrelic-dashboard': minor ---- - -Add storybook for newrelic-dashboard plugin. diff --git a/.changeset/yellow-numbers-own.md b/.changeset/yellow-numbers-own.md deleted file mode 100644 index 3a6e8937eb..0000000000 --- a/.changeset/yellow-numbers-own.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Added missing `.eslintignore` file - -To apply this change to an existing app, create a new `.eslintignore` file at the root of your project with the following content: - -```diff -+ playwright.config.ts -``` diff --git a/.changeset/yellow-rings-invent.md b/.changeset/yellow-rings-invent.md deleted file mode 100644 index f0335ff492..0000000000 --- a/.changeset/yellow-rings-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -MissingAnnotationEmptyState component can now dynamically generate a YAML example based off the current entity being used. diff --git a/.changeset/young-ducks-heal.md b/.changeset/young-ducks-heal.md deleted file mode 100644 index 28614e47bc..0000000000 --- a/.changeset/young-ducks-heal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-node': patch ---- - -Adding optional audience parameter to OAuthState type declaration diff --git a/.changeset/young-toes-knock.md b/.changeset/young-toes-knock.md deleted file mode 100644 index 6371dec193..0000000000 --- a/.changeset/young-toes-knock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-opencost': patch ---- - -Fix for broken image reference. diff --git a/docs/releases/v1.19.0-changelog.md b/docs/releases/v1.19.0-changelog.md new file mode 100644 index 0000000000..7397ccdba7 --- /dev/null +++ b/docs/releases/v1.19.0-changelog.md @@ -0,0 +1,3632 @@ +# Release v1.19.0 + +## @backstage/cli@0.23.0 + +### Minor Changes + +- 8defbd5434: Update typescript-eslint to 6.7.x, adding compatibility with TypeScript 5.2. + + This includes a major update on typescript-eslint, you can see the details in the [release notes](https://typescript-eslint.io/blog/announcing-typescript-eslint-v6/). + +- 7077dbf131: **BREAKING** The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior set `LEGACY_BACKEND_START`, which is recommended if you haven't migrated to the new backend system. + + This new command is no longer based on Webpack, but instead uses Node.js loaders to transpile on the fly. Rather than hot reloading modules the entire backend is now restarted on change, but the SQLite database state is still maintained across restarts via a parent process. + +### Patch Changes + +- 9468a67b92: In frontend builds and tests `process.env.HAS_REACT_DOM_CLIENT` will now be defined if `react-dom/client` is present, i.e. if using React 18. This allows for conditional imports of `react-dom/client`. + +- 68158034e8: Fix for the new backend `start` command to make it work on Windows. + +- 4f16e60e6d: Request slightly smaller pages of data from GitHub + +- 21cd3b1b24: Added a template for creating `node-library` packages with `yarn new`. + +- d0f26cfa4f: Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows. + +- 1ea20b0be5: Updated dependency `@typescript-eslint/eslint-plugin` to `6.7.5`. + +- 2ef6522552: Support for the `.icon.svg` extension has been deprecated and will be removed in the future. The implementation of this extension is too tied to a particular version of MUI and the SVGO, and it makes it harder to evolve the build system. We may introduce the ability to reintroduce this kind of functionality in the future through configuration for use in internal plugins, but for now we're forced to remove it. + + To migrate existing code, rename the `.icon.svg` file to `.tsx` and replace the `` element with `` from MUI and add necessary imports. For example: + + ```tsx + import React from 'react'; + import SvgIcon from '@material-ui/core/SvgIcon'; + import { IconComponent } from '@backstage/core-plugin-api'; + + export const CodeSceneIcon = (props: SvgIconProps) => ( + + + + + + ); + ``` + +- b9ec93430e: The scaffolder-module template now recommends usage of `createMockDirectory` instead of `mock-fs`. + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. + +- 425203f898: Fixed recursive reloading issues of the backend, caused by unwanted watched files. + +- 3ef18f8c06: Explicitly set `exports: 'named'` for CJS builds, ensuring that they have e.g. `exports["default"] = catalogPlugin;` + +- 7187f2953e: The experimental package discovery will now always use the package name for include and exclude filtering, rather than the full module id. Entries pointing to a subpath export will now instead have an `export` field specifying the subpath that the import is from. + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.10 + - @backstage/types@1.1.1 + +## @backstage/core-app-api@1.11.0 + +### Minor Changes + +- c9d9bfeca2: URL encode some well known unsafe characters in `RouteResolver` (and therefore `useRouteRef`) + +### Patch Changes + +- 29e4d8b76b: Fixed bug in `AppRouter` to determine the correct `signOutTargetUrl` if `app.baseUrl` contains a `basePath` +- acca17e91a: Wrap entire app in ``, enabling support for using translations outside plugins. +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- f1b349cfba: Fixed a bug in `TranslationApi` implementation where in some cases it wouldn't notify subscribers of language changes. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/core-plugin-api@1.7.0 + +### Minor Changes + +- 322bbcae24: Removed the exprimental plugin configuration API. The `__experimentalReconfigure()` from the plugin options as well as the `__experimentalConfigure()` method on plugin instances have both been removed. + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/e2e-test-utils@0.1.0 + +### Minor Changes + +- f5b41b27a9: Initial release. + +## @backstage/frontend-app-api@0.2.0 + +### Minor Changes + +- 4461d87d5a: Removed support for the new `useRouteRef`. +- 9d03dfe5e3: The `createApp` config option has been replaced by a new `configLoader` option. There is now also a `pluginLoader` option that can be used to dynamically load plugins into the app. +- d7c5d80c57: The hidden `'root'` extension has been removed and has instead been made an input of the `'core'` extension. The checks for rejecting configuration of the `'root'` extension to rejects configuration of the `'core'` extension instead. +- d920b8c343: Added support for installing `ExtensionOverrides` via `createApp` options. As part of this change the `plugins` option has been renamed to `features`, and the `pluginLoader` has been renamed to `featureLoader`. + +### Patch Changes + +- 322bbcae24: Internal update for removal of experimental plugin configuration API. +- f78ac58f88: Filters for discovered packages are now also applied at runtime. This makes it possible to disable packages through the `app.experimental.packages` config at runtime. +- 68ffb9e67d: The app will now reject any extensions that attach to nonexistent inputs. +- 5072824817: Implement `toString()` and `toJSON()` for extension instances. +- 1e60a9c3a5: Fixed an issue preventing the routing system to match subroutes +- 52366db5b3: Make themes configurable through extensions, and switched default themes to use extensions instead. +- 2ecd33618a: Added the `bindRoutes` option to `createApp`. +- e5a2956dd2: Register default api implementations when creating declarative integrated apps. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 06432f900c: Updates for `at` -> `attachTo` refactor. +- 1718ec75b7: Added support for the existing routing system. +- 66d51a4827: Prevents root extension override and duplicated plugin extensions. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/frontend-plugin-api@0.2.0 + +### Minor Changes + +- 06432f900c: Extension attachment point is now configured via `attachTo: { id, input }` instead of `at: 'id/input'`. +- 4461d87d5a: Removed support for the new `useRouteRef`. + +### Patch Changes + +- d3a37f55c0: Add support for `SidebarGroup` on the sidebar item extension. +- 2ecd33618a: Plugins can now be assigned `routes` and `externalRoutes` when created. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- c1e9ca6500: Added `createExtensionOverrides` which can be used to install a collection of extensions in an app that will replace any existing ones. +- 52366db5b3: Added `createThemeExtension` and `coreExtensionData.theme`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/types@1.1.1 + +## @techdocs/cli@1.6.0 + +### Minor Changes + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs. with the serve command using the `--mkdocs-config-file-name\` argument + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- 2b6e572051: Restructured tests. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.0 + +### Minor Changes + +- 6f142d5356: **BREAKING** `gcpIapAuthenticator.initialize()` is no longer `async` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.1.0 + +### Minor Changes + +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.1.0 + +### Minor Changes + +- ae34255836: Add new Pinniped auth module and authenticator to be used alongside the new Pinniped auth provider. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-node@0.4.0 + +### Minor Changes + +- 6f142d5356: **BREAKING**: The recently introduced `ProxyAuthenticator.initialize()` method is no longer `async` to match the way the OAuth equivalent is implemented. + +### Patch Changes + +- 6c2b0793bf: Fix for persisted scopes not being properly restored on sign-in. +- 8b8b1d23ae: Fixed cookie persisted scope not returned in OAuth refresh handler response. +- ae34255836: Adding optional audience parameter to OAuthState type declaration +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog@1.14.0 + +### Minor Changes + +- 28f1ab2e1a: The catalog plugin no longer implements the experimental reconfiguration API. The create button title can now instead be configured using the new experimental internationalization API, via the `catalogTranslationRef` exported at `/alpha`. For example: + + ```ts + import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'; + + const app = createApp({ + __experimentalTranslations: { + resources: [ + createTranslationMessages({ + ref: catalogTranslationRef, + catalog_page_create_button_title: 'Create Software', + }), + ], + }, + }); + ``` + +- f3561a2935: include owner chip in catalog search result item + +### Patch Changes + +- 7c4a8e4d5f: Create an experimental `CatalogSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- 0296f272b4: The \`spec.lifecycle' field in entities will now always be rendered as a string. +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- e5a2956dd2: Migrate catalog api to declarative integration system, it is exported from `/alpha` subpath. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-catalog-backend@1.14.0 + +### Minor Changes + +- 78af9433c8: Instrumenting some missing metrics with `OpenTelemetry` + +### Patch Changes + +- 7a2e2924c7: Marked the `LocationEntityProcessor` as deprecated, as it is no longer used internally since way back and can even be harmful at this point. +- 0b55f773a7: Removed some unused dependencies +- 348e8c1cdb: Fixes a bug where eagerly deleted entities did not properly trigger re-stitching of entities that they had relations to. +- b97e9790f0: Internal refactors, laying the foundation for later introducing deferred stitching (see #18062). +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-catalog-backend-module-aws@0.3.0 + +### Minor Changes + +- 5abc2fd4d6: AwsEksClusterProcessor supports Entity callback function and passes in region when initialize EKS cluster + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-github-org@0.1.0 + +### Minor Changes + +- c101e683d5: Added `catalogModuleGithubOrgEntityProvider` to ingest users and teams from multiple Github organizations. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend-module-github@0.4.4 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-graphql@0.4.0 + +### Minor Changes + +- 9def1e95ab: This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-graphql-backend@0.2.0 + +### Minor Changes + +- 9def1e95ab: This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-graphql@0.4.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-jenkins@0.9.0 + +### Minor Changes + +- 411896faf9: Added JobRunTable Component. + Added new Route and extended Api to get buildJobs. + Actions column has a new icon button, clicking on which takes us to page where we + can see all the job runs. + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 1a05cf34f6: Extend EntityJenkinsContent to receive columns as prop +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-jenkins-common@0.1.20 + +## @backstage/plugin-jenkins-backend@0.3.0 + +### Minor Changes + +- 411896faf9: Added JobRunTable Component. + Added new Route and extended Api to get buildJobs. + Actions column has a new icon button, clicking on which takes us to page where we + can see all the job runs. + +### Patch Changes + +- 930ac236d8: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-jenkins-common@0.1.20 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-kubernetes@0.11.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- b0aca1a798: Updated dependency `xterm-addon-attach` to `^0.9.0`. + Updated dependency `xterm-addon-fit` to `^0.8.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-react@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-kubernetes-backend@0.13.0 + +### Minor Changes + +- ae943c3bb1: **BREAKING** Allow passing undefined `labelSelector` to `KubernetesFetcher` + + `KubernetesFetch` no longer auto-adds `labelSelector` when empty string was passed. + This is only applicable if you have custom ObjectProvider implementation, as build-in `KubernetesFanOutHandler` already does this + +### Patch Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-node@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-kubernetes-common@0.7.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-kubernetes-node@0.1.0 + +### Minor Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-kubernetes-react@0.1.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 4262e12921: Handle mixed decimals and bigint when calculating k8s resource usage +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-newrelic-dashboard@0.3.0 + +### Minor Changes + +- d7eba6cab4: Changes in `newrelic-dashboard` plugin: + + - Make DashboardSnapshotList component public + - Settle discrepancies in the exported API + - Deprecate DashboardSnapshotComponent + +- e605ea4906: Add storybook for newrelic-dashboard plugin. + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 61d55942ae: Fix the styles for NewRelicDashboard, add more responsiveness +- 5194a51a1c: Fixed React Warning: "Each child in a list should have a unique 'key' prop" during the rendering of `EntityNewRelicDashboardCard` +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-scaffolder-backend@1.18.0 + +### Minor Changes + +- dea0aafda7: Updated `publish:gitlab` action properties to support additional Gitlab project settings: + + - general project settings provided by gitlab project create API (new `settings` property) + - branch level settings to create additional branches and make them protected (new `branches` property) + - project level environment variables settings (new `projectVariables` property) + + Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. + +- f41099bb31: Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. + +### Patch Changes + +- 7dd82cc07e: Add examples for `github:issues:label` scaffolder action & improve related tests +- 733ddf7130: Add examples for `publish:Azure` scaffolder action. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-techdocs@1.8.0 + +### Minor Changes + +- 27740caa2d: Added experimental support for declarative integration via the `/alpha` subpath. + +### Patch Changes + +- 4918f65ab2: Create an experimental `TechDocsSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- 3605370af6: Improved `DocsTable` to display pagination controls dynamically, appearing only when needed. +- 0296f272b4: The \`spec.lifecycle' field in entities will now always be rendered as a string. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 9468a67b92: Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. +- df449a7a31: Add kind column by default to TechDocsTable +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-techdocs-backend@1.8.0 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-techdocs-node@1.9.0 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs. with the serve command using the `--mkdocs-config-file-name\` argument + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/app-defaults@1.4.4 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + +## @backstage/backend-app-api@0.5.6 + +### Patch Changes + +- 74491c9602: Moved `HostDiscovery` from `@backstage/backend-common`. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/backend-common@0.19.8 + +### Patch Changes + +- 74491c9602: The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. +- b95d66d4ea: Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. +- b94f32271e: Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository +- 0b55f773a7: Removed some unused dependencies +- 4c39e38f1e: Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- a250ad775f: Removed `mock-fs` dev dependency. +- 2a40cd46a8: Adds the optional flag for useRedisSets for the Redis cache to the config. +- 1c3d6fa2b2: The `useHotCleanup` and `useHotMemoize` helpers are now deprecated, since hot module reloads for backend are being phased out. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + +## @backstage/backend-defaults@0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/backend-dev-utils@0.1.2 + +### Patch Changes + +- afa48341fb: Fix an issue where early IPC responses would be lost. + +## @backstage/backend-openapi-utils@0.0.5 + +### Patch Changes + +- 7c83975531: Adds new public utility types for common OpenAPI values, like request and response shapes and parameters available on an endpoint. + + **deprecated** `internal` namespace + The internal namespace will continue to be exported but now uses OpenAPI format for path parameters. You should use the new utility types. + +- Updated dependencies + - @backstage/errors@1.2.3 + +## @backstage/backend-plugin-api@0.6.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/backend-tasks@0.5.11 + +### Patch Changes + +- 5db102bfdf: Instrument `backend-tasks` with some counters and histograms for duration. + + `backend_tasks.task.runs.count`: Counter with the total number of times a task has been run. + `backend_tasks.task.runs.duration`: Histogram with the run durations for each task. + + Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping. + +- ddd76ac98d: Fix bug where backend tasks that are defined with HumanDuration are immediately triggered on application startup + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/backend-test-utils@0.2.7 + +### Patch Changes + +- a250ad775f: Added `createMockDirectory()` to help out with file system mocking in tests. +- 5ddc03813e: Remove third type parameter used for `MockInstance`, in order to be compatible with older versions of `@types/jest`. +- 74491c9602: Updated to import `HostDiscovery` from `@backstage/backend-app-api`. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/catalog-client@1.4.5 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/catalog-model@1.4.3 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/cli-common@0.1.13 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. + +## @backstage/cli-node@0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + +## @backstage/codemods@0.1.46 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## @backstage/config@1.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/config-loader@1.5.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 30c553c1d2: Updated dependency `typescript-json-schema` to `^0.61.0`. +- 773ea341d2: The `FileConfigSource` will now retry file reading after a short delay if it reads an empty file. This is to avoid flakiness during watch mode where change events can trigger before the file content has been written. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/core-components@0.13.6 + +### Patch Changes + +- 4eab5cf901: The `TabbedLayout` component will now also navigate when clicking the active tab, which allows for navigation back from any sub routes. +- 0b55f773a7: Removed some unused dependencies +- 8a15360bb4: Fixed overflowing messages in `WarningPanel`. +- 997a71850c: Changed SupportButton menuitems to support text wrap +- 0296f272b4: Fixed the type declaration of `DependencyGraphProps`, the `defs` prop now expects `JSX.Element`s. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 16126dbe6a: Change overlay header colors in the mobile menu to use navigation color from the theme +- d19a827ef1: MissingAnnotationEmptyState component can now dynamically generate a YAML example based off the current entity being used. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/create-app@0.5.6 + +### Patch Changes + +- ba6a3b59c1: Removed duplicate `apple-touch-icon` link from `packages/app/public/index.html` that linked to nonexistent icon. + +- c8ec0dea4a: Create unique temp directory for each `create-app` execution. + +- e43d3eb1b7: Bumped create-app version. + +- b665f2ce65: Change base node image from node:18-bullseye-slim to node:18-bookworm-slim due to Docker build error on bullseye. + + You can apply these change to your own `Dockerfile` by replacing `node:18-bullseye-slim` with `node:18-bookworm-slim` + +- deed089a3d: Bump `cypress` to fix the end-to-end tests + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. + +- 04a3f65e15: Bump Docker base images to `node:18-bookworm-slim` to fix node compatibility issues raised during image build. + + You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bookworm-slim` + +- 9864f263ba: Bump dev dependencies `lerna@7.3.0` on the template + +- 5eacd5d213: The E2E test setup based on Cypress has been replaced with one based on [Playwright](https://playwright.dev/). Migrating existing apps is not required as this is a standalone setup, only do so if you also want to switch from Cypress to Playwright. + + The scripts to run the E2E tests have been removed from `packages/app/package.json`, as they are now instead run from the root. Instead, a new script has been added to the root `package.json`, `yarn test:e2e`, which runs the E2E tests in development mode, unless `CI` is set in the environment. + + The Playwright setup uses utilities from the new `@backstage/e2e-test-utils` package to find and include all packages in the monorepo that have an `e2e-tests` folder. + +- 8d2e640af4: Added missing `.eslintignore` file + + To apply this change to an existing app, create a new `.eslintignore` file at the root of your project with the following content: + + ```diff + + playwright.config.ts + ``` + +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## @backstage/dev-utils@1.0.22 + +### Patch Changes + +- 080d1beb2a: Moving development `dependencies` to `devDependencies` +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 9468a67b92: Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/app-defaults@1.4.4 + - @backstage/theme@0.4.3 + +## @backstage/errors@1.2.3 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/types@1.1.1 + +## @backstage/integration@1.7.1 + +### Patch Changes + +- 3963d0b885: Ensure that all relevant config fields are properly marked as secret +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/config@1.1.1 + +## @backstage/integration-aws-node@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + +## @backstage/integration-react@1.1.20 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/config@1.1.1 + +## @backstage/repo-tools@0.3.5 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.1.5 + +## @backstage/test-utils@1.4.4 + +### Patch Changes + +- 322bbcae24: Removed the alpha `MockPluginProvider` export since the plugin configuration API has been removed. +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/theme@0.4.3 + +### Patch Changes + +- 5ad5344756: Added support for string `fontSize` values (e.g. `"2.5rem"`) in themes in addition to numbers. Also added an optional `fontFamily` prop for header typography variants to allow further customization. + +## @backstage/version-bridge@1.0.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. + +## @backstage/plugin-adr@0.6.8 + +### Patch Changes + +- 499e34656e: Fix icon alignment in `AdrSearchResultListItem` +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 1204e7628e: Create an experimental `AdrSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/theme@0.4.3 + - @backstage/plugin-adr-common@0.2.16 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-adr-backend@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-adr-common@0.2.16 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-adr-common@0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-airbrake@0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/test-utils@1.4.4 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/dev-utils@1.0.22 + - @backstage/theme@0.4.3 + +## @backstage/plugin-airbrake-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-allure@0.1.41 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-analytics-module-ga@0.1.34 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-analytics-module-ga4@0.1.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-analytics-module-newrelic-browser@0.0.3 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-apache-airflow@0.2.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + +## @backstage/plugin-api-docs@0.9.12 + +### Patch Changes + +- 0117a6b47e: Adding `requestInterceptor` option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 18f1756908: added aria-label on api definition button for better a11y. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-api-docs-module-protoc-gen-doc@0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. + +## @backstage/plugin-apollo-explorer@0.1.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-app-backend@0.3.54 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config-loader@1.5.1 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.6 + +## @backstage/plugin-app-node@0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend@0.19.3 + +### Patch Changes + +- 9ff7935152: Fixed bug in oidc refresh handler, if token endpoints response on refresh request does not contain a scope, the requested scope is used. +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-backend-module-github-provider@0.1.3 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.0 + - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.3 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.3 + +## @backstage/plugin-auth-backend-module-github-provider@0.1.3 + +### Patch Changes + +- 5d32a58b5a: Fixed a bug where the GitHub authenticator did not properly persist granted OAuth scopes. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend-module-google-provider@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-azure-devops@0.3.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-devops-backend@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-sites@0.1.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-azure-sites-backend@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-badges@0.2.49 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-badges-backend@0.3.3 + +### Patch Changes + +- 817f2acbb1: Make sure the default badge factory is used if nothing is defined +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + +## @backstage/plugin-bazaar@0.2.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + +## @backstage/plugin-bazaar-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-bitbucket-cloud-common@0.2.13 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + +## @backstage/plugin-bitrise@0.1.52 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-catalog-backend-module-azure@0.1.25 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-bitbucket-cloud-common@0.2.13 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.21 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-bitbucket-cloud-common@0.2.13 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.19 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.22 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-github@0.4.4 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- 0b55f773a7: Removed some unused dependencies +- 4f16e60e6d: Request slightly smaller pages of data from GitHub +- b4b1cbf9fa: Make `defaultUserTransformer` resolve to `UserEntity` instead of `Entity` +- c101e683d5: Removed `catalogModuleGithubOrgEntityProvider`. Import from `@backstage/plugin-catalog-backend-module-github-org` instead. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-catalog-backend-module-gitlab@0.3.3 + +### Patch Changes + +- 4f70fdfc93: fix: use REST API to get root group memberships for GitLab SaaS users listing + + This API is the only one that shows `email` field for enterprise users and + allows to filter out bot users not using a license using the `is_using_seat` + field. + + We also added the annotation `gitlab.com/saml-external-uid` taking the value + of `group_saml_identity.extern_uid` of the `groups/:group-id/members` endpoint + response. This is useful in case you want to create a `SignInResolver` that + references the user with the id of your identity provider (e.g. OneLogin). + + ref: + + + + +- 890e3b5ad4: Make sure to include the error message when ingestion fails + +- 0b55f773a7: Removed some unused dependencies + +- 6ae7f12abb: Make sure the archived projects are skipped with the Gitlab API + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.10 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.21 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.13 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.23 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.11 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-catalog-common@1.0.17 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-catalog-graph@0.2.37 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-import@0.10.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The `app.title` configuration is now properly required to be a string. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-node@1.4.7 + +### Patch Changes + +- 7a2e2924c7: Added docs to `processingResult` +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-react@1.8.5 + +### Patch Changes + +- a402e1dfb9: Fixed an issue causing `EntityPage` to show an error for entities containing special characters +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The `spec.type` field in entities will now always be rendered as a string. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-cicd-statistics@0.1.27 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-cicd-statistics@0.1.27 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-circleci@0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-cloudbuild@0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-code-climate@0.1.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-code-coverage@0.2.18 + +### Patch Changes + +- 88b0b32547: Fixed the coverage history statistics to compare newest with oldest record +- 0296f272b4: The warning for missing code coverage will now render the entity as a reference. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- a468544fa9: Updated layout to improve contrasts and consistency with other plugins +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-code-coverage-backend@0.2.20 + +### Patch Changes + +- 4aa27aa200: Added option to set body size limit +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + +## @backstage/plugin-codescene@0.1.18 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-config-schema@0.1.46 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-cost-insights@0.12.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- ba4820883c: Updated dependency `@types/pluralize` to `^0.0.31`. +- 959aa2a09f: The experimental plugin configuration has been removed. The trend line can now instead be hidden by setting `costInsights.hideTrendLine` to `true` in the configuration. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-cost-insights-common@0.1.2 + +## @backstage/plugin-devtools@0.1.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5 + +## @backstage/plugin-devtools-backend@0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-devtools-common@0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-dynatrace@7.0.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-entity-feedback@0.2.8 + +### Patch Changes + +- 48c8b93e98: Added tooltip to like dislike buttons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-feedback-backend@0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-validation@0.1.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-events-backend@0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-azure@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-gerrit@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-github@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-gitlab@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-test-utils@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-node@0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-explore@0.4.11 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0f10c53a05: Create an experimental `ExploreSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-explore-react@0.0.32 + - @backstage/theme@0.4.3 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-explore-backend@0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-explore-react@0.0.32 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-explore-common@0.0.2 + +## @backstage/plugin-firehydrant@0.2.9 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-fossa@0.2.57 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-gcalendar@0.3.19 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-gcp-projects@0.3.42 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-git-release-manager@0.3.38 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-github-actions@0.6.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-github-deployments@0.1.56 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-github-issues@0.2.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 7bd0a8ab3c: Filters out entities that belonged to a different github instance other than the one configured by the plugin +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-github-pull-requests-board@0.1.19 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-gitops-profiles@0.3.41 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-gocd@0.1.31 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-graphiql@0.2.55 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-graphql-voyager@0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-home@0.5.9 + +### Patch Changes + +- f997f771da: Adds Top/Recently Visited components to homepage +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-home-react@0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + +## @backstage/plugin-ilert@0.2.14 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-jenkins-common@0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-kafka@0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-kafka-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-kubernetes-cluster@0.0.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-react@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-lighthouse@0.4.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/plugin-lighthouse-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/plugin-lighthouse-common@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + +## @backstage/plugin-linguist@0.1.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-linguist-backend@0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-microsoft-calendar@0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-newrelic@0.3.41 + +### Patch Changes + +- ce50a15506: Fixed sorting and searching in the NewRelic table. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-nomad@0.1.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-nomad-backend@0.1.8 + +### Patch Changes + +- 6822918c50: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-octopus-deploy@0.2.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-opencost@0.2.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 777b9a16a4: Fix for broken image reference. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-org@0.6.15 + +### Patch Changes + +- dc5b6b971b: Fixed the display of OwnershipCard with aggregated relations by loading relations when getting children of entity. + This allows the already existing recursive method to work properly when children of entity have children themselves. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-org-react@0.1.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + +## @backstage/plugin-pagerduty@0.6.6 + +### Patch Changes + +- b9ce306814: Minor fix to avoid usage of deprecated prop +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + +## @backstage/plugin-periskop@0.1.23 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-periskop-backend@0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-permission-backend@0.5.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-permission-common@0.7.9 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-permission-node@0.7.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-permission-react@0.4.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-playlist@0.1.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 65498193e8: Updated Playlist read me with additional screenshots +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-playlist-common@0.1.11 + +## @backstage/plugin-playlist-backend@0.3.10 + +### Patch Changes + +- 9e46f5ff49: Added support to the playlist plugin for the new backend +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-playlist-common@0.1.11 + +## @backstage/plugin-playlist-common@0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-proxy-backend@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-puppetdb@0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-rollbar@0.4.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-rollbar-backend@0.1.51 + +### Patch Changes + +- 407f4284be: ensure rollbar token is hidden +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + +## @backstage/plugin-scaffolder@1.15.1 + +### Patch Changes + +- b337d78c3b: fixed issue related template editor fails with multiple templates per file. +- ff2ab02690: Make entity picker more reliable with only one available entity +- 83e4a42ccd: Display log visibility button on the template panel +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 4c70fe497d: `RepoUrlPickerRepoName` now correctly handles value changes in allowed repos. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.30 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.23 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-common@1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-scaffolder-node@0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-scaffolder-react@1.5.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-search@1.4.1 + +### Patch Changes + +- e5a2956dd2: Create an experimental search plugin that is compatible with the declarative integration system, it is exported from `/alpha` subpath. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: Minor internal code cleanup. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend@1.4.6 + +### Patch Changes + +- 16be6f9473: Set the default length limit to search query to 100. To override it, define `search.maxTermLength` in the config file. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-catalog@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.9 + +### Patch Changes + +- 3963d0b885: Ensure that all relevant config fields are properly marked as secret +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-explore@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-pg@0.5.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-techdocs@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-node@1.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-common@1.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-search-react@1.7.1 + +### Patch Changes + +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The filter options passed to `SearchResultGroupLayout` are now always explicitly rendered as strings by default. +- 703a4ffc5b: Create `createSearchResultListItem` alpha version that only supports declarative integration. +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-sentry@0.5.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-shortcuts@0.3.15 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-sonarqube@0.7.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-sonarqube-react@0.1.9 + +## @backstage/plugin-sonarqube-backend@0.2.8 + +### Patch Changes + +- a5d592d0ad: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-sonarqube-react@0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-splunk-on-call@0.4.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-stack-overflow@0.1.21 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-stack-overflow-backend@0.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-stackstorm@0.1.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-tech-insights@0.3.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 21f409d776: Export `ScorecardInfo` and `ScorecardsList` components to be able to use manually queried check results directly. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend@0.5.20 + +### Patch Changes + +- cc7dddfa7f: Increase the maximum allowed length of an entity filter for tech insights fact schemas. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.38 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/config@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-node@0.4.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-radar@0.6.9 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- c09d2fa1d6: Added experimental support for the declarative integration. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.22 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog@1.14.0 + - @backstage/test-utils@1.4.4 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + +## @backstage/plugin-techdocs-react@1.1.12 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-todo@0.2.28 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-todo-backend@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + +## @backstage/plugin-user-settings@0.7.11 + +### Patch Changes + +- 18c8dee6f5: Added experimental support for declarative integration via the `/alpha` subpath. +- d1b637d005: Fixed a bug where the theme icons would not be colored according to their active state. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-user-settings-backend@0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + +## @backstage/plugin-vault@0.1.20 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-vault-backend@0.3.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-xcmetrics@0.2.44 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## example-app@0.2.88 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/plugin-pagerduty@0.6.6 + - @backstage/plugin-org@0.6.15 + - @backstage/plugin-code-coverage@0.2.18 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-home@0.5.9 + - @backstage/plugin-newrelic@0.3.41 + - @backstage/plugin-user-settings@0.7.11 + - @backstage/plugin-scaffolder@1.15.1 + - @backstage/core-components@0.13.6 + - @backstage/plugin-entity-feedback@0.2.8 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-tech-radar@0.6.9 + - @backstage/plugin-adr@0.6.8 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/plugin-search@1.4.1 + - @backstage/plugin-jenkins@0.9.0 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-api-docs@0.9.12 + - @backstage/plugin-kubernetes@0.11.0 + - @backstage/plugin-airbrake@0.3.25 + - @backstage/plugin-apache-airflow@0.2.16 + - @backstage/plugin-azure-devops@0.3.7 + - @backstage/plugin-azure-sites@0.1.14 + - @backstage/plugin-badges@0.2.49 + - @backstage/plugin-catalog-graph@0.2.37 + - @backstage/plugin-catalog-import@0.10.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4 + - @backstage/plugin-circleci@0.3.25 + - @backstage/plugin-cloudbuild@0.3.25 + - @backstage/plugin-cost-insights@0.12.14 + - @backstage/plugin-devtools@0.1.5 + - @backstage/plugin-dynatrace@7.0.5 + - @backstage/plugin-explore@0.4.11 + - @backstage/plugin-gcalendar@0.3.19 + - @backstage/plugin-gcp-projects@0.3.42 + - @backstage/plugin-github-actions@0.6.6 + - @backstage/plugin-gocd@0.1.31 + - @backstage/plugin-kafka@0.3.25 + - @backstage/plugin-kubernetes-cluster@0.0.1 + - @backstage/plugin-lighthouse@0.4.10 + - @backstage/plugin-linguist@0.1.10 + - @backstage/plugin-microsoft-calendar@0.1.8 + - @backstage/plugin-newrelic-dashboard@0.3.0 + - @backstage/plugin-nomad@0.1.6 + - @backstage/plugin-octopus-deploy@0.2.7 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-playlist@0.1.17 + - @backstage/plugin-puppetdb@0.1.8 + - @backstage/plugin-rollbar@0.4.25 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/plugin-sentry@0.5.10 + - @backstage/plugin-shortcuts@0.3.15 + - @backstage/plugin-stack-overflow@0.1.21 + - @backstage/plugin-stackstorm@0.1.7 + - @backstage/plugin-tech-insights@0.3.17 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/plugin-todo@0.2.28 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.7 + +## example-app-next@0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/plugin-pagerduty@0.6.6 + - @backstage/plugin-org@0.6.15 + - @backstage/plugin-code-coverage@0.2.18 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-home@0.5.9 + - @backstage/plugin-newrelic@0.3.41 + - @backstage/plugin-user-settings@0.7.11 + - @backstage/plugin-scaffolder@1.15.1 + - @backstage/core-components@0.13.6 + - @backstage/plugin-entity-feedback@0.2.8 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-tech-radar@0.6.9 + - @backstage/plugin-adr@0.6.8 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/plugin-search@1.4.1 + - @backstage/plugin-jenkins@0.9.0 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-api-docs@0.9.12 + - @backstage/plugin-kubernetes@0.11.0 + - @backstage/plugin-airbrake@0.3.25 + - @backstage/plugin-apache-airflow@0.2.16 + - @backstage/plugin-azure-devops@0.3.7 + - @backstage/plugin-azure-sites@0.1.14 + - @backstage/plugin-badges@0.2.49 + - @backstage/plugin-catalog-graph@0.2.37 + - @backstage/plugin-catalog-import@0.10.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4 + - @backstage/plugin-circleci@0.3.25 + - @backstage/plugin-cloudbuild@0.3.25 + - @backstage/plugin-cost-insights@0.12.14 + - @backstage/plugin-devtools@0.1.5 + - @backstage/plugin-dynatrace@7.0.5 + - @backstage/plugin-explore@0.4.11 + - @backstage/plugin-gcalendar@0.3.19 + - @backstage/plugin-gcp-projects@0.3.42 + - @backstage/plugin-github-actions@0.6.6 + - @backstage/plugin-gocd@0.1.31 + - @backstage/plugin-kafka@0.3.25 + - @backstage/plugin-lighthouse@0.4.10 + - @backstage/plugin-linguist@0.1.10 + - @backstage/plugin-microsoft-calendar@0.1.8 + - @backstage/plugin-newrelic-dashboard@0.3.0 + - @backstage/plugin-octopus-deploy@0.2.7 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-playlist@0.1.17 + - @backstage/plugin-puppetdb@0.1.8 + - @backstage/plugin-rollbar@0.4.25 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/plugin-sentry@0.5.10 + - @backstage/plugin-shortcuts@0.3.15 + - @backstage/plugin-stack-overflow@0.1.21 + - @backstage/plugin-stackstorm@0.1.7 + - @backstage/plugin-tech-insights@0.3.17 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/plugin-todo@0.2.28 + - @backstage/theme@0.4.3 + - app-next-example-plugin@0.0.2 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.7 + +## app-next-example-plugin@0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-components@0.13.6 + +## example-backend@0.2.88 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8 + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-scaffolder-backend@1.18.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.9 + - @backstage/integration@1.7.1 + - @backstage/plugin-playlist-backend@0.3.10 + - @backstage/plugin-techdocs-backend@1.8.0 + - @backstage/plugin-auth-backend@0.19.3 + - @backstage/plugin-rollbar-backend@0.1.51 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/plugin-graphql-backend@0.2.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-badges-backend@0.3.3 + - @backstage/plugin-tech-insights-backend@0.5.20 + - @backstage/plugin-kubernetes-backend@0.13.0 + - @backstage/plugin-jenkins-backend@0.3.0 + - @backstage/plugin-code-coverage-backend@0.2.20 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.23 + - @backstage/plugin-search-backend@1.4.6 + - example-app@0.2.88 + - @backstage/plugin-lighthouse-backend@0.3.3 + - @backstage/plugin-linguist-backend@0.5.3 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/plugin-adr-backend@0.4.3 + - @backstage/plugin-app-backend@0.3.54 + - @backstage/plugin-azure-devops-backend@0.4.3 + - @backstage/plugin-azure-sites-backend@0.1.16 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-devtools-backend@0.2.3 + - @backstage/plugin-entity-feedback-backend@0.2.3 + - @backstage/plugin-events-backend@0.2.15 + - @backstage/plugin-explore-backend@0.0.16 + - @backstage/plugin-kafka-backend@0.3.3 + - @backstage/plugin-permission-backend@0.5.29 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-proxy-backend@0.4.3 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.7 + - @backstage/plugin-search-backend-module-pg@0.5.15 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.38 + - @backstage/plugin-todo-backend@0.3.4 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## example-backend-next@0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8 + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-sonarqube-backend@0.2.8 + - @backstage/plugin-scaffolder-backend@1.18.0 + - @backstage/plugin-playlist-backend@0.3.10 + - @backstage/plugin-techdocs-backend@1.8.0 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/plugin-badges-backend@0.3.3 + - @backstage/plugin-kubernetes-backend@0.13.0 + - @backstage/plugin-jenkins-backend@0.3.0 + - @backstage/plugin-search-backend@1.4.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-lighthouse-backend@0.3.3 + - @backstage/plugin-linguist-backend@0.5.3 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/backend-defaults@0.2.6 + - @backstage/plugin-adr-backend@0.4.3 + - @backstage/plugin-app-backend@0.3.54 + - @backstage/plugin-azure-devops-backend@0.4.3 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-devtools-backend@0.2.3 + - @backstage/plugin-entity-feedback-backend@0.2.3 + - @backstage/plugin-permission-backend@0.5.29 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.3 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-proxy-backend@0.4.3 + - @backstage/plugin-todo-backend@0.3.4 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/backend-plugin-manager@0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-events-backend@0.2.15 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## e2e-test@0.2.8 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.6 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + +## techdocs-cli-embedded-app@0.2.87 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/test-utils@1.4.4 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @internal/plugin-todo-list@1.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @internal/plugin-todo-list-backend@1.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @internal/plugin-todo-list-common@1.0.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9 diff --git a/package.json b/package.json index b50e087aa7..80b3d4a374 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "jest-haste-map@^29.4.3": "patch:jest-haste-map@npm%3A29.4.3#./.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch", "mock-fs@^5.2.0": "patch:mock-fs@npm%3A5.2.0#./.yarn/patches/mock-fs-npm-5.2.0-5103a7b507.patch" }, - "version": "1.19.0-next.2", + "version": "1.19.0", "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3" diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index ce6bdb23fa..d212580484 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/app-defaults +## 1.4.4 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + ## 1.4.4-next.2 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 7695d128e7..40507f0bb9 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": "1.4.4-next.2", + "version": "1.4.4", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app-next-example-plugin/CHANGELOG.md b/packages/app-next-example-plugin/CHANGELOG.md index 10874da64a..3402944211 100644 --- a/packages/app-next-example-plugin/CHANGELOG.md +++ b/packages/app-next-example-plugin/CHANGELOG.md @@ -1,5 +1,13 @@ # app-next-example-plugin +## 0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-components@0.13.6 + ## 0.0.2-next.2 ### Patch Changes diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index 6304dcd028..73666a569d 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -1,7 +1,7 @@ { "name": "app-next-example-plugin", "description": "Backstage internal example plugin", - "version": "0.0.2-next.2", + "version": "0.0.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index 3195255f36..0a80d6d902 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,82 @@ # example-app-next +## 0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/plugin-pagerduty@0.6.6 + - @backstage/plugin-org@0.6.15 + - @backstage/plugin-code-coverage@0.2.18 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-home@0.5.9 + - @backstage/plugin-newrelic@0.3.41 + - @backstage/plugin-user-settings@0.7.11 + - @backstage/plugin-scaffolder@1.15.1 + - @backstage/core-components@0.13.6 + - @backstage/plugin-entity-feedback@0.2.8 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-tech-radar@0.6.9 + - @backstage/plugin-adr@0.6.8 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/plugin-search@1.4.1 + - @backstage/plugin-jenkins@0.9.0 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-api-docs@0.9.12 + - @backstage/plugin-kubernetes@0.11.0 + - @backstage/plugin-airbrake@0.3.25 + - @backstage/plugin-apache-airflow@0.2.16 + - @backstage/plugin-azure-devops@0.3.7 + - @backstage/plugin-azure-sites@0.1.14 + - @backstage/plugin-badges@0.2.49 + - @backstage/plugin-catalog-graph@0.2.37 + - @backstage/plugin-catalog-import@0.10.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4 + - @backstage/plugin-circleci@0.3.25 + - @backstage/plugin-cloudbuild@0.3.25 + - @backstage/plugin-cost-insights@0.12.14 + - @backstage/plugin-devtools@0.1.5 + - @backstage/plugin-dynatrace@7.0.5 + - @backstage/plugin-explore@0.4.11 + - @backstage/plugin-gcalendar@0.3.19 + - @backstage/plugin-gcp-projects@0.3.42 + - @backstage/plugin-github-actions@0.6.6 + - @backstage/plugin-gocd@0.1.31 + - @backstage/plugin-kafka@0.3.25 + - @backstage/plugin-lighthouse@0.4.10 + - @backstage/plugin-linguist@0.1.10 + - @backstage/plugin-microsoft-calendar@0.1.8 + - @backstage/plugin-newrelic-dashboard@0.3.0 + - @backstage/plugin-octopus-deploy@0.2.7 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-playlist@0.1.17 + - @backstage/plugin-puppetdb@0.1.8 + - @backstage/plugin-rollbar@0.4.25 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/plugin-sentry@0.5.10 + - @backstage/plugin-shortcuts@0.3.15 + - @backstage/plugin-stack-overflow@0.1.21 + - @backstage/plugin-stackstorm@0.1.7 + - @backstage/plugin-tech-insights@0.3.17 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/plugin-todo@0.2.28 + - @backstage/theme@0.4.3 + - app-next-example-plugin@0.0.2 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.7 + ## 0.0.2-next.2 ### Patch Changes diff --git a/packages/app-next/package.json b/packages/app-next/package.json index b1d158fb9f..0b0dcd7429 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.2-next.2", + "version": "0.0.2", "private": true, "backstage": { "role": "frontend" diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index dc7635f51a..f339cf74da 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,82 @@ # example-app +## 0.2.88 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/plugin-pagerduty@0.6.6 + - @backstage/plugin-org@0.6.15 + - @backstage/plugin-code-coverage@0.2.18 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-home@0.5.9 + - @backstage/plugin-newrelic@0.3.41 + - @backstage/plugin-user-settings@0.7.11 + - @backstage/plugin-scaffolder@1.15.1 + - @backstage/core-components@0.13.6 + - @backstage/plugin-entity-feedback@0.2.8 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-tech-radar@0.6.9 + - @backstage/plugin-adr@0.6.8 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/plugin-search@1.4.1 + - @backstage/plugin-jenkins@0.9.0 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-api-docs@0.9.12 + - @backstage/plugin-kubernetes@0.11.0 + - @backstage/plugin-airbrake@0.3.25 + - @backstage/plugin-apache-airflow@0.2.16 + - @backstage/plugin-azure-devops@0.3.7 + - @backstage/plugin-azure-sites@0.1.14 + - @backstage/plugin-badges@0.2.49 + - @backstage/plugin-catalog-graph@0.2.37 + - @backstage/plugin-catalog-import@0.10.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4 + - @backstage/plugin-circleci@0.3.25 + - @backstage/plugin-cloudbuild@0.3.25 + - @backstage/plugin-cost-insights@0.12.14 + - @backstage/plugin-devtools@0.1.5 + - @backstage/plugin-dynatrace@7.0.5 + - @backstage/plugin-explore@0.4.11 + - @backstage/plugin-gcalendar@0.3.19 + - @backstage/plugin-gcp-projects@0.3.42 + - @backstage/plugin-github-actions@0.6.6 + - @backstage/plugin-gocd@0.1.31 + - @backstage/plugin-kafka@0.3.25 + - @backstage/plugin-kubernetes-cluster@0.0.1 + - @backstage/plugin-lighthouse@0.4.10 + - @backstage/plugin-linguist@0.1.10 + - @backstage/plugin-microsoft-calendar@0.1.8 + - @backstage/plugin-newrelic-dashboard@0.3.0 + - @backstage/plugin-nomad@0.1.6 + - @backstage/plugin-octopus-deploy@0.2.7 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-playlist@0.1.17 + - @backstage/plugin-puppetdb@0.1.8 + - @backstage/plugin-rollbar@0.4.25 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/plugin-sentry@0.5.10 + - @backstage/plugin-shortcuts@0.3.15 + - @backstage/plugin-stack-overflow@0.1.21 + - @backstage/plugin-stackstorm@0.1.7 + - @backstage/plugin-tech-insights@0.3.17 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/plugin-todo@0.2.28 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.7 + ## 0.2.88-next.2 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index ce344d1aa9..59aa16734e 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.88-next.2", + "version": "0.2.88", "private": true, "backstage": { "role": "frontend" diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index dc81b18678..efc72cefc8 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/backend-app-api +## 0.5.6 + +### Patch Changes + +- 74491c9602: Moved `HostDiscovery` from `@backstage/backend-common`. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.5.6-next.2 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index c83a4acfd7..48a3b7a05b 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-app-api", "description": "Core API used by Backstage backend apps", - "version": "0.5.6-next.2", + "version": "0.5.6", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 5a84733f86..50216d5139 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/backend-common +## 0.19.8 + +### Patch Changes + +- 74491c9602: The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. +- b95d66d4ea: Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. +- b94f32271e: Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository +- 0b55f773a7: Removed some unused dependencies +- 4c39e38f1e: Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- a250ad775f: Removed `mock-fs` dev dependency. +- 2a40cd46a8: Adds the optional flag for useRedisSets for the Redis cache to the config. +- 1c3d6fa2b2: The `useHotCleanup` and `useHotMemoize` helpers are now deprecated, since hot module reloads for backend are being phased out. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + ## 0.19.8-next.2 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 9ca46d9473..11facfa7ce 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.19.8-next.2", + "version": "0.19.8", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index c4e9ef1026..6c9089fd06 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-defaults +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + ## 0.2.6-next.2 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 9b901f0e74..c843bbc412 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-defaults", "description": "Backend defaults used by Backstage backend apps", - "version": "0.2.6-next.2", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-dev-utils/CHANGELOG.md b/packages/backend-dev-utils/CHANGELOG.md index 3710cf3bd5..f1d1887b78 100644 --- a/packages/backend-dev-utils/CHANGELOG.md +++ b/packages/backend-dev-utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/backend-dev-utils +## 0.1.2 + +### Patch Changes + +- afa48341fb: Fix an issue where early IPC responses would be lost. + ## 0.1.2-next.0 ### Patch Changes diff --git a/packages/backend-dev-utils/package.json b/packages/backend-dev-utils/package.json index 8d461b46cf..b6156e622c 100644 --- a/packages/backend-dev-utils/package.json +++ b/packages/backend-dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-dev-utils", - "version": "0.1.2-next.0", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index b09af35602..171d82887c 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,44 @@ # example-backend-next +## 0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8 + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-sonarqube-backend@0.2.8 + - @backstage/plugin-scaffolder-backend@1.18.0 + - @backstage/plugin-playlist-backend@0.3.10 + - @backstage/plugin-techdocs-backend@1.8.0 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/plugin-badges-backend@0.3.3 + - @backstage/plugin-kubernetes-backend@0.13.0 + - @backstage/plugin-jenkins-backend@0.3.0 + - @backstage/plugin-search-backend@1.4.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-lighthouse-backend@0.3.3 + - @backstage/plugin-linguist-backend@0.5.3 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/backend-defaults@0.2.6 + - @backstage/plugin-adr-backend@0.4.3 + - @backstage/plugin-app-backend@0.3.54 + - @backstage/plugin-azure-devops-backend@0.4.3 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-devtools-backend@0.2.3 + - @backstage/plugin-entity-feedback-backend@0.2.3 + - @backstage/plugin-permission-backend@0.5.29 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.3 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-proxy-backend@0.4.3 + - @backstage/plugin-todo-backend@0.3.4 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + - @backstage/plugin-permission-common@0.7.9 + ## 0.0.16-next.2 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index f057b87523..69aa81a9cb 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.16-next.2", + "version": "0.0.16", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index 9061bfe90b..097b0aa089 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/backend-openapi-utils +## 0.0.5 + +### Patch Changes + +- 7c83975531: Adds new public utility types for common OpenAPI values, like request and response shapes and parameters available on an endpoint. + + **deprecated** `internal` namespace + The internal namespace will continue to be exported but now uses OpenAPI format for path parameters. You should use the new utility types. + +- Updated dependencies + - @backstage/errors@1.2.3 + ## 0.0.5-next.0 ### Patch Changes diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index 54428236af..04dc3f19f2 100644 --- a/packages/backend-openapi-utils/package.json +++ b/packages/backend-openapi-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-openapi-utils", "description": "OpenAPI typescript support.", - "version": "0.0.5-next.0", + "version": "0.0.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 4e656538c8..63600bed9f 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-plugin-api +## 0.6.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 0.6.6-next.2 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index c733d394c3..2706b1bdaf 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-api", "description": "Core API used by Backstage backend plugins", - "version": "0.6.6-next.2", + "version": "0.6.6", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-plugin-manager/CHANGELOG.md b/packages/backend-plugin-manager/CHANGELOG.md index 3603dd0dc8..526bc6c802 100644 --- a/packages/backend-plugin-manager/CHANGELOG.md +++ b/packages/backend-plugin-manager/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/backend-plugin-manager +## 0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-events-backend@0.2.15 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + ## 0.0.2-next.2 ### Patch Changes diff --git a/packages/backend-plugin-manager/package.json b/packages/backend-plugin-manager/package.json index 5653513b80..20446196cf 100644 --- a/packages/backend-plugin-manager/package.json +++ b/packages/backend-plugin-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-manager", "description": "Backstage plugin management backend", - "version": "0.0.2-next.2", + "version": "0.0.2", "private": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index 2dfa563592..2a209521f1 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/backend-tasks +## 0.5.11 + +### Patch Changes + +- 5db102bfdf: Instrument `backend-tasks` with some counters and histograms for duration. + + `backend_tasks.task.runs.count`: Counter with the total number of times a task has been run. + `backend_tasks.task.runs.duration`: Histogram with the run durations for each task. + + Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping. + +- ddd76ac98d: Fix bug where backend tasks that are defined with HumanDuration are immediately triggered on application startup +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.5.11-next.2 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index a1fe6497b2..c386654a24 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-tasks", "description": "Common distributed task management library for Backstage backends", - "version": "0.5.11-next.2", + "version": "0.5.11", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index c3b92ebf4f..8cb13b24c5 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/backend-test-utils +## 0.2.7 + +### Patch Changes + +- a250ad775f: Added `createMockDirectory()` to help out with file system mocking in tests. +- 5ddc03813e: Remove third type parameter used for `MockInstance`, in order to be compatible with older versions of `@types/jest`. +- 74491c9602: Updated to import `HostDiscovery` from `@backstage/backend-app-api`. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.2.7-next.2 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index edcb5b7414..1094de8ced 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.2.7-next.2", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 088f05cfd1..9eb282bb1c 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,64 @@ # example-backend +## 0.2.88 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8 + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-scaffolder-backend@1.18.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.9 + - @backstage/integration@1.7.1 + - @backstage/plugin-playlist-backend@0.3.10 + - @backstage/plugin-techdocs-backend@1.8.0 + - @backstage/plugin-auth-backend@0.19.3 + - @backstage/plugin-rollbar-backend@0.1.51 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/plugin-graphql-backend@0.2.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-badges-backend@0.3.3 + - @backstage/plugin-tech-insights-backend@0.5.20 + - @backstage/plugin-kubernetes-backend@0.13.0 + - @backstage/plugin-jenkins-backend@0.3.0 + - @backstage/plugin-code-coverage-backend@0.2.20 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.23 + - @backstage/plugin-search-backend@1.4.6 + - example-app@0.2.88 + - @backstage/plugin-lighthouse-backend@0.3.3 + - @backstage/plugin-linguist-backend@0.5.3 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/plugin-adr-backend@0.4.3 + - @backstage/plugin-app-backend@0.3.54 + - @backstage/plugin-azure-devops-backend@0.4.3 + - @backstage/plugin-azure-sites-backend@0.1.16 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-devtools-backend@0.2.3 + - @backstage/plugin-entity-feedback-backend@0.2.3 + - @backstage/plugin-events-backend@0.2.15 + - @backstage/plugin-explore-backend@0.0.16 + - @backstage/plugin-kafka-backend@0.3.3 + - @backstage/plugin-permission-backend@0.5.29 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-proxy-backend@0.4.3 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.7 + - @backstage/plugin-search-backend-module-pg@0.5.15 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.38 + - @backstage/plugin-todo-backend@0.3.4 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + ## 0.2.88-next.2 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index cd0191f7fa..76ef8dfb2d 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.88-next.2", + "version": "0.2.88", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 71593b5a33..b3c1aeb56f 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-client +## 1.4.5 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 1.4.5-next.0 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 2be748fbce..28cbe0879a 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": "1.4.5-next.0", + "version": "1.4.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index a6b3715d28..6f374cdbc5 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/catalog-model +## 1.4.3 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 1.4.3-next.0 ### Patch Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 58097decec..746ef803ff 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": "1.4.3-next.0", + "version": "1.4.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md index 30b9670251..70e98da8dd 100644 --- a/packages/cli-common/CHANGELOG.md +++ b/packages/cli-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/cli-common +## 0.1.13 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. + ## 0.1.13-next.0 ### Patch Changes diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index 8aed6881e2..b8bd27cef9 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.13-next.0", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/cli-node/CHANGELOG.md b/packages/cli-node/CHANGELOG.md index 2d896f3e7b..d5dcb6e976 100644 --- a/packages/cli-node/CHANGELOG.md +++ b/packages/cli-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/cli-node +## 0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + ## 0.1.5-next.1 ### Patch Changes diff --git a/packages/cli-node/package.json b/packages/cli-node/package.json index 1190d134f5..1d1158c818 100644 --- a/packages/cli-node/package.json +++ b/packages/cli-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-node", "description": "Node.js library for Backstage CLIs", - "version": "0.1.5-next.1", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index a3a6b005c0..65d0b752e7 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,60 @@ # @backstage/cli +## 0.23.0 + +### Minor Changes + +- 8defbd5434: Update typescript-eslint to 6.7.x, adding compatibility with TypeScript 5.2. + + This includes a major update on typescript-eslint, you can see the details in the [release notes](https://typescript-eslint.io/blog/announcing-typescript-eslint-v6/). + +- 7077dbf131: **BREAKING** The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior set `LEGACY_BACKEND_START`, which is recommended if you haven't migrated to the new backend system. + + This new command is no longer based on Webpack, but instead uses Node.js loaders to transpile on the fly. Rather than hot reloading modules the entire backend is now restarted on change, but the SQLite database state is still maintained across restarts via a parent process. + +### Patch Changes + +- 9468a67b92: In frontend builds and tests `process.env.HAS_REACT_DOM_CLIENT` will now be defined if `react-dom/client` is present, i.e. if using React 18. This allows for conditional imports of `react-dom/client`. +- 68158034e8: Fix for the new backend `start` command to make it work on Windows. +- 4f16e60e6d: Request slightly smaller pages of data from GitHub +- 21cd3b1b24: Added a template for creating `node-library` packages with `yarn new`. +- d0f26cfa4f: Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows. +- 1ea20b0be5: Updated dependency `@typescript-eslint/eslint-plugin` to `6.7.5`. +- 2ef6522552: Support for the `.icon.svg` extension has been deprecated and will be removed in the future. The implementation of this extension is too tied to a particular version of MUI and the SVGO, and it makes it harder to evolve the build system. We may introduce the ability to reintroduce this kind of functionality in the future through configuration for use in internal plugins, but for now we're forced to remove it. + + To migrate existing code, rename the `.icon.svg` file to `.tsx` and replace the `` element with `` from MUI and add necessary imports. For example: + + ```tsx + import React from 'react'; + import SvgIcon from '@material-ui/core/SvgIcon'; + import { IconComponent } from '@backstage/core-plugin-api'; + + export const CodeSceneIcon = (props: SvgIconProps) => ( + + + + + + ); + ``` + +- b9ec93430e: The scaffolder-module template now recommends usage of `createMockDirectory` instead of `mock-fs`. +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- 425203f898: Fixed recursive reloading issues of the backend, caused by unwanted watched files. +- 3ef18f8c06: Explicitly set `exports: 'named'` for CJS builds, ensuring that they have e.g. `exports["default"] = catalogPlugin;` +- 7187f2953e: The experimental package discovery will now always use the package name for include and exclude filtering, rather than the full module id. Entries pointing to a subpath export will now instead have an `export` field specifying the subpath that the import is from. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.10 + - @backstage/types@1.1.1 + ## 0.23.0-next.2 ### Minor Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 1a5af11de3..419b02d929 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.23.0-next.2", + "version": "0.23.0", "publishConfig": { "access": "public" }, diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 7db642945f..133da12a64 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/codemods +## 0.1.46 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/cli-common@0.1.13 + ## 0.1.46-next.0 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 34f4b5d748..d469ad47ea 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.46-next.0", + "version": "0.1.46", "publishConfig": { "access": "public", "main": "dist/index.cjs.js" diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 8e25cf28fa..b0d59d8a8b 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/config-loader +## 1.5.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 30c553c1d2: Updated dependency `typescript-json-schema` to `^0.61.0`. +- 773ea341d2: The `FileConfigSource` will now retry file reading after a short delay if it reads an empty file. This is to avoid flakiness during watch mode where change events can trigger before the file content has been written. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 1.5.1-next.1 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 3ddd84fdb5..fa2ad992c6 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": "1.5.1-next.1", + "version": "1.5.1", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 8f0f5202f4..1ba8b45805 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/config +## 1.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 1.1.1-next.0 ### Patch Changes diff --git a/packages/config/package.json b/packages/config/package.json index 538429e569..d7127b8c05 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config", "description": "Config API used by Backstage core, backend, and CLI", - "version": "1.1.1-next.0", + "version": "1.1.1", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 35bbee7183..bce1da4c9d 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/core-app-api +## 1.11.0 + +### Minor Changes + +- c9d9bfeca2: URL encode some well known unsafe characters in `RouteResolver` (and therefore `useRouteRef`) + +### Patch Changes + +- 29e4d8b76b: Fixed bug in `AppRouter` to determine the correct `signOutTargetUrl` if `app.baseUrl` contains a `basePath` +- acca17e91a: Wrap entire app in ``, enabling support for using translations outside plugins. +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- f1b349cfba: Fixed a bug in `TranslationApi` implementation where in some cases it wouldn't notify subscribers of language changes. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 1.11.0-next.2 ### Minor Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index b566ff6fe6..3ae162315f 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": "1.11.0-next.2", + "version": "1.11.0", "publishConfig": { "access": "public" }, diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index b6a2f05cd1..3ee6eae062 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/core-components +## 0.13.6 + +### Patch Changes + +- 4eab5cf901: The `TabbedLayout` component will now also navigate when clicking the active tab, which allows for navigation back from any sub routes. +- 0b55f773a7: Removed some unused dependencies +- 8a15360bb4: Fixed overflowing messages in `WarningPanel`. +- 997a71850c: Changed SupportButton menuitems to support text wrap +- 0296f272b4: Fixed the type declaration of `DependencyGraphProps`, the `defs` prop now expects `JSX.Element`s. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 16126dbe6a: Change overlay header colors in the mobile menu to use navigation color from the theme +- d19a827ef1: MissingAnnotationEmptyState component can now dynamically generate a YAML example based off the current entity being used. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.13.6-next.2 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 3bbaa8ee6a..09b6dfb2b8 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.13.6-next.2", + "version": "0.13.6", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index 3c1516c646..e35fd4d6a3 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/core-plugin-api +## 1.7.0 + +### Minor Changes + +- 322bbcae24: Removed the exprimental plugin configuration API. The `__experimentalReconfigure()` from the plugin options as well as the `__experimentalConfigure()` method on plugin instances have both been removed. + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 1.7.0-next.1 ### Patch Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 81f77e7dcf..56362eac7b 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": "1.7.0-next.1", + "version": "1.7.0", "publishConfig": { "access": "public" }, diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 2ad4280db0..25728675d6 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/create-app +## 0.5.6 + +### Patch Changes + +- ba6a3b59c1: Removed duplicate `apple-touch-icon` link from `packages/app/public/index.html` that linked to nonexistent icon. +- c8ec0dea4a: Create unique temp directory for each `create-app` execution. +- e43d3eb1b7: Bumped create-app version. +- b665f2ce65: Change base node image from node:18-bullseye-slim to node:18-bookworm-slim due to Docker build error on bullseye. + + You can apply these change to your own `Dockerfile` by replacing `node:18-bullseye-slim` with `node:18-bookworm-slim` + +- deed089a3d: Bump `cypress` to fix the end-to-end tests +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- 04a3f65e15: Bump Docker base images to `node:18-bookworm-slim` to fix node compatibility issues raised during image build. + + You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bookworm-slim` + +- 9864f263ba: Bump dev dependencies `lerna@7.3.0` on the template +- 5eacd5d213: The E2E test setup based on Cypress has been replaced with one based on [Playwright](https://playwright.dev/). Migrating existing apps is not required as this is a standalone setup, only do so if you also want to switch from Cypress to Playwright. + + The scripts to run the E2E tests have been removed from `packages/app/package.json`, as they are now instead run from the root. Instead, a new script has been added to the root `package.json`, `yarn test:e2e`, which runs the E2E tests in development mode, unless `CI` is set in the environment. + + The Playwright setup uses utilities from the new `@backstage/e2e-test-utils` package to find and include all packages in the monorepo that have an `e2e-tests` folder. + +- 8d2e640af4: Added missing `.eslintignore` file + + To apply this change to an existing app, create a new `.eslintignore` file at the root of your project with the following content: + + ```diff + + playwright.config.ts + ``` + +- Updated dependencies + - @backstage/cli-common@0.1.13 + ## 0.5.6-next.2 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 467ceb1cfe..597908c894 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.5.6-next.2", + "version": "0.5.6", "publishConfig": { "access": "public" }, diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 3869ee9281..3bb6f8e324 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/dev-utils +## 1.0.22 + +### Patch Changes + +- 080d1beb2a: Moving development `dependencies` to `devDependencies` +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 9468a67b92: Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/app-defaults@1.4.4 + - @backstage/theme@0.4.3 + ## 1.0.22-next.2 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index bbb55d9b14..31e12b80cd 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": "1.0.22-next.2", + "version": "1.0.22", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index de15b39751..914644a9f6 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/e2e-test-utils +## 0.1.0 + +### Minor Changes + +- f5b41b27a9: Initial release. + ## 0.1.0-next.0 ### Minor Changes diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index fcbae56796..3448497395 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/e2e-test-utils", "description": "Shared end-to-end test utilities Backstage", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index 846f7e62a4..37d8b1d24a 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,14 @@ # e2e-test +## 0.2.8 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.6 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + ## 0.2.8-next.2 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 9d5654098d..f6e90e116e 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,7 +1,7 @@ { "name": "e2e-test", "description": "E2E test for verifying Backstage packages", - "version": "0.2.8-next.2", + "version": "0.2.8", "private": true, "backstage": { "role": "cli" diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 2568ca095e..92655a25d8 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/errors +## 1.2.3 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/types@1.1.1 + ## 1.2.3-next.0 ### Patch Changes diff --git a/packages/errors/package.json b/packages/errors/package.json index c064765aca..7dc17a10a2 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/errors", "description": "Common utilities for error handling within Backstage", - "version": "1.2.3-next.0", + "version": "1.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/frontend-app-api/CHANGELOG.md b/packages/frontend-app-api/CHANGELOG.md index 12983fdcd6..96bf43f73c 100644 --- a/packages/frontend-app-api/CHANGELOG.md +++ b/packages/frontend-app-api/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/frontend-app-api +## 0.2.0 + +### Minor Changes + +- 4461d87d5a: Removed support for the new `useRouteRef`. +- 9d03dfe5e3: The `createApp` config option has been replaced by a new `configLoader` option. There is now also a `pluginLoader` option that can be used to dynamically load plugins into the app. +- d7c5d80c57: The hidden `'root'` extension has been removed and has instead been made an input of the `'core'` extension. The checks for rejecting configuration of the `'root'` extension to rejects configuration of the `'core'` extension instead. +- d920b8c343: Added support for installing `ExtensionOverrides` via `createApp` options. As part of this change the `plugins` option has been renamed to `features`, and the `pluginLoader` has been renamed to `featureLoader`. + +### Patch Changes + +- 322bbcae24: Internal update for removal of experimental plugin configuration API. +- f78ac58f88: Filters for discovered packages are now also applied at runtime. This makes it possible to disable packages through the `app.experimental.packages` config at runtime. +- 68ffb9e67d: The app will now reject any extensions that attach to nonexistent inputs. +- 5072824817: Implement `toString()` and `toJSON()` for extension instances. +- 1e60a9c3a5: Fixed an issue preventing the routing system to match subroutes +- 52366db5b3: Make themes configurable through extensions, and switched default themes to use extensions instead. +- 2ecd33618a: Added the `bindRoutes` option to `createApp`. +- e5a2956dd2: Register default api implementations when creating declarative integrated apps. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 06432f900c: Updates for `at` -> `attachTo` refactor. +- 1718ec75b7: Added support for the existing routing system. +- 66d51a4827: Prevents root extension override and duplicated plugin extensions. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.2.0-next.2 ### Minor Changes diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index 7a1c5aa79f..ebd4291317 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-app-api", - "version": "0.2.0-next.2", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/frontend-plugin-api/CHANGELOG.md b/packages/frontend-plugin-api/CHANGELOG.md index 056ff0b143..8fa9a49726 100644 --- a/packages/frontend-plugin-api/CHANGELOG.md +++ b/packages/frontend-plugin-api/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/frontend-plugin-api +## 0.2.0 + +### Minor Changes + +- 06432f900c: Extension attachment point is now configured via `attachTo: { id, input }` instead of `at: 'id/input'`. +- 4461d87d5a: Removed support for the new `useRouteRef`. + +### Patch Changes + +- d3a37f55c0: Add support for `SidebarGroup` on the sidebar item extension. +- 2ecd33618a: Plugins can now be assigned `routes` and `externalRoutes` when created. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- c1e9ca6500: Added `createExtensionOverrides` which can be used to install a collection of extensions in an app that will replace any existing ones. +- 52366db5b3: Added `createThemeExtension` and `coreExtensionData.theme`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/types@1.1.1 + ## 0.2.0-next.2 ### Minor Changes diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index d80e2baee4..6100e30cf3 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-plugin-api", - "version": "0.2.0-next.2", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/integration-aws-node/CHANGELOG.md b/packages/integration-aws-node/CHANGELOG.md index e1004246ff..87156a5623 100644 --- a/packages/integration-aws-node/CHANGELOG.md +++ b/packages/integration-aws-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration-aws-node +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + ## 0.1.7-next.0 ### Patch Changes diff --git a/packages/integration-aws-node/package.json b/packages/integration-aws-node/package.json index 38948f03ad..714ccf4767 100644 --- a/packages/integration-aws-node/package.json +++ b/packages/integration-aws-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-aws-node", "description": "Helpers for fetching AWS account credentials", - "version": "0.1.7-next.0", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 9374887da8..f26a0e631b 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/integration-react +## 1.1.20 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/config@1.1.1 + ## 1.1.20-next.2 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 7a919ed13a..9909350e91 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": "1.1.20-next.2", + "version": "1.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 93332a6b23..552e225e3b 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/integration +## 1.7.1 + +### Patch Changes + +- 3963d0b885: Ensure that all relevant config fields are properly marked as secret +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/config@1.1.1 + ## 1.7.1-next.1 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index 45d9474336..42a6ba4bf3 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration", "description": "Helpers for managing integrations towards external systems", - "version": "1.7.1-next.1", + "version": "1.7.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index fc5cae179c..75ee910172 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/repo-tools +## 0.3.5 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.1.5 + ## 0.3.5-next.1 ### Patch Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 304df34bec..fa398e598e 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/repo-tools", "description": "CLI for Backstage repo tooling ", - "version": "0.3.5-next.1", + "version": "0.3.5", "publishConfig": { "access": "public" }, diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index f54090b226..7a935bc85c 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,24 @@ # techdocs-cli-embedded-app +## 0.2.87 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/test-utils@1.4.4 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.2.87-next.2 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 86e85f9173..71e80fa2f0 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.87-next.2", + "version": "0.2.87", "private": true, "backstage": { "role": "frontend" diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index a6592085bb..1ab192f698 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,22 @@ # @techdocs/cli +## 1.6.0 + +### Minor Changes + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs. with the serve command using the `--mkdocs-config-file-name` argument + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- 2b6e572051: Restructured tests. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + ## 1.6.0-next.2 ### Minor Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 516a7d108e..7b97f13e3f 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": "1.6.0-next.2", + "version": "1.6.0", "publishConfig": { "access": "public" }, diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 9b9b90f838..213877cfb0 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/test-utils +## 1.4.4 + +### Patch Changes + +- 322bbcae24: Removed the alpha `MockPluginProvider` export since the plugin configuration API has been removed. +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 1.4.4-next.2 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 5f7bbb6af8..28aa1715e6 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": "1.4.4-next.2", + "version": "1.4.4", "publishConfig": { "access": "public" }, diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index cf7d552883..69c88c79ab 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/theme +## 0.4.3 + +### Patch Changes + +- 5ad5344756: Added support for string `fontSize` values (e.g. `"2.5rem"`) in themes in addition to numbers. Also added an optional `fontFamily` prop for header typography variants to allow further customization. + ## 0.4.3-next.0 ### Patch Changes diff --git a/packages/theme/package.json b/packages/theme/package.json index 2129067042..15046d057b 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.4.3-next.0", + "version": "0.4.3", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/version-bridge/CHANGELOG.md b/packages/version-bridge/CHANGELOG.md index bd7136e3ed..bffaff7177 100644 --- a/packages/version-bridge/CHANGELOG.md +++ b/packages/version-bridge/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/version-bridge +## 1.0.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. + ## 1.0.5 ### Patch Changes diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index 851128d025..8424ac54fc 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/version-bridge", "description": "Utilities used by @backstage packages to support multiple concurrent versions", - "version": "1.0.5", + "version": "1.0.6", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index 44743f856a..16446bee2a 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-adr-backend +## 0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-adr-common@0.2.16 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + ## 0.4.3-next.2 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 444e238158..ffc5740aaf 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.4.3-next.2", + "version": "0.4.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index 32ac484e17..849b00fdac 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-adr-common +## 0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-common@1.2.7 + ## 0.2.16-next.1 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index d1c32a852a..f3021eb4b1 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.2.16-next.1", + "version": "0.2.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index a52862b7f7..ea9f9519b0 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-adr +## 0.6.8 + +### Patch Changes + +- 499e34656e: Fix icon alignment in `AdrSearchResultListItem` +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 1204e7628e: Create an experimental `AdrSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/theme@0.4.3 + - @backstage/plugin-adr-common@0.2.16 + - @backstage/plugin-search-common@1.2.7 + ## 0.6.8-next.2 ### Patch Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 72511596e7..8c20d7a93a 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.6.8-next.2", + "version": "0.6.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index 948861944a..d10077998b 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-airbrake-backend +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.3.3-next.2 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index cccacd8197..dda7f4e28d 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.3.3-next.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index f930cc50df..725d9f883a 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-airbrake +## 0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/test-utils@1.4.4 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/dev-utils@1.0.22 + - @backstage/theme@0.4.3 + ## 0.3.25-next.2 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index e308bee851..80cf3adc35 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.25-next.2", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index 591036d45e..7117a5e22a 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-allure +## 0.1.41 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.1.41-next.2 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index f3f02f86dd..d351388326 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.41-next.2", + "version": "0.1.41", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 05f2a97e4a..72c42c20fb 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-analytics-module-ga +## 0.1.34 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.1.34-next.2 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 0b79da313f..5d5a9505da 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.34-next.2", + "version": "0.1.34", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga4/CHANGELOG.md b/plugins/analytics-module-ga4/CHANGELOG.md index d50658a59f..366fc6e16f 100644 --- a/plugins/analytics-module-ga4/CHANGELOG.md +++ b/plugins/analytics-module-ga4/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-analytics-module-ga4 +## 0.1.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.1.5-next.2 ### Patch Changes diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index db8259cdfb..a786986f5e 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga4", - "version": "0.1.5-next.2", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-newrelic-browser/CHANGELOG.md b/plugins/analytics-module-newrelic-browser/CHANGELOG.md index b22d4e64fc..2d7e7ea467 100644 --- a/plugins/analytics-module-newrelic-browser/CHANGELOG.md +++ b/plugins/analytics-module-newrelic-browser/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-newrelic-browser +## 0.0.3 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/config@1.1.1 + ## 0.0.3-next.2 ### Patch Changes diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index 040462ad20..f42911a93c 100644 --- a/plugins/analytics-module-newrelic-browser/package.json +++ b/plugins/analytics-module-newrelic-browser/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-newrelic-browser", - "version": "0.0.3-next.2", + "version": "0.0.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index cd7d737b8e..d245b155f6 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-apache-airflow +## 0.2.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + ## 0.2.16-next.2 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 1b314c9004..e0cc0619b3 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.2.16-next.2", + "version": "0.2.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md b/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md index 3786ca011a..883ed270fa 100644 --- a/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md +++ b/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-api-docs-module-protoc-gen-doc +## 0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. + ## 0.1.3 ### Patch Changes diff --git a/plugins/api-docs-module-protoc-gen-doc/package.json b/plugins/api-docs-module-protoc-gen-doc/package.json index c7a952bc4f..ac1b941a7d 100644 --- a/plugins/api-docs-module-protoc-gen-doc/package.json +++ b/plugins/api-docs-module-protoc-gen-doc/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs-module-protoc-gen-doc", "description": "Additional functionalities for the api-docs plugin that renders the output of the protoc-gen-doc", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 609a552a55..5cefe7b94b 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-api-docs +## 0.9.12 + +### Patch Changes + +- 0117a6b47e: Adding `requestInterceptor` option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 18f1756908: added aria-label on api definition button for better a11y. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.9.12-next.2 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index fb00aa8683..0f5e9214a3 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.9.12-next.2", + "version": "0.9.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index 5b7905e69f..a502d30e7d 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-apollo-explorer +## 0.1.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + ## 0.1.16-next.2 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index c15726029d..386eab6ab0 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.16-next.2", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 7478189eba..991c1defc5 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-app-backend +## 0.3.54 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config-loader@1.5.1 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.6 + ## 0.3.54-next.2 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index a8425c5186..cda5301de8 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.54-next.2", + "version": "0.3.54", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-node/CHANGELOG.md b/plugins/app-node/CHANGELOG.md index b6bb4d4425..30bfaecc96 100644 --- a/plugins/app-node/CHANGELOG.md +++ b/plugins/app-node/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-app-node +## 0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + ## 0.1.6-next.2 ### Patch Changes diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json index f25333588a..915c5a0881 100644 --- a/plugins/app-node/package.json +++ b/plugins/app-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-node", "description": "Node.js library for the app plugin", - "version": "0.1.6-next.2", + "version": "0.1.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md index 4c57589972..9cf2657b6b 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-auth-backend-module-gcp-iap-provider +## 0.2.0 + +### Minor Changes + +- 6f142d5356: **BREAKING** `gcpIapAuthenticator.initialize()` is no longer `async` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + ## 0.2.0-next.2 ### Minor Changes diff --git a/plugins/auth-backend-module-gcp-iap-provider/package.json b/plugins/auth-backend-module-gcp-iap-provider/package.json index 65f4c1c0ed..85ddf5aaba 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/package.json +++ b/plugins/auth-backend-module-gcp-iap-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-gcp-iap-provider", "description": "A GCP IAP auth provider module for the Backstage auth backend", - "version": "0.2.0-next.2", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-github-provider/CHANGELOG.md b/plugins/auth-backend-module-github-provider/CHANGELOG.md index 4bebdabd8b..80f47d6c2b 100644 --- a/plugins/auth-backend-module-github-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-github-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-auth-backend-module-github-provider +## 0.1.3 + +### Patch Changes + +- 5d32a58b5a: Fixed a bug where the GitHub authenticator did not properly persist granted OAuth scopes. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + ## 0.1.3-next.2 ### Patch Changes diff --git a/plugins/auth-backend-module-github-provider/package.json b/plugins/auth-backend-module-github-provider/package.json index a9bcc1f21f..85b6927ba5 100644 --- a/plugins/auth-backend-module-github-provider/package.json +++ b/plugins/auth-backend-module-github-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-github-provider", "description": "The github-provider backend module for the auth plugin.", - "version": "0.1.3-next.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md index eca91f503e..aad16984c2 100644 --- a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-gitlab-provider +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + ## 0.1.3-next.2 ### Patch Changes diff --git a/plugins/auth-backend-module-gitlab-provider/package.json b/plugins/auth-backend-module-gitlab-provider/package.json index 375b386fb8..85fb4b77df 100644 --- a/plugins/auth-backend-module-gitlab-provider/package.json +++ b/plugins/auth-backend-module-gitlab-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-gitlab-provider", "description": "The gitlab-provider backend module for the auth plugin.", - "version": "0.1.3-next.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-google-provider/CHANGELOG.md b/plugins/auth-backend-module-google-provider/CHANGELOG.md index c06c8dfee0..4b78ea58fa 100644 --- a/plugins/auth-backend-module-google-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-google-provider/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-backend-module-google-provider +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + ## 0.1.3-next.2 ### Patch Changes diff --git a/plugins/auth-backend-module-google-provider/package.json b/plugins/auth-backend-module-google-provider/package.json index 74a6688e7c..7332f0c5e9 100644 --- a/plugins/auth-backend-module-google-provider/package.json +++ b/plugins/auth-backend-module-google-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-google-provider", "description": "A Google auth provider module for the Backstage auth backend", - "version": "0.1.3-next.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md index c9b6227920..4d982911e7 100644 --- a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-auth-backend-module-microsoft-provider +## 0.1.0 + +### Minor Changes + +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/auth-backend-module-microsoft-provider/package.json b/plugins/auth-backend-module-microsoft-provider/package.json index 8555af2cbe..16c10667fe 100644 --- a/plugins/auth-backend-module-microsoft-provider/package.json +++ b/plugins/auth-backend-module-microsoft-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-microsoft-provider", "description": "The microsoft-provider backend module for the auth plugin.", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md index 2588afe13a..3920726928 100644 --- a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-oauth2-provider +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + ## 0.1.3-next.2 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-provider/package.json b/plugins/auth-backend-module-oauth2-provider/package.json index 1f610405a0..dda9aca87a 100644 --- a/plugins/auth-backend-module-oauth2-provider/package.json +++ b/plugins/auth-backend-module-oauth2-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-provider", "description": "The oauth2-provider backend module for the auth plugin.", - "version": "0.1.3-next.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md new file mode 100644 index 0000000000..3d24e48a89 --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md @@ -0,0 +1,14 @@ +# @backstage/plugin-auth-backend-module-pinniped-provider + +## 0.1.0 + +### Minor Changes + +- ae34255836: Add new Pinniped auth module and authenticator to be used alongside the new Pinniped auth provider. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 diff --git a/plugins/auth-backend-module-pinniped-provider/package.json b/plugins/auth-backend-module-pinniped-provider/package.json index 3d7dcf97d9..013fd6c49f 100644 --- a/plugins/auth-backend-module-pinniped-provider/package.json +++ b/plugins/auth-backend-module-pinniped-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-pinniped-provider", "description": "The pinniped-provider backend module for the auth plugin.", - "version": "0.0.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 8f00fb0e9a..d682f21c26 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-auth-backend +## 0.19.3 + +### Patch Changes + +- 9ff7935152: Fixed bug in oidc refresh handler, if token endpoints response on refresh request does not contain a scope, the requested scope is used. +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-backend-module-github-provider@0.1.3 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.0 + - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.3 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.3 + ## 0.19.3-next.2 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 355c8eb554..61e7993ab3 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.19.3-next.2", + "version": "0.19.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 9c5bf12cac..b20ddd7697 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-auth-node +## 0.4.0 + +### Minor Changes + +- 6f142d5356: **BREAKING**: The recently introduced `ProxyAuthenticator.initialize()` method is no longer `async` to match the way the OAuth equivalent is implemented. + +### Patch Changes + +- 6c2b0793bf: Fix for persisted scopes not being properly restored on sign-in. +- 8b8b1d23ae: Fixed cookie persisted scope not returned in OAuth refresh handler response. +- ae34255836: Adding optional audience parameter to OAuthState type declaration +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.4.0-next.2 ### Minor Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 9174e91d4c..bf2257c942 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.4.0-next.2", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 7303ae4de7..605bc9c81c 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-azure-devops-backend +## 0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-devops-common@0.3.1 + ## 0.4.3-next.2 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 7a81effc70..0186a9268b 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.4.3-next.2", + "version": "0.4.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index c136b8c5c7..1277fa0f1e 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-azure-devops +## 0.3.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-azure-devops-common@0.3.1 + ## 0.3.7-next.2 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 45dccce464..2e88ac76ab 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.3.7-next.2", + "version": "0.3.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index 08309c6073..203b9bab9c 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-azure-sites-backend +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + ## 0.1.16-next.2 ### Patch Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index 5063a671d2..aa5d700be2 100644 --- a/plugins/azure-sites-backend/package.json +++ b/plugins/azure-sites-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites-backend", - "version": "0.1.16-next.2", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index c4746dba08..1d96a10e10 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-azure-sites +## 0.1.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-azure-sites-common@0.1.1 + ## 0.1.14-next.2 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index ee97dae742..77bc1d3833 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites", - "version": "0.1.14-next.2", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 40fa6773f0..3bf44d0960 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-badges-backend +## 0.3.3 + +### Patch Changes + +- 817f2acbb1: Make sure the default badge factory is used if nothing is defined +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + ## 0.3.3-next.2 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index e539075ff2..fb2ab72985 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.3.3-next.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 75de6d7e62..7ba4750487 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-badges +## 0.2.49 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.2.49-next.2 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index e52a8a1c3c..ccd4e37db0 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.49-next.2", + "version": "0.2.49", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index 8561a42918..f5df21413d 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-bazaar-backend +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.3.3-next.2 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index ff466356ce..3fdfa32a7f 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.3.3-next.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index 28af791ac4..e39456be88 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-bazaar +## 0.2.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + ## 0.2.17-next.2 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index b035ec8fd9..2c2f2ba1e8 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.17-next.2", + "version": "0.2.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitbucket-cloud-common/CHANGELOG.md b/plugins/bitbucket-cloud-common/CHANGELOG.md index c7fc10f98f..ce604a6ef5 100644 --- a/plugins/bitbucket-cloud-common/CHANGELOG.md +++ b/plugins/bitbucket-cloud-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-bitbucket-cloud-common +## 0.2.13 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + ## 0.2.13-next.1 ### Patch Changes diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index 63c197ecbd..9f0488749e 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitbucket-cloud-common", "description": "Common functionalities for bitbucket-cloud plugins", - "version": "0.2.13-next.1", + "version": "0.2.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 814ef241c2..175d1c20b0 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-bitrise +## 0.1.52 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.1.52-next.2 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 5a00a4e4b8..fdf18f4380 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.52-next.2", + "version": "0.1.52", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 8db117460c..26971186d6 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.3.0 + +### Minor Changes + +- 5abc2fd4d6: AwsEksClusterProcessor supports Entity callback function and passes in region when initialize EKS cluster + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 246def8c94..a8999430fa 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", "description": "A Backstage catalog backend module that helps integrate towards AWS", - "version": "0.2.9-next.2", + "version": "0.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 57cfff7cb2..315d39baab 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.25 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + ## 0.1.25-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index f7353a1f37..ef21110f7b 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", "description": "A Backstage catalog backend module that helps integrate towards Azure", - "version": "0.1.25-next.2", + "version": "0.1.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index bfd363123a..7682992e01 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.21 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-bitbucket-cloud-common@0.2.13 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + ## 0.1.21-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 5f8acc82ca..ed10c8433e 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", - "version": "0.1.21-next.2", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index 4501171eda..67ea880c96 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.19 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.1.19-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 1e937da6ea..e0f395a1a2 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.1.19-next.2", + "version": "0.1.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index ffca76bddc..cf7e871bc5 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-bitbucket-cloud-common@0.2.13 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.2.21-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index a85596ea32..a68cb1e674 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket", - "version": "0.2.21-next.2", + "version": "0.2.21", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/catalog-backend-module-gcp/CHANGELOG.md b/plugins/catalog-backend-module-gcp/CHANGELOG.md index e9509a5d02..c755f7a72b 100644 --- a/plugins/catalog-backend-module-gcp/CHANGELOG.md +++ b/plugins/catalog-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-gcp +## 0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.1.6-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json index cf297b186d..70bf6f7b88 100644 --- a/plugins/catalog-backend-module-gcp/package.json +++ b/plugins/catalog-backend-module-gcp/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gcp", "description": "A Backstage catalog backend module that helps integrate towards GCP", - "version": "0.1.6-next.2", + "version": "0.1.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index a6b8cb8167..e55d30ed12 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.22 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.1.22-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index d4baf186d0..576f772968 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.1.22-next.2", + "version": "0.1.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github-org/CHANGELOG.md b/plugins/catalog-backend-module-github-org/CHANGELOG.md index 7dbac7fcc5..e0a24889c4 100644 --- a/plugins/catalog-backend-module-github-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-github-org/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-github-org +## 0.1.0 + +### Minor Changes + +- c101e683d5: Added `catalogModuleGithubOrgEntityProvider` to ingest users and teams from multiple Github organizations. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend-module-github@0.4.4 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json index d970f3013a..7ad96c65e2 100644 --- a/plugins/catalog-backend-module-github-org/package.json +++ b/plugins/catalog-backend-module-github-org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github-org", "description": "The github-org backend module for the catalog plugin.", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index b5d563617c..21e8ad0e1b 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog-backend-module-github +## 0.4.4 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- 0b55f773a7: Removed some unused dependencies +- 4f16e60e6d: Request slightly smaller pages of data from GitHub +- b4b1cbf9fa: Make `defaultUserTransformer` resolve to `UserEntity` instead of `Entity` +- c101e683d5: Removed `catalogModuleGithubOrgEntityProvider`. Import from `@backstage/plugin-catalog-backend-module-github-org` instead. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + ## 0.4.4-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 0d3bc4191b..f2c321f84a 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.4.4-next.2", + "version": "0.4.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 790320f5db..5378ba5448 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.3.3 + +### Patch Changes + +- 4f70fdfc93: fix: use REST API to get root group memberships for GitLab SaaS users listing + + This API is the only one that shows `email` field for enterprise users and + allows to filter out bot users not using a license using the `is_using_seat` + field. + + We also added the annotation `gitlab.com/saml-external-uid` taking the value + of `group_saml_identity.extern_uid` of the `groups/:group-id/members` endpoint + response. This is useful in case you want to create a `SignInResolver` that + references the user with the id of your identity provider (e.g. OneLogin). + + ref: + + https://docs.gitlab.com/ee/user/enterprise_user/#get-users-email-addresses-through-the-api + https://docs.gitlab.com/ee/api/members.html#limitations + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- 0b55f773a7: Removed some unused dependencies +- 6ae7f12abb: Make sure the archived projects are skipped with the Gitlab API +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.3.3-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index d5a8069460..2c5966bb68 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.3.3-next.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index cf18c6dddc..58e19beae8 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.4.10 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + ## 0.4.10-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 1aa470dcc3..a0df7f5449 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", "description": "An entity provider for streaming large asset sources into the catalog", - "version": "0.4.10-next.2", + "version": "0.4.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index cb7b48d509..f9d38ee033 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.21 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + ## 0.5.21-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index ac8693251f..36c1e6c46f 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend module that helps integrate towards LDAP", - "version": "0.5.21-next.2", + "version": "0.5.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index b759abb9ab..3cb7b30b3d 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.13 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + ## 0.5.13-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index d02dddcaea..91459e847e 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", - "version": "0.5.13-next.2", + "version": "0.5.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 90fe155927..65b55833ca 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.23 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + ## 0.1.23-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 2230782402..1f85d0d844 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.1.23-next.2", + "version": "0.1.23", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index 67e1696141..7ce2b70e20 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.1.11 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.1.11-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index 381d1fcfb4..db267bc22e 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", - "version": "0.1.11-next.2", + "version": "0.1.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md index 2dc4e82d31..b077261f25 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md +++ b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-scaffolder-entity-model +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + ## 0.1.3-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/package.json b/plugins/catalog-backend-module-scaffolder-entity-model/package.json index b49a308146..f20a772a30 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/package.json +++ b/plugins/catalog-backend-module-scaffolder-entity-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-scaffolder-entity-model", "description": "Adds support for the scaffolder specific entity model (e.g. the Template kind) to the catalog backend plugin.", - "version": "0.1.3-next.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md index 21b25797bc..310f3b9b5f 100644 --- a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md +++ b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-backend-module-unprocessed +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + ## 0.3.3-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index 5c45699175..5adc6e1f5f 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-unprocessed", "description": "Backstage Catalog module to view unprocessed entities", - "version": "0.3.3-next.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index ca34451992..f6dee7b12f 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-catalog-backend +## 1.14.0 + +### Minor Changes + +- 78af9433c8: Instrumenting some missing metrics with `OpenTelemetry` + +### Patch Changes + +- 7a2e2924c7: Marked the `LocationEntityProcessor` as deprecated, as it is no longer used internally since way back and can even be harmful at this point. +- 0b55f773a7: Removed some unused dependencies +- 348e8c1cdb: Fixes a bug where eagerly deleted entities did not properly trigger re-stitching of entities that they had relations to. +- b97e9790f0: Internal refactors, laying the foundation for later introducing deferred stitching (see #18062). +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + ## 1.14.0-next.2 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 49f4d7a7b1..388f6b5ffc 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": "1.14.0-next.2", + "version": "1.14.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index e3ad0c858f..3dbde65433 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-common +## 1.0.17 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + ## 1.0.17-next.0 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 35529e2cd1..68ab60e7c3 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-common", "description": "Common functionalities for the catalog plugin", - "version": "1.0.17-next.0", + "version": "1.0.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 2dfa6dffe4..5d10ff94f3 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-graph +## 0.2.37 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + ## 0.2.37-next.2 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 909ed5329d..52079e0fa1 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.37-next.2", + "version": "0.2.37", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index 867d52cb4b..0a08803e7d 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-graphql +## 0.4.0 + +### Minor Changes + +- 9def1e95ab: This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.3.24-next.0 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 75f08a6bf9..599ca62d2b 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-graphql", "description": "Deprecated, consider using @frontside/backstage-plugin-graphql-backend instead", - "version": "0.3.24-next.0", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 2043cca0f4..8a84c211e5 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-import +## 0.10.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The `app.title` configuration is now properly required to be a string. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + ## 0.10.1-next.2 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 9c550ebee9..efb4922f6f 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.10.1-next.2", + "version": "0.10.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index a60a3e21aa..22a2319142 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-node +## 1.4.7 + +### Patch Changes + +- 7a2e2924c7: Added docs to `processingResult` +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + ## 1.4.7-next.2 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index cbc17219c5..2817703044 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-node", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", - "version": "1.4.7-next.2", + "version": "1.4.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 3e65e4b55c..9d6dbd2840 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-catalog-react +## 1.8.5 + +### Patch Changes + +- a402e1dfb9: Fixed an issue causing `EntityPage` to show an error for entities containing special characters +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The `spec.type` field in entities will now always be rendered as a string. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + ## 1.8.5-next.2 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 4d52a96ccc..7c1dcb5551 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": "1.8.5-next.2", + "version": "1.8.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-unprocessed-entities/CHANGELOG.md b/plugins/catalog-unprocessed-entities/CHANGELOG.md index f42483fc92..afd3890a12 100644 --- a/plugins/catalog-unprocessed-entities/CHANGELOG.md +++ b/plugins/catalog-unprocessed-entities/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-unprocessed-entities +## 0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index 822fffa343..5bf8a0150c 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-unprocessed-entities", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 2286652eb8..6b5ba8b956 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,52 @@ # @backstage/plugin-catalog +## 1.14.0 + +### Minor Changes + +- 28f1ab2e1a: The catalog plugin no longer implements the experimental reconfiguration API. The create button title can now instead be configured using the new experimental internationalization API, via the `catalogTranslationRef` exported at `/alpha`. For example: + + ```ts + import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'; + + const app = createApp({ + __experimentalTranslations: { + resources: [ + createTranslationMessages({ + ref: catalogTranslationRef, + catalog_page_create_button_title: 'Create Software', + }), + ], + }, + }); + ``` + +- f3561a2935: include owner chip in catalog search result item + +### Patch Changes + +- 7c4a8e4d5f: Create an experimental `CatalogSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- 0296f272b4: The `spec.lifecycle' field in entities will now always be rendered as a string. +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- e5a2956dd2: Migrate catalog api to declarative integration system, it is exported from `/alpha` subpath. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + - @backstage/plugin-search-common@1.2.7 + ## 1.14.0-next.2 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 67106a5d5e..73440c6ba1 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": "1.14.0-next.2", + "version": "1.14.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index 8821eeab83..b0cb0fb020 100644 --- a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md +++ b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cicd-statistics-module-gitlab +## 0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-cicd-statistics@0.1.27 + - @backstage/catalog-model@1.4.3 + ## 0.1.21-next.2 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index d2997056fc..c5d2332904 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics-module-gitlab", "description": "CI/CD Statistics plugin module; Gitlab CICD", - "version": "0.1.21-next.2", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index 7d07199028..9fe1717192 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-cicd-statistics +## 0.1.27 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.27-next.2 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index 744963d55c..4a1fcfd960 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics", "description": "A frontend plugin visualizing CI/CD pipeline statistics (build time)", - "version": "0.1.27-next.2", + "version": "0.1.27", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 7a25c01f56..c8ba1ae27f 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-circleci +## 0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.3.25-next.2 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 752e908374..590385e7c2 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.3.25-next.2", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index c1ac4d0747..a322da009c 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-cloudbuild +## 0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.3.25-next.2 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 055fb5bb62..3a2d3c8d95 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.3.25-next.2", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index 5f97316244..65dda2e3f5 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-code-climate +## 0.1.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.1.25-next.2 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 4b2bfcd9b3..21218a4850 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-climate", - "version": "0.1.25-next.2", + "version": "0.1.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index c7fb955e9f..2cc9d85f3b 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-code-coverage-backend +## 0.2.20 + +### Patch Changes + +- 4aa27aa200: Added option to set body size limit +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + ## 0.2.20-next.2 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 3c07f28eb8..9ee98d52ad 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage-backend", "description": "A Backstage backend plugin that helps you keep track of your code coverage", - "version": "0.2.20-next.2", + "version": "0.2.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 06a29ca4cc..f5ba60eeb4 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-code-coverage +## 0.2.18 + +### Patch Changes + +- 88b0b32547: Fixed the coverage history statistics to compare newest with oldest record +- 0296f272b4: The warning for missing code coverage will now render the entity as a reference. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- a468544fa9: Updated layout to improve contrasts and consistency with other plugins +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.2.18-next.2 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index c2c16f69b6..93b06e7c85 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.2.18-next.2", + "version": "0.2.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index aed76f3c8b..29f0700e65 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-codescene +## 0.1.18 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.1.18-next.2 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 4d3e5ab597..3eeb6452af 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.18-next.2", + "version": "0.1.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index 0b1a03c5e5..3e09c6dd98 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-config-schema +## 0.1.46 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.1.46-next.2 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 6b97abc91d..55b716f1f4 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.46-next.2", + "version": "0.1.46", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 08dc64071e..a60e531966 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-cost-insights +## 0.12.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- ba4820883c: Updated dependency `@types/pluralize` to `^0.0.31`. +- 959aa2a09f: The experimental plugin configuration has been removed. The trend line can now instead be hidden by setting `costInsights.hideTrendLine` to `true` in the configuration. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-cost-insights-common@0.1.2 + ## 0.12.14-next.2 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index a66fde70ad..8f9bb07fc8 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.12.14-next.2", + "version": "0.12.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/devtools-backend/CHANGELOG.md b/plugins/devtools-backend/CHANGELOG.md index 16de7b7e6f..fd9108d28d 100644 --- a/plugins/devtools-backend/CHANGELOG.md +++ b/plugins/devtools-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-devtools-backend +## 0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5 + - @backstage/plugin-permission-common@0.7.9 + ## 0.2.3-next.2 ### Patch Changes diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index 865bbae714..acf7788d8c 100644 --- a/plugins/devtools-backend/package.json +++ b/plugins/devtools-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools-backend", - "version": "0.2.3-next.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/devtools-common/CHANGELOG.md b/plugins/devtools-common/CHANGELOG.md index 48688e77de..4a95434b3d 100644 --- a/plugins/devtools-common/CHANGELOG.md +++ b/plugins/devtools-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-devtools-common +## 0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/devtools-common/package.json b/plugins/devtools-common/package.json index 7f1aa0f93f..703ad2a5e3 100644 --- a/plugins/devtools-common/package.json +++ b/plugins/devtools-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-devtools-common", "description": "Common functionalities for the devtools plugin", - "version": "0.1.5-next.0", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/devtools/CHANGELOG.md b/plugins/devtools/CHANGELOG.md index a585b7bde7..b200af4d82 100644 --- a/plugins/devtools/CHANGELOG.md +++ b/plugins/devtools/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-devtools +## 0.1.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5 + ## 0.1.5-next.2 ### Patch Changes diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index 7dffd4fdc4..c1ad7b53fd 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools", - "version": "0.1.5-next.2", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index 71b6670ab6..2de9b4555b 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-dynatrace +## 7.0.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 7.0.5-next.2 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index bfea48cc90..97c79f84f5 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "7.0.5-next.2", + "version": "7.0.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback-backend/CHANGELOG.md b/plugins/entity-feedback-backend/CHANGELOG.md index 3f7cac2902..acfdaf360f 100644 --- a/plugins/entity-feedback-backend/CHANGELOG.md +++ b/plugins/entity-feedback-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-entity-feedback-backend +## 0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.3-next.2 ### Patch Changes diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index 8fe5048e4b..c493be7075 100644 --- a/plugins/entity-feedback-backend/package.json +++ b/plugins/entity-feedback-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback-backend", - "version": "0.2.3-next.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback/CHANGELOG.md b/plugins/entity-feedback/CHANGELOG.md index a88d2edb3f..469ff16ca2 100644 --- a/plugins/entity-feedback/CHANGELOG.md +++ b/plugins/entity-feedback/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-entity-feedback +## 0.2.8 + +### Patch Changes + +- 48c8b93e98: Added tooltip to like dislike buttons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.8-next.2 ### Patch Changes diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index fb2d03d6c4..876653986e 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback", - "version": "0.2.8-next.2", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-validation/CHANGELOG.md b/plugins/entity-validation/CHANGELOG.md index 1c4d966583..4aeb6cfd03 100644 --- a/plugins/entity-validation/CHANGELOG.md +++ b/plugins/entity-validation/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-entity-validation +## 0.1.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/plugin-catalog-common@1.0.17 + ## 0.1.10-next.2 ### Patch Changes diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index eb102cce17..e47ff094bf 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-validation", - "version": "0.1.10-next.2", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index 3f162afd2e..304271a0a4 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index 8ca4e27abf..a114136c7e 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-aws-sqs", - "version": "0.2.9-next.2", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index bd0ca38f85..593b77bdf3 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-azure +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + ## 0.1.16-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 87c95c0dbe..175f952a4b 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-azure", - "version": "0.1.16-next.2", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index 813824f84b..2bfd659892 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + ## 0.1.16-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index b3217dc782..e81bea9415 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", - "version": "0.1.16-next.2", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index a5b9334e3a..fd49c7df3b 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + ## 0.1.16-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index e23ade8c7b..d30063e14f 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gerrit", - "version": "0.1.16-next.2", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index cfac727ae8..f87a77ea7e 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-github +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + ## 0.1.16-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 7a7d0f8a29..bf9caa3bfd 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-github", - "version": "0.1.16-next.2", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index a2dc5c06e0..90f9ce8e5d 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + ## 0.1.16-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index bc5708a589..9ce53681d0 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gitlab", - "version": "0.1.16-next.2", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index ced0c8f8ce..fd4afbc91c 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.15 + ## 0.1.16-next.2 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 79e512f16c..f7cfa76cef 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-backend-test-utils", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", - "version": "0.1.16-next.2", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index 618bbfaeb1..0ecbc4461e 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-events-backend +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + ## 0.2.15-next.2 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index d06abe1d69..6c330ce996 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend", - "version": "0.2.15-next.2", + "version": "0.2.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index de950928af..cf2c846c93 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-events-node +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + ## 0.2.15-next.2 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 1918c7f247..804eabe491 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-node", "description": "The plugin-events-node module for @backstage/plugin-events-backend", - "version": "0.2.15-next.2", + "version": "0.2.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index 95d2fead77..3ce8bb2103 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @internal/plugin-todo-list-backend +## 1.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 1.0.18-next.2 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index d8ad84d67a..c13bb571e2 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.18-next.2", + "version": "1.0.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list-common/CHANGELOG.md b/plugins/example-todo-list-common/CHANGELOG.md index ad0c7d91e9..8deaa18374 100644 --- a/plugins/example-todo-list-common/CHANGELOG.md +++ b/plugins/example-todo-list-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @internal/plugin-todo-list-common +## 1.0.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9 + ## 1.0.14-next.0 ### Patch Changes diff --git a/plugins/example-todo-list-common/package.json b/plugins/example-todo-list-common/package.json index f2c852921c..57e6a9dbdf 100644 --- a/plugins/example-todo-list-common/package.json +++ b/plugins/example-todo-list-common/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-common", - "version": "1.0.14-next.0", + "version": "1.0.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index f23c1769d3..1a4c10fb2b 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,14 @@ # @internal/plugin-todo-list +## 1.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + ## 1.0.18-next.2 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 698f4547c7..36eb464bb5 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list", - "version": "1.0.18-next.2", + "version": "1.0.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-backend/CHANGELOG.md b/plugins/explore-backend/CHANGELOG.md index 1e49ebec92..c02ad2da28 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-explore-backend +## 0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + ## 0.0.16-next.2 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index 72c461a539..8c1ae12922 100644 --- a/plugins/explore-backend/package.json +++ b/plugins/explore-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore-backend", - "version": "0.0.16-next.2", + "version": "0.0.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-react/CHANGELOG.md b/plugins/explore-react/CHANGELOG.md index 499e04120f..ba70624ec9 100644 --- a/plugins/explore-react/CHANGELOG.md +++ b/plugins/explore-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-explore-react +## 0.0.32 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-explore-common@0.0.2 + ## 0.0.32-next.1 ### Patch Changes diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index cd9cd037e7..d9b9145c27 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.32-next.1", + "version": "0.0.32", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 687cad7d4c..82e0a66d3c 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-explore +## 0.4.11 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0f10c53a05: Create an experimental `ExploreSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-explore-react@0.0.32 + - @backstage/theme@0.4.3 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + ## 0.4.11-next.2 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index e9967fda71..1b4dc7b3e0 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.4.11-next.2", + "version": "0.4.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 8bb37cc531..ef28aa04c6 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-firehydrant +## 0.2.9 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 5ea154d32f..6cd468514a 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.2.9-next.2", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index e22cf6629c..099ab5f5a4 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-fossa +## 0.2.57 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.2.57-next.2 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index cb79e48325..8851cfc766 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.57-next.2", + "version": "0.2.57", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index 0a64fd7019..f9ac25d7f6 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-gcalendar +## 0.3.19 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.3.19-next.2 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index b871d49729..1b74941ce3 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.19-next.2", + "version": "0.3.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index c5c8d88264..5a2c289a94 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-gcp-projects +## 0.3.42 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + ## 0.3.42-next.2 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 4c365e4a33..0544c904a2 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.42-next.2", + "version": "0.3.42", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 7471d15867..a91f49bbe1 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-git-release-manager +## 0.3.38 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + ## 0.3.38-next.2 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 3a49aee327..1cb5f9e4f2 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.38-next.2", + "version": "0.3.38", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 9c57b8914b..f5e9f1bc4c 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-github-actions +## 0.6.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.6.6-next.2 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 446b7434c5..de8f2e64dc 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.6.6-next.2", + "version": "0.6.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 37f8d61176..e44c124264 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-github-deployments +## 0.1.56 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.1.56-next.2 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 0d5f24427f..75fef7213c 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.56-next.2", + "version": "0.1.56", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index c79e8c21eb..11901150bb 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-github-issues +## 0.2.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 7bd0a8ab3c: Filters out entities that belonged to a different github instance other than the one configured by the plugin +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.2.14-next.2 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index ec68838caa..b728856388 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-issues", - "version": "0.2.14-next.2", + "version": "0.2.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index 3dd30fd68e..8721accd79 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.19 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.1.19-next.2 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index cfd6434668..3246afce3c 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-pull-requests-board", "description": "A Backstage plugin that allows you to see all open Pull Requests for all the repositories owned by your team", - "version": "0.1.19-next.2", + "version": "0.1.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index fbcdded7dd..f254fd8eac 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-gitops-profiles +## 0.3.41 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.3.41-next.2 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 5969918cb7..4593ab1e1a 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.41-next.2", + "version": "0.3.41", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index 6b952b9a74..be089e60a5 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-gocd +## 0.1.31 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.1.31-next.2 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index adbb2936b4..809eca8a14 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gocd", "description": "A Backstage plugin that integrates towards GoCD", - "version": "0.1.31-next.2", + "version": "0.1.31", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index b39dd16f2c..dea81e130c 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-graphiql +## 0.2.55 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + ## 0.2.55-next.2 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 36e55b8c66..c2b71fc11c 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.55-next.2", + "version": "0.2.55", "publishConfig": { "access": "public" }, diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index 182d8840b0..dcf6b8f243 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-graphql-backend +## 0.2.0 + +### Minor Changes + +- 9def1e95ab: This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-graphql@0.4.0 + - @backstage/config@1.1.1 + ## 0.1.44-next.2 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index d07cd29a3d..c0b89ef0ce 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-backend", "description": "Deprecated, consider using @frontside/backstage-plugin-graphql-backend instead", - "version": "0.1.44-next.2", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphql-voyager/CHANGELOG.md b/plugins/graphql-voyager/CHANGELOG.md index 85b1cf7dae..20130f64dd 100644 --- a/plugins/graphql-voyager/CHANGELOG.md +++ b/plugins/graphql-voyager/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-graphql-voyager +## 0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + ## 0.1.8-next.2 ### Patch Changes diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index 7d8a07c2ac..f7b89a5b83 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-voyager", "description": "Backstage plugin for GraphQL Voyager", - "version": "0.1.8-next.2", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/home-react/CHANGELOG.md b/plugins/home-react/CHANGELOG.md index 63f73232fe..8124f70308 100644 --- a/plugins/home-react/CHANGELOG.md +++ b/plugins/home-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-home-react +## 0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index 9708367ae4..64a4bcf6f6 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home-react", "description": "A Backstage plugin that contains react components helps you build a home page", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 1f0a83c1c9..cd27145f6c 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-home +## 0.5.9 + +### Patch Changes + +- f997f771da: Adds Top/Recently Visited components to homepage +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.5.9-next.2 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index 017f78be57..58b25eb22c 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.5.9-next.2", + "version": "0.5.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index 1960cff7b1..8e07fa787f 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-ilert +## 0.2.14 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.2.14-next.2 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index da4161cc91..fc860e10c4 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.2.14-next.2", + "version": "0.2.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index e93668b500..27af4041da 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-jenkins-backend +## 0.3.0 + +### Minor Changes + +- 411896faf9: Added JobRunTable Component. + Added new Route and extended Api to get buildJobs. + Actions column has a new icon button, clicking on which takes us to page where we + can see all the job runs. + +### Patch Changes + +- 930ac236d8: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-jenkins-common@0.1.20 + - @backstage/plugin-permission-common@0.7.9 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 02c9c8bf21..740ef8710a 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins-backend", "description": "A Backstage backend plugin that integrates towards Jenkins", - "version": "0.2.9-next.2", + "version": "0.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-common/CHANGELOG.md b/plugins/jenkins-common/CHANGELOG.md index 816bc32b02..f91ea5074c 100644 --- a/plugins/jenkins-common/CHANGELOG.md +++ b/plugins/jenkins-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-jenkins-common +## 0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + ## 0.1.20-next.0 ### Patch Changes diff --git a/plugins/jenkins-common/package.json b/plugins/jenkins-common/package.json index bf9dd8f344..0856d27ad0 100644 --- a/plugins/jenkins-common/package.json +++ b/plugins/jenkins-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins-common", - "version": "0.1.20-next.0", + "version": "0.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 9874ab8bfc..5878d16f47 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-jenkins +## 0.9.0 + +### Minor Changes + +- 411896faf9: Added JobRunTable Component. + Added new Route and extended Api to get buildJobs. + Actions column has a new icon button, clicking on which takes us to page where we + can see all the job runs. + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 1a05cf34f6: Extend EntityJenkinsContent to receive columns as prop +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-jenkins-common@0.1.20 + ## 0.8.7-next.2 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 7d4e60f19b..8153a8bec2 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.8.7-next.2", + "version": "0.9.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index 79183bce97..573be0062f 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-kafka-backend +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.3.3-next.2 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 64aa68be19..68060f254c 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.3.3-next.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index d3f967dc0c..d24a6db0e2 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-kafka +## 0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.3.25-next.2 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 7b03465504..9068de9134 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.3.25-next.2", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index 1f3532632b..138b47b345 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-kubernetes-backend +## 0.13.0 + +### Minor Changes + +- ae943c3bb1: **BREAKING** Allow passing undefined `labelSelector` to `KubernetesFetcher` + + `KubernetesFetch` no longer auto-adds `labelSelector` when empty string was passed. + This is only applicable if you have custom ObjectProvider implementation, as build-in `KubernetesFanOutHandler` already does this + +### Patch Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-node@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 0.12.3-next.2 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 32bc958286..cc0b5016e4 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-backend", "description": "A Backstage backend plugin that integrates towards Kubernetes", - "version": "0.12.3-next.2", + "version": "0.13.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-cluster/CHANGELOG.md b/plugins/kubernetes-cluster/CHANGELOG.md index 9e0961f3f7..fbb762282e 100644 --- a/plugins/kubernetes-cluster/CHANGELOG.md +++ b/plugins/kubernetes-cluster/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-kubernetes-cluster +## 0.0.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-react@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.0.1-next.0 ### Patch Changes diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index 8d0509b448..b54c32f214 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-cluster", "description": "A Backstage plugin that shows details of Kubernetes clusters", - "version": "0.0.1-next.0", + "version": "0.0.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index c95c8afa61..4db1264d6b 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-kubernetes-common +## 0.7.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 0.7.0-next.1 ### Patch Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 3a68e07495..9fe232e68f 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-common", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", - "version": "0.7.0-next.1", + "version": "0.7.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-node/CHANGELOG.md b/plugins/kubernetes-node/CHANGELOG.md index 6aa0b7be7f..cc128fcd7f 100644 --- a/plugins/kubernetes-node/CHANGELOG.md +++ b/plugins/kubernetes-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kubernetes-node +## 0.1.0 + +### Minor Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index 433fadf2f2..6f63ba1364 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-node", "description": "Node.js library for the kubernetes plugin", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-react/CHANGELOG.md b/plugins/kubernetes-react/CHANGELOG.md index bd2c4759de..13c23a75bf 100644 --- a/plugins/kubernetes-react/CHANGELOG.md +++ b/plugins/kubernetes-react/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-kubernetes-react +## 0.1.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 4262e12921: Handle mixed decimals and bigint when calculating k8s resource usage +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/types@1.1.1 + ## 0.1.0-next.1 ### Patch Changes diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index 2463f0bb62..59d4b15bee 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-react", "description": "Web library for the kubernetes-react plugin", - "version": "0.1.0-next.1", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 58016d750a..e208c83b06 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-kubernetes +## 0.11.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- b0aca1a798: Updated dependency `xterm-addon-attach` to `^0.9.0`. + Updated dependency `xterm-addon-fit` to `^0.8.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-react@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.11.0-next.2 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 6075687478..db8f6455ce 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.11.0-next.2", + "version": "0.11.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse-backend/CHANGELOG.md b/plugins/lighthouse-backend/CHANGELOG.md index ae3bc3ec7b..76b12fb1f4 100644 --- a/plugins/lighthouse-backend/CHANGELOG.md +++ b/plugins/lighthouse-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-lighthouse-backend +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + ## 0.3.3-next.2 ### Patch Changes diff --git a/plugins/lighthouse-backend/package.json b/plugins/lighthouse-backend/package.json index 9f7c582060..e5306695cc 100644 --- a/plugins/lighthouse-backend/package.json +++ b/plugins/lighthouse-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-backend", "description": "Backend functionalities for lighthouse", - "version": "0.3.3-next.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse-common/CHANGELOG.md b/plugins/lighthouse-common/CHANGELOG.md index 16133e9d52..ded0273147 100644 --- a/plugins/lighthouse-common/CHANGELOG.md +++ b/plugins/lighthouse-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-lighthouse-common +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/lighthouse-common/package.json b/plugins/lighthouse-common/package.json index e3cab60d5e..e03436fd88 100644 --- a/plugins/lighthouse-common/package.json +++ b/plugins/lighthouse-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-common", "description": "Common functionalities for lighthouse, to be shared between lighthouse and lighthouse-backend plugin", - "version": "0.1.4-next.0", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index a462393423..0b9130363f 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-lighthouse +## 0.4.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + ## 0.4.10-next.2 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 25735b9a31..a63c6bab59 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.4.10-next.2", + "version": "0.4.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist-backend/CHANGELOG.md b/plugins/linguist-backend/CHANGELOG.md index ccdcf24842..74a4eb35a6 100644 --- a/plugins/linguist-backend/CHANGELOG.md +++ b/plugins/linguist-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-linguist-backend +## 0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + ## 0.5.3-next.2 ### Patch Changes diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index 954eb5c634..78aa0868d4 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist-backend", - "version": "0.5.3-next.2", + "version": "0.5.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist/CHANGELOG.md b/plugins/linguist/CHANGELOG.md index 003e1b6d80..85db830a62 100644 --- a/plugins/linguist/CHANGELOG.md +++ b/plugins/linguist/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-linguist +## 0.1.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-linguist-common@0.1.2 + ## 0.1.10-next.2 ### Patch Changes diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index b3f3fedafe..df1e1f962b 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist", - "version": "0.1.10-next.2", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/microsoft-calendar/CHANGELOG.md b/plugins/microsoft-calendar/CHANGELOG.md index fc3a2c86b1..9e8f04b435 100644 --- a/plugins/microsoft-calendar/CHANGELOG.md +++ b/plugins/microsoft-calendar/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-microsoft-calendar +## 0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.1.8-next.2 ### Patch Changes diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index 610940977c..8b19d35ef0 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-microsoft-calendar", - "version": "0.1.8-next.2", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index 8b9e3b4555..1c1a8bc5bf 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-newrelic-dashboard +## 0.3.0 + +### Minor Changes + +- d7eba6cab4: Changes in `newrelic-dashboard` plugin: + + - Make DashboardSnapshotList component public + - Settle discrepancies in the exported API + - Deprecate DashboardSnapshotComponent + +- e605ea4906: Add storybook for newrelic-dashboard plugin. + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 61d55942ae: Fix the styles for NewRelicDashboard, add more responsiveness +- 5194a51a1c: Fixed React Warning: "Each child in a list should have a unique 'key' prop" during the rendering of `EntityNewRelicDashboardCard` +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.3.0-next.2 ### Minor Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index d4d40c8e26..bd24971549 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.3.0-next.2", + "version": "0.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index 5274857950..65d2aad766 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-newrelic +## 0.3.41 + +### Patch Changes + +- ce50a15506: Fixed sorting and searching in the NewRelic table. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + ## 0.3.41-next.2 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 1499839493..3fb1326005 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.41-next.2", + "version": "0.3.41", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/nomad-backend/CHANGELOG.md b/plugins/nomad-backend/CHANGELOG.md index f5ceaf5b9e..b5661c4b40 100644 --- a/plugins/nomad-backend/CHANGELOG.md +++ b/plugins/nomad-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-nomad-backend +## 0.1.8 + +### Patch Changes + +- 6822918c50: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.1.8-next.2 ### Patch Changes diff --git a/plugins/nomad-backend/package.json b/plugins/nomad-backend/package.json index caff96aa11..60ba974467 100644 --- a/plugins/nomad-backend/package.json +++ b/plugins/nomad-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-nomad-backend", - "version": "0.1.8-next.2", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/nomad/CHANGELOG.md b/plugins/nomad/CHANGELOG.md index e16f5ea02c..b6dff83c44 100644 --- a/plugins/nomad/CHANGELOG.md +++ b/plugins/nomad/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-nomad +## 0.1.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + ## 0.1.6-next.2 ### Patch Changes diff --git a/plugins/nomad/package.json b/plugins/nomad/package.json index a500250507..3623019c4c 100644 --- a/plugins/nomad/package.json +++ b/plugins/nomad/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-nomad", - "version": "0.1.6-next.2", + "version": "0.1.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/octopus-deploy/CHANGELOG.md b/plugins/octopus-deploy/CHANGELOG.md index 9ac914a653..64b61be538 100644 --- a/plugins/octopus-deploy/CHANGELOG.md +++ b/plugins/octopus-deploy/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-octopus-deploy +## 0.2.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.2.7-next.2 ### Patch Changes diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index fd375d59f5..6c72fe2446 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-octopus-deploy", - "version": "0.2.7-next.2", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/opencost/CHANGELOG.md b/plugins/opencost/CHANGELOG.md index 24625e7f2d..b20b34b9c4 100644 --- a/plugins/opencost/CHANGELOG.md +++ b/plugins/opencost/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-opencost +## 0.2.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 777b9a16a4: Fix for broken image reference. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + ## 0.2.1-next.2 ### Patch Changes diff --git a/plugins/opencost/package.json b/plugins/opencost/package.json index a2f8aa2ed7..a79b79c0b2 100644 --- a/plugins/opencost/package.json +++ b/plugins/opencost/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-opencost", - "version": "0.2.1-next.2", + "version": "0.2.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 8f1a3bcaf0..1b39333288 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-org-react +## 0.1.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + ## 0.1.14-next.2 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 1877d025fe..9e49b7bda6 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.14-next.2", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index ff34eae200..1faaf20dbb 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-org +## 0.6.15 + +### Patch Changes + +- dc5b6b971b: Fixed the display of OwnershipCard with aggregated relations by loading relations when getting children of entity. + This allows the already existing recursive method to work properly when children of entity have children themselves. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.6.15-next.2 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 8289db0805..d5dca29faa 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.6.15-next.2", + "version": "0.6.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 92721d7cc8..457905f993 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-pagerduty +## 0.6.6 + +### Patch Changes + +- b9ce306814: Minor fix to avoid usage of deprecated prop +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + ## 0.6.6-next.2 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 92337a3ae5..d221a753e4 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.6.6-next.2", + "version": "0.6.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index d0653d6836..03f74fb422 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-periskop-backend +## 0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.2.3-next.2 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index 91a7ee4ebd..1ef6c62431 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.2.3-next.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index 32cccbb745..26c40e8b97 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-periskop +## 0.1.23 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.1.23-next.2 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 2bf9bab4b8..e1cd374cce 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.23-next.2", + "version": "0.1.23", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md index ad8d765829..63e6e54cc2 100644 --- a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md +++ b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-backend-module-allow-all-policy +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-permission-common@0.7.9 + ## 0.1.3-next.2 ### Patch Changes diff --git a/plugins/permission-backend-module-policy-allow-all/package.json b/plugins/permission-backend-module-policy-allow-all/package.json index 0dc2e20689..6ae8cc459d 100644 --- a/plugins/permission-backend-module-policy-allow-all/package.json +++ b/plugins/permission-backend-module-policy-allow-all/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-backend-module-allow-all-policy", "description": "Allow all policy backend module for the permission plugin.", - "version": "0.1.3-next.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 679e235598..a26b60baaf 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-permission-backend +## 0.5.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 0.5.29-next.2 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index a3bd75e6db..f222d51451 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.5.29-next.2", + "version": "0.5.29", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-common/CHANGELOG.md b/plugins/permission-common/CHANGELOG.md index 56af3e310e..c017cd00fc 100644 --- a/plugins/permission-common/CHANGELOG.md +++ b/plugins/permission-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-permission-common +## 0.7.9 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.7.9-next.0 ### Patch Changes diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index c08d962e4a..0c8292a24d 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-common", "description": "Isomorphic types and client for Backstage permissions and authorization", - "version": "0.7.9-next.0", + "version": "0.7.9", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 05af5694ca..222399e878 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-permission-node +## 0.7.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 0.7.17-next.2 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 6aee34ad50..4ed3ceb7ae 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.7.17-next.2", + "version": "0.7.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index 6db19085fb..493ee440b6 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-permission-react +## 0.4.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 0.4.16-next.1 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index b21d3fc6fb..145b6f7d42 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.4.16-next.1", + "version": "0.4.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist-backend/CHANGELOG.md b/plugins/playlist-backend/CHANGELOG.md index 503f4a1796..2fa8f35268 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-playlist-backend +## 0.3.10 + +### Patch Changes + +- 9e46f5ff49: Added support to the playlist plugin for the new backend +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-playlist-common@0.1.11 + ## 0.3.10-next.2 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index 193ecd3fe0..d5b6a5bdaf 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist-backend", - "version": "0.3.10-next.2", + "version": "0.3.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist-common/CHANGELOG.md b/plugins/playlist-common/CHANGELOG.md index cc3cd85cb8..5916ed33e8 100644 --- a/plugins/playlist-common/CHANGELOG.md +++ b/plugins/playlist-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-playlist-common +## 0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9 + ## 0.1.11-next.0 ### Patch Changes diff --git a/plugins/playlist-common/package.json b/plugins/playlist-common/package.json index 08b0b8bb32..e08afb8392 100644 --- a/plugins/playlist-common/package.json +++ b/plugins/playlist-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-playlist-common", "description": "Common functionalities for the playlist plugin", - "version": "0.1.11-next.0", + "version": "0.1.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist/CHANGELOG.md b/plugins/playlist/CHANGELOG.md index 9682635f51..16c0f02912 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-playlist +## 0.1.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 65498193e8: Updated Playlist read me with additional screenshots +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-playlist-common@0.1.11 + ## 0.1.17-next.2 ### Patch Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index a479c2946d..224705983b 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.1.17-next.2", + "version": "0.1.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index a4059a1828..6137545f06 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-proxy-backend +## 0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.4.3-next.2 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 28f8d3ea5f..adbfe9fce9 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.4.3-next.2", + "version": "0.4.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/puppetdb/CHANGELOG.md b/plugins/puppetdb/CHANGELOG.md index 98680eed03..2d184e7a48 100644 --- a/plugins/puppetdb/CHANGELOG.md +++ b/plugins/puppetdb/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-puppetdb +## 0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.1.8-next.2 ### Patch Changes diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index b493b78d71..ae351f5df7 100644 --- a/plugins/puppetdb/package.json +++ b/plugins/puppetdb/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-puppetdb", "description": "Backstage plugin to visualize resource information and Puppet facts from PuppetDB.", - "version": "0.1.8-next.2", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index b6a0bb6a79..dd2df54811 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-rollbar-backend +## 0.1.51 + +### Patch Changes + +- 407f4284be: ensure rollbar token is hidden +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + ## 0.1.51-next.2 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index b58241b5e2..e5dbd3a997 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar-backend", "description": "A Backstage backend plugin that integrates towards Rollbar", - "version": "0.1.51-next.2", + "version": "0.1.51", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index cc3f2e564d..46d27e8bad 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-rollbar +## 0.4.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.4.25-next.2 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 2444240a78..316f9532a1 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.4.25-next.2", + "version": "0.4.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md index 7344084491..2b931dd7da 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend-module-confluence-to-markdown +## 0.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.2.7-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json index dcdfc51f93..9d506d824b 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown", "description": "The confluence-to-markdown module for @backstage/plugin-scaffolder-backend", - "version": "0.2.7-next.2", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 4373cf9a1a..9c68b53d40 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.30 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.2.30-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 68bbd40294..fed7cd4596 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", - "version": "0.2.30-next.2", + "version": "0.2.30", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md index 950fd2edb5..2582ed3227 100644 --- a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-backend-module-gitlab +## 0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index aa57094af4..99c84ed4b9 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitlab", - "version": "0.2.9-next.2", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index e8ee3e7d35..70af7932b8 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.23 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.4.23-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index fad98d5216..2bc91478e4 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", "description": "A module for the scaffolder backend that lets you template projects using Rails", - "version": "0.4.23-next.2", + "version": "0.4.23", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index 55de9576e5..9e0bd8734b 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + ## 0.1.14-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index 53613c14b6..ce1b8247f8 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-sentry", - "version": "0.1.14-next.2", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index 41522939e6..fa7774558a 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.2.27-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 8f17f30e7c..36b8c4e76b 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-yeoman", - "version": "0.2.27-next.2", + "version": "0.2.27", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index f468e42f72..f2258517a6 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-scaffolder-backend +## 1.18.0 + +### Minor Changes + +- dea0aafda7: Updated `publish:gitlab` action properties to support additional Gitlab project settings: + + - general project settings provided by gitlab project create API (new `settings` property) + - branch level settings to create additional branches and make them protected (new `branches` property) + - project level environment variables settings (new `projectVariables` property) + + Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. + +- f41099bb31: Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. + +### Patch Changes + +- 7dd82cc07e: Add examples for `github:issues:label` scaffolder action & improve related tests +- 733ddf7130: Add examples for `publish:Azure` scaffolder action. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-scaffolder-common@1.4.2 + ## 1.18.0-next.2 ### Minor Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 1c87b1f289..20c56e9a8d 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": "1.18.0-next.2", + "version": "1.18.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index 523ce514d6..6e81966514 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-scaffolder-common +## 1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 1.4.2-next.0 ### Patch Changes diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 5fe72348c1..0d9ef37999 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-common", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", - "version": "1.4.2-next.0", + "version": "1.4.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index 0d95cd77cc..33bf8dd380 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-node +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2 + ## 0.2.6-next.2 ### Patch Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index fd49db0371..3194f0c0d6 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-node", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", - "version": "0.2.6-next.2", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index eb20d79d2a..2aed192d7d 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-scaffolder-react +## 1.5.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2 + ## 1.5.6-next.2 ### Patch Changes diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 7a5aa49a01..05dccfa1fe 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-react", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", - "version": "1.5.6-next.2", + "version": "1.5.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index f32e05eed7..2f681837ea 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-scaffolder +## 1.15.1 + +### Patch Changes + +- b337d78c3b: fixed issue related template editor fails with multiple templates per file. +- ff2ab02690: Make entity picker more reliable with only one available entity +- 83e4a42ccd: Display log visibility button on the template panel +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 4c70fe497d: `RepoUrlPickerRepoName` now correctly handles value changes in allowed repos. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + ## 1.15.1-next.2 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 68066a5a79..5cfc038e77 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": "1.15.1-next.2", + "version": "1.15.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-catalog/CHANGELOG.md b/plugins/search-backend-module-catalog/CHANGELOG.md index 80f8e6b2b9..c65b3a119c 100644 --- a/plugins/search-backend-module-catalog/CHANGELOG.md +++ b/plugins/search-backend-module-catalog/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-backend-module-catalog +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + ## 0.1.10-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index dc69657e74..4bcdf8f53b 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-catalog", "description": "A module for the search backend that exports catalog modules", - "version": "0.1.10-next.2", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index e08124fc5a..94727e88a2 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.3.9 + +### Patch Changes + +- 3963d0b885: Ensure that all relevant config fields are properly marked as secret +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/plugin-search-common@1.2.7 + ## 1.3.9-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 505af44be1..ef15b13290 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", "description": "A module for the search backend that implements search using ElasticSearch", - "version": "1.3.9-next.2", + "version": "1.3.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-explore/CHANGELOG.md b/plugins/search-backend-module-explore/CHANGELOG.md index 9acc5a8616..f4b64f07c8 100644 --- a/plugins/search-backend-module-explore/CHANGELOG.md +++ b/plugins/search-backend-module-explore/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search-backend-module-explore +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + ## 0.1.10-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-explore/package.json b/plugins/search-backend-module-explore/package.json index e050734050..41a390d773 100644 --- a/plugins/search-backend-module-explore/package.json +++ b/plugins/search-backend-module-explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-explore", "description": "A module for the search backend that exports explore modules", - "version": "0.1.10-next.2", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 0e2b137bbc..3f8d5adeb7 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + ## 0.5.15-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 1a34413dcc..2bdea9b391 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-pg", "description": "A module for the search backend that implements search using PostgreSQL", - "version": "0.5.15-next.2", + "version": "0.5.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-techdocs/CHANGELOG.md b/plugins/search-backend-module-techdocs/CHANGELOG.md index 557b7edd13..fa8997a990 100644 --- a/plugins/search-backend-module-techdocs/CHANGELOG.md +++ b/plugins/search-backend-module-techdocs/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-backend-module-techdocs +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + ## 0.1.10-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index ec57b3f624..aa888a3d8a 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-techdocs", "description": "A module for the search backend that exports techdocs modules", - "version": "0.1.10-next.2", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 58f334fb30..c2767e6463 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search-backend-node +## 1.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + ## 1.2.10-next.2 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index a040f3a8f7..78d693466d 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-node", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", - "version": "1.2.10-next.2", + "version": "1.2.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index ea0a17908c..94f8c5d605 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-backend +## 1.4.6 + +### Patch Changes + +- 16be6f9473: Set the default length limit to search query to 100. To override it, define `search.maxTermLength` in the config file. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + ## 1.4.6-next.2 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index ead9e7f6b6..cd3c16efe2 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend", "description": "The Backstage backend plugin that provides your backstage app with search", - "version": "1.4.6-next.2", + "version": "1.4.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-common/CHANGELOG.md b/plugins/search-common/CHANGELOG.md index f1ca109111..bfb7959327 100644 --- a/plugins/search-common/CHANGELOG.md +++ b/plugins/search-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-search-common +## 1.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + ## 1.2.7-next.0 ### Patch Changes diff --git a/plugins/search-common/package.json b/plugins/search-common/package.json index 427d6b8498..3fe45d84d2 100644 --- a/plugins/search-common/package.json +++ b/plugins/search-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-common", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", - "version": "1.2.7-next.0", + "version": "1.2.7", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index 0a5cc65d96..91ec2e4421 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-search-react +## 1.7.1 + +### Patch Changes + +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The filter options passed to `SearchResultGroupLayout` are now always explicitly rendered as strings by default. +- 703a4ffc5b: Create `createSearchResultListItem` alpha version that only supports declarative integration. +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-search-common@1.2.7 + ## 1.7.1-next.2 ### Patch Changes diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index fa01c9cb5a..b4a370e639 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.7.1-next.2", + "version": "1.7.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 067c7dfc41..ff8d87c347 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-search +## 1.4.1 + +### Patch Changes + +- e5a2956dd2: Create an experimental search plugin that is compatible with the declarative integration system, it is exported from `/alpha` subpath. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: Minor internal code cleanup. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-search-common@1.2.7 + ## 1.4.1-next.2 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index e4e5ee5aa0..fe84cbe0df 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": "1.4.1-next.2", + "version": "1.4.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 7794d30a34..77895eb2f1 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-sentry +## 0.5.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.5.10-next.2 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index cc9c553bf1..f0a47e966b 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.5.10-next.2", + "version": "0.5.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 49298f1942..6774c7eaf2 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-shortcuts +## 0.3.15 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + ## 0.3.15-next.2 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index db2a5ab6fb..263b476c0e 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.3.15-next.2", + "version": "0.3.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index 72533260d3..caf2a677c1 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-sonarqube-backend +## 0.2.8 + +### Patch Changes + +- a5d592d0ad: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + ## 0.2.8-next.2 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 2b9baba2de..63592380db 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-backend", - "version": "0.2.8-next.2", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-react/CHANGELOG.md b/plugins/sonarqube-react/CHANGELOG.md index 9bf9e3177f..af370f6d1a 100644 --- a/plugins/sonarqube-react/CHANGELOG.md +++ b/plugins/sonarqube-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-sonarqube-react +## 0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index 958c41dde9..c04fdf394c 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-react", - "version": "0.1.9-next.1", + "version": "0.1.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index f8e8b1dde1..3ed88667a9 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-sonarqube +## 0.7.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-sonarqube-react@0.1.9 + ## 0.7.6-next.2 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index b99233d945..b812b5dd8f 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.7.6-next.2", + "version": "0.7.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index 086deabcb7..4b1ac632d1 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-splunk-on-call +## 0.4.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + ## 0.4.14-next.2 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 5066b28a52..bef2ebbb52 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.4.14-next.2", + "version": "0.4.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 588eb3e4c0..bb83becff1 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-stack-overflow-backend +## 0.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + ## 0.2.10-next.2 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 17f5edd9ad..320d35d3b6 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", - "version": "0.2.10-next.2", + "version": "0.2.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index cb9d27d7e1..7ff52c4364 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-stack-overflow +## 0.1.21 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + ## 0.1.21-next.2 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 857b6f22cf..74a30cfd73 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow", - "version": "0.1.21-next.2", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stackstorm/CHANGELOG.md b/plugins/stackstorm/CHANGELOG.md index 199e2e320e..d831792629 100644 --- a/plugins/stackstorm/CHANGELOG.md +++ b/plugins/stackstorm/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-stackstorm +## 0.1.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.1.7-next.2 ### Patch Changes diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index a0c2a0ecdf..ac96d2dbc2 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-stackstorm", "description": "A Backstage plugin that integrates towards StackStorm", - "version": "0.1.7-next.2", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 531e00b079..f319b515ec 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.38 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/config@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.1.38-next.2 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index 496b61cf7b..17fa4702e3 100644 --- a/plugins/tech-insights-backend-module-jsonfc/package.json +++ b/plugins/tech-insights-backend-module-jsonfc/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend-module-jsonfc", - "version": "0.1.38-next.2", + "version": "0.1.38", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index 9a41dd8389..fcd5520d29 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-tech-insights-backend +## 0.5.20 + +### Patch Changes + +- cc7dddfa7f: Increase the maximum allowed length of an entity filter for tech insights fact schemas. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.5.20-next.2 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index 048ea64364..1dda0595f5 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.5.20-next.2", + "version": "0.5.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index fa99e50423..37117bc0d8 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-tech-insights-node +## 0.4.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.4.12-next.2 ### Patch Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 1d72568bc9..23863a774d 100644 --- a/plugins/tech-insights-node/package.json +++ b/plugins/tech-insights-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-node", - "version": "0.4.12-next.2", + "version": "0.4.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index ee64de0b64..83644ecdab 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-tech-insights +## 0.3.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 21f409d776: Export `ScorecardInfo` and `ScorecardsList` components to be able to use manually queried check results directly. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.3.17-next.2 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index e8d9d7a12c..6539d74abb 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.3.17-next.2", + "version": "0.3.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index b182aa25a9..276c50be04 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-tech-radar +## 0.6.9 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- c09d2fa1d6: Added experimental support for the declarative integration. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + ## 0.6.9-next.2 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index d954c71a0c..b7bb44bf81 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.6.9-next.2", + "version": "0.6.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index 321bf0737e..e215d3d842 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.22 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog@1.14.0 + - @backstage/test-utils@1.4.4 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + ## 1.0.22-next.2 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 90fac69b95..b59ffc537c 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.22-next.2", + "version": "1.0.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index caa2e42dcf..ad2b8f67ed 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-techdocs-backend +## 1.8.0 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + ## 1.8.0-next.2 ### Minor Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 3c247508ef..c3e2ee0708 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": "1.8.0-next.2", + "version": "1.8.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index fe8fd1834c..37b6a46b20 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.1.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + ## 1.1.1-next.2 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index c4ff929540..76f358a3a7 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", "description": "Plugin module for contributed TechDocs Addons", - "version": "1.1.1-next.2", + "version": "1.1.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index 91290cc550..2576313037 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-techdocs-node +## 1.9.0 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs. with the serve command using the `--mkdocs-config-file-name` argument + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/plugin-search-common@1.2.7 + ## 1.9.0-next.2 ### Minor Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 4ec11fde71..712693f6af 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-node", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "1.9.0-next.2", + "version": "1.9.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 0d5aafecbc..42edbad969 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-techdocs-react +## 1.1.12 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + ## 1.1.12-next.2 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index f324f3be76..17b681a68b 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-react", "description": "Shared frontend utilities for TechDocs and Addons", - "version": "1.1.12-next.2", + "version": "1.1.12", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 8797b30bd2..4db98ea055 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-techdocs +## 1.8.0 + +### Minor Changes + +- 27740caa2d: Added experimental support for declarative integration via the `/alpha` subpath. + +### Patch Changes + +- 4918f65ab2: Create an experimental `TechDocsSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- 3605370af6: Improved `DocsTable` to display pagination controls dynamically, appearing only when needed. +- 0296f272b4: The `spec.lifecycle' field in entities will now always be rendered as a string. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 9468a67b92: Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. +- df449a7a31: Add kind column by default to TechDocsTable +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + ## 1.7.1-next.2 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 578535c351..eb69181027 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": "1.7.1-next.2", + "version": "1.8.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index cb782356f8..6edbe92aa7 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-todo-backend +## 0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + ## 0.3.4-next.2 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 1df098c517..d3296b70f0 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo-backend", "description": "A Backstage backend plugin that lets you browse TODO comments in your source code", - "version": "0.3.4-next.2", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index b091767889..b30c9d259e 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-todo +## 0.2.28 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.2.28-next.2 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 20fde05ff2..0ce3e92315 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.2.28-next.2", + "version": "0.2.28", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 9554c73992..53e8a6f30f 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-user-settings-backend +## 0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + ## 0.2.4-next.2 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index eb1d08bbe2..cb4e2b4fde 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings-backend", "description": "The Backstage backend plugin to manage user settings", - "version": "0.2.4-next.2", + "version": "0.2.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 3ba16ac03d..3353f23a79 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-user-settings +## 0.7.11 + +### Patch Changes + +- 18c8dee6f5: Added experimental support for declarative integration via the `/alpha` subpath. +- d1b637d005: Fixed a bug where the theme icons would not be colored according to their active state. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + ## 0.7.11-next.2 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 8937cb7dc1..849785907d 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.7.11-next.2", + "version": "0.7.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index 2664187ac0..d623adcf33 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-vault-backend +## 0.3.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + ## 0.3.11-next.2 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index e27a8d0524..883bb5281b 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault-backend", "description": "A Backstage backend plugin that integrates towards Vault", - "version": "0.3.11-next.2", + "version": "0.3.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index c2037ad665..37ed1eb14e 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-vault +## 0.1.20 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.1.20-next.2 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 5eef7bca88..bd7dc3cd7f 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault", "description": "A Backstage plugin that integrates towards Vault", - "version": "0.1.20-next.2", + "version": "0.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index 19f23149bd..9682aa6411 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-xcmetrics +## 0.2.44 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + ## 0.2.44-next.2 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 7a67fd4d5e..27216f5fc2 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.44-next.2", + "version": "0.2.44", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/yarn.lock b/yarn.lock index 9f79ca0ec4..cc986877ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3650,17 +3650,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-client@npm:^1.4.4": - version: 1.4.4 - resolution: "@backstage/catalog-client@npm:1.4.4" - dependencies: - "@backstage/catalog-model": ^1.4.2 - "@backstage/errors": ^1.2.2 - cross-fetch: ^3.1.5 - checksum: 3f821ee7450b192bf750a0275d095a96f7ce137283cecd0353cef817a43fd7f55141d828268cf839b3cfbfc41cea0d6519c4c4411b297b7423728dc7018f68ed - languageName: node - linkType: hard - "@backstage/catalog-client@workspace:^, @backstage/catalog-client@workspace:packages/catalog-client": version: 0.0.0-use.local resolution: "@backstage/catalog-client@workspace:packages/catalog-client" @@ -3673,22 +3662,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@npm:^1.1.5, @backstage/catalog-model@npm:^1.4.2": - version: 1.4.2 - resolution: "@backstage/catalog-model@npm:1.4.2" - dependencies: - "@backstage/config": ^1.1.0 - "@backstage/errors": ^1.2.2 - "@backstage/types": ^1.1.1 - ajv: ^8.10.0 - json-schema: ^0.4.0 - lodash: ^4.17.21 - uuid: ^8.0.0 - checksum: 7e0d8cfb7fc6bab02803201552a24b73a3d7b502f7ba22e3408e86400e2a4f8937e0e91dea9a063d1f8bc128064400e93d05301611772502811feea10e8ad4e9 - languageName: node - linkType: hard - -"@backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.2, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": version: 0.0.0-use.local resolution: "@backstage/catalog-model@workspace:packages/catalog-model" dependencies: @@ -3929,18 +3903,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/config@npm:^1.0.6, @backstage/config@npm:^1.0.7, @backstage/config@npm:^1.1.0": - version: 1.1.0 - resolution: "@backstage/config@npm:1.1.0" - dependencies: - "@backstage/errors": ^1.2.2 - "@backstage/types": ^1.1.1 - lodash: ^4.17.21 - checksum: 9c17ab41b3e4bd6a0ad75caaf46ed3fad198aa8d190cb9a85415140bc9d6506022a4d5450ea5810004fc2d7a3f7a0a00583b468af4a0fa1655ce444606283010 - languageName: node - linkType: hard - -"@backstage/config@workspace:^, @backstage/config@workspace:packages/config": +"@backstage/config@^1.0.6, @backstage/config@^1.0.7, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": version: 0.0.0-use.local resolution: "@backstage/config@workspace:packages/config" dependencies: @@ -3989,111 +3952,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-components@npm:^0.12.3": - version: 0.12.5 - resolution: "@backstage/core-components@npm:0.12.5" - dependencies: - "@backstage/config": ^1.0.7 - "@backstage/core-plugin-api": ^1.5.0 - "@backstage/errors": ^1.1.5 - "@backstage/theme": ^0.2.18 - "@backstage/version-bridge": ^1.0.3 - "@material-table/core": ^3.1.0 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.57 - "@react-hookz/web": ^20.0.0 - "@types/react-sparklines": ^1.7.0 - "@types/react-text-truncate": ^0.14.0 - ansi-regex: ^6.0.1 - classnames: ^2.2.6 - d3-selection: ^3.0.0 - d3-shape: ^3.0.0 - d3-zoom: ^3.0.0 - dagre: ^0.8.5 - history: ^5.0.0 - immer: ^9.0.1 - lodash: ^4.17.21 - pluralize: ^8.0.0 - prop-types: ^15.7.2 - qs: ^6.9.4 - rc-progress: 3.4.1 - react-helmet: 6.1.0 - react-hook-form: ^7.12.2 - react-markdown: ^8.0.0 - react-sparklines: ^1.7.0 - react-syntax-highlighter: ^15.4.5 - react-text-truncate: ^0.19.0 - react-use: ^17.3.2 - react-virtualized-auto-sizer: ^1.0.6 - react-window: ^1.8.6 - remark-gfm: ^3.0.1 - zen-observable: ^0.10.0 - zod: ~3.18.0 - peerDependencies: - "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 8308c1b90247911f6cf22963b530cef169287f508ff29d159d0c83758134dd43bd5acd2113350690a46a02246bc05dca975bcc38325000aefb1c93c80e2f19c7 - languageName: node - linkType: hard - -"@backstage/core-components@npm:^0.13.5": - version: 0.13.5 - resolution: "@backstage/core-components@npm:0.13.5" - dependencies: - "@backstage/config": ^1.1.0 - "@backstage/core-plugin-api": ^1.6.0 - "@backstage/errors": ^1.2.2 - "@backstage/theme": ^0.4.2 - "@backstage/version-bridge": ^1.0.5 - "@date-io/core": ^1.3.13 - "@material-table/core": ^3.1.0 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.61 - "@react-hookz/web": ^20.0.0 - "@types/react": ^16.13.1 || ^17.0.0 - "@types/react-sparklines": ^1.7.0 - "@types/react-text-truncate": ^0.14.0 - ansi-regex: ^6.0.1 - classnames: ^2.2.6 - d3-selection: ^3.0.0 - d3-shape: ^3.0.0 - d3-zoom: ^3.0.0 - dagre: ^0.8.5 - history: ^5.0.0 - immer: ^9.0.1 - linkify-react: 4.1.1 - linkifyjs: 4.1.1 - lodash: ^4.17.21 - pluralize: ^8.0.0 - prop-types: ^15.7.2 - qs: ^6.9.4 - rc-progress: 3.5.1 - react-helmet: 6.1.0 - react-hook-form: ^7.12.2 - react-idle-timer: 5.6.2 - react-markdown: ^8.0.0 - react-sparklines: ^1.7.0 - react-syntax-highlighter: ^15.4.5 - react-text-truncate: ^0.19.0 - react-use: ^17.3.2 - react-virtualized-auto-sizer: ^1.0.11 - react-window: ^1.8.6 - remark-gfm: ^3.0.1 - zen-observable: ^0.10.0 - zod: ^3.21.4 - peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: f1c9290fd1358561c9a1098200cdf1d2dc16117aebf4010759f122b0a638acb50a89faa24988ad4a854ace59a74606329550c59fc98ab6281feb4b4f5bfe52c0 - languageName: node - linkType: hard - -"@backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": +"@backstage/core-components@^0.13.5, @backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" dependencies: @@ -4169,27 +4028,57 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.6.0": - version: 1.6.0 - resolution: "@backstage/core-plugin-api@npm:1.6.0" +"@backstage/core-components@npm:^0.12.3": + version: 0.12.5 + resolution: "@backstage/core-components@npm:0.12.5" dependencies: - "@backstage/config": ^1.1.0 - "@backstage/types": ^1.1.1 - "@backstage/version-bridge": ^1.0.5 - "@types/react": ^16.13.1 || ^17.0.0 + "@backstage/config": ^1.0.7 + "@backstage/core-plugin-api": ^1.5.0 + "@backstage/errors": ^1.1.5 + "@backstage/theme": ^0.2.18 + "@backstage/version-bridge": ^1.0.3 + "@material-table/core": ^3.1.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + "@react-hookz/web": ^20.0.0 + "@types/react-sparklines": ^1.7.0 + "@types/react-text-truncate": ^0.14.0 + ansi-regex: ^6.0.1 + classnames: ^2.2.6 + d3-selection: ^3.0.0 + d3-shape: ^3.0.0 + d3-zoom: ^3.0.0 + dagre: ^0.8.5 history: ^5.0.0 - i18next: ^22.4.15 + immer: ^9.0.1 + lodash: ^4.17.21 + pluralize: ^8.0.0 prop-types: ^15.7.2 + qs: ^6.9.4 + rc-progress: 3.4.1 + react-helmet: 6.1.0 + react-hook-form: ^7.12.2 + react-markdown: ^8.0.0 + react-sparklines: ^1.7.0 + react-syntax-highlighter: ^15.4.5 + react-text-truncate: ^0.19.0 + react-use: ^17.3.2 + react-virtualized-auto-sizer: ^1.0.6 + react-window: ^1.8.6 + remark-gfm: ^3.0.1 zen-observable: ^0.10.0 + zod: ~3.18.0 peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 540deb91d3c143ce1c3736359c3301af64fbd6eccbaae61bfc96f4e180654e7eb025bb1d4ff5be62b7ea3d6dac7ed617e4dba0c176cfdbf865400fde0f987ddb + checksum: 8308c1b90247911f6cf22963b530cef169287f508ff29d159d0c83758134dd43bd5acd2113350690a46a02246bc05dca975bcc38325000aefb1c93c80e2f19c7 languageName: node linkType: hard -"@backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": +"@backstage/core-plugin-api@^1.3.0, @backstage/core-plugin-api@^1.5.0, @backstage/core-plugin-api@^1.6.0, @backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": version: 0.0.0-use.local resolution: "@backstage/core-plugin-api@workspace:packages/core-plugin-api" dependencies: @@ -4288,18 +4177,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/errors@npm:^1.1.5, @backstage/errors@npm:^1.2.2": - version: 1.2.2 - resolution: "@backstage/errors@npm:1.2.2" - dependencies: - "@backstage/types": ^1.1.1 - cross-fetch: ^3.1.5 - serialize-error: ^8.0.1 - checksum: 2fd323d528023654ac0910a5bd8ea703fa97a4bd62ee34b6c75e1c992d1a78cae661f0929c1ffd72df5465a1bda69c1bcad2682f017e5e52daa73154e6284234 - languageName: node - linkType: hard - -"@backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": +"@backstage/errors@^1.1.5, @backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": version: 0.0.0-use.local resolution: "@backstage/errors@workspace:packages/errors" dependencies: @@ -4387,29 +4265,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-react@npm:^1.1.19": - version: 1.1.19 - resolution: "@backstage/integration-react@npm:1.1.19" - dependencies: - "@backstage/config": ^1.1.0 - "@backstage/core-components": ^0.13.5 - "@backstage/core-plugin-api": ^1.6.0 - "@backstage/integration": ^1.7.0 - "@backstage/theme": ^0.4.2 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.61 - "@types/react": ^16.13.1 || ^17.0.0 - react-use: ^17.2.4 - peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 8ef2b46bf91b71351aa4b114de147d130e0298d8849cf2fa358ac1559c2026ffbfad10b15f6fa4bf94c7bbb4f4419766c6c66b77d2859fe184a43351f1f5df81 - languageName: node - linkType: hard - -"@backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": +"@backstage/integration-react@^1.1.19, @backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": version: 0.0.0-use.local resolution: "@backstage/integration-react@workspace:packages/integration-react" dependencies: @@ -4433,23 +4289,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration@npm:^1.7.0": - version: 1.7.0 - resolution: "@backstage/integration@npm:1.7.0" - dependencies: - "@azure/identity": ^3.2.1 - "@backstage/config": ^1.1.0 - "@backstage/errors": ^1.2.2 - "@octokit/auth-app": ^4.0.0 - "@octokit/rest": ^19.0.3 - cross-fetch: ^3.1.5 - git-url-parse: ^13.0.0 - lodash: ^4.17.21 - luxon: ^3.0.0 - checksum: f02516b7bdb7adb0516b49b90802e588f09c43b4db66bcce68314518c46b9c6fb8ca76ac7a55d4a80cdd414bb6876475b42eb6256b2efda9824ad3667ffa8f54 - languageName: node - linkType: hard - "@backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": version: 0.0.0-use.local resolution: "@backstage/integration@workspace:packages/integration" @@ -5831,18 +5670,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-common@npm:^1.0.10, @backstage/plugin-catalog-common@npm:^1.0.16": - version: 1.0.16 - resolution: "@backstage/plugin-catalog-common@npm:1.0.16" - dependencies: - "@backstage/catalog-model": ^1.4.2 - "@backstage/plugin-permission-common": ^0.7.8 - "@backstage/plugin-search-common": ^1.2.6 - checksum: 0dd21c3b704abff78fb091c4c35b0217e557d9a7298fe4227c3a58aa7b2a906ba2d7b7aefce9534ad03d152502dec465d30c07873409f8f803929d62acef9594 - languageName: node - linkType: hard - -"@backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": +"@backstage/plugin-catalog-common@^1.0.10, @backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-common@workspace:plugins/catalog-common" dependencies: @@ -5979,44 +5807,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.4": - version: 1.8.4 - resolution: "@backstage/plugin-catalog-react@npm:1.8.4" - dependencies: - "@backstage/catalog-client": ^1.4.4 - "@backstage/catalog-model": ^1.4.2 - "@backstage/core-components": ^0.13.5 - "@backstage/core-plugin-api": ^1.6.0 - "@backstage/errors": ^1.2.2 - "@backstage/integration": ^1.7.0 - "@backstage/plugin-catalog-common": ^1.0.16 - "@backstage/plugin-permission-common": ^0.7.8 - "@backstage/plugin-permission-react": ^0.4.15 - "@backstage/theme": ^0.4.2 - "@backstage/types": ^1.1.1 - "@backstage/version-bridge": ^1.0.5 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.61 - "@react-hookz/web": ^23.0.0 - "@types/react": ^16.13.1 || ^17.0.0 - classnames: ^2.2.6 - jwt-decode: ^3.1.0 - lodash: ^4.17.21 - material-ui-popup-state: ^1.9.3 - qs: ^6.9.4 - react-use: ^17.2.4 - yaml: ^2.0.0 - zen-observable: ^0.10.0 - peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 6434741a60e4f53604a958c121d283d3d8b2756e1013d3a9b32659ae41b58359cbc3bee0791a95a35c847f43a76de9f9d2ea1f8e5fa6697adfc9115b5042a57e - languageName: node - linkType: hard - -"@backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": +"@backstage/plugin-catalog-react@^1.2.4, @backstage/plugin-catalog-react@^1.8.4, @backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-react@workspace:plugins/catalog-react" dependencies: @@ -7375,25 +7166,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-home-react@npm:^0.1.3": - version: 0.1.3 - resolution: "@backstage/plugin-home-react@npm:0.1.3" - dependencies: - "@backstage/core-components": ^0.13.5 - "@backstage/core-plugin-api": ^1.6.0 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@rjsf/utils": 5.13.0 - "@types/react": ^16.13.1 || ^17.0.0 - peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: e87c9fd44c65aa1a768555812f32f42b1d2dc7ab1097c283cae37105d1f17a7b1b198c85d39d72258551015161f317c8e4538a652f6e8ebe9800c3a365f6ebc3 - languageName: node - linkType: hard - -"@backstage/plugin-home-react@workspace:^, @backstage/plugin-home-react@workspace:plugins/home-react": +"@backstage/plugin-home-react@^0.1.3, @backstage/plugin-home-react@workspace:^, @backstage/plugin-home-react@workspace:plugins/home-react": version: 0.0.0-use.local resolution: "@backstage/plugin-home-react@workspace:plugins/home-react" dependencies: @@ -8389,20 +8162,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-common@npm:^0.7.8": - version: 0.7.8 - resolution: "@backstage/plugin-permission-common@npm:0.7.8" - dependencies: - "@backstage/config": ^1.1.0 - "@backstage/errors": ^1.2.2 - "@backstage/types": ^1.1.1 - cross-fetch: ^3.1.5 - uuid: ^8.0.0 - zod: ^3.21.4 - checksum: 495f92d0360ab36bb707b0de527e31f42d699b177875c2ed4e8519c9721745ec1b67be547cd5862162e5d48e240ed07d9ab179c022adaf8367f03ef7ded6459e - languageName: node - linkType: hard - "@backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-common@workspace:plugins/permission-common" @@ -8441,25 +8200,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-react@npm:^0.4.15": - version: 0.4.15 - resolution: "@backstage/plugin-permission-react@npm:0.4.15" - dependencies: - "@backstage/config": ^1.1.0 - "@backstage/core-plugin-api": ^1.6.0 - "@backstage/plugin-permission-common": ^0.7.8 - "@types/react": ^16.13.1 || ^17.0.0 - cross-fetch: ^3.1.5 - react-use: ^17.2.4 - swr: ^2.0.0 - peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 5f11264a7d46bee0924b9a00133e756e38d3cce5ce842104546963e08b8bfc6445e28ac4b2b75878fd5407631353e964e5f0b399bc958a76aaa732741b80a52a - languageName: node - linkType: hard - "@backstage/plugin-permission-react@workspace:^, @backstage/plugin-permission-react@workspace:plugins/permission-react": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-react@workspace:plugins/permission-react" @@ -9184,16 +8924,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-common@npm:^1.2.6": - version: 1.2.6 - resolution: "@backstage/plugin-search-common@npm:1.2.6" - dependencies: - "@backstage/plugin-permission-common": ^0.7.8 - "@backstage/types": ^1.1.1 - checksum: 19ee6ef72ce75fce6c0e3da5e978419fd01f795db3e701460da652e8581e3eb53fba800c56d518147d03bd4e1e3889fa18e1d11a82a38c26a304fdc3bc5438bc - languageName: node - linkType: hard - "@backstage/plugin-search-common@workspace:^, @backstage/plugin-search-common@workspace:plugins/search-common": version: 0.0.0-use.local resolution: "@backstage/plugin-search-common@workspace:plugins/search-common" @@ -10202,35 +9932,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@npm:^0.2.16, @backstage/theme@npm:^0.2.18": - version: 0.2.19 - resolution: "@backstage/theme@npm:0.2.19" - dependencies: - "@material-ui/core": ^4.12.2 - peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 - checksum: 93ca110a3f953d6d98b4a5f2163beaa1bd1f95adb66a593e85eb523a7012acf654b6148db54008a6434805a4bd9016d67e5c6a317bc56940ee6800aecbb97d6f - languageName: node - linkType: hard - -"@backstage/theme@npm:^0.4.2": - version: 0.4.2 - resolution: "@backstage/theme@npm:0.4.2" - dependencies: - "@emotion/react": ^11.10.5 - "@emotion/styled": ^11.10.5 - "@mui/material": ^5.12.2 - peerDependencies: - "@material-ui/core": ^4.12.2 - "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 - checksum: 22371c3159ed4d2f6d53925d48318d5f8f66ac9d6df6ff32f34b4b52e070e88ada25031b2a8fc3264cb352a24f4128fa1295b1302d1d3f12df3bcb76c785f605 - languageName: node - linkType: hard - -"@backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: @@ -10247,7 +9949,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/types@^1.0.2, @backstage/types@^1.1.1, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": +"@backstage/theme@npm:^0.2.16, @backstage/theme@npm:^0.2.18": + version: 0.2.19 + resolution: "@backstage/theme@npm:0.2.19" + dependencies: + "@material-ui/core": ^4.12.2 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + react-dom: ^16.13.1 || ^17.0.0 + checksum: 93ca110a3f953d6d98b4a5f2163beaa1bd1f95adb66a593e85eb523a7012acf654b6148db54008a6434805a4bd9016d67e5c6a317bc56940ee6800aecbb97d6f + languageName: node + linkType: hard + +"@backstage/types@^1.0.2, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": version: 0.0.0-use.local resolution: "@backstage/types@workspace:packages/types" dependencies: @@ -10258,7 +9972,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/version-bridge@^1.0.3, @backstage/version-bridge@^1.0.5, @backstage/version-bridge@workspace:^, @backstage/version-bridge@workspace:packages/version-bridge": +"@backstage/version-bridge@^1.0.3, @backstage/version-bridge@workspace:^, @backstage/version-bridge@workspace:packages/version-bridge": version: 0.0.0-use.local resolution: "@backstage/version-bridge@workspace:packages/version-bridge" dependencies: From 9b1e71a7e7059a01b26533aee27aed843da4fc97 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 16 Oct 2023 18:09:39 +0200 Subject: [PATCH 032/348] docs: draft a v1.19.0 release notes Signed-off-by: Camila Belo --- docs/releases/v1.19.0.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 docs/releases/v1.19.0.md diff --git a/docs/releases/v1.19.0.md b/docs/releases/v1.19.0.md new file mode 100644 index 0000000000..39dc28d07a --- /dev/null +++ b/docs/releases/v1.19.0.md @@ -0,0 +1,34 @@ +--- +id: v1.19.0 +title: v1.19.0 +description: Backstage Release v1.19.0 +--- + +These are the release notes for the v1.19.0 release of [Backstage](https://backstage.io/). + +A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done. + +## Highlights + +TODO: @backstage/discoverability-maintainers will add an entry for the insightful homepage. + +## Security Fixes + +This release does not contain any security fixes. + +## Upgrade path + +We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated). + +## Links and References + +Below you can find a list of links and references to help you learn about and start using this new release. + +- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) +- [GitHub repository](https://github.com/backstage/backstage) +- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support +- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.19.0-changelog.md) +- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) + +Sign up for our [newsletter](https://info.backstage.spotify.com/newsletter_subscribe) if you want to be informed about what is happening in the world of Backstage. From 9796eaea8b545ea4a2fdbf8ccb6df6c4efb8c900 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 16 Oct 2023 18:10:05 +0200 Subject: [PATCH 033/348] docs: update microsite configs Signed-off-by: Camila Belo --- docs/releases/v1.19.0.md | 56 ++++++++++++++++++++++++++++++++-- microsite/docusaurus.config.js | 2 +- microsite/sidebars.json | 1 + 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/docs/releases/v1.19.0.md b/docs/releases/v1.19.0.md index 39dc28d07a..49a31f32b6 100644 --- a/docs/releases/v1.19.0.md +++ b/docs/releases/v1.19.0.md @@ -10,11 +10,63 @@ A huge thanks to the whole team of maintainers and contributors as well as the a ## Highlights -TODO: @backstage/discoverability-maintainers will add an entry for the insightful homepage. +### Node.js v18 + v20 + +The supported versions of Node.js are now v18 and v20. Be sure to update the `engine` field in your root `package.json` accordingly and update your Dockerfile base images, for example to `node:18-bookworm-slim`. + +### New default `start` command for backends + +Backend packages now use the new `package start` implementation by default. This new version uses module loaders rather than a Webpack build for transpilation. The largest difference from the old version is that the backend process is now restarted on change, rather than using Webpack hot module reloads. When using SQLite the database state is serialized and stored in the parent process across restart, which requires a [migration to the new backend system](https://backstage.io/docs/backend-system/building-backends/migrating). If you have yet to migrate to the new system it is recommended that you set the `LEGACY_BACKEND_START` environment variable when starting the backend to keep the old behavior. + +### **BREAKING**: Allow passing undefined `labelSelector` to `KubernetesFetcher` + +`KubernetesFetch` no longer auto-adds `labelSelector` when an empty string is passed. +This is only applicable if you have a custom ObjectProvider implementation, as build-in `KubernetesFanOutHandler` already does this. + +Contributed by [@szubster](https://github.com/szubster) in [#20541](https://github.com/backstage/backstage/pull/20541) + +### **DEPRECATION**: Catalog GraphQL Backend Package + +This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. + +### **DEPRECATION**: `.icon.svg` Extension Support + +Support for the `.icon.svg` extension has been deprecated and will be removed in a future release. Please migrate existing usage to either inline the SVG elements in a `` component from MUI, or switch to a regular `.svg` asset import. + +### Insightful Homepage + +You can now create an Insightful homepage to show your users their recent and top visited activity in Backstage. Add [this](https://github.com/backstage/backstage/tree/master/plugins/home#page-visit-homepage-component-homepagetopvisited--homepagerecentlyvisited) plugin to track your users’ recent navigation history in your Backstage database and display it in the Backstage Homepage using the customizable Recent and Top visits components (`` and ``)and the extensible Visits API interface. This feature is released with an example that extends the Visits API with LocalStorage as an alternative storage solution for user visit activity. + +### New plugin: Kubernetes Clusters + +This plugin lets you view Kubernetes clusters as an admin. + +### New feature: New Pinniped Auth Provider Module + +This module provides a Pinniped auth provider implementation for the auth backend. + +Contributed by [@RubenV-dev](https://github.com/RubenV-dev) in [#19846](https://github.com/backstage/backstage/pull/19846) + +## More Movement Toward the New Backend System + +Since the last release, a lot of contributions have been made toward migrating features to support [the new backend system](https://backstage.io/docs/backend-system/). + +The following backend plugins were migrated: + +- jenkins +- nomad +- sonarqube +- playlist + +The Kubernetes backend broadened its backend system feature set, with a new extension point. For the catalog backend, some new modules were added, including GitHub org and Microsoft/Azure. + +If you would like to help out with these efforts, check out [this issue](https://github.com/backstage/backstage/issues/18301)! ## Security Fixes -This release does not contain any security fixes. +Some improvements were made in the configuration schemas, ensuring that no secret fields could be read outside of a backend context. + +The `lerna` package in newly scaffolded Backstage repositories is now of version >7 which has security fixes. ## Upgrade path diff --git a/microsite/docusaurus.config.js b/microsite/docusaurus.config.js index 83a5d3ac3d..f4dd76b8e3 100644 --- a/microsite/docusaurus.config.js +++ b/microsite/docusaurus.config.js @@ -178,7 +178,7 @@ module.exports = { position: 'left', }, { - to: 'docs/releases/v1.18.0', + to: 'docs/releases/v1.19.0', label: 'Releases', position: 'left', }, diff --git a/microsite/sidebars.json b/microsite/sidebars.json index bc394982ca..8d8cb39eaa 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -1,6 +1,7 @@ { "releases": { "Release Notes": [ + "releases/v1.19.0", "releases/v1.18.0", "releases/v1.17.0", "releases/v1.16.0", From 640fe3dbef01529263f3793d1d984740b7c61eb4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 11 Oct 2023 15:47:00 +0200 Subject: [PATCH 034/348] frontend-plugin-api: extract Expand to top-level types Signed-off-by: Patrik Oldsberg --- .../src/extensions/createApiExtension.ts | 3 ++- .../src/extensions/createPageExtension.tsx | 3 ++- packages/frontend-plugin-api/src/types.ts | 22 +++++++++++++++++++ .../src/wiring/createExtension.ts | 8 +------ 4 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 packages/frontend-plugin-api/src/types.ts diff --git a/packages/frontend-plugin-api/src/extensions/createApiExtension.ts b/packages/frontend-plugin-api/src/extensions/createApiExtension.ts index 8e5a9e9f33..f728261072 100644 --- a/packages/frontend-plugin-api/src/extensions/createApiExtension.ts +++ b/packages/frontend-plugin-api/src/extensions/createApiExtension.ts @@ -21,7 +21,8 @@ import { createExtension, coreExtensionData, } from '../wiring'; -import { AnyExtensionInputMap, Expand } from '../wiring/createExtension'; +import { AnyExtensionInputMap } from '../wiring/createExtension'; +import { Expand } from '../types'; /** @public */ export function createApiExtension< diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx index 712c55f896..43edfaa36d 100644 --- a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx @@ -24,7 +24,8 @@ import { Extension, ExtensionInputValues, } from '../wiring'; -import { AnyExtensionInputMap, Expand } from '../wiring/createExtension'; +import { AnyExtensionInputMap } from '../wiring/createExtension'; +import { Expand } from '../types'; /** * Helper for creating extensions for a routable React page component. diff --git a/packages/frontend-plugin-api/src/types.ts b/packages/frontend-plugin-api/src/types.ts new file mode 100644 index 0000000000..8b6f02a942 --- /dev/null +++ b/packages/frontend-plugin-api/src/types.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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. + */ + +// TODO(Rugvip): This might be a quite useful utility type, maybe add to @backstage/types? +/** + * Utility type to expand type aliases into their equivalent type. + * @ignore + */ +export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index 01d4962965..fa24a24797 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -15,6 +15,7 @@ */ import { PortableSchema } from '../schema'; +import { Expand } from '../types'; import { ExtensionDataRef } from './createExtensionDataRef'; import { ExtensionInput } from './createExtensionInput'; import { BackstagePlugin } from './createPlugin'; @@ -32,13 +33,6 @@ export type AnyExtensionInputMap = { >; }; -// TODO(Rugvip): This might be a quite useful utility type, maybe add to @backstage/types? -/** - * Utility type to expand type aliases into their equivalent type. - * @ignore - */ -export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; - /** * Converts an extension data map into the matching concrete data values type. * @public From d41c97e5db2c9fb7bebfd9c2bf483a41781c93cc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 11 Oct 2023 20:04:21 +0200 Subject: [PATCH 035/348] frontend-plugin-api: forklift routing API from core-plugin-api Signed-off-by: Patrik Oldsberg --- packages/frontend-plugin-api/package.json | 4 +- .../src/routing/ExternalRouteRef.test.ts | 112 +++++++++++++ .../src/routing/ExternalRouteRef.ts | 86 ++++++++++ .../src/routing/RouteRef.test.ts | 74 +++++++++ .../src/routing/RouteRef.ts | 73 ++++++++ .../src/routing/SubRouteRef.test.ts | 128 ++++++++++++++ .../src/routing/SubRouteRef.ts | 148 +++++++++++++++++ .../frontend-plugin-api/src/routing/index.ts | 37 +++++ .../frontend-plugin-api/src/routing/types.ts | 146 ++++++++++++++++ .../src/routing/useRouteRef.test.tsx | 157 ++++++++++++++++++ .../src/routing/useRouteRef.tsx | 115 +++++++++++++ .../src/routing/useRouteRefParams.test.tsx | 52 ++++++ .../src/routing/useRouteRefParams.ts | 29 ++++ yarn.lock | 6 +- 14 files changed, 1164 insertions(+), 3 deletions(-) create mode 100644 packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts create mode 100644 packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts create mode 100644 packages/frontend-plugin-api/src/routing/RouteRef.test.ts create mode 100644 packages/frontend-plugin-api/src/routing/RouteRef.ts create mode 100644 packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts create mode 100644 packages/frontend-plugin-api/src/routing/SubRouteRef.ts create mode 100644 packages/frontend-plugin-api/src/routing/index.ts create mode 100644 packages/frontend-plugin-api/src/routing/types.ts create mode 100644 packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx create mode 100644 packages/frontend-plugin-api/src/routing/useRouteRef.tsx create mode 100644 packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx create mode 100644 packages/frontend-plugin-api/src/routing/useRouteRefParams.ts diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 6100e30cf3..e996881611 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -27,7 +27,8 @@ "@backstage/frontend-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3" + "@testing-library/react-hooks": "^8.0.1", + "history": "^5.3.0" }, "files": [ "dist" @@ -39,6 +40,7 @@ "dependencies": { "@backstage/core-plugin-api": "workspace:^", "@backstage/types": "workspace:^", + "@backstage/version-bridge": "workspace:^", "@types/react": "^16.13.1 || ^17.0.0", "lodash": "^4.17.21", "zod": "^3.21.4", diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts new file mode 100644 index 0000000000..f6e072f760 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts @@ -0,0 +1,112 @@ +/* + * Copyright 2020 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 { AnyParams, ExternalRouteRef } from './types'; +import { createExternalRouteRef } from './ExternalRouteRef'; + +describe('ExternalRouteRef', () => { + it('should be created', () => { + const routeRef: ExternalRouteRef = createExternalRouteRef({ + id: 'my-route-ref', + }); + expect(routeRef.params).toEqual([]); + expect(routeRef.optional).toBe(false); + expect(String(routeRef)).toBe('routeRef{type=external,id=my-route-ref}'); + }); + + it('should be created as optional', () => { + const routeRef: ExternalRouteRef<{ + x: string; + y: string; + }> = createExternalRouteRef({ + id: 'my-other-route-ref', + params: [], + optional: true, + }); + expect(routeRef.params).toEqual([]); + expect(routeRef.optional).toEqual(true); + }); + + it('should be created with params', () => { + const routeRef: ExternalRouteRef<{ + x: string; + y: string; + }> = createExternalRouteRef({ + id: 'my-other-route-ref', + params: ['x', 'y'], + }); + expect(routeRef.params).toEqual(['x', 'y']); + expect(routeRef.optional).toEqual(false); + }); + + it('should be created as optional with params', () => { + const routeRef: ExternalRouteRef<{ + x: string; + y: string; + }> = createExternalRouteRef({ + id: 'my-other-route-ref', + params: ['x', 'y'], + optional: true, + }); + expect(routeRef.params).toEqual(['x', 'y']); + expect(routeRef.optional).toEqual(true); + }); + + it('should properly infer and validate parameter types and assignments', () => { + function validateType( + _ref: ExternalRouteRef, + ) {} + + const _1 = createExternalRouteRef({ id: '1', params: ['notX'] }); + // @ts-expect-error + validateType<{ x: string }, any>(_1); + validateType<{ notX: string }, any>(_1); + + const _2 = createExternalRouteRef({ + id: '2', + params: ['x'], + optional: true, + }); + // @ts-expect-error + validateType(_2); + validateType<{ x: string }, true>(_2); + + const _3 = createExternalRouteRef({ id: '3', params: ['x', 'y'] }); + // @ts-expect-error + validateType<{ x: string }, any>(_3); + // extra z, we validate this at runtime instead + validateType<{ x: string; y: string; z: string }, any>(_3); + validateType<{ x: string; y: string }, false>(_3); + + const _4 = createExternalRouteRef({ id: '4', params: [] }); + // @ts-expect-error + validateType<{ x: string }, any>(_4); + validateType(_4); + + const _5 = createExternalRouteRef({ id: '5' }); + // @ts-expect-error + validateType<{ x: string }, any>(_5); + validateType(_5); + + const _6 = createExternalRouteRef({ id: '6', optional: true }); + // @ts-expect-error + validateType(_6); + validateType(_6); + + // To avoid complains about missing expectations and unused vars + expect([_1, _2, _3, _4, _5, _6].join('')).toEqual(expect.any(String)); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts new file mode 100644 index 0000000000..2ebb81dbfb --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts @@ -0,0 +1,86 @@ +/* + * Copyright 2020 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 { + ExternalRouteRef, + routeRefType, + AnyParams, + ParamKeys, + OptionalParams, +} from './types'; + +/** + * @internal + */ +export class ExternalRouteRefImpl< + Params extends AnyParams, + Optional extends boolean, +> implements ExternalRouteRef +{ + // The marker is used for type checking while the symbol is used at runtime. + declare $$routeRefType: 'external'; + readonly [routeRefType] = 'external'; + + constructor( + private readonly id: string, + readonly params: ParamKeys, + readonly optional: Optional, + ) {} + + toString() { + return `routeRef{type=external,id=${this.id}}`; + } +} + +/** + * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @param options - Description of the route reference to be created. + * @public + */ +export function createExternalRouteRef< + Params extends { [param in ParamKey]: string }, + Optional extends boolean = false, + ParamKey extends string = never, +>(options: { + /** + * An identifier for this route, used to identify it in error messages + */ + id: string; + + /** + * The parameters that will be provided to the external route reference. + */ + params?: ParamKey[]; + + /** + * Whether or not this route is optional, defaults to false. + * + * Optional external routes are not required to be bound in the app, and + * if they aren't, `useRouteRef` will return `undefined`. + */ + optional?: Optional; +}): ExternalRouteRef, Optional> { + return new ExternalRouteRefImpl( + options.id, + (options.params ?? []) as ParamKeys>, + Boolean(options.optional) as Optional, + ); +} diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts new file mode 100644 index 0000000000..5314957a25 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts @@ -0,0 +1,74 @@ +/* + * Copyright 2020 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 { AnyParams, RouteRef } from './types'; +import { createRouteRef } from './RouteRef'; + +describe('RouteRef', () => { + it('should be created', () => { + const routeRef: RouteRef = createRouteRef({ + id: 'my-route-ref', + }); + expect(routeRef.params).toEqual([]); + expect(String(routeRef)).toBe('routeRef{type=absolute,id=my-route-ref}'); + }); + + it('should be created with params', () => { + const routeRef: RouteRef<{ + x: string; + y: string; + }> = createRouteRef({ + id: 'my-other-route-ref', + params: ['x', 'y'], + }); + expect(routeRef.params).toEqual(['x', 'y']); + }); + + it('should properly infer and validate parameter types and assignments', () => { + function validateType(_ref: RouteRef) {} + + const _1 = createRouteRef({ id: '1', params: ['x'] }); + // @ts-expect-error + validateType<{ y: string }>(_1); + // @ts-expect-error + validateType(_1); + validateType<{ x: string }>(_1); + + const _2 = createRouteRef({ id: '2', params: ['x', 'y'] }); + // @ts-expect-error + validateType<{ x: string }>(_2); + // @ts-expect-error + validateType(_2); + // @ts-expect-error + validateType<{ x: string; z: string }>(_2); + // extra z, we validate this at runtime instead + validateType<{ x: string; y: string; z: string }>(_2); + validateType<{ x: string; y: string }>(_2); + + const _3 = createRouteRef({ id: '3', params: [] }); + // @ts-expect-error + validateType<{ x: string }>(_3); + validateType(_3); + + const _4 = createRouteRef({ id: '4' }); + // @ts-expect-error + validateType<{ x: string }>(_4); + validateType(_4); + + // To avoid complains about missing expectations and unused vars + expect([_1, _2, _3, _4].join('')).toEqual(expect.any(String)); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.ts b/packages/frontend-plugin-api/src/routing/RouteRef.ts new file mode 100644 index 0000000000..36ca3f073d --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/RouteRef.ts @@ -0,0 +1,73 @@ +/* + * Copyright 2020 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 { + RouteRef, + routeRefType, + AnyParams, + ParamKeys, + OptionalParams, +} from './types'; + +/** + * @internal + */ +export class RouteRefImpl + implements RouteRef +{ + // The marker is used for type checking while the symbol is used at runtime. + declare $$routeRefType: 'absolute'; + readonly [routeRefType] = 'absolute'; + + constructor( + private readonly id: string, + readonly params: ParamKeys, + ) {} + + get title() { + return this.id; + } + + toString() { + return `routeRef{type=absolute,id=${this.id}}`; + } +} + +/** + * Create a {@link RouteRef} from a route descriptor. + * + * @param config - Description of the route reference to be created. + * @public + */ +export function createRouteRef< + // Params is the type that we care about and the one to be embedded in the route ref. + // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string} + Params extends { [param in ParamKey]: string }, + // ParamKey is here to make sure the Params type properly has its keys narrowed down + // to only the elements of params. Defaulting to never makes sure we end up with + // Param = {} if the params array is empty. + ParamKey extends string = never, +>(config: { + /** The id of the route ref, used to identify it when printed */ + id: string; + /** A list of parameter names that the path that this route ref is bound to must contain */ + params?: ParamKey[]; +}): RouteRef> { + return new RouteRefImpl( + config.id, + (config.params ?? []) as ParamKeys>, + ); +} diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts new file mode 100644 index 0000000000..cec00de025 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts @@ -0,0 +1,128 @@ +/* + * Copyright 2020 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 { AnyParams, SubRouteRef } from './types'; +import { createSubRouteRef } from './SubRouteRef'; +import { createRouteRef } from './RouteRef'; + +const parent = createRouteRef({ id: 'parent' }); +const parentX = createRouteRef({ id: 'parent-x', params: ['x'] }); + +describe('SubRouteRef', () => { + it('should be created', () => { + const routeRef: SubRouteRef = createSubRouteRef({ + parent, + id: 'my-route-ref', + path: '/foo', + }); + expect(routeRef.path).toBe('/foo'); + expect(routeRef.parent).toBe(parent); + expect(routeRef.params).toEqual([]); + expect(String(routeRef)).toBe('routeRef{type=sub,id=my-route-ref}'); + }); + + it('should be created with params', () => { + const routeRef: SubRouteRef<{ bar: string }> = createSubRouteRef({ + parent, + id: 'my-other-route-ref', + path: '/foo/:bar', + }); + expect(routeRef.path).toBe('/foo/:bar'); + expect(routeRef.parent).toBe(parent); + expect(routeRef.params).toEqual(['bar']); + }); + + it('should be created with merged params', () => { + const routeRef: SubRouteRef<{ + x: string; + y: string; + z: string; + }> = createSubRouteRef({ + parent: parentX, + id: 'my-other-route-ref', + path: '/foo/:y/:z', + }); + expect(routeRef.path).toBe('/foo/:y/:z'); + expect(routeRef.parent).toBe(parentX); + expect(routeRef.params).toEqual(['x', 'y', 'z']); + }); + + it('should be created with params from parent', () => { + const routeRef: SubRouteRef<{ x: string }> = createSubRouteRef({ + parent: parentX, + id: 'my-other-route-ref', + path: '/foo/bar', + }); + expect(routeRef.path).toBe('/foo/bar'); + expect(routeRef.parent).toBe(parentX); + expect(routeRef.params).toEqual(['x']); + }); + + it.each([ + ['foo', "SubRouteRef path must start with '/', got 'foo'"], + [':foo', "SubRouteRef path must start with '/', got ':foo'"], + ['', "SubRouteRef path must start with '/', got ''"], + ['/', "SubRouteRef path must not end with '/', got '/'"], + ['/foo/', "SubRouteRef path must not end with '/', got '/foo/'"], + ['/foo/:x', 'SubRouteRef may not have params that overlap with its parent'], + ['/:/foo', "SubRouteRef path has invalid param, got ''"], + ['/:inva:lid/foo', "SubRouteRef path has invalid param, got 'inva:lid'"], + ['/:inva=lid/foo', "SubRouteRef path has invalid param, got 'inva=lid'"], + ])('should throw if path is invalid, %s', (path, message) => { + expect(() => + createSubRouteRef({ path, parent: parentX, id: path }), + ).toThrow(message); + }); + + it('should properly infer and parse path parameters', () => { + function validateType(_ref: SubRouteRef) {} + + const _1 = createSubRouteRef({ id: '1', parent, path: '/foo/bar' }); + // @ts-expect-error + validateType<{ x: string }>(_1); + validateType(_1); + + const _2 = createSubRouteRef({ id: '2', parent, path: '/foo/:x/:y' }); + // @ts-expect-error + validateType(_2); + // @ts-expect-error + validateType<{ x: string; z: string }>(_2); + // @ts-expect-error + validateType<{ y: string }>(_2); + // extra z, we validate this at runtime instead + validateType<{ x: string; y: string; z: string }>(_2); + validateType<{ x: string; y: string }>(_2); + + const _3 = createSubRouteRef({ id: '3', parent: parentX, path: '/foo' }); + // @ts-expect-error + validateType(_3); + // @ts-expect-error + validateType<{ y: string }>(_3); + validateType<{ x: string }>(_3); + + const _4 = createSubRouteRef({ id: '4', parent: parentX, path: '/foo/:y' }); + // @ts-expect-error + validateType(_4); + // @ts-expect-error + validateType<{ x: string; z: string }>(_4); + // @ts-expect-error + validateType<{ y: string }>(_4); + validateType<{ x: string; y: string }>(_4); + + // To avoid complains about missing expectations and unused vars + expect([_1, _2, _3, _4].join('')).toEqual(expect.any(String)); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts new file mode 100644 index 0000000000..14a614c2ba --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts @@ -0,0 +1,148 @@ +/* + * Copyright 2020 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 { + AnyParams, + OptionalParams, + ParamKeys, + RouteRef, + routeRefType, + SubRouteRef, +} from './types'; + +// Should match the pattern in react-router +const PARAM_PATTERN = /^\w+$/; + +/** + * @internal + */ +export class SubRouteRefImpl + implements SubRouteRef +{ + // The marker is used for type checking while the symbol is used at runtime. + declare $$routeRefType: 'sub'; + readonly [routeRefType] = 'sub'; + + constructor( + private readonly id: string, + readonly path: string, + readonly parent: RouteRef, + readonly params: ParamKeys, + ) {} + + toString() { + return `routeRef{type=sub,id=${this.id}}`; + } +} + +/** + * Used in {@link PathParams} type declaration. + * @public + */ +export type ParamPart = S extends `:${infer Param}` + ? Param + : never; + +/** + * Used in {@link PathParams} type declaration. + * @public + */ +export type ParamNames = + S extends `${infer Part}/${infer Rest}` + ? ParamPart | ParamNames + : ParamPart; +/** + * This utility type helps us infer a Param object type from a string path + * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }` + * @public + */ +export type PathParams = { [name in ParamNames]: string }; + +/** + * Merges a param object type with an optional params type into a params object. + * @public + */ +export type MergeParams< + P1 extends { [param in string]: string }, + P2 extends AnyParams, +> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2); + +/** + * Creates a SubRouteRef type given the desired parameters and parent route parameters. + * The parameters types are merged together while ensuring that there is no overlap between the two. + * + * @public + */ +export type MakeSubRouteRef< + Params extends { [param in string]: string }, + ParentParams extends AnyParams, +> = keyof Params & keyof ParentParams extends never + ? SubRouteRef>> + : never; + +/** + * Create a {@link SubRouteRef} from a route descriptor. + * + * @param config - Description of the route reference to be created. + * @public + */ +export function createSubRouteRef< + Path extends string, + ParentParams extends AnyParams = never, +>(config: { + id: string; + path: Path; + parent: RouteRef; +}): MakeSubRouteRef, ParentParams> { + const { id, path, parent } = config; + type Params = PathParams; + + // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz' + const pathParams = path + .split('/') + .filter(p => p.startsWith(':')) + .map(p => p.substring(1)); + const params = [...parent.params, ...pathParams]; + + if (parent.params.some(p => pathParams.includes(p as string))) { + throw new Error( + 'SubRouteRef may not have params that overlap with its parent', + ); + } + if (!path.startsWith('/')) { + throw new Error(`SubRouteRef path must start with '/', got '${path}'`); + } + if (path.endsWith('/')) { + throw new Error(`SubRouteRef path must not end with '/', got '${path}'`); + } + for (const param of pathParams) { + if (!PARAM_PATTERN.test(param)) { + throw new Error(`SubRouteRef path has invalid param, got '${param}'`); + } + } + + // We ensure that the type of the return type is sane here + const subRouteRef = new SubRouteRefImpl( + id, + path, + parent, + params as ParamKeys>, + ) as SubRouteRef>>; + + // But skip type checking of the return value itself, because the conditional + // type checking of the parent parameter overlap is tricky to express. + return subRouteRef as any; +} diff --git a/packages/frontend-plugin-api/src/routing/index.ts b/packages/frontend-plugin-api/src/routing/index.ts new file mode 100644 index 0000000000..01d69cd4b0 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/index.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2020 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 { + AnyParams, + RouteRef, + SubRouteRef, + ExternalRouteRef, + OptionalParams, + ParamKeys, + RouteFunc, +} from './types'; +export { createRouteRef } from './RouteRef'; +export { createSubRouteRef } from './SubRouteRef'; +export type { + MakeSubRouteRef, + MergeParams, + ParamNames, + ParamPart, + PathParams, +} from './SubRouteRef'; +export { createExternalRouteRef } from './ExternalRouteRef'; +export { useRouteRef } from './useRouteRef'; +export { useRouteRefParams } from './useRouteRefParams'; diff --git a/packages/frontend-plugin-api/src/routing/types.ts b/packages/frontend-plugin-api/src/routing/types.ts new file mode 100644 index 0000000000..80653518bb --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/types.ts @@ -0,0 +1,146 @@ +/* + * Copyright 2020 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 { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; + +/** + * Catch-all type for route params. + * + * @public + */ +export type AnyParams = { [param in string]: string } | undefined; + +/** + * Type describing the key type of a route parameter mapping. + * + * @public + */ +export type ParamKeys = keyof Params extends never + ? [] + : (keyof Params)[]; + +/** + * Optional route params. + * + * @public + */ +export type OptionalParams = + Params[keyof Params] extends never ? undefined : Params; + +/** + * TS magic for handling route parameters. + * + * @remarks + * + * The extra TS magic here is to require a single params argument if the RouteRef + * had at least one param defined, but require 0 arguments if there are no params defined. + * Without this we'd have to pass in empty object to all parameter-less RouteRefs + * just to make TypeScript happy, or we would have to make the argument optional in + * which case you might forget to pass it in when it is actually required. + * + * @public + */ +export type RouteFunc = ( + ...[params]: Params extends undefined ? readonly [] : readonly [Params] +) => string; + +/** + * This symbol is what we use at runtime to determine whether a given object + * is a type of RouteRef or not. It doesn't work well in TypeScript though since + * the `unique symbol` will refer to different values between package versions. + * For that reason we use the marker $$routeRefType to represent the symbol at + * compile-time instead of using the symbol directly. + * + * @internal + */ +export const routeRefType: unique symbol = getOrCreateGlobalSingleton( + 'route-ref-type', + () => Symbol('route-ref-type'), +); + +/** + * Absolute route reference. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @public + */ +export type RouteRef = { + $$routeRefType: 'absolute'; // See routeRefType above + + params: ParamKeys; +}; + +/** + * Descriptor of a route relative to an absolute {@link RouteRef}. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @public + */ +export type SubRouteRef = { + $$routeRefType: 'sub'; // See routeRefType above + + parent: RouteRef; + + path: string; + + params: ParamKeys; +}; + +/** + * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @public + */ +export type ExternalRouteRef< + Params extends AnyParams = any, + Optional extends boolean = any, +> = { + $$routeRefType: 'external'; // See routeRefType above + + params: ParamKeys; + + optional?: Optional; +}; + +/** + * @internal + */ +export type AnyRouteRef = + | RouteRef + | SubRouteRef + | ExternalRouteRef; + +/** + * A duplicate of the react-router RouteObject, but with routeRef added + * @internal + */ +export interface BackstageRouteObject { + caseSensitive: boolean; + children?: BackstageRouteObject[]; + element: React.ReactNode; + path: string; + routeRefs: Set; +} diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx b/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx new file mode 100644 index 0000000000..7a03a1cdc4 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx @@ -0,0 +1,157 @@ +/* + * Copyright 2020 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 { renderHook } from '@testing-library/react-hooks'; +import React from 'react'; +import { MemoryRouter, Router } from 'react-router-dom'; +import { createVersionedContextForTesting } from '@backstage/version-bridge'; +import { useRouteRef } from './useRouteRef'; +import { createRouteRef } from './RouteRef'; +import { createBrowserHistory } from 'history'; + +describe('v1 consumer', () => { + const context = createVersionedContextForTesting('routing-context'); + + afterEach(() => { + context.reset(); + }); + + it('should resolve routes', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef({ id: 'ref1' }); + + const renderedHook = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + + ), + }); + + const routeFunc = renderedHook.result.current; + expect(routeFunc()).toBe('/hello'); + expect(resolve).toHaveBeenCalledWith( + routeRef, + expect.objectContaining({ + pathname: '/my-page', + }), + ); + }); + + it('re-resolves the routeFunc when the search parameters change', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef({ id: 'ref1' }); + const history = createBrowserHistory(); + history.push('/my-page'); + + const { rerender } = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + + ), + }); + + expect(resolve).toHaveBeenCalledTimes(1); + + history.push('/my-new-page'); + rerender(); + + expect(resolve).toHaveBeenCalledTimes(2); + }); + + it('does not re-resolve the routeFunc the location pathname does not change', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef({ id: 'ref1' }); + const history = createBrowserHistory(); + history.push('/my-page'); + + const { rerender } = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + + ), + }); + + expect(resolve).toHaveBeenCalledTimes(1); + + history.push('/my-page'); + rerender(); + + expect(resolve).toHaveBeenCalledTimes(1); + }); + + it('does not re-resolve the routeFunc when the search parameter changes', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef({ id: 'ref1' }); + const history = createBrowserHistory(); + history.push('/my-page'); + + const { rerender } = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + + ), + }); + + expect(resolve).toHaveBeenCalledTimes(1); + + history.push('/my-page?foo=bar'); + rerender(); + + expect(resolve).toHaveBeenCalledTimes(1); + }); + + it('does not re-resolve the routeFunc when the hash parameter changes', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef({ id: 'ref1' }); + const history = createBrowserHistory(); + history.push('/my-page'); + + const { rerender } = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + + ), + }); + + expect(resolve).toHaveBeenCalledTimes(1); + + history.push('/my-page#foo'); + rerender(); + + expect(resolve).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.tsx b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx new file mode 100644 index 0000000000..cf292b110f --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx @@ -0,0 +1,115 @@ +/* + * Copyright 2020 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 { useMemo } from 'react'; +import { matchRoutes, useLocation } from 'react-router-dom'; +import { useVersionedContext } from '@backstage/version-bridge'; +import { + AnyParams, + ExternalRouteRef, + RouteFunc, + RouteRef, + SubRouteRef, +} from './types'; + +/** + * @internal + */ +export interface RouteResolver { + resolve( + anyRouteRef: + | RouteRef + | SubRouteRef + | ExternalRouteRef, + sourceLocation: Parameters[1], + ): RouteFunc | undefined; +} + +/** + * React hook for constructing URLs to routes. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system} + * + * @param routeRef - The ref to route that should be converted to URL. + * @returns A function that will in turn return the concrete URL of the `routeRef`. + * @public + */ +export function useRouteRef( + routeRef: ExternalRouteRef, +): Optional extends true ? RouteFunc | undefined : RouteFunc; + +/** + * React hook for constructing URLs to routes. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system} + * + * @param routeRef - The ref to route that should be converted to URL. + * @returns A function that will in turn return the concrete URL of the `routeRef`. + * @public + */ +export function useRouteRef( + routeRef: RouteRef | SubRouteRef, +): RouteFunc; + +/** + * React hook for constructing URLs to routes. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system} + * + * @param routeRef - The ref to route that should be converted to URL. + * @returns A function that will in turn return the concrete URL of the `routeRef`. + * @public + */ +export function useRouteRef( + routeRef: + | RouteRef + | SubRouteRef + | ExternalRouteRef, +): RouteFunc | undefined { + const { pathname } = useLocation(); + const versionedContext = useVersionedContext<{ 1: RouteResolver }>( + 'routing-context', + ); + if (!versionedContext) { + throw new Error('Routing context is not available'); + } + + const resolver = versionedContext.atVersion(1); + const routeFunc = useMemo( + () => resolver && resolver.resolve(routeRef, { pathname }), + [resolver, routeRef, pathname], + ); + + if (!versionedContext) { + throw new Error('useRouteRef used outside of routing context'); + } + if (!resolver) { + throw new Error('RoutingContext v1 not available'); + } + + const isOptional = 'optional' in routeRef && routeRef.optional; + if (!routeFunc && !isOptional) { + throw new Error(`No path for ${routeRef}`); + } + + return routeFunc; +} diff --git a/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx b/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx new file mode 100644 index 0000000000..40ee7219c2 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx @@ -0,0 +1,52 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { useRouteRefParams } from './useRouteRefParams'; +import { createRouteRef } from './RouteRef'; + +describe('useRouteRefParams', () => { + it('should provide types params', () => { + const routeRef = createRouteRef({ + id: 'ref1', + params: ['a', 'b'], + }); + + const Page = () => { + const params: { a: string; b: string } = useRouteRefParams(routeRef); + + return ( +
+ {params.a} + {params.b} +
+ ); + }; + + const { getByText } = render( + + + } /> + + , + ); + + expect(getByText('foo')).toBeInTheDocument(); + expect(getByText('bar')).toBeInTheDocument(); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts new file mode 100644 index 0000000000..e24576372b --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts @@ -0,0 +1,29 @@ +/* + * 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 { useParams } from 'react-router-dom'; +import { RouteRef, AnyParams, SubRouteRef } from './types'; + +/** + * React hook for retrieving dynamic params from the current URL. + * @param _routeRef - Ref of the current route. + * @public + */ +export function useRouteRefParams( + _routeRef: RouteRef | SubRouteRef, +): Params { + return useParams() as Params; +} diff --git a/yarn.lock b/yarn.lock index cc986877ed..4e47f15fd3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4234,9 +4234,11 @@ __metadata: "@backstage/frontend-app-api": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" + "@backstage/version-bridge": "workspace:^" "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react-hooks": ^8.0.1 "@types/react": ^16.13.1 || ^17.0.0 + history: ^5.3.0 lodash: ^4.17.21 zod: ^3.21.4 zod-to-json-schema: ^3.21.4 @@ -27641,7 +27643,7 @@ __metadata: languageName: node linkType: hard -"history@npm:^5.0.0": +"history@npm:^5.0.0, history@npm:^5.3.0": version: 5.3.0 resolution: "history@npm:5.3.0" dependencies: From 18882a9bbe87591f1ff6b5e0254da4546beff0b7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 11 Oct 2023 20:25:00 +0200 Subject: [PATCH 036/348] frontend-plugin-api: refactor RouteRef to modern structure Signed-off-by: Patrik Oldsberg --- .../src/routing/RouteRef.test.ts | 54 ++++----- .../src/routing/RouteRef.ts | 103 ++++++++++++------ .../frontend-plugin-api/src/routing/types.ts | 48 ++------ 3 files changed, 107 insertions(+), 98 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts index 5314957a25..b8e86d1b99 100644 --- a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts @@ -14,16 +14,14 @@ * limitations under the License. */ -import { AnyParams, RouteRef } from './types'; -import { createRouteRef } from './RouteRef'; +import { AnyRouteParams } from './types'; +import { RouteRef, createRouteRef } from './RouteRef'; describe('RouteRef', () => { it('should be created', () => { - const routeRef: RouteRef = createRouteRef({ - id: 'my-route-ref', - }); - expect(routeRef.params).toEqual([]); - expect(String(routeRef)).toBe('routeRef{type=absolute,id=my-route-ref}'); + const routeRef: RouteRef = createRouteRef(); + expect(() => routeRef.T).toThrow(); + expect(String(routeRef)).toBe('RouteRef{}'); }); it('should be created with params', () => { @@ -31,42 +29,44 @@ describe('RouteRef', () => { x: string; y: string; }> = createRouteRef({ - id: 'my-other-route-ref', params: ['x', 'y'], }); - expect(routeRef.params).toEqual(['x', 'y']); + expect(() => routeRef.T).toThrow(); }); it('should properly infer and validate parameter types and assignments', () => { - function validateType(_ref: RouteRef) {} + function checkRouteRef( + _ref: RouteRef, + _params: T extends undefined ? undefined : T, + ) {} - const _1 = createRouteRef({ id: '1', params: ['x'] }); + const _1 = createRouteRef({ params: ['x'] }); + checkRouteRef(_1, { x: '' }); // @ts-expect-error - validateType<{ y: string }>(_1); + checkRouteRef(_1, { y: '' }); // @ts-expect-error - validateType(_1); - validateType<{ x: string }>(_1); + checkRouteRef(_1, undefined); - const _2 = createRouteRef({ id: '2', params: ['x', 'y'] }); + const _2 = createRouteRef({ params: ['x', 'y'] }); + checkRouteRef(_2, { x: '', y: '' }); // @ts-expect-error - validateType<{ x: string }>(_2); + checkRouteRef(_2, { x: '' }); // @ts-expect-error - validateType(_2); + checkRouteRef(_2, undefined); // @ts-expect-error - validateType<{ x: string; z: string }>(_2); - // extra z, we validate this at runtime instead - validateType<{ x: string; y: string; z: string }>(_2); - validateType<{ x: string; y: string }>(_2); + checkRouteRef(_2, { x: '', z: '' }); + // @ts-expect-error + checkRouteRef(_2, { x: '', y: '', z: '' }); - const _3 = createRouteRef({ id: '3', params: [] }); + const _3 = createRouteRef({ params: [] }); + checkRouteRef(_3, undefined); // @ts-expect-error - validateType<{ x: string }>(_3); - validateType(_3); + checkRouteRef(_3, { x: '' }); - const _4 = createRouteRef({ id: '4' }); + const _4 = createRouteRef(); + checkRouteRef(_4, undefined); // @ts-expect-error - validateType<{ x: string }>(_4); - validateType(_4); + checkRouteRef(_4, { x: '' }); // To avoid complains about missing expectations and unused vars expect([_1, _2, _3, _4].join('')).toEqual(expect.any(String)); diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.ts b/packages/frontend-plugin-api/src/routing/RouteRef.ts index 36ca3f073d..b19b77d298 100644 --- a/packages/frontend-plugin-api/src/routing/RouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/RouteRef.ts @@ -14,35 +14,68 @@ * limitations under the License. */ -import { - RouteRef, - routeRefType, - AnyParams, - ParamKeys, - OptionalParams, -} from './types'; +import { AnyRouteParams } from './types'; /** - * @internal + * Absolute route reference. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @public */ -export class RouteRefImpl - implements RouteRef -{ - // The marker is used for type checking while the symbol is used at runtime. - declare $$routeRefType: 'absolute'; - readonly [routeRefType] = 'absolute'; +export interface RouteRef { + readonly $$type: '@backstage/RouteRef'; + readonly T: TParams; +} - constructor( - private readonly id: string, - readonly params: ParamKeys, - ) {} +/** @internal */ +export interface InternalRouteRef< + TParams extends AnyRouteParams = AnyRouteParams, +> extends RouteRef { + readonly version: 'v1'; + getParams(): string[]; +} - get title() { - return this.id; +/** @internal */ +export function toInternalRouteRef< + TParams extends AnyRouteParams = AnyRouteParams, +>(resource: RouteRef): InternalRouteRef { + const r = resource as InternalRouteRef; + if (r.$$type !== '@backstage/RouteRef') { + throw new Error(`Invalid RouteRef, bad type '${r.$$type}'`); } - toString() { - return `routeRef{type=absolute,id=${this.id}}`; + return r; +} + +/** @internal */ +export function isRouteRef(opaque: { $$type: string }): opaque is RouteRef { + return opaque.$$type === '@backstage/RouteRef'; +} + +/** @internal */ +export class RouteRefImpl implements InternalRouteRef { + readonly $$type = '@backstage/RouteRef'; + readonly version = 'v1'; + + #params: string[]; + + constructor(readonly params: string[] = []) { + this.#params = params; + } + + get T(): never { + throw new Error(`tried to read RouteRef.T of ${this}`); + } + + getParams(): string[] { + return this.#params; + } + + toString(): string { + return `RouteRef{}`; } } @@ -55,19 +88,19 @@ export class RouteRefImpl export function createRouteRef< // Params is the type that we care about and the one to be embedded in the route ref. // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string} - Params extends { [param in ParamKey]: string }, - // ParamKey is here to make sure the Params type properly has its keys narrowed down - // to only the elements of params. Defaulting to never makes sure we end up with - // Param = {} if the params array is empty. - ParamKey extends string = never, ->(config: { - /** The id of the route ref, used to identify it when printed */ - id: string; + TParams extends { [param in TParamKeys]: string } | undefined = undefined, + TParamKeys extends string = string, +>(config?: { /** A list of parameter names that the path that this route ref is bound to must contain */ - params?: ParamKey[]; -}): RouteRef> { + readonly params: string extends TParamKeys ? (keyof TParams)[] : TParamKeys[]; +}): RouteRef< + keyof TParams extends never + ? undefined + : string extends TParamKeys + ? TParams + : { [param in TParamKeys]: string } +> { return new RouteRefImpl( - config.id, - (config.params ?? []) as ParamKeys>, - ); + config?.params as string[] | undefined, + ) as RouteRef; } diff --git a/packages/frontend-plugin-api/src/routing/types.ts b/packages/frontend-plugin-api/src/routing/types.ts index 80653518bb..b9893c1fdf 100644 --- a/packages/frontend-plugin-api/src/routing/types.ts +++ b/packages/frontend-plugin-api/src/routing/types.ts @@ -21,24 +21,7 @@ import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; * * @public */ -export type AnyParams = { [param in string]: string } | undefined; - -/** - * Type describing the key type of a route parameter mapping. - * - * @public - */ -export type ParamKeys = keyof Params extends never - ? [] - : (keyof Params)[]; - -/** - * Optional route params. - * - * @public - */ -export type OptionalParams = - Params[keyof Params] extends never ? undefined : Params; +export type AnyRouteParams = { [param in string]: string } | undefined; /** * TS magic for handling route parameters. @@ -72,19 +55,20 @@ export const routeRefType: unique symbol = getOrCreateGlobalSingleton( ); /** - * Absolute route reference. + * Optional route params. * - * @remarks - * - * See {@link https://backstage.io/docs/plugins/composability#routing-system}. - * - * @public + * @internal */ -export type RouteRef = { - $$routeRefType: 'absolute'; // See routeRefType above +export type OptionalParams = + Params[keyof Params] extends never ? undefined : Params; - params: ParamKeys; -}; +/** + * Type describing the key type of a route parameter mapping. + * + * @ignore + */ +export type ParamKeys = + keyof TParams extends never ? [] : (keyof TParams)[]; /** * Descriptor of a route relative to an absolute {@link RouteRef}. @@ -125,14 +109,6 @@ export type ExternalRouteRef< optional?: Optional; }; -/** - * @internal - */ -export type AnyRouteRef = - | RouteRef - | SubRouteRef - | ExternalRouteRef; - /** * A duplicate of the react-router RouteObject, but with routeRef added * @internal From 08bf1db3fe21c6f10c27abf54ea9bef8e5b9aa17 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 11 Oct 2023 21:06:06 +0200 Subject: [PATCH 037/348] frontend-plugin-api: refactor SubRouteRef to modern structure Signed-off-by: Patrik Oldsberg --- .../src/routing/SubRouteRef.test.ts | 79 ++++++----- .../src/routing/SubRouteRef.ts | 133 +++++++++++++----- .../frontend-plugin-api/src/routing/types.ts | 19 --- 3 files changed, 141 insertions(+), 90 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts index cec00de025..54d54f9cf8 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts @@ -14,24 +14,29 @@ * limitations under the License. */ -import { AnyParams, SubRouteRef } from './types'; -import { createSubRouteRef } from './SubRouteRef'; +import { AnyRouteParams } from './types'; +import { + SubRouteRef, + createSubRouteRef, + toInternalSubRouteRef, +} from './SubRouteRef'; import { createRouteRef } from './RouteRef'; -const parent = createRouteRef({ id: 'parent' }); -const parentX = createRouteRef({ id: 'parent-x', params: ['x'] }); +const parent = createRouteRef(); +const parentX = createRouteRef({ params: ['x'] }); describe('SubRouteRef', () => { it('should be created', () => { - const routeRef: SubRouteRef = createSubRouteRef({ + const routeRef: SubRouteRef = createSubRouteRef({ parent, id: 'my-route-ref', path: '/foo', }); - expect(routeRef.path).toBe('/foo'); - expect(routeRef.parent).toBe(parent); - expect(routeRef.params).toEqual([]); - expect(String(routeRef)).toBe('routeRef{type=sub,id=my-route-ref}'); + const internal = toInternalSubRouteRef(routeRef); + expect(internal.path).toBe('/foo'); + expect(internal.getParent()).toBe(parent); + expect(internal.getParams()).toEqual([]); + expect(String(internal)).toBe('SubRouteRef{}'); }); it('should be created with params', () => { @@ -40,9 +45,10 @@ describe('SubRouteRef', () => { id: 'my-other-route-ref', path: '/foo/:bar', }); - expect(routeRef.path).toBe('/foo/:bar'); - expect(routeRef.parent).toBe(parent); - expect(routeRef.params).toEqual(['bar']); + const internal = toInternalSubRouteRef(routeRef); + expect(internal.path).toBe('/foo/:bar'); + expect(internal.getParent()).toBe(parent); + expect(internal.getParams()).toEqual(['bar']); }); it('should be created with merged params', () => { @@ -55,9 +61,10 @@ describe('SubRouteRef', () => { id: 'my-other-route-ref', path: '/foo/:y/:z', }); - expect(routeRef.path).toBe('/foo/:y/:z'); - expect(routeRef.parent).toBe(parentX); - expect(routeRef.params).toEqual(['x', 'y', 'z']); + const internal = toInternalSubRouteRef(routeRef); + expect(internal.path).toBe('/foo/:y/:z'); + expect(internal.getParent()).toBe(parentX); + expect(internal.getParams()).toEqual(['x', 'y', 'z']); }); it('should be created with params from parent', () => { @@ -66,9 +73,10 @@ describe('SubRouteRef', () => { id: 'my-other-route-ref', path: '/foo/bar', }); - expect(routeRef.path).toBe('/foo/bar'); - expect(routeRef.parent).toBe(parentX); - expect(routeRef.params).toEqual(['x']); + const internal = toInternalSubRouteRef(routeRef); + expect(internal.path).toBe('/foo/bar'); + expect(internal.getParent()).toBe(parentX); + expect(internal.getParams()).toEqual(['x']); }); it.each([ @@ -88,39 +96,42 @@ describe('SubRouteRef', () => { }); it('should properly infer and parse path parameters', () => { - function validateType(_ref: SubRouteRef) {} + function checkSubRouteRef( + _ref: SubRouteRef, + _params: T extends undefined ? undefined : T, + ) {} const _1 = createSubRouteRef({ id: '1', parent, path: '/foo/bar' }); // @ts-expect-error - validateType<{ x: string }>(_1); - validateType(_1); + checkSubRouteRef(_1, { x: '' }); + checkSubRouteRef(_1, undefined); const _2 = createSubRouteRef({ id: '2', parent, path: '/foo/:x/:y' }); // @ts-expect-error - validateType(_2); + checkSubRouteRef(_2, undefined); // @ts-expect-error - validateType<{ x: string; z: string }>(_2); + checkSubRouteRef(_2, { x: '', z: '' }); // @ts-expect-error - validateType<{ y: string }>(_2); - // extra z, we validate this at runtime instead - validateType<{ x: string; y: string; z: string }>(_2); - validateType<{ x: string; y: string }>(_2); + checkSubRouteRef(_2, { y: '' }); + // @ts-expect-error + checkSubRouteRef(_2, { x: '', y: '', z: '' }); + checkSubRouteRef(_2, { x: '', y: '' }); const _3 = createSubRouteRef({ id: '3', parent: parentX, path: '/foo' }); // @ts-expect-error - validateType(_3); + checkSubRouteRef(_3, undefined); // @ts-expect-error - validateType<{ y: string }>(_3); - validateType<{ x: string }>(_3); + checkSubRouteRef(_3, { y: '' }); + checkSubRouteRef(_3, { x: '' }); const _4 = createSubRouteRef({ id: '4', parent: parentX, path: '/foo/:y' }); // @ts-expect-error - validateType(_4); + checkSubRouteRef(_4, undefined); // @ts-expect-error - validateType<{ x: string; z: string }>(_4); + checkSubRouteRef(_4, { x: '', z: '' }); // @ts-expect-error - validateType<{ y: string }>(_4); - validateType<{ x: string; y: string }>(_4); + checkSubRouteRef(_4, { y: '' }); + checkSubRouteRef(_4, { x: '', y: '' }); // To avoid complains about missing expectations and unused vars expect([_1, _2, _3, _4].join('')).toEqual(expect.any(String)); diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts index 14a614c2ba..ed03c17ada 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts @@ -14,43 +14,93 @@ * limitations under the License. */ -import { - AnyParams, - OptionalParams, - ParamKeys, - RouteRef, - routeRefType, - SubRouteRef, -} from './types'; +import { RouteRef, toInternalRouteRef } from './RouteRef'; +import { AnyRouteParams } from './types'; // Should match the pattern in react-router const PARAM_PATTERN = /^\w+$/; /** - * @internal + * Descriptor of a route relative to an absolute {@link RouteRef}. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @public */ -export class SubRouteRefImpl - implements SubRouteRef -{ - // The marker is used for type checking while the symbol is used at runtime. - declare $$routeRefType: 'sub'; - readonly [routeRefType] = 'sub'; +export interface SubRouteRef { + readonly $$type: '@backstage/SubRouteRef'; - constructor( - private readonly id: string, - readonly path: string, - readonly parent: RouteRef, - readonly params: ParamKeys, - ) {} + readonly T: TParams; + + readonly path: string; +} + +/** @internal */ +export interface InternalSubRouteRef< + TParams extends AnyRouteParams = AnyRouteParams, +> extends SubRouteRef { + readonly version: 'v1'; + + getParams(): string[]; + getParent(): RouteRef; +} + +/** @internal */ +export function toInternalSubRouteRef< + TParams extends AnyRouteParams = AnyRouteParams, +>(resource: SubRouteRef): InternalSubRouteRef { + const r = resource as InternalSubRouteRef; + if (r.$$type !== '@backstage/SubRouteRef') { + throw new Error(`Invalid SubRouteRef, bad type '${r.$$type}'`); + } + + return r; +} + +/** @internal */ +export function isSubRouteRef(opaque: { + $$type: string; +}): opaque is SubRouteRef { + return opaque.$$type === '@backstage/SubRouteRef'; +} + +/** @internal */ +export class SubRouteRefImpl + implements SubRouteRef +{ + readonly $$type = '@backstage/SubRouteRef'; + readonly version = 'v1'; + + #params: string[]; + #parent: RouteRef; + + constructor(readonly path: string, params: string[], parent: RouteRef) { + this.#params = params; + this.#parent = parent; + } + + get T(): never { + throw new Error(`tried to read RouteRef.T of ${this}`); + } + + getParams(): string[] { + return this.#params; + } + + getParent(): RouteRef { + return this.#parent; + } toString() { - return `routeRef{type=sub,id=${this.id}}`; + return `SubRouteRef{}`; } } /** * Used in {@link PathParams} type declaration. - * @public + * @ignore */ export type ParamPart = S extends `:${infer Param}` ? Param @@ -58,7 +108,7 @@ export type ParamPart = S extends `:${infer Param}` /** * Used in {@link PathParams} type declaration. - * @public + * @ignore */ export type ParamNames = S extends `${infer Part}/${infer Rest}` @@ -67,30 +117,37 @@ export type ParamNames = /** * This utility type helps us infer a Param object type from a string path * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }` - * @public + * @ignore */ export type PathParams = { [name in ParamNames]: string }; /** * Merges a param object type with an optional params type into a params object. - * @public + * @ignore */ export type MergeParams< P1 extends { [param in string]: string }, - P2 extends AnyParams, + P2 extends AnyRouteParams, > = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2); +/** + * Convert empty params to undefined. + * @ignore + */ +export type TrimEmptyParams = + keyof Params extends never ? undefined : Params; + /** * Creates a SubRouteRef type given the desired parameters and parent route parameters. * The parameters types are merged together while ensuring that there is no overlap between the two. * - * @public + * @ignore */ export type MakeSubRouteRef< Params extends { [param in string]: string }, - ParentParams extends AnyParams, + ParentParams extends AnyRouteParams, > = keyof Params & keyof ParentParams extends never - ? SubRouteRef>> + ? SubRouteRef>> : never; /** @@ -101,23 +158,26 @@ export type MakeSubRouteRef< */ export function createSubRouteRef< Path extends string, - ParentParams extends AnyParams = never, + ParentParams extends AnyRouteParams = never, >(config: { id: string; path: Path; parent: RouteRef; }): MakeSubRouteRef, ParentParams> { - const { id, path, parent } = config; + const { path, parent } = config; type Params = PathParams; + const internalParent = toInternalRouteRef(parent); + const parentParams = internalParent.getParams(); + // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz' const pathParams = path .split('/') .filter(p => p.startsWith(':')) .map(p => p.substring(1)); - const params = [...parent.params, ...pathParams]; + const params = [...parentParams, ...pathParams]; - if (parent.params.some(p => pathParams.includes(p as string))) { + if (parentParams.some(p => pathParams.includes(p as string))) { throw new Error( 'SubRouteRef may not have params that overlap with its parent', ); @@ -136,11 +196,10 @@ export function createSubRouteRef< // We ensure that the type of the return type is sane here const subRouteRef = new SubRouteRefImpl( - id, path, + params as string[], parent, - params as ParamKeys>, - ) as SubRouteRef>>; + ) as SubRouteRef>>; // But skip type checking of the return value itself, because the conditional // type checking of the parent parameter overlap is tricky to express. diff --git a/packages/frontend-plugin-api/src/routing/types.ts b/packages/frontend-plugin-api/src/routing/types.ts index b9893c1fdf..d5afc9213c 100644 --- a/packages/frontend-plugin-api/src/routing/types.ts +++ b/packages/frontend-plugin-api/src/routing/types.ts @@ -70,25 +70,6 @@ export type OptionalParams = export type ParamKeys = keyof TParams extends never ? [] : (keyof TParams)[]; -/** - * Descriptor of a route relative to an absolute {@link RouteRef}. - * - * @remarks - * - * See {@link https://backstage.io/docs/plugins/composability#routing-system}. - * - * @public - */ -export type SubRouteRef = { - $$routeRefType: 'sub'; // See routeRefType above - - parent: RouteRef; - - path: string; - - params: ParamKeys; -}; - /** * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. * From 720b6cda3db10ae16aab51a0659914735aaca5b1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 00:52:41 +0200 Subject: [PATCH 038/348] frontend-plugin-api: refactor ExternalRouteRef to modern structure Signed-off-by: Patrik Oldsberg --- .../src/routing/ExternalRouteRef.test.ts | 105 +++++++-------- .../src/routing/ExternalRouteRef.ts | 127 ++++++++++++------ .../frontend-plugin-api/src/routing/types.ts | 20 --- 3 files changed, 138 insertions(+), 114 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts index f6e072f760..a38937775c 100644 --- a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts @@ -14,97 +14,94 @@ * limitations under the License. */ -import { AnyParams, ExternalRouteRef } from './types'; -import { createExternalRouteRef } from './ExternalRouteRef'; +import { + ExternalRouteRef, + createExternalRouteRef, + toInternalExternalRouteRef, +} from './ExternalRouteRef'; +import { AnyRouteParams } from './types'; describe('ExternalRouteRef', () => { it('should be created', () => { - const routeRef: ExternalRouteRef = createExternalRouteRef({ - id: 'my-route-ref', - }); - expect(routeRef.params).toEqual([]); - expect(routeRef.optional).toBe(false); - expect(String(routeRef)).toBe('routeRef{type=external,id=my-route-ref}'); + const routeRef: ExternalRouteRef = createExternalRouteRef(); + const internal = toInternalExternalRouteRef(routeRef); + expect(internal.getParams()).toEqual([]); + expect(internal.optional).toBe(false); + expect(String(internal)).toBe('routeRef{type=external,id=my-route-ref}'); }); it('should be created as optional', () => { - const routeRef: ExternalRouteRef<{ - x: string; - y: string; - }> = createExternalRouteRef({ - id: 'my-other-route-ref', + const routeRef: ExternalRouteRef = createExternalRouteRef({ params: [], optional: true, }); - expect(routeRef.params).toEqual([]); - expect(routeRef.optional).toEqual(true); + const internal = toInternalExternalRouteRef(routeRef); + expect(internal.getParams()).toEqual([]); + expect(internal.optional).toEqual(true); }); it('should be created with params', () => { const routeRef: ExternalRouteRef<{ x: string; y: string; - }> = createExternalRouteRef({ - id: 'my-other-route-ref', - params: ['x', 'y'], - }); - expect(routeRef.params).toEqual(['x', 'y']); - expect(routeRef.optional).toEqual(false); + }> = createExternalRouteRef({ params: ['x', 'y'] }); + const internal = toInternalExternalRouteRef(routeRef); + expect(internal.getParams()).toEqual(['x', 'y']); + expect(internal.optional).toEqual(false); }); it('should be created as optional with params', () => { const routeRef: ExternalRouteRef<{ x: string; y: string; - }> = createExternalRouteRef({ - id: 'my-other-route-ref', - params: ['x', 'y'], - optional: true, - }); - expect(routeRef.params).toEqual(['x', 'y']); - expect(routeRef.optional).toEqual(true); + }> = createExternalRouteRef({ params: ['x', 'y'], optional: true }); + const internal = toInternalExternalRouteRef(routeRef); + expect(internal.getParams()).toEqual(['x', 'y']); + expect(internal.optional).toEqual(true); }); it('should properly infer and validate parameter types and assignments', () => { - function validateType( - _ref: ExternalRouteRef, + function checkRouteRef< + T extends AnyRouteParams, + TOptional extends boolean, + TCheck extends TOptional, + >( + _ref: ExternalRouteRef, + _params: T extends undefined ? undefined : T, + _optional: TCheck, ) {} - const _1 = createExternalRouteRef({ id: '1', params: ['notX'] }); + const _1 = createExternalRouteRef({ params: ['notX'] }); + checkRouteRef(_1, { notX: '' }, false); // @ts-expect-error - validateType<{ x: string }, any>(_1); - validateType<{ notX: string }, any>(_1); + checkRouteRef(_1, { x: '' }, false); - const _2 = createExternalRouteRef({ - id: '2', - params: ['x'], - optional: true, - }); + const _2 = createExternalRouteRef({ params: ['x'], optional: true }); + checkRouteRef(_2, { x: '' }, true); // @ts-expect-error - validateType(_2); - validateType<{ x: string }, true>(_2); + checkRouteRef(_2, undefined, false); - const _3 = createExternalRouteRef({ id: '3', params: ['x', 'y'] }); + const _3 = createExternalRouteRef({ params: ['x', 'y'] }); + checkRouteRef(_3, { x: '', y: '' }, false); // @ts-expect-error - validateType<{ x: string }, any>(_3); - // extra z, we validate this at runtime instead - validateType<{ x: string; y: string; z: string }, any>(_3); - validateType<{ x: string; y: string }, false>(_3); + checkRouteRef(_3, { x: '' }, false); + // @ts-expect-error + checkRouteRef(_3, { x: '', y: '', z: '' }, false); - const _4 = createExternalRouteRef({ id: '4', params: [] }); + const _4 = createExternalRouteRef({ params: [] }); + checkRouteRef(_4, undefined, false); // @ts-expect-error - validateType<{ x: string }, any>(_4); - validateType(_4); + checkRouteRef(_4, { x: '' }); - const _5 = createExternalRouteRef({ id: '5' }); + const _5 = createExternalRouteRef(); + checkRouteRef(_5, undefined, false); // @ts-expect-error - validateType<{ x: string }, any>(_5); - validateType(_5); + checkRouteRef(_5, { x: '' }); - const _6 = createExternalRouteRef({ id: '6', optional: true }); + const _6 = createExternalRouteRef({ optional: true }); + checkRouteRef(_6, undefined, true); // @ts-expect-error - validateType(_6); - validateType(_6); + checkRouteRef(_6, undefined, false); // To avoid complains about missing expectations and unused vars expect([_1, _2, _3, _4, _5, _6].join('')).toEqual(expect.any(String)); diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts index 2ebb81dbfb..edc546ee23 100644 --- a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts @@ -14,34 +14,78 @@ * limitations under the License. */ -import { - ExternalRouteRef, - routeRefType, - AnyParams, - ParamKeys, - OptionalParams, -} from './types'; +import { AnyRouteParams } from './types'; /** - * @internal + * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @public */ -export class ExternalRouteRefImpl< - Params extends AnyParams, - Optional extends boolean, -> implements ExternalRouteRef -{ - // The marker is used for type checking while the symbol is used at runtime. - declare $$routeRefType: 'external'; - readonly [routeRefType] = 'external'; +export interface ExternalRouteRef< + TParams extends AnyRouteParams = AnyRouteParams, + TOptional extends boolean = boolean, +> { + readonly $$type: '@backstage/ExternalRouteRef'; + readonly T: TParams; + readonly optional: TOptional; +} - constructor( - private readonly id: string, - readonly params: ParamKeys, - readonly optional: Optional, - ) {} +/** @internal */ +export interface InternalExternalRouteRef< + TParams extends AnyRouteParams = AnyRouteParams, + TOptional extends boolean = boolean, +> extends ExternalRouteRef { + readonly version: 'v1'; + getParams(): string[]; +} - toString() { - return `routeRef{type=external,id=${this.id}}`; +/** @internal */ +export function toInternalExternalRouteRef< + TParams extends AnyRouteParams = AnyRouteParams, + TOptional extends boolean = boolean, +>( + resource: ExternalRouteRef, +): InternalExternalRouteRef { + const r = resource as InternalExternalRouteRef; + if (r.$$type !== '@backstage/ExternalRouteRef') { + throw new Error(`Invalid ExternalRouteRef, bad type '${r.$$type}'`); + } + + return r; +} + +/** @internal */ +export function isExternalRouteRef(opaque: { + $$type: string; +}): opaque is ExternalRouteRef { + return opaque.$$type === '@backstage/ExternalRouteRef'; +} + +/** @internal */ +export class ExternalRouteRefImpl implements InternalExternalRouteRef { + readonly $$type = '@backstage/ExternalRouteRef'; + readonly version = 'v1'; + + #params: string[]; + + constructor(readonly optional: boolean, readonly params: string[] = []) { + this.#params = params; + } + + get T(): never { + throw new Error(`tried to read ExternalRouteRef.T of ${this}`); + } + + getParams(): string[] { + return this.#params; + } + + toString(): string { + return `ExternalRouteRef{}`; } } @@ -56,31 +100,34 @@ export class ExternalRouteRefImpl< * @public */ export function createExternalRouteRef< - Params extends { [param in ParamKey]: string }, - Optional extends boolean = false, - ParamKey extends string = never, ->(options: { - /** - * An identifier for this route, used to identify it in error messages - */ - id: string; - + TParams extends { [param in TParamKeys]: string } | undefined = undefined, + TOptional extends boolean = false, + TParamKeys extends string = string, +>(options?: { /** * The parameters that will be provided to the external route reference. */ - params?: ParamKey[]; + readonly params?: string extends TParamKeys + ? (keyof TParams)[] + : TParamKeys[]; /** * Whether or not this route is optional, defaults to false. * * Optional external routes are not required to be bound in the app, and - * if they aren't, `useRouteRef` will return `undefined`. + * if they aren't, `useExternalRouteRef` will return `undefined`. */ - optional?: Optional; -}): ExternalRouteRef, Optional> { + optional?: TOptional; +}): ExternalRouteRef< + keyof TParams extends never + ? undefined + : string extends TParamKeys + ? TParams + : { [param in TParamKeys]: string }, + TOptional +> { return new ExternalRouteRefImpl( - options.id, - (options.params ?? []) as ParamKeys>, - Boolean(options.optional) as Optional, - ); + Boolean(options?.optional), + options?.params as string[] | undefined, + ) as ExternalRouteRef; } diff --git a/packages/frontend-plugin-api/src/routing/types.ts b/packages/frontend-plugin-api/src/routing/types.ts index d5afc9213c..2eaa25ba94 100644 --- a/packages/frontend-plugin-api/src/routing/types.ts +++ b/packages/frontend-plugin-api/src/routing/types.ts @@ -70,26 +70,6 @@ export type OptionalParams = export type ParamKeys = keyof TParams extends never ? [] : (keyof TParams)[]; -/** - * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. - * - * @remarks - * - * See {@link https://backstage.io/docs/plugins/composability#routing-system}. - * - * @public - */ -export type ExternalRouteRef< - Params extends AnyParams = any, - Optional extends boolean = any, -> = { - $$routeRefType: 'external'; // See routeRefType above - - params: ParamKeys; - - optional?: Optional; -}; - /** * A duplicate of the react-router RouteObject, but with routeRef added * @internal From 49b0d0dfa9c4dcd641de738f7bf15a6001050210 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 11:01:10 +0200 Subject: [PATCH 039/348] frontend-plugin-api: add helper for locating the callsite of a function Signed-off-by: Patrik Oldsberg --- .../routing/describeParentCallSite.test.ts | 84 +++++++++++++++++++ .../src/routing/describeParentCallSite.ts | 59 +++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 packages/frontend-plugin-api/src/routing/describeParentCallSite.test.ts create mode 100644 packages/frontend-plugin-api/src/routing/describeParentCallSite.ts diff --git a/packages/frontend-plugin-api/src/routing/describeParentCallSite.test.ts b/packages/frontend-plugin-api/src/routing/describeParentCallSite.test.ts new file mode 100644 index 0000000000..03a94dcb45 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/describeParentCallSite.test.ts @@ -0,0 +1,84 @@ +/* + * Copyright 2023 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 { describeParentCallSite } from './describeParentCallSite'; + +class ChromeError { + name = 'Error'; + message = 'eHgtF5hmbrXyiEvo'; + get stack() { + return `Error: eHgtF5hmbrXyiEvo + at describeParentCallSite (describeParentCallSite.js:1:11) + at parent (parent.js:2:22) + at caller (parent-caller.js:3:33) + at other.js:3:33`; + } +} + +class SafariError { + name = 'Error'; + message = 'eHgtF5hmbrXyiEvo'; + get stack() { + return `describeParentCallSite@describeParentCallSite.js:1:11 +parent@parent.js:2:22 +caller@parent-caller.js:3:33 +code@other.js:3:33`; + } +} + +class FirefoxError { + name = 'Error'; + message = 'eHgtF5hmbrXyiEvo'; + get stack() { + return `describeParentCallSite@describeParentCallSite.js:1:11 +parent@parent.js:2:22 +caller@parent-caller.js:3:33 +@other.js:3:33 +`; + } +} + +describe('describeParentCallSite', () => { + it('should work in Chrome', () => { + function myFactory() { + return describeParentCallSite(ChromeError); + } + function myCaller() { + return myFactory(); + } + expect(myCaller()).toBe('parent-caller.js:3:33'); + }); + + it('should work in Safari', () => { + function myFactory() { + return describeParentCallSite(SafariError); + } + function myCaller() { + return myFactory(); + } + expect(myCaller()).toBe('parent-caller.js:3:33'); + }); + + it('should work in Firefox', () => { + function myFactory() { + return describeParentCallSite(FirefoxError); + } + function myCaller() { + return myFactory(); + } + expect(myCaller()).toBe('parent-caller.js:3:33'); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/describeParentCallSite.ts b/packages/frontend-plugin-api/src/routing/describeParentCallSite.ts new file mode 100644 index 0000000000..72997e07db --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/describeParentCallSite.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2023 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. + */ + +const MESSAGE_MARKER = 'eHgtF5hmbrXyiEvo'; + +/** + * Internal helper that describes the location of the parent caller. + * @internal + */ +export function describeParentCallSite( + ErrorConstructor: { new (message: string): Error } = Error, +): string { + const { stack } = new ErrorConstructor(MESSAGE_MARKER); + if (!stack) { + return ''; + } + + // Safari and Firefox don't include the error itself in the stack + const startIndex = stack.includes(MESSAGE_MARKER) + ? stack.indexOf('\n') + 1 + : 0; + const secondEntryStart = + stack.indexOf('\n', stack.indexOf('\n', startIndex) + 1) + 1; + const secondEntryEnd = stack.indexOf('\n', secondEntryStart); + + const line = stack.substring(secondEntryStart, secondEntryEnd).trim(); + if (!line) { + return 'unknown'; + } + + // Below we try to extract the location for different browsers. + // Since RouteRefs are declared at the top-level of modules the caller name isn't interesting. + + // Chrome + if (line.includes('(')) { + return line.substring(line.indexOf('(') + 1, line.indexOf(')')); + } + + // Safari & Firefox + if (line.includes('@')) { + return line.substring(line.indexOf('@') + 1); + } + + // Give up + return line; +} From a0c90a23ad0e4cec39149f306a28f4f50acde3c2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 11:35:10 +0200 Subject: [PATCH 040/348] frontend-plugin-api: add ID and description for RouteRef Signed-off-by: Patrik Oldsberg --- .../src/routing/RouteRef.test.ts | 30 ++++++++++++++--- .../src/routing/RouteRef.ts | 32 +++++++++++++++++-- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts index b8e86d1b99..cb1c85ccea 100644 --- a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts @@ -15,13 +15,30 @@ */ import { AnyRouteParams } from './types'; -import { RouteRef, createRouteRef } from './RouteRef'; +import { RouteRef, createRouteRef, toInternalRouteRef } from './RouteRef'; describe('RouteRef', () => { - it('should be created', () => { + it('should be created and have a mutable ID', () => { const routeRef: RouteRef = createRouteRef(); - expect(() => routeRef.T).toThrow(); - expect(String(routeRef)).toBe('RouteRef{}'); + const internal = toInternalRouteRef(routeRef); + expect(() => internal.T).toThrow(); + expect(internal.getParams()).toEqual([]); + expect(internal.getDescription()).toMatch(/RouteRef\.test\.ts/); + + expect(String(internal)).toMatch( + /^RouteRef\{created at .*RouteRef\.test\.ts.*\}$/, + ); + + expect(() => internal.setId('')).toThrow( + 'RouteRef id must be a non-empty string', + ); + + internal.setId('some-id'); + expect(String(internal)).toBe('RouteRef{some-id}'); + + expect(() => internal.setId('some-other-id')).toThrow( + "RouteRef was referenced twice as both 'some-id' and 'some-other-id'", + ); }); it('should be created with params', () => { @@ -31,7 +48,10 @@ describe('RouteRef', () => { }> = createRouteRef({ params: ['x', 'y'], }); - expect(() => routeRef.T).toThrow(); + const internal = toInternalRouteRef(routeRef); + expect(internal.getParams()).toEqual(['x', 'y']); + expect(internal.getDescription()).toMatch(/RouteRef\.test\.ts/); + expect(() => internal.T).toThrow(); }); it('should properly infer and validate parameter types and assignments', () => { diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.ts b/packages/frontend-plugin-api/src/routing/RouteRef.ts index b19b77d298..5f1f7a135d 100644 --- a/packages/frontend-plugin-api/src/routing/RouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/RouteRef.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { describeParentCallSite } from './describeParentCallSite'; import { AnyRouteParams } from './types'; /** @@ -36,6 +37,9 @@ export interface InternalRouteRef< > extends RouteRef { readonly version: 'v1'; getParams(): string[]; + getDescription(): string; + + setId(id: string): void; } /** @internal */ @@ -60,10 +64,13 @@ export class RouteRefImpl implements InternalRouteRef { readonly $$type = '@backstage/RouteRef'; readonly version = 'v1'; + #id?: string; #params: string[]; + #creationSite: string; - constructor(readonly params: string[] = []) { + constructor(readonly params: string[] = [], creationSite: string) { this.#params = params; + this.#creationSite = creationSite; } get T(): never { @@ -74,8 +81,27 @@ export class RouteRefImpl implements InternalRouteRef { return this.#params; } + getDescription(): string { + if (this.#id) { + return this.#id; + } + return `created at '${this.#creationSite}'`; + } + + setId(id: string): void { + if (!id) { + throw new Error('RouteRef id must be a non-empty string'); + } + if (this.#id) { + throw new Error( + `RouteRef was referenced twice as both '${this.#id}' and '${id}'`, + ); + } + this.#id = id; + } + toString(): string { - return `RouteRef{}`; + return `RouteRef{${this.getDescription()}}`; } } @@ -100,7 +126,9 @@ export function createRouteRef< ? TParams : { [param in TParamKeys]: string } > { + const creationSite = describeParentCallSite(); return new RouteRefImpl( config?.params as string[] | undefined, + creationSite, ) as RouteRef; } From c82477ae81ec55237b59da1e86b144269eb2e918 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 11:53:34 +0200 Subject: [PATCH 041/348] frontend-plugin-api: add description for SubRouteRefs Signed-off-by: Patrik Oldsberg --- .../src/routing/SubRouteRef.test.ts | 13 +++++++++---- .../frontend-plugin-api/src/routing/SubRouteRef.ts | 10 ++++++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts index 54d54f9cf8..bf38bacbf5 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts @@ -20,23 +20,28 @@ import { createSubRouteRef, toInternalSubRouteRef, } from './SubRouteRef'; -import { createRouteRef } from './RouteRef'; +import { createRouteRef, toInternalRouteRef } from './RouteRef'; const parent = createRouteRef(); const parentX = createRouteRef({ params: ['x'] }); describe('SubRouteRef', () => { it('should be created', () => { + const internalParent = toInternalRouteRef(createRouteRef()); const routeRef: SubRouteRef = createSubRouteRef({ - parent, + parent: internalParent, id: 'my-route-ref', path: '/foo', }); const internal = toInternalSubRouteRef(routeRef); expect(internal.path).toBe('/foo'); - expect(internal.getParent()).toBe(parent); + expect(internal.getParent()).toBe(internalParent); expect(internal.getParams()).toEqual([]); - expect(String(internal)).toBe('SubRouteRef{}'); + expect(String(internal)).toMatch( + /SubRouteRef\{at \/foo with parent created at '.*SubRouteRef\.test\.ts.*'\}/, + ); + internalParent.setId('some-id'); + expect(String(internal)).toBe('SubRouteRef{at /foo with parent some-id}'); }); it('should be created with params', () => { diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts index ed03c17ada..a4becf5e44 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts @@ -45,6 +45,7 @@ export interface InternalSubRouteRef< getParams(): string[]; getParent(): RouteRef; + getDescription(): string; } /** @internal */ @@ -93,8 +94,13 @@ export class SubRouteRefImpl return this.#parent; } - toString() { - return `SubRouteRef{}`; + getDescription(): string { + const parent = toInternalRouteRef(this.#parent); + return `at ${this.path} with parent ${parent.getDescription()}`; + } + + toString(): string { + return `SubRouteRef{${this.getDescription()}}`; } } From 3ad24292094dbcdca99c1a821dbeacc854aad1dc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 12:03:53 +0200 Subject: [PATCH 042/348] frontend-plugin-api: add description and ID for ExternalRouteRef Signed-off-by: Patrik Oldsberg --- .../src/routing/ExternalRouteRef.test.ts | 7 +++- .../src/routing/ExternalRouteRef.ts | 36 +++++++++---------- .../src/routing/RouteRef.ts | 13 ++++--- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts index a38937775c..ad47941833 100644 --- a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts @@ -27,7 +27,12 @@ describe('ExternalRouteRef', () => { const internal = toInternalExternalRouteRef(routeRef); expect(internal.getParams()).toEqual([]); expect(internal.optional).toBe(false); - expect(String(internal)).toBe('routeRef{type=external,id=my-route-ref}'); + + expect(String(internal)).toMatch( + /^ExternalRouteRef\{created at '.*ExternalRouteRef\.test\.ts.*'\}$/, + ); + internal.setId('some-id'); + expect(String(internal)).toBe('ExternalRouteRef{some-id}'); }); it('should be created as optional', () => { diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts index edc546ee23..ad5ad05f05 100644 --- a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { RouteRefImpl } from './RouteRef'; +import { describeParentCallSite } from './describeParentCallSite'; import { AnyRouteParams } from './types'; /** @@ -41,6 +43,9 @@ export interface InternalExternalRouteRef< > extends ExternalRouteRef { readonly version: 'v1'; getParams(): string[]; + getDescription(): string; + + setId(id: string): void; } /** @internal */ @@ -66,26 +71,18 @@ export function isExternalRouteRef(opaque: { } /** @internal */ -export class ExternalRouteRefImpl implements InternalExternalRouteRef { - readonly $$type = '@backstage/ExternalRouteRef'; - readonly version = 'v1'; +class ExternalRouteRefImpl + extends RouteRefImpl + implements InternalExternalRouteRef +{ + readonly $$type = '@backstage/ExternalRouteRef' as any; - #params: string[]; - - constructor(readonly optional: boolean, readonly params: string[] = []) { - this.#params = params; - } - - get T(): never { - throw new Error(`tried to read ExternalRouteRef.T of ${this}`); - } - - getParams(): string[] { - return this.#params; - } - - toString(): string { - return `ExternalRouteRef{}`; + constructor( + readonly optional: boolean, + readonly params: string[] = [], + creationSite: string, + ) { + super(params, creationSite); } } @@ -129,5 +126,6 @@ export function createExternalRouteRef< return new ExternalRouteRefImpl( Boolean(options?.optional), options?.params as string[] | undefined, + describeParentCallSite(), ) as ExternalRouteRef; } diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.ts b/packages/frontend-plugin-api/src/routing/RouteRef.ts index 5f1f7a135d..f8ca088d0f 100644 --- a/packages/frontend-plugin-api/src/routing/RouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/RouteRef.ts @@ -88,20 +88,24 @@ export class RouteRefImpl implements InternalRouteRef { return `created at '${this.#creationSite}'`; } + get #name() { + return this.$$type.slice('@backstage/'.length); + } + setId(id: string): void { if (!id) { - throw new Error('RouteRef id must be a non-empty string'); + throw new Error(`${this.#name} id must be a non-empty string`); } if (this.#id) { throw new Error( - `RouteRef was referenced twice as both '${this.#id}' and '${id}'`, + `${this.#name} was referenced twice as both '${this.#id}' and '${id}'`, ); } this.#id = id; } toString(): string { - return `RouteRef{${this.getDescription()}}`; + return `${this.#name}{${this.getDescription()}}`; } } @@ -126,9 +130,8 @@ export function createRouteRef< ? TParams : { [param in TParamKeys]: string } > { - const creationSite = describeParentCallSite(); return new RouteRefImpl( config?.params as string[] | undefined, - creationSite, + describeParentCallSite(), ) as RouteRef; } From ae212c91699bafeb96b65cd827572da88c6ba294 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 12:05:41 +0200 Subject: [PATCH 043/348] frontend-plugin-api: cleanup common and useRouteRef type declarations Signed-off-by: Patrik Oldsberg --- .../frontend-plugin-api/src/routing/types.ts | 49 -------------- .../src/routing/useRouteRef.tsx | 65 ++++++++++++------- .../src/routing/useRouteRefParams.ts | 6 +- 3 files changed, 46 insertions(+), 74 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/types.ts b/packages/frontend-plugin-api/src/routing/types.ts index 2eaa25ba94..583bc4f815 100644 --- a/packages/frontend-plugin-api/src/routing/types.ts +++ b/packages/frontend-plugin-api/src/routing/types.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; - /** * Catch-all type for route params. * @@ -23,53 +21,6 @@ import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; */ export type AnyRouteParams = { [param in string]: string } | undefined; -/** - * TS magic for handling route parameters. - * - * @remarks - * - * The extra TS magic here is to require a single params argument if the RouteRef - * had at least one param defined, but require 0 arguments if there are no params defined. - * Without this we'd have to pass in empty object to all parameter-less RouteRefs - * just to make TypeScript happy, or we would have to make the argument optional in - * which case you might forget to pass it in when it is actually required. - * - * @public - */ -export type RouteFunc = ( - ...[params]: Params extends undefined ? readonly [] : readonly [Params] -) => string; - -/** - * This symbol is what we use at runtime to determine whether a given object - * is a type of RouteRef or not. It doesn't work well in TypeScript though since - * the `unique symbol` will refer to different values between package versions. - * For that reason we use the marker $$routeRefType to represent the symbol at - * compile-time instead of using the symbol directly. - * - * @internal - */ -export const routeRefType: unique symbol = getOrCreateGlobalSingleton( - 'route-ref-type', - () => Symbol('route-ref-type'), -); - -/** - * Optional route params. - * - * @internal - */ -export type OptionalParams = - Params[keyof Params] extends never ? undefined : Params; - -/** - * Type describing the key type of a route parameter mapping. - * - * @ignore - */ -export type ParamKeys = - keyof TParams extends never ? [] : (keyof TParams)[]; - /** * A duplicate of the react-router RouteObject, but with routeRef added * @internal diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.tsx b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx index cf292b110f..3754d2e6d5 100644 --- a/packages/frontend-plugin-api/src/routing/useRouteRef.tsx +++ b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx @@ -17,25 +17,41 @@ import { useMemo } from 'react'; import { matchRoutes, useLocation } from 'react-router-dom'; import { useVersionedContext } from '@backstage/version-bridge'; -import { - AnyParams, - ExternalRouteRef, - RouteFunc, - RouteRef, - SubRouteRef, -} from './types'; +import { AnyRouteParams } from './types'; +import { RouteRef } from './RouteRef'; +import { SubRouteRef } from './SubRouteRef'; +import { ExternalRouteRef } from './ExternalRouteRef'; + +/** + * TS magic for handling route parameters. + * + * @remarks + * + * The extra TS magic here is to require a single params argument if the RouteRef + * had at least one param defined, but require 0 arguments if there are no params defined. + * Without this we'd have to pass in empty object to all parameter-less RouteRefs + * just to make TypeScript happy, or we would have to make the argument optional in + * which case you might forget to pass it in when it is actually required. + * + * @public + */ +export type RouteFunc = ( + ...[params]: TParams extends undefined + ? readonly [] + : readonly [params: TParams] +) => string; /** * @internal */ export interface RouteResolver { - resolve( + resolve( anyRouteRef: - | RouteRef - | SubRouteRef - | ExternalRouteRef, + | RouteRef + | SubRouteRef + | ExternalRouteRef, sourceLocation: Parameters[1], - ): RouteFunc | undefined; + ): RouteFunc | undefined; } /** @@ -49,9 +65,12 @@ export interface RouteResolver { * @returns A function that will in turn return the concrete URL of the `routeRef`. * @public */ -export function useRouteRef( - routeRef: ExternalRouteRef, -): Optional extends true ? RouteFunc | undefined : RouteFunc; +export function useRouteRef< + TOptional extends boolean, + TParams extends AnyRouteParams, +>( + routeRef: ExternalRouteRef, +): TParams extends true ? RouteFunc | undefined : RouteFunc; /** * React hook for constructing URLs to routes. @@ -64,9 +83,9 @@ export function useRouteRef( * @returns A function that will in turn return the concrete URL of the `routeRef`. * @public */ -export function useRouteRef( - routeRef: RouteRef | SubRouteRef, -): RouteFunc; +export function useRouteRef( + routeRef: RouteRef | SubRouteRef, +): RouteFunc; /** * React hook for constructing URLs to routes. @@ -79,12 +98,12 @@ export function useRouteRef( * @returns A function that will in turn return the concrete URL of the `routeRef`. * @public */ -export function useRouteRef( +export function useRouteRef( routeRef: - | RouteRef - | SubRouteRef - | ExternalRouteRef, -): RouteFunc | undefined { + | RouteRef + | SubRouteRef + | ExternalRouteRef, +): RouteFunc | undefined { const { pathname } = useLocation(); const versionedContext = useVersionedContext<{ 1: RouteResolver }>( 'routing-context', diff --git a/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts index e24576372b..dbe34a4d01 100644 --- a/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts +++ b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts @@ -15,14 +15,16 @@ */ import { useParams } from 'react-router-dom'; -import { RouteRef, AnyParams, SubRouteRef } from './types'; +import { AnyRouteParams } from './types'; +import { RouteRef } from './RouteRef'; +import { SubRouteRef } from './SubRouteRef'; /** * React hook for retrieving dynamic params from the current URL. * @param _routeRef - Ref of the current route. * @public */ -export function useRouteRefParams( +export function useRouteRefParams( _routeRef: RouteRef | SubRouteRef, ): Params { return useParams() as Params; From 61c59aadd9c9fb330affdc3bfeec130f446871f7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 12:07:17 +0200 Subject: [PATCH 044/348] frontend-plugin-api: cleanup routing index exports Signed-off-by: Patrik Oldsberg --- .../frontend-plugin-api/src/routing/index.ts | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/index.ts b/packages/frontend-plugin-api/src/routing/index.ts index 01d69cd4b0..d262bbed58 100644 --- a/packages/frontend-plugin-api/src/routing/index.ts +++ b/packages/frontend-plugin-api/src/routing/index.ts @@ -14,24 +14,12 @@ * limitations under the License. */ -export type { - AnyParams, - RouteRef, - SubRouteRef, - ExternalRouteRef, - OptionalParams, - ParamKeys, - RouteFunc, -} from './types'; -export { createRouteRef } from './RouteRef'; -export { createSubRouteRef } from './SubRouteRef'; -export type { - MakeSubRouteRef, - MergeParams, - ParamNames, - ParamPart, - PathParams, -} from './SubRouteRef'; -export { createExternalRouteRef } from './ExternalRouteRef'; -export { useRouteRef } from './useRouteRef'; +export type { AnyRouteParams } from './types'; +export { createRouteRef, type RouteRef } from './RouteRef'; +export { createSubRouteRef, type SubRouteRef } from './SubRouteRef'; +export { + createExternalRouteRef, + type ExternalRouteRef, +} from './ExternalRouteRef'; +export { useRouteRef, type RouteFunc } from './useRouteRef'; export { useRouteRefParams } from './useRouteRefParams'; From b0e3809acc5485d7381f7895a4026756ca92f39d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 13:57:53 +0200 Subject: [PATCH 045/348] frontend-plugin-api: remove id from SubRouteRef Signed-off-by: Patrik Oldsberg --- .../src/routing/SubRouteRef.test.ts | 16 +++++----------- .../src/routing/SubRouteRef.ts | 1 - 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts index bf38bacbf5..7e8efe7842 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts @@ -30,7 +30,6 @@ describe('SubRouteRef', () => { const internalParent = toInternalRouteRef(createRouteRef()); const routeRef: SubRouteRef = createSubRouteRef({ parent: internalParent, - id: 'my-route-ref', path: '/foo', }); const internal = toInternalSubRouteRef(routeRef); @@ -47,7 +46,6 @@ describe('SubRouteRef', () => { it('should be created with params', () => { const routeRef: SubRouteRef<{ bar: string }> = createSubRouteRef({ parent, - id: 'my-other-route-ref', path: '/foo/:bar', }); const internal = toInternalSubRouteRef(routeRef); @@ -63,7 +61,6 @@ describe('SubRouteRef', () => { z: string; }> = createSubRouteRef({ parent: parentX, - id: 'my-other-route-ref', path: '/foo/:y/:z', }); const internal = toInternalSubRouteRef(routeRef); @@ -75,7 +72,6 @@ describe('SubRouteRef', () => { it('should be created with params from parent', () => { const routeRef: SubRouteRef<{ x: string }> = createSubRouteRef({ parent: parentX, - id: 'my-other-route-ref', path: '/foo/bar', }); const internal = toInternalSubRouteRef(routeRef); @@ -95,9 +91,7 @@ describe('SubRouteRef', () => { ['/:inva:lid/foo', "SubRouteRef path has invalid param, got 'inva:lid'"], ['/:inva=lid/foo', "SubRouteRef path has invalid param, got 'inva=lid'"], ])('should throw if path is invalid, %s', (path, message) => { - expect(() => - createSubRouteRef({ path, parent: parentX, id: path }), - ).toThrow(message); + expect(() => createSubRouteRef({ path, parent: parentX })).toThrow(message); }); it('should properly infer and parse path parameters', () => { @@ -106,12 +100,12 @@ describe('SubRouteRef', () => { _params: T extends undefined ? undefined : T, ) {} - const _1 = createSubRouteRef({ id: '1', parent, path: '/foo/bar' }); + const _1 = createSubRouteRef({ parent, path: '/foo/bar' }); // @ts-expect-error checkSubRouteRef(_1, { x: '' }); checkSubRouteRef(_1, undefined); - const _2 = createSubRouteRef({ id: '2', parent, path: '/foo/:x/:y' }); + const _2 = createSubRouteRef({ parent, path: '/foo/:x/:y' }); // @ts-expect-error checkSubRouteRef(_2, undefined); // @ts-expect-error @@ -122,14 +116,14 @@ describe('SubRouteRef', () => { checkSubRouteRef(_2, { x: '', y: '', z: '' }); checkSubRouteRef(_2, { x: '', y: '' }); - const _3 = createSubRouteRef({ id: '3', parent: parentX, path: '/foo' }); + const _3 = createSubRouteRef({ parent: parentX, path: '/foo' }); // @ts-expect-error checkSubRouteRef(_3, undefined); // @ts-expect-error checkSubRouteRef(_3, { y: '' }); checkSubRouteRef(_3, { x: '' }); - const _4 = createSubRouteRef({ id: '4', parent: parentX, path: '/foo/:y' }); + const _4 = createSubRouteRef({ parent: parentX, path: '/foo/:y' }); // @ts-expect-error checkSubRouteRef(_4, undefined); // @ts-expect-error diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts index a4becf5e44..3fb3778d6f 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts @@ -166,7 +166,6 @@ export function createSubRouteRef< Path extends string, ParentParams extends AnyRouteParams = never, >(config: { - id: string; path: Path; parent: RouteRef; }): MakeSubRouteRef, ParentParams> { From b22245369547ebbb9015daa3aca63d9108815d51 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 14:02:14 +0200 Subject: [PATCH 046/348] frontend-plugin-api: forward routing exports Signed-off-by: Patrik Oldsberg --- packages/frontend-plugin-api/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/frontend-plugin-api/src/index.ts b/packages/frontend-plugin-api/src/index.ts index 512723b5d4..73abf28ce4 100644 --- a/packages/frontend-plugin-api/src/index.ts +++ b/packages/frontend-plugin-api/src/index.ts @@ -22,5 +22,6 @@ export * from './components'; export * from './extensions'; +export * from './routing'; export * from './schema'; export * from './wiring'; From b9d0b80a98de23cc7563f7d8a167a1275dbe440d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 14:02:47 +0200 Subject: [PATCH 047/348] core-plugin-api: added utility for converting legacy API refs into new format Signed-off-by: Patrik Oldsberg --- packages/core-plugin-api/src/alpha.ts | 1 + .../src/routing/convertLegacyRouteRef.ts | 145 ++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts diff --git a/packages/core-plugin-api/src/alpha.ts b/packages/core-plugin-api/src/alpha.ts index ebcbcf34c0..540b4ed22a 100644 --- a/packages/core-plugin-api/src/alpha.ts +++ b/packages/core-plugin-api/src/alpha.ts @@ -16,3 +16,4 @@ export * from './translation'; export * from './apis/alpha'; +export { convertLegacyRouteRef } from './routing/convertLegacyRouteRef'; diff --git a/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts b/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts new file mode 100644 index 0000000000..2b84440108 --- /dev/null +++ b/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts @@ -0,0 +1,145 @@ +/* + * Copyright 2023 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 { + routeRefType, + RouteRef as LegacyRouteRef, + SubRouteRef as LegacySubRouteRef, + ExternalRouteRef as LegacyExternalRouteRef, +} from './types'; + +// Relative imports to avoid dependency, at least for now + +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + RouteRef, + SubRouteRef, + ExternalRouteRef, + AnyRouteParams, + createRouteRef, + createSubRouteRef, + createExternalRouteRef, +} from '../../../frontend-plugin-api/src/routing'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalSubRouteRef } from '../../../frontend-plugin-api/src/routing/SubRouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; + +export function convertLegacyRouteRef( + ref: LegacyRouteRef, +): RouteRef; +export function convertLegacyRouteRef( + ref: LegacySubRouteRef, +): SubRouteRef; +export function convertLegacyRouteRef< + TParams extends AnyRouteParams, + TOptional extends boolean, +>( + ref: LegacyExternalRouteRef, +): ExternalRouteRef; +export function convertLegacyRouteRef( + ref: LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef, +): RouteRef | SubRouteRef | ExternalRouteRef { + // Ref has already been converted + if ('$$type' in ref) { + return ref as unknown as RouteRef | SubRouteRef | ExternalRouteRef; + } + + const type = (ref as unknown as { [routeRefType]: unknown })[routeRefType]; + + if (type === 'absolute') { + const legacyRef = ref as LegacyRouteRef; + const newRef = toInternalRouteRef( + createRouteRef<{ [key in string]: string }>({ + params: legacyRef.params as string[], + }), + ); + return Object.assign(legacyRef, { + $$type: '@backstage/RouteRef' as const, + version: 'v1', + T: newRef.T, + getParams() { + return newRef.getParams(); + }, + getDescription() { + return newRef.getDescription(); + }, + setId(id: string) { + newRef.setId(id); + }, + toString() { + return newRef.toString(); + }, + }); + } + if (type === 'sub') { + const legacyRef = ref as LegacySubRouteRef; + const newRef = toInternalSubRouteRef( + createSubRouteRef({ + path: legacyRef.path, + parent: convertLegacyRouteRef(legacyRef.parent), + }), + ); + return Object.assign(legacyRef, { + $$type: '@backstage/SubRouteRef' as const, + version: 'v1', + T: newRef.T, + getParams() { + return newRef.getParams(); + }, + getParent() { + return newRef.getParent(); + }, + getDescription() { + return newRef.getDescription(); + }, + toString() { + return newRef.toString(); + }, + }); + } + if (type === 'external') { + const legacyRef = ref as LegacyExternalRouteRef; + const newRef = toInternalExternalRouteRef( + createExternalRouteRef<{ [key in string]: string }>({ + params: legacyRef.params as string[], + optional: legacyRef.optional, + }), + ); + return Object.assign(legacyRef, { + $$type: '@backstage/ExternalRouteRef' as const, + version: 'v1', + T: newRef.T, + optional: newRef.optional, + getParams() { + return newRef.getParams(); + }, + getDescription() { + return newRef.getDescription(); + }, + setId(id: string) { + newRef.setId(id); + }, + toString() { + return newRef.toString(); + }, + }); + } + + throw new Error(`Failed to convert legacy route ref, unknown type '${type}'`); +} From bad46b25e1d70ca446b3f996f94bcb915b1e7da4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 14:29:17 +0200 Subject: [PATCH 048/348] core-plugin-api: added docs for convertLegacyRouteRef and note that it's temporary Signed-off-by: Patrik Oldsberg --- .../src/routing/convertLegacyRouteRef.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts b/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts index 2b84440108..9778625355 100644 --- a/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts +++ b/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts @@ -40,12 +40,38 @@ import { toInternalSubRouteRef } from '../../../frontend-plugin-api/src/routing/ // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; +/** + * A temporary helper to convert a legacy route ref to the new system. + * + * @public + * @remarks + * + * In the future the legacy createRouteRef will instead create refs compatible with both systems. + */ export function convertLegacyRouteRef( ref: LegacyRouteRef, ): RouteRef; + +/** + * A temporary helper to convert a legacy sub route ref to the new system. + * + * @public + * @remarks + * + * In the future the legacy createSubRouteRef will instead create refs compatible with both systems. + */ export function convertLegacyRouteRef( ref: LegacySubRouteRef, ): SubRouteRef; + +/** + * A temporary helper to convert a legacy external route ref to the new system. + * + * @public + * @remarks + * + * In the future the legacy createExternalRouteRef will instead create refs compatible with both systems. + */ export function convertLegacyRouteRef< TParams extends AnyRouteParams, TOptional extends boolean, From f4efd3d30a9cce49d1cafc7816ffb6cb0d861998 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 14:29:50 +0200 Subject: [PATCH 049/348] frontend-plugin-api: updates to use new routing API Signed-off-by: Patrik Oldsberg --- .../src/extensions/createNavItemExtension.tsx | 5 +++-- .../src/extensions/createPageExtension.tsx | 2 +- packages/frontend-plugin-api/src/routing/types.ts | 12 ------------ .../src/routing/useRouteRef.test.tsx | 10 +++++----- .../src/routing/useRouteRefParams.test.tsx | 1 - .../src/wiring/coreExtensionData.ts | 4 ++-- .../frontend-plugin-api/src/wiring/createPlugin.ts | 12 +++++++++--- 7 files changed, 20 insertions(+), 26 deletions(-) diff --git a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx index f208c975b7..ee38dda016 100644 --- a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx @@ -14,9 +14,10 @@ * limitations under the License. */ -import { IconComponent, RouteRef } from '@backstage/core-plugin-api'; +import { IconComponent } from '@backstage/core-plugin-api'; import { createSchemaFromZod } from '../schema/createSchemaFromZod'; import { coreExtensionData, createExtension } from '../wiring'; +import { RouteRef } from '../routing'; /** * Helper for creating extensions for a nav item. @@ -24,7 +25,7 @@ import { coreExtensionData, createExtension } from '../wiring'; */ export function createNavItemExtension(options: { id: string; - routeRef: RouteRef; + routeRef: RouteRef; title: string; icon: IconComponent; }) { diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx index 43edfaa36d..217fb33ce5 100644 --- a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { RouteRef } from '@backstage/core-plugin-api'; import React from 'react'; import { ExtensionBoundary } from '../components'; import { createSchemaFromZod, PortableSchema } from '../schema'; @@ -26,6 +25,7 @@ import { } from '../wiring'; import { AnyExtensionInputMap } from '../wiring/createExtension'; import { Expand } from '../types'; +import { RouteRef } from '../routing'; /** * Helper for creating extensions for a routable React page component. diff --git a/packages/frontend-plugin-api/src/routing/types.ts b/packages/frontend-plugin-api/src/routing/types.ts index 583bc4f815..8fe0d7e8a4 100644 --- a/packages/frontend-plugin-api/src/routing/types.ts +++ b/packages/frontend-plugin-api/src/routing/types.ts @@ -20,15 +20,3 @@ * @public */ export type AnyRouteParams = { [param in string]: string } | undefined; - -/** - * A duplicate of the react-router RouteObject, but with routeRef added - * @internal - */ -export interface BackstageRouteObject { - caseSensitive: boolean; - children?: BackstageRouteObject[]; - element: React.ReactNode; - path: string; - routeRefs: Set; -} diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx b/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx index 7a03a1cdc4..c786cd71fa 100644 --- a/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx +++ b/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx @@ -33,7 +33,7 @@ describe('v1 consumer', () => { const resolve = jest.fn(() => () => '/hello'); context.set({ 1: { resolve } }); - const routeRef = createRouteRef({ id: 'ref1' }); + const routeRef = createRouteRef(); const renderedHook = renderHook(() => useRouteRef(routeRef), { wrapper: ({ children }: React.PropsWithChildren<{}>) => ( @@ -55,7 +55,7 @@ describe('v1 consumer', () => { const resolve = jest.fn(() => () => '/hello'); context.set({ 1: { resolve } }); - const routeRef = createRouteRef({ id: 'ref1' }); + const routeRef = createRouteRef(); const history = createBrowserHistory(); history.push('/my-page'); @@ -81,7 +81,7 @@ describe('v1 consumer', () => { const resolve = jest.fn(() => () => '/hello'); context.set({ 1: { resolve } }); - const routeRef = createRouteRef({ id: 'ref1' }); + const routeRef = createRouteRef(); const history = createBrowserHistory(); history.push('/my-page'); @@ -107,7 +107,7 @@ describe('v1 consumer', () => { const resolve = jest.fn(() => () => '/hello'); context.set({ 1: { resolve } }); - const routeRef = createRouteRef({ id: 'ref1' }); + const routeRef = createRouteRef(); const history = createBrowserHistory(); history.push('/my-page'); @@ -133,7 +133,7 @@ describe('v1 consumer', () => { const resolve = jest.fn(() => () => '/hello'); context.set({ 1: { resolve } }); - const routeRef = createRouteRef({ id: 'ref1' }); + const routeRef = createRouteRef(); const history = createBrowserHistory(); history.push('/my-page'); diff --git a/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx b/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx index 40ee7219c2..37432b294e 100644 --- a/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx +++ b/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx @@ -23,7 +23,6 @@ import { createRouteRef } from './RouteRef'; describe('useRouteRefParams', () => { it('should provide types params', () => { const routeRef = createRouteRef({ - id: 'ref1', params: ['a', 'b'], }); diff --git a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts index 6913501907..023eab57e1 100644 --- a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts +++ b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts @@ -19,15 +19,15 @@ import { AnyApiFactory, AppTheme, IconComponent, - RouteRef, } from '@backstage/core-plugin-api'; import { createExtensionDataRef } from './createExtensionDataRef'; +import { RouteRef } from '../routing'; /** @public */ export type NavTarget = { title: string; icon: IconComponent; - routeRef: RouteRef<{}>; + routeRef: RouteRef; }; /** @public */ diff --git a/packages/frontend-plugin-api/src/wiring/createPlugin.ts b/packages/frontend-plugin-api/src/wiring/createPlugin.ts index 3afb5cedff..782e5134ec 100644 --- a/packages/frontend-plugin-api/src/wiring/createPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createPlugin.ts @@ -14,8 +14,14 @@ * limitations under the License. */ -import { AnyExternalRoutes, AnyRoutes } from '@backstage/core-plugin-api'; import { Extension } from './createExtension'; +import { ExternalRouteRef, RouteRef } from '../routing'; + +/** @internal */ +export type AnyRoutes = { [name in string]: RouteRef }; + +/** @internal */ +export type AnyExternalRoutes = { [name in string]: ExternalRouteRef }; /** @public */ export interface PluginOptions< @@ -42,8 +48,8 @@ export interface BackstagePlugin< /** @public */ export function createPlugin< - Routes extends AnyRoutes = AnyRoutes, - ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, + Routes extends AnyRoutes, + ExternalRoutes extends AnyExternalRoutes, >( options: PluginOptions, ): BackstagePlugin { From 2c09f44ccef88f539c88caea8f742684e9ab599e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 14:30:32 +0200 Subject: [PATCH 050/348] frontend-app-api: updates to use new routing API Signed-off-by: Patrik Oldsberg --- .../src/extensions/CoreNav.tsx | 4 +- .../extractRouteInfoFromInstanceTree.test.ts | 21 +++---- .../extractRouteInfoFromInstanceTree.ts | 18 +++++- .../src/wiring/createApp.test.tsx | 6 +- .../frontend-app-api/src/wiring/createApp.tsx | 63 +++++++++++++++++-- 5 files changed, 88 insertions(+), 24 deletions(-) diff --git a/packages/frontend-app-api/src/extensions/CoreNav.tsx b/packages/frontend-app-api/src/extensions/CoreNav.tsx index 3406c1d637..cd12ca129a 100644 --- a/packages/frontend-app-api/src/extensions/CoreNav.tsx +++ b/packages/frontend-app-api/src/extensions/CoreNav.tsx @@ -20,8 +20,8 @@ import { coreExtensionData, createExtensionInput, NavTarget, + useRouteRef, } from '@backstage/frontend-plugin-api'; -import { useRouteRef } from '@backstage/core-plugin-api'; import { makeStyles } from '@material-ui/core'; import { Sidebar, @@ -66,7 +66,7 @@ const SidebarLogo = () => { const SidebarNavItem = (props: NavTarget) => { const { icon: Icon, title, routeRef } = props; - const to = useRouteRef(routeRef)({}); + const to = useRouteRef(routeRef)(); // TODO: Support opening modal, for example, the search one return ; }; diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts index e70f588e0e..86a071df79 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts @@ -15,28 +15,27 @@ */ import React from 'react'; -import { - BackstagePlugin, - RouteRef, - createRouteRef, -} from '@backstage/core-plugin-api'; +import { BackstagePlugin } from '@backstage/core-plugin-api'; import { extractRouteInfoFromInstanceTree } from './extractRouteInfoFromInstanceTree'; import { + AnyRouteParams, Extension, + RouteRef, coreExtensionData, createExtension, createExtensionInput, createPlugin, + createRouteRef, } from '@backstage/frontend-plugin-api'; import { createInstances } from '../wiring/createApp'; import { MockConfigApi } from '@backstage/test-utils'; -const ref1 = createRouteRef({ id: 'page1' }); -const ref2 = createRouteRef({ id: 'page2' }); -const ref3 = createRouteRef({ id: 'page3' }); -const ref4 = createRouteRef({ id: 'page4' }); -const ref5 = createRouteRef({ id: 'page5' }); -const refOrder = [ref1, ref2, ref3, ref4, ref5]; +const ref1 = createRouteRef(); +const ref2 = createRouteRef(); +const ref3 = createRouteRef(); +const ref4 = createRouteRef(); +const ref5 = createRouteRef(); +const refOrder: RouteRef[] = [ref1, ref2, ref3, ref4, ref5]; function createTestExtension(options: { id: string; diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts index fa9f87dce0..e6e714e3d1 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts @@ -14,12 +14,24 @@ * limitations under the License. */ -import { RouteRef } from '@backstage/core-plugin-api'; -import { coreExtensionData } from '@backstage/frontend-plugin-api'; +import { RouteRef, coreExtensionData } from '@backstage/frontend-plugin-api'; import { ExtensionInstance } from '../wiring/createExtensionInstance'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { BackstageRouteObject } from '../../../core-app-api/src/routing/types'; import { toLegacyPlugin } from '../wiring/createApp'; +import { BackstagePlugin as LegacyBackstagePlugin } from '@backstage/core-plugin-api'; + +/** + * A duplicate of the react-router RouteObject, but with routeRef added + * @internal + */ +export interface BackstageRouteObject { + caseSensitive: boolean; + children?: BackstageRouteObject[]; + element: React.ReactNode; + path: string; + routeRefs: Set; + plugins: Set; +} // We always add a child that matches all subroutes but without any route refs. This makes // sure that we're always able to match each route no matter how deep the navigation goes. diff --git a/packages/frontend-app-api/src/wiring/createApp.test.tsx b/packages/frontend-app-api/src/wiring/createApp.test.tsx index 65f278b49b..0f2a6d38ce 100644 --- a/packages/frontend-app-api/src/wiring/createApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.test.tsx @@ -19,13 +19,13 @@ import { createExtensionOverrides, createPageExtension, createPlugin, + createRouteRef, createThemeExtension, } from '@backstage/frontend-plugin-api'; import { createApp, createInstances } from './createApp'; import { screen } from '@testing-library/react'; import { MockConfigApi, renderWithEffects } from '@backstage/test-utils'; import React from 'react'; -import { createRouteRef } from '@backstage/core-plugin-api'; const extBaseConfig = { id: 'test', @@ -83,14 +83,14 @@ describe('createInstances', () => { const ExtensionA = createPageExtension({ id: 'A', defaultPath: '/', - routeRef: createRouteRef({ id: 'A.route' }), + routeRef: createRouteRef(), loader: async () =>
Extension A
, }); const ExtensionB = createPageExtension({ id: 'B', defaultPath: '/', - routeRef: createRouteRef({ id: 'B.route' }), + routeRef: createRouteRef(), loader: async () =>
Extension B
, }); diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index 4b7e4985f3..beb29eacff 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -21,6 +21,10 @@ import { coreExtensionData, ExtensionDataRef, ExtensionOverrides, + ExternalRouteRef, + RouteRef, + SubRouteRef, + useRouteRef, } from '@backstage/frontend-plugin-api'; import { Core } from '../extensions/Core'; import { CoreRoutes } from '../extensions/CoreRoutes'; @@ -44,11 +48,9 @@ import { ConfigApi, configApiRef, IconComponent, - RouteRef, BackstagePlugin as LegacyBackstagePlugin, featureFlagsApiRef, attachComponentData, - useRouteRef, identityApiRef, AppTheme, } from '@backstage/core-plugin-api'; @@ -57,7 +59,6 @@ import { ApiFactoryRegistry, ApiProvider, ApiResolver, - AppRouteBinder, AppThemeSelector, } from '@backstage/core-app-api'; @@ -98,6 +99,57 @@ import { translationApiRef, } from '@backstage/core-plugin-api/alpha'; +/** + * Extracts a union of the keys in a map whose value extends the given type + * + * @ignore + */ +type KeysWithType = { + [key in keyof Obj]: Obj[key] extends Type ? key : never; +}[keyof Obj]; + +/** + * Takes a map Map required values and makes all keys matching Keys optional + * + * @ignore + */ +type PartialKeys< + Map extends { [name in string]: any }, + Keys extends keyof Map, +> = Partial> & Required>; + +/** + * Creates a map of target routes with matching parameters based on a map of external routes. + * + * @ignore + */ +type TargetRouteMap< + ExternalRoutes extends { [name: string]: ExternalRouteRef }, +> = { + [name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef< + infer Params, + any + > + ? RouteRef | SubRouteRef + : never; +}; + +/** + * A function that can bind from external routes of a given plugin, to concrete + * routes of other plugins. See {@link createApp}. + * + * @public + */ +export type AppRouteBinder = < + TExternalRoutes extends { [name: string]: ExternalRouteRef }, +>( + externalRoutes: TExternalRoutes, + targetRoutes: PartialKeys< + TargetRouteMap, + KeysWithType> + >, +) => void; + /** @public */ export interface ExtensionTreeNode { id: string; @@ -312,8 +364,9 @@ export function createApp(options: { {/* TODO: set base path using the logic from AppRouter */} From d84f5efa60f40736ab7af62d71c35d8f366a290f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 14:31:12 +0200 Subject: [PATCH 051/348] plugins: updates to convert legacy route refs to new system Signed-off-by: Patrik Oldsberg --- plugins/graphiql/src/alpha.tsx | 17 ++++++++--------- plugins/search/src/alpha.tsx | 12 +++++++----- plugins/tech-radar/src/alpha.tsx | 11 +++++++---- plugins/tech-radar/src/plugin.ts | 2 +- plugins/user-settings/src/alpha.tsx | 15 ++++++--------- 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/plugins/graphiql/src/alpha.tsx b/plugins/graphiql/src/alpha.tsx index 0a27f6151b..58b6686daa 100644 --- a/plugins/graphiql/src/alpha.tsx +++ b/plugins/graphiql/src/alpha.tsx @@ -32,19 +32,15 @@ import { GraphQLEndpoint, GraphiQLIcon, } from '@backstage/plugin-graphiql'; -import { - createApiFactory, - createRouteRef, - IconComponent, -} from '@backstage/core-plugin-api'; - -const graphiqlRouteRef = createRouteRef({ id: 'plugin.graphiql.page' }); +import { createApiFactory, IconComponent } from '@backstage/core-plugin-api'; +import { graphiQLRouteRef } from './route-refs'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; /** @alpha */ export const GraphiqlPage = createPageExtension({ id: 'plugin.graphiql.page', defaultPath: '/graphiql', - routeRef: graphiqlRouteRef, + routeRef: convertLegacyRouteRef(graphiQLRouteRef), loader: () => import('./components').then(m => ), }); @@ -53,7 +49,7 @@ export const graphiqlPageSidebarItem = createNavItemExtension({ id: 'plugin.graphiql.nav.index', title: 'GraphiQL', icon: GraphiQLIcon as IconComponent, - routeRef: graphiqlRouteRef, + routeRef: convertLegacyRouteRef(graphiQLRouteRef), }); /** @internal */ @@ -125,4 +121,7 @@ export default createPlugin({ gitlabGraphiQLBrowseExtension, graphiqlPageSidebarItem, ], + routes: { + root: convertLegacyRouteRef(graphiQLRouteRef), + }, }); diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index f1c4f68d02..a471cf730d 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -28,7 +28,6 @@ import { useSidebarPinState, } from '@backstage/core-components'; import { - createRouteRef, useApi, DiscoveryApi, IdentityApi, @@ -64,9 +63,11 @@ import { SearchResult } from '@backstage/plugin-search-common'; import { searchApiRef } from '@backstage/plugin-search-react'; import { searchResultItemExtensionData } from '@backstage/plugin-search-react/alpha'; +import { rootRouteRef } from './plugin'; import { SearchClient } from './apis'; import { SearchType } from './components/SearchType'; import { UrlUpdater } from './components/SearchPage/SearchPage'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; /** @alpha */ export const SearchApi = createApiExtension({ @@ -95,12 +96,10 @@ const useSearchPageStyles = makeStyles((theme: Theme) => ({ }, })); -const searchRouteRef = createRouteRef({ id: 'plugin.search.page' }); - /** @alpha */ export const SearchPage = createPageExtension({ id: 'plugin.search.page', - routeRef: searchRouteRef, + routeRef: convertLegacyRouteRef(rootRouteRef), configSchema: createSchemaFromZod(z => z.object({ path: z.string().default('/search'), @@ -237,7 +236,7 @@ export const SearchPage = createPageExtension({ /** @alpha */ export const SearchNavItem = createNavItemExtension({ id: 'plugin.search.nav.index', - routeRef: searchRouteRef, + routeRef: convertLegacyRouteRef(rootRouteRef), title: 'Search', icon: SearchIcon, }); @@ -246,4 +245,7 @@ export const SearchNavItem = createNavItemExtension({ export default createPlugin({ id: 'plugin.search', extensions: [SearchApi, SearchPage, SearchNavItem], + routes: { + root: convertLegacyRouteRef(rootRouteRef), + }, }); diff --git a/plugins/tech-radar/src/alpha.tsx b/plugins/tech-radar/src/alpha.tsx index 6a2ec882ba..78230c0337 100644 --- a/plugins/tech-radar/src/alpha.tsx +++ b/plugins/tech-radar/src/alpha.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createApiFactory, createRouteRef } from '@backstage/core-plugin-api'; +import { createApiFactory } from '@backstage/core-plugin-api'; import { createApiExtension, createPageExtension, @@ -24,14 +24,14 @@ import { import React from 'react'; import { techRadarApiRef } from './api'; import { SampleTechRadarApi } from './sample'; - -const techRadarRouteRef = createRouteRef({ id: 'plugin.techradar.page' }); +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { rootRouteRef } from './plugin'; /** @alpha */ export const TechRadarPage = createPageExtension({ id: 'plugin.techradar.page', defaultPath: '/tech-radar', - routeRef: techRadarRouteRef, + routeRef: convertLegacyRouteRef(rootRouteRef), configSchema: createSchemaFromZod(z => z.object({ title: z.string().default('Tech Radar'), @@ -59,4 +59,7 @@ const sampleTechRadarApi = createApiExtension({ export default createPlugin({ id: 'tech-radar', extensions: [TechRadarPage, sampleTechRadarApi], + routes: { + root: convertLegacyRouteRef(rootRouteRef), + }, }); diff --git a/plugins/tech-radar/src/plugin.ts b/plugins/tech-radar/src/plugin.ts index 7f042a1b6f..3a8e0a5f2d 100644 --- a/plugins/tech-radar/src/plugin.ts +++ b/plugins/tech-radar/src/plugin.ts @@ -23,7 +23,7 @@ import { createApiFactory, } from '@backstage/core-plugin-api'; -const rootRouteRef = createRouteRef({ +export const rootRouteRef = createRouteRef({ id: 'tech-radar', }); diff --git a/plugins/user-settings/src/alpha.tsx b/plugins/user-settings/src/alpha.tsx index 8d68ccf259..07cc8ce547 100644 --- a/plugins/user-settings/src/alpha.tsx +++ b/plugins/user-settings/src/alpha.tsx @@ -13,29 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createRouteRef } from '@backstage/core-plugin-api'; import { coreExtensionData, createExtensionInput, createPageExtension, createPlugin, } from '@backstage/frontend-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { settingsRouteRef } from './plugin'; import React from 'react'; export * from './translation'; -/** - * @alpha - */ -export const userSettingsRouteRef = createRouteRef({ - id: 'plugin.user-settings.page', -}); - const UserSettingsPage = createPageExtension({ id: 'plugin.user-settings.page', defaultPath: '/settings', - routeRef: userSettingsRouteRef, + routeRef: convertLegacyRouteRef(settingsRouteRef), inputs: { providerSettings: createExtensionInput( { @@ -56,4 +50,7 @@ const UserSettingsPage = createPageExtension({ export default createPlugin({ id: 'user-settings', extensions: [UserSettingsPage], + routes: { + root: convertLegacyRouteRef(settingsRouteRef), + }, }); From 6b4ae484adba5d08d8f6fb2cab20c08501442668 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 14:36:54 +0200 Subject: [PATCH 052/348] frontend-plugin-api: implement .T on route refs as declared props Signed-off-by: Patrik Oldsberg --- packages/frontend-plugin-api/src/routing/RouteRef.test.ts | 3 +-- packages/frontend-plugin-api/src/routing/RouteRef.ts | 5 +---- packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts | 1 + packages/frontend-plugin-api/src/routing/SubRouteRef.ts | 5 +---- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts index cb1c85ccea..c8d7c22e35 100644 --- a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts @@ -21,7 +21,7 @@ describe('RouteRef', () => { it('should be created and have a mutable ID', () => { const routeRef: RouteRef = createRouteRef(); const internal = toInternalRouteRef(routeRef); - expect(() => internal.T).toThrow(); + expect(internal.T).toBe(undefined); expect(internal.getParams()).toEqual([]); expect(internal.getDescription()).toMatch(/RouteRef\.test\.ts/); @@ -51,7 +51,6 @@ describe('RouteRef', () => { const internal = toInternalRouteRef(routeRef); expect(internal.getParams()).toEqual(['x', 'y']); expect(internal.getDescription()).toMatch(/RouteRef\.test\.ts/); - expect(() => internal.T).toThrow(); }); it('should properly infer and validate parameter types and assignments', () => { diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.ts b/packages/frontend-plugin-api/src/routing/RouteRef.ts index f8ca088d0f..1085644993 100644 --- a/packages/frontend-plugin-api/src/routing/RouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/RouteRef.ts @@ -63,6 +63,7 @@ export function isRouteRef(opaque: { $$type: string }): opaque is RouteRef { export class RouteRefImpl implements InternalRouteRef { readonly $$type = '@backstage/RouteRef'; readonly version = 'v1'; + declare readonly T: never; #id?: string; #params: string[]; @@ -73,10 +74,6 @@ export class RouteRefImpl implements InternalRouteRef { this.#creationSite = creationSite; } - get T(): never { - throw new Error(`tried to read RouteRef.T of ${this}`); - } - getParams(): string[] { return this.#params; } diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts index 7e8efe7842..5b1ef6d836 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts @@ -34,6 +34,7 @@ describe('SubRouteRef', () => { }); const internal = toInternalSubRouteRef(routeRef); expect(internal.path).toBe('/foo'); + expect(internal.T).toBe(undefined); expect(internal.getParent()).toBe(internalParent); expect(internal.getParams()).toEqual([]); expect(String(internal)).toMatch( diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts index 3fb3778d6f..b71ceb6a95 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts @@ -73,6 +73,7 @@ export class SubRouteRefImpl { readonly $$type = '@backstage/SubRouteRef'; readonly version = 'v1'; + declare readonly T: never; #params: string[]; #parent: RouteRef; @@ -82,10 +83,6 @@ export class SubRouteRefImpl this.#parent = parent; } - get T(): never { - throw new Error(`tried to read RouteRef.T of ${this}`); - } - getParams(): string[] { return this.#params; } From 44c9b738c27ec1bde23412bf62a6c15e86218862 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 14:38:51 +0200 Subject: [PATCH 053/348] app-next: updates for new routing APIs Signed-off-by: Patrik Oldsberg --- packages/app-next/src/App.tsx | 3 ++- packages/app-next/src/examples/pagesPlugin.tsx | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 4d72cca14f..03fa03cfb3 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -26,6 +26,7 @@ import { } from '@backstage/frontend-plugin-api'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; import techdocsPlugin from '@backstage/plugin-techdocs/alpha'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; /* @@ -59,7 +60,7 @@ TODO: const entityPageExtension = createPageExtension({ id: 'catalog:entity', defaultPath: '/catalog/:namespace/:kind/:name', - routeRef: entityRouteRef, + routeRef: convertLegacyRouteRef(entityRouteRef), loader: async () =>
Just a temporary mocked entity page
, }); diff --git a/packages/app-next/src/examples/pagesPlugin.tsx b/packages/app-next/src/examples/pagesPlugin.tsx index ef6b55ff4c..6e040c2faf 100644 --- a/packages/app-next/src/examples/pagesPlugin.tsx +++ b/packages/app-next/src/examples/pagesPlugin.tsx @@ -19,18 +19,16 @@ import { Link } from '@backstage/core-components'; import { createPageExtension, createPlugin, -} from '@backstage/frontend-plugin-api'; -import { - useRouteRef, createRouteRef, createExternalRouteRef, -} from '@backstage/core-plugin-api'; + useRouteRef, +} from '@backstage/frontend-plugin-api'; import { Route, Routes } from 'react-router-dom'; -const indexRouteRef = createRouteRef({ id: 'index' }); -const page1RouteRef = createRouteRef({ id: 'page1' }); -export const externalPageXRouteRef = createExternalRouteRef({ id: 'pageX' }); -export const pageXRouteRef = createRouteRef({ id: 'pageX' }); +const indexRouteRef = createRouteRef(); +const page1RouteRef = createRouteRef(); +export const externalPageXRouteRef = createExternalRouteRef(); +export const pageXRouteRef = createRouteRef(); // const page2RouteRef = createSubRouteRef({ // id: 'page2', // parent: page1RouteRef, From 275dd573bc3716091e9d11ab58b676430e3f33ea Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 14:42:47 +0200 Subject: [PATCH 054/348] frontend-app-api: no longer force route refs to have same ID as page extensions Signed-off-by: Patrik Oldsberg --- .../src/routing/extractRouteInfoFromInstanceTree.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts index e6e714e3d1..13602b3c6d 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts @@ -121,13 +121,6 @@ export function extractRouteInfoFromInstanceTree(core: ExtensionInstance): { // Whenever a route ref is encountered, we need to give it a route path and position in the ref tree. if (routeRef) { - const routeRefId = (routeRef as any).id; // TODO: properly - if (routeRefId !== current.id) { - throw new Error( - `Route ref '${routeRefId}' must have the same ID as extension '${current.id}'`, - ); - } - // The first route ref we find after encountering a route path is selected to be used as the // parent ref further down the tree. We don't start using this candidate ref until we encounter // another route path though, at which point we repeat the process and select another candidate. From aee98148c06ebdb719814cf906fb33aab9ae0fb5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 15:46:31 +0200 Subject: [PATCH 055/348] frontend-app-api: lift over and migrate RouteResolver Signed-off-by: Patrik Oldsberg --- .../src/routing/RouteResolver.test.ts | 366 ++++++++++++++++++ .../src/routing/RouteResolver.ts | 268 +++++++++++++ .../extractRouteInfoFromInstanceTree.ts | 15 +- .../frontend-app-api/src/routing/types.ts | 38 ++ 4 files changed, 673 insertions(+), 14 deletions(-) create mode 100644 packages/frontend-app-api/src/routing/RouteResolver.test.ts create mode 100644 packages/frontend-app-api/src/routing/RouteResolver.ts create mode 100644 packages/frontend-app-api/src/routing/types.ts diff --git a/packages/frontend-app-api/src/routing/RouteResolver.test.ts b/packages/frontend-app-api/src/routing/RouteResolver.test.ts new file mode 100644 index 0000000000..ef7a438734 --- /dev/null +++ b/packages/frontend-app-api/src/routing/RouteResolver.test.ts @@ -0,0 +1,366 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + createRouteRef, + createSubRouteRef, + createExternalRouteRef, + ExternalRouteRef, + RouteRef, + SubRouteRef, +} from '@backstage/frontend-plugin-api'; +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { RouteResolver } from './RouteResolver'; +import { MATCH_ALL_ROUTE } from './extractRouteInfoFromInstanceTree'; + +const element = () => null; +const rest = { + element, + caseSensitive: false, + children: [MATCH_ALL_ROUTE], + plugins: new Set(), +}; + +const ref1 = createRouteRef(); +const ref2 = createRouteRef({ params: ['x'] }); +const ref3 = createRouteRef({ params: ['y'] }); +const subRef1 = createSubRouteRef({ parent: ref1, path: '/foo' }); +const subRef2 = createSubRouteRef({ parent: ref1, path: '/foo/:a' }); +const subRef3 = createSubRouteRef({ parent: ref2, path: '/bar' }); +const subRef4 = createSubRouteRef({ parent: ref2, path: '/bar/:a' }); +const externalRef1 = createExternalRouteRef(); +const externalRef2 = createExternalRouteRef({ optional: true }); +const externalRef3 = createExternalRouteRef({ params: ['x'] }); +const externalRef4 = createExternalRouteRef({ optional: true, params: ['x'] }); + +describe('RouteResolver', () => { + it('should not resolve anything with an empty resolver', () => { + const r = new RouteResolver(new Map(), new Map(), [], new Map(), ''); + + expect(r.resolve(ref1, '/')?.()).toBe(undefined); + expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe(undefined); + expect(r.resolve(subRef1, '/')?.()).toBe(undefined); + expect(r.resolve(subRef2, '/')?.({ a: '2a' })).toBe(undefined); + expect(r.resolve(subRef3, '/')?.({ x: '3x' })).toBe(undefined); + expect(r.resolve(subRef4, '/')?.({ x: '4x', a: '4a' })).toBe(undefined); + expect(r.resolve(externalRef1, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef2, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef3, '/')?.({ x: '5x' })).toBe(undefined); + expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe(undefined); + }); + + it('should resolve an absolute route', () => { + const r = new RouteResolver( + new Map([[ref1, 'my-route']]), + new Map(), + [{ routeRefs: new Set([ref1]), path: 'my-route', ...rest }], + new Map(), + '', + ); + + expect(r.resolve(ref1, '/')?.()).toBe('/my-route'); + expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe(undefined); + expect(r.resolve(subRef1, '/')?.()).toBe('/my-route/foo'); + expect(r.resolve(subRef2, '/')?.({ a: '2a' })).toBe('/my-route/foo/2a'); + expect(r.resolve(subRef3, '/')?.({ x: '3x' })).toBe(undefined); + expect(r.resolve(subRef4, '/')?.({ x: '4x', a: '4a' })).toBe(undefined); + expect(r.resolve(externalRef1, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef2, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef3, '/')?.({ x: '5x' })).toBe(undefined); + expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe(undefined); + }); + + it('should resolve an absolute route and sub route with an app base path', () => { + const r = new RouteResolver( + new Map([ + [ref2, 'my-parent/:x'], + [ref1, 'my-route'], + ]), + new Map([[ref1, ref2]]), + [ + { + routeRefs: new Set([ref2]), + path: 'my-parent/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { routeRefs: new Set([ref1]), path: 'my-route', ...rest }, + ], + }, + ], + new Map(), + '/base', + ); + + expect(r.resolve(ref1, '/my-parent/1x')?.()).toBe( + '/base/my-parent/1x/my-route', + ); + expect(r.resolve(ref1, '/base/my-parent/1x')?.()).toBe( + '/base/my-parent/1x/my-route', + ); + expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe('/base/my-parent/1x'); + expect(r.resolve(ref2, '/base')?.({ x: '1x' })).toBe('/base/my-parent/1x'); + expect(r.resolve(ref3, '/')?.({ y: '1y' })).toBe(undefined); + expect(r.resolve(subRef1, '/my-parent/2x')?.()).toBe( + '/base/my-parent/2x/my-route/foo', + ); + expect(r.resolve(subRef1, '/base/my-parent/2x')?.()).toBe( + '/base/my-parent/2x/my-route/foo', + ); + expect(r.resolve(subRef2, '/my-parent/3x')?.({ a: '2a' })).toBe( + '/base/my-parent/3x/my-route/foo/2a', + ); + expect(r.resolve(subRef2, '/base/my-parent/3x')?.({ a: '2a' })).toBe( + '/base/my-parent/3x/my-route/foo/2a', + ); + expect(r.resolve(subRef3, '/')?.({ x: '5x' })).toBe( + '/base/my-parent/5x/bar', + ); + expect(r.resolve(subRef4, '/')?.({ x: '6x', a: '4a' })).toBe( + '/base/my-parent/6x/bar/4a', + ); + expect(r.resolve(externalRef1, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef2, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef3, '/')?.({ x: '5x' })).toBe(undefined); + expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe(undefined); + }); + + it('should resolve an absolute route with a param and with a parent', () => { + const r = new RouteResolver( + new Map([ + [ref1, 'my-route'], + [ref2, 'my-parent/:x'], + ]), + new Map([[ref2, ref1]]), + [ + { + routeRefs: new Set([ref2]), + path: 'my-parent/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { routeRefs: new Set([ref1]), path: 'my-route', ...rest }, + ], + }, + ], + new Map([ + [externalRef1, ref1], + [externalRef3, ref2], + [externalRef4, subRef3], + ]), + '', + ); + + expect(r.resolve(ref1, '/')?.()).toBe('/my-route'); + expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe('/my-route/my-parent/1x'); + expect(r.resolve(subRef1, '/')?.()).toBe('/my-route/foo'); + expect(r.resolve(subRef2, '/')?.({ a: '2a' })).toBe('/my-route/foo/2a'); + expect(r.resolve(subRef3, '/')?.({ x: '3x' })).toBe( + '/my-route/my-parent/3x/bar', + ); + expect(r.resolve(subRef4, '/')?.({ x: '4x', a: '4a' })).toBe( + '/my-route/my-parent/4x/bar/4a', + ); + expect(r.resolve(externalRef1, '/')?.()).toBe('/my-route'); + expect(r.resolve(externalRef2, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef3, '/')?.({ x: '5x' })).toBe( + '/my-route/my-parent/5x', + ); + expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe( + '/my-route/my-parent/6x/bar', + ); + }); + + it('should resolve the most specific match', () => { + const r = new RouteResolver( + new Map([ + [ref1, 'deep'], + [ref2, 'root/:x'], + [ref3, 'sub/:y'], + ]), + new Map([ + [ref3, ref2], + [ref1, ref3], + ]), + [ + { + routeRefs: new Set([ref2]), + path: 'root/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { + routeRefs: new Set([ref3]), + path: 'sub/:y', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { + routeRefs: new Set([ref1]), + path: 'deep', + ...rest, + }, + ], + }, + ], + }, + ], + new Map(), + '', + ); + + expect(r.resolve(ref2, '/')?.({ x: 'x' })).toBe('/root/x'); + expect(r.resolve(ref3, '/root/x')?.({ y: 'y' })).toBe('/root/x/sub/y'); + + expect(() => r.resolve(ref1, '/')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(() => r.resolve(ref1, '/root/x')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(ref1, '/root/x/sub/y')?.()).toBe('/root/x/sub/y/deep'); + // Without the MATCH_ALL_ROUTE, we wouldn't properly match the route here + expect(r.resolve(ref1, '/root/x/sub/y/any/nested/path/here')?.()).toBe( + '/root/x/sub/y/deep', + ); + }); + + it('should resolve an absolute route with multiple parents', () => { + const r = new RouteResolver( + new Map([ + [ref1, 'my-route'], + [ref2, 'my-parent/:x'], + [ref3, 'my-grandparent/:y'], + ]), + new Map([ + [ref1, ref2], + [ref2, ref3], + ]), + [ + { + routeRefs: new Set([ref3]), + path: 'my-grandparent/:y', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { + routeRefs: new Set([ref2]), + path: 'my-parent/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { routeRefs: new Set([ref1]), path: 'my-route', ...rest }, + ], + }, + ], + }, + ], + new Map([ + [externalRef1, ref1], + [externalRef3, ref2], + [externalRef4, subRef3], + ]), + '', + ); + + const l = '/my-grandparent/my-y/my-parent/my-x'; + expect(r.resolve(ref1, l)?.()).toBe( + '/my-grandparent/my-y/my-parent/my-x/my-route', + ); + expect(() => r.resolve(ref1, '/')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(ref2, l)?.({ x: '1x' })).toBe( + '/my-grandparent/my-y/my-parent/1x', + ); + expect(r.resolve(ref2, '/my-grandparent/my-y')?.({ x: '1x' })).toBe( + '/my-grandparent/my-y/my-parent/1x', + ); + expect(() => r.resolve(ref2, '/')?.({ x: '1x' })).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(subRef1, l)?.()).toBe( + '/my-grandparent/my-y/my-parent/my-x/my-route/foo', + ); + expect(() => r.resolve(subRef1, '/')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(subRef2, l)?.({ a: '2a' })).toBe( + '/my-grandparent/my-y/my-parent/my-x/my-route/foo/2a', + ); + expect(() => r.resolve(subRef2, '/')?.({ a: '2a' })).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(subRef3, l)?.({ x: '3x' })).toBe( + '/my-grandparent/my-y/my-parent/3x/bar', + ); + expect(r.resolve(subRef3, '/my-grandparent/my-y')?.({ x: '3x' })).toBe( + '/my-grandparent/my-y/my-parent/3x/bar', + ); + expect(r.resolve(subRef4, l)?.({ x: '4x', a: '4a' })).toBe( + '/my-grandparent/my-y/my-parent/4x/bar/4a', + ); + expect( + r.resolve(subRef4, '/my-grandparent/my-y')?.({ x: '4x', a: '4a' }), + ).toBe('/my-grandparent/my-y/my-parent/4x/bar/4a'); + expect(r.resolve(externalRef1, l)?.()).toBe( + '/my-grandparent/my-y/my-parent/my-x/my-route', + ); + expect(() => r.resolve(externalRef1, '/')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(externalRef2, l)?.()).toBe(undefined); + expect(r.resolve(externalRef3, l)?.({ x: '5x' })).toBe( + '/my-grandparent/my-y/my-parent/5x', + ); + expect(() => r.resolve(externalRef3, '/')?.({ x: '5x' })).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(externalRef4, l)?.({ x: '6x' })).toBe( + '/my-grandparent/my-y/my-parent/6x/bar', + ); + expect(() => r.resolve(externalRef4, '/')?.({ x: '6x' })).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + }); + + it('should encode some characters in params', () => { + const r = new RouteResolver( + new Map([ + [ref2, 'my-parent/:x'], + [ref1, 'my-route'], + ]), + new Map([[ref1, ref2]]), + [ + { + routeRefs: new Set([ref2]), + path: 'my-parent/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { routeRefs: new Set([ref1]), path: 'my-route', ...rest }, + ], + }, + ], + new Map(), + '/base', + ); + + expect(r.resolve(ref2, '/')?.({ x: 'a/#&?b' })).toBe( + '/base/my-parent/a%2F%23%26%3Fb', + ); + }); +}); diff --git a/packages/frontend-app-api/src/routing/RouteResolver.ts b/packages/frontend-app-api/src/routing/RouteResolver.ts new file mode 100644 index 0000000000..9da5836be4 --- /dev/null +++ b/packages/frontend-app-api/src/routing/RouteResolver.ts @@ -0,0 +1,268 @@ +/* + * Copyright 2020 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 { generatePath, matchRoutes } from 'react-router-dom'; +import { + RouteRef, + ExternalRouteRef, + SubRouteRef, + AnyRouteParams, + RouteFunc, +} from '@backstage/frontend-plugin-api'; +import mapValues from 'lodash/mapValues'; +import { AnyRouteRef, BackstageRouteObject } from './types'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { isRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + isSubRouteRef, + toInternalSubRouteRef, +} from '../../../frontend-plugin-api/src/routing/SubRouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { isExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; + +// Joins a list of paths together, avoiding trailing and duplicate slashes +export function joinPaths(...paths: string[]): string { + const normalized = paths.join('/').replace(/\/\/+/g, '/'); + if (normalized !== '/' && normalized.endsWith('/')) { + return normalized.slice(0, -1); + } + return normalized; +} + +/** + * Resolves the absolute route ref that our target route ref is pointing pointing to, as well + * as the relative target path. + * + * Returns an undefined target ref if one could not be fully resolved. + */ +function resolveTargetRef( + anyRouteRef: AnyRouteRef, + routePaths: Map, + routeBindings: Map, +): readonly [RouteRef | undefined, string] { + // First we figure out which absolute route ref we're dealing with, an if there was an sub route path to append. + // For sub routes it will be the parent path, while for external routes it will be the bound route. + let targetRef: RouteRef; + let subRoutePath = ''; + if (isRouteRef(anyRouteRef)) { + targetRef = anyRouteRef; + } else if (isSubRouteRef(anyRouteRef)) { + const internal = toInternalSubRouteRef(anyRouteRef); + targetRef = internal.getParent(); + subRoutePath = internal.path; + } else if (isExternalRouteRef(anyRouteRef)) { + const resolvedRoute = routeBindings.get(anyRouteRef); + if (!resolvedRoute) { + return [undefined, '']; + } + if (isRouteRef(resolvedRoute)) { + targetRef = resolvedRoute; + } else if (isSubRouteRef(resolvedRoute)) { + const internal = toInternalSubRouteRef(resolvedRoute); + targetRef = internal.getParent(); + subRoutePath = resolvedRoute.path; + } else { + throw new Error( + `ExternalRouteRef was bound to invalid target, ${resolvedRoute}`, + ); + } + } else { + throw new Error(`Unknown object passed to useRouteRef, got ${anyRouteRef}`); + } + + // Bail if no absolute path could be resolved + if (!targetRef) { + return [undefined, '']; + } + + // Find the path that our target route is bound to + const resolvedPath = routePaths.get(targetRef); + if (resolvedPath === undefined) { + return [undefined, '']; + } + + // SubRouteRefs join the path from the parent route with its own path + const targetPath = joinPaths(resolvedPath, subRoutePath); + return [targetRef, targetPath]; +} + +/** + * Resolves the complete base path for navigating to the target RouteRef. + */ +function resolveBasePath( + targetRef: RouteRef, + sourceLocation: Parameters[1], + routePaths: Map, + routeParents: Map, + routeObjects: BackstageRouteObject[], +) { + // While traversing the app element tree we build up the routeObjects structure + // used here. It is the same kind of structure that react-router creates, with the + // addition that associated route refs are stored throughout the tree. This lets + // us look up all route refs that can be reached from our source location. + // Because of the similar route object structure, we can use `matchRoutes` from + // react-router to do the lookup of our current location. + const match = matchRoutes(routeObjects, sourceLocation) ?? []; + + // While we search for a common routing root between our current location and + // the target route, we build a list of all route refs we find that we need + // to traverse to reach the target. + const refDiffList = Array(); + + let matchIndex = -1; + for ( + let targetSearchRef: RouteRef | undefined = targetRef; + targetSearchRef; + targetSearchRef = routeParents.get(targetSearchRef) + ) { + // The match contains a list of all ancestral route refs present at our current location + // Starting at the desired target ref and traversing back through its parents, we search + // for a target ref that is present in the match for our current location. When a match + // is found it means we have found a common base to resolve the route from. + matchIndex = match.findIndex(m => + (m.route as BackstageRouteObject).routeRefs.has(targetSearchRef!), + ); + if (matchIndex !== -1) { + break; + } + + // Every time we move a step up in the ancestry of the target ref, we add the current ref + // to the diff list, which ends up being the list of route refs to traverse form the common base + // in order to reach our target. + refDiffList.unshift(targetSearchRef); + } + + // If our target route is present in the initial match we need to construct the final path + // from the parent of the matched route segment. That's to allow the caller of the route + // function to supply their own params. + if (refDiffList.length === 0) { + matchIndex -= 1; + } + + // This is the part of the route tree that the target and source locations have in common. + // We re-use the existing pathname directly along with all params. + const parentPath = matchIndex === -1 ? '' : match[matchIndex].pathname; + + // This constructs the mid section of the path using paths resolved from all route refs + // we need to traverse to reach our target except for the very last one. None of these + // paths are allowed to require any parameters, as the caller would have no way of knowing + // what parameters those are. + const diffPaths = refDiffList.slice(0, -1).map(ref => { + const path = routePaths.get(ref); + if (path === undefined) { + throw new Error(`No path for ${ref}`); + } + if (path.includes(':')) { + throw new Error( + `Cannot route to ${targetRef} with parent ${ref} as it has parameters`, + ); + } + return path; + }); + + return `${joinPaths(parentPath, ...diffPaths)}/`; +} + +export class RouteResolver { + constructor( + private readonly routePaths: Map, + private readonly routeParents: Map, + private readonly routeObjects: BackstageRouteObject[], + private readonly routeBindings: Map< + ExternalRouteRef, + RouteRef | SubRouteRef + >, + private readonly appBasePath: string, // base path without a trailing slash + ) {} + + resolve( + anyRouteRef: + | RouteRef + | SubRouteRef + | ExternalRouteRef, + sourceLocation: Parameters[1], + ): RouteFunc | undefined { + // First figure out what our target absolute ref is, as well as our target path. + const [targetRef, targetPath] = resolveTargetRef( + anyRouteRef, + this.routePaths, + this.routeBindings, + ); + if (!targetRef) { + return undefined; + } + + // The location that we get passed in uses the full path, so start by trimming off + // the app base path prefix in case we're running the app on a sub-path. + let relativeSourceLocation: Parameters[1]; + if (typeof sourceLocation === 'string') { + relativeSourceLocation = this.trimPath(sourceLocation); + } else if (sourceLocation.pathname) { + relativeSourceLocation = { + ...sourceLocation, + pathname: this.trimPath(sourceLocation.pathname), + }; + } else { + relativeSourceLocation = sourceLocation; + } + + // Next we figure out the base path, which is the combination of the common parent path + // between our current location and our target location, as well as the additional path + // that is the difference between the parent path and the base of our target location. + const basePath = + this.appBasePath + + resolveBasePath( + targetRef, + relativeSourceLocation, + this.routePaths, + this.routeParents, + this.routeObjects, + ); + + const routeFunc: RouteFunc = (...[params]) => { + // We selectively encode some some known-dangerous characters in the + // params. The reason that we don't perform a blanket `encodeURIComponent` + // here is that this encoding was added defensively long after the initial + // release of this code. There's likely to be many users of this code that + // already encode their parameters knowing that this code didn't do this + // for them in the past. Therefore, we are extra careful NOT to include + // the percent character in this set, even though that might seem like a + // bad idea. + const encodedParams = + params && + mapValues(params, value => { + if (typeof value === 'string') { + return value.replaceAll(/[&?#;\/]/g, c => encodeURIComponent(c)); + } + return value; + }); + return joinPaths(basePath, generatePath(targetPath, encodedParams)); + }; + return routeFunc; + } + + private trimPath(targetPath: string) { + if (!targetPath) { + return targetPath; + } + + if (targetPath.startsWith(this.appBasePath)) { + return targetPath.slice(this.appBasePath.length); + } + return targetPath; + } +} diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts index 13602b3c6d..0bf9c2d1dd 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts @@ -18,20 +18,7 @@ import { RouteRef, coreExtensionData } from '@backstage/frontend-plugin-api'; import { ExtensionInstance } from '../wiring/createExtensionInstance'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toLegacyPlugin } from '../wiring/createApp'; -import { BackstagePlugin as LegacyBackstagePlugin } from '@backstage/core-plugin-api'; - -/** - * A duplicate of the react-router RouteObject, but with routeRef added - * @internal - */ -export interface BackstageRouteObject { - caseSensitive: boolean; - children?: BackstageRouteObject[]; - element: React.ReactNode; - path: string; - routeRefs: Set; - plugins: Set; -} +import { BackstageRouteObject } from './types'; // We always add a child that matches all subroutes but without any route refs. This makes // sure that we're always able to match each route no matter how deep the navigation goes. diff --git a/packages/frontend-app-api/src/routing/types.ts b/packages/frontend-app-api/src/routing/types.ts new file mode 100644 index 0000000000..5f1ed9be84 --- /dev/null +++ b/packages/frontend-app-api/src/routing/types.ts @@ -0,0 +1,38 @@ +/* + * Copyright 2023 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 { + ExternalRouteRef, + RouteRef, + SubRouteRef, +} from '@backstage/frontend-plugin-api'; +import { BackstagePlugin as LegacyBackstagePlugin } from '@backstage/core-plugin-api'; + +/** @internal */ +export type AnyRouteRef = RouteRef | SubRouteRef | ExternalRouteRef; + +/** + * A duplicate of the react-router RouteObject, but with routeRef added + * @internal + */ +export interface BackstageRouteObject { + caseSensitive: boolean; + children?: BackstageRouteObject[]; + element: React.ReactNode; + path: string; + routeRefs: Set; + plugins: Set; +} From d4400f5e276bb1c0bbc1bb5828c95d1ed91fbb54 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 16:26:38 +0200 Subject: [PATCH 056/348] frontend-app-api: lift over resolveRouteBindings and RoutingProvider Signed-off-by: Patrik Oldsberg --- .../src/routing/RoutingProvider.tsx | 66 +++++++++++ .../frontend-app-api/src/routing/index.ts | 17 +++ .../src/routing/resolveRouteBindings.test.ts | 43 ++++++++ .../src/routing/resolveRouteBindings.ts | 104 ++++++++++++++++++ .../frontend-app-api/src/wiring/createApp.tsx | 64 +---------- 5 files changed, 235 insertions(+), 59 deletions(-) create mode 100644 packages/frontend-app-api/src/routing/RoutingProvider.tsx create mode 100644 packages/frontend-app-api/src/routing/index.ts create mode 100644 packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts create mode 100644 packages/frontend-app-api/src/routing/resolveRouteBindings.ts diff --git a/packages/frontend-app-api/src/routing/RoutingProvider.tsx b/packages/frontend-app-api/src/routing/RoutingProvider.tsx new file mode 100644 index 0000000000..965faa3655 --- /dev/null +++ b/packages/frontend-app-api/src/routing/RoutingProvider.tsx @@ -0,0 +1,66 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { ReactNode } from 'react'; +import { + ExternalRouteRef, + RouteRef, + SubRouteRef, +} from '@backstage/frontend-plugin-api'; +import { + createVersionedValueMap, + createVersionedContext, +} from '@backstage/version-bridge'; +import { RouteResolver } from './RouteResolver'; +import { BackstageRouteObject } from './types'; + +const RoutingContext = createVersionedContext<{ 1: RouteResolver }>( + 'routing-context', +); + +type ProviderProps = { + routePaths: Map; + routeParents: Map; + routeObjects: BackstageRouteObject[]; + routeBindings: Map; + basePath?: string; + children: ReactNode; +}; + +// TODO(Rugvip): Migrate to a routing API instead +export const RoutingProvider = ({ + routePaths, + routeParents, + routeObjects, + routeBindings, + basePath = '', + children, +}: ProviderProps) => { + const resolver = new RouteResolver( + routePaths, + routeParents, + routeObjects, + routeBindings, + basePath, + ); + + const versionedValue = createVersionedValueMap({ 1: resolver }); + return ( + + {children} + + ); +}; diff --git a/packages/frontend-app-api/src/routing/index.ts b/packages/frontend-app-api/src/routing/index.ts new file mode 100644 index 0000000000..8c26a732d3 --- /dev/null +++ b/packages/frontend-app-api/src/routing/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 AppRouteBinder } from './resolveRouteBindings'; diff --git a/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts b/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts new file mode 100644 index 0000000000..9ea288c196 --- /dev/null +++ b/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts @@ -0,0 +1,43 @@ +/* + * Copyright 2020 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 { + createExternalRouteRef, + createRouteRef, +} from '@backstage/frontend-plugin-api'; +import { resolveRouteBindings } from './resolveRouteBindings'; + +describe('resolveRouteBindings', () => { + it('runs happy path', () => { + const external = { myRoute: createExternalRouteRef() }; + const ref = createRouteRef(); + const result = resolveRouteBindings(({ bind }) => { + bind(external, { myRoute: ref }); + }); + + expect(result.get(external.myRoute)).toBe(ref); + }); + + it('throws on unknown keys', () => { + const external = { myRoute: createExternalRouteRef() }; + const ref = createRouteRef(); + expect(() => + resolveRouteBindings(({ bind }) => { + bind(external, { someOtherRoute: ref } as any); + }), + ).toThrow('Key someOtherRoute is not an existing external route'); + }); +}); diff --git a/packages/frontend-app-api/src/routing/resolveRouteBindings.ts b/packages/frontend-app-api/src/routing/resolveRouteBindings.ts new file mode 100644 index 0000000000..968da005ec --- /dev/null +++ b/packages/frontend-app-api/src/routing/resolveRouteBindings.ts @@ -0,0 +1,104 @@ +/* + * Copyright 2020 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 { + RouteRef, + SubRouteRef, + ExternalRouteRef, +} from '@backstage/frontend-plugin-api'; + +/** + * Extracts a union of the keys in a map whose value extends the given type + * + * @ignore + */ +type KeysWithType = { + [key in keyof Obj]: Obj[key] extends Type ? key : never; +}[keyof Obj]; + +/** + * Takes a map Map required values and makes all keys matching Keys optional + * + * @ignore + */ +type PartialKeys< + Map extends { [name in string]: any }, + Keys extends keyof Map, +> = Partial> & Required>; + +/** + * Creates a map of target routes with matching parameters based on a map of external routes. + * + * @ignore + */ +type TargetRouteMap< + ExternalRoutes extends { [name: string]: ExternalRouteRef }, +> = { + [name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef< + infer Params, + any + > + ? RouteRef | SubRouteRef + : never; +}; + +/** + * A function that can bind from external routes of a given plugin, to concrete + * routes of other plugins. See {@link createApp}. + * + * @public + */ +export type AppRouteBinder = < + TExternalRoutes extends { [name: string]: ExternalRouteRef }, +>( + externalRoutes: TExternalRoutes, + targetRoutes: PartialKeys< + TargetRouteMap, + KeysWithType> + >, +) => void; + +/** @internal */ +export function resolveRouteBindings( + bindRoutes?: (context: { bind: AppRouteBinder }) => void, +): Map { + const result = new Map(); + + if (bindRoutes) { + const bind: AppRouteBinder = ( + externalRoutes, + targetRoutes: { [name: string]: RouteRef | SubRouteRef }, + ) => { + for (const [key, value] of Object.entries(targetRoutes)) { + const externalRoute = externalRoutes[key]; + if (!externalRoute) { + throw new Error(`Key ${key} is not an existing external route`); + } + if (!value && !externalRoute.optional) { + throw new Error( + `External route ${key} is required but was undefined`, + ); + } + if (value) { + result.set(externalRoute, value); + } + } + }; + bindRoutes({ bind }); + } + + return result; +} diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index beb29eacff..4842383096 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -21,9 +21,7 @@ import { coreExtensionData, ExtensionDataRef, ExtensionOverrides, - ExternalRouteRef, RouteRef, - SubRouteRef, useRouteRef, } from '@backstage/frontend-plugin-api'; import { Core } from '../extensions/Core'; @@ -76,10 +74,6 @@ import { defaultConfigLoaderSync } from '../../../core-app-api/src/app/defaultCo // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { overrideBaseUrlConfigs } from '../../../core-app-api/src/app/overrideBaseUrlConfigs'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { RoutingProvider } from '../../../core-app-api/src/routing/RoutingProvider'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { resolveRouteBindings } from '../../../core-app-api/src/app/resolveRouteBindings'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports import { AppLanguageSelector } from '../../../core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { I18nextTranslationApi } from '../../../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi'; @@ -98,57 +92,9 @@ import { appLanguageApiRef, translationApiRef, } from '@backstage/core-plugin-api/alpha'; - -/** - * Extracts a union of the keys in a map whose value extends the given type - * - * @ignore - */ -type KeysWithType = { - [key in keyof Obj]: Obj[key] extends Type ? key : never; -}[keyof Obj]; - -/** - * Takes a map Map required values and makes all keys matching Keys optional - * - * @ignore - */ -type PartialKeys< - Map extends { [name in string]: any }, - Keys extends keyof Map, -> = Partial> & Required>; - -/** - * Creates a map of target routes with matching parameters based on a map of external routes. - * - * @ignore - */ -type TargetRouteMap< - ExternalRoutes extends { [name: string]: ExternalRouteRef }, -> = { - [name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef< - infer Params, - any - > - ? RouteRef | SubRouteRef - : never; -}; - -/** - * A function that can bind from external routes of a given plugin, to concrete - * routes of other plugins. See {@link createApp}. - * - * @public - */ -export type AppRouteBinder = < - TExternalRoutes extends { [name: string]: ExternalRouteRef }, ->( - externalRoutes: TExternalRoutes, - targetRoutes: PartialKeys< - TargetRouteMap, - KeysWithType> - >, -) => void; +import { AppRouteBinder } from '../routing'; +import { RoutingProvider } from '../routing/RoutingProvider'; +import { resolveRouteBindings } from '../routing/resolveRouteBindings'; /** @public */ export interface ExtensionTreeNode { @@ -365,8 +311,8 @@ export function createApp(options: { {/* TODO: set base path using the logic from AppRouter */} From 659651bfcca1f9e9ae71b22a19b812c33d89654b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 17:26:04 +0200 Subject: [PATCH 057/348] frontend-app-api: added utility for collecting route IDs Signed-off-by: Patrik Oldsberg --- .../src/routing/collectRouteIds.test.ts | 51 ++++++++++++++ .../src/routing/collectRouteIds.ts | 70 +++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 packages/frontend-app-api/src/routing/collectRouteIds.test.ts create mode 100644 packages/frontend-app-api/src/routing/collectRouteIds.ts diff --git a/packages/frontend-app-api/src/routing/collectRouteIds.test.ts b/packages/frontend-app-api/src/routing/collectRouteIds.test.ts new file mode 100644 index 0000000000..95a5afd8cd --- /dev/null +++ b/packages/frontend-app-api/src/routing/collectRouteIds.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + createRouteRef, + createExternalRouteRef, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { collectRouteIds } from './collectRouteIds'; + +describe('collectRouteIds', () => { + it('should assign IDs to routes', () => { + const ref = createRouteRef(); + const extRef = createExternalRouteRef(); + + expect(String(ref)).toMatch( + /^RouteRef\{created at '.*collectRouteIds\.test\.ts.*'\}$/, + ); + expect(String(extRef)).toMatch( + /^ExternalRouteRef\{created at '.*collectRouteIds\.test\.ts.*'\}$/, + ); + + const collected = collectRouteIds([ + createPlugin({ id: 'test', routes: { ref }, externalRoutes: { extRef } }), + ]); + expect(Object.fromEntries(collected.routes)).toEqual({ + 'plugin.test.routes.ref': ref, + }); + expect(Object.fromEntries(collected.externalRoutes)).toEqual({ + 'plugin.test.externalRoutes.extRef': extRef, + }); + + expect(String(ref)).toBe('RouteRef{plugin.test.routes.ref}'); + expect(String(extRef)).toBe( + 'ExternalRouteRef{plugin.test.externalRoutes.extRef}', + ); + }); +}); diff --git a/packages/frontend-app-api/src/routing/collectRouteIds.ts b/packages/frontend-app-api/src/routing/collectRouteIds.ts new file mode 100644 index 0000000000..7e2a4cad2e --- /dev/null +++ b/packages/frontend-app-api/src/routing/collectRouteIds.ts @@ -0,0 +1,70 @@ +/* + * Copyright 2023 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 { + BackstagePlugin, + ExtensionOverrides, + RouteRef, + SubRouteRef, + ExternalRouteRef, +} from '@backstage/frontend-plugin-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; + +/** @internal */ +export interface RouteRefsById { + routes: Map; + externalRoutes: Map; +} + +/** @internal */ +export function collectRouteIds( + features: (BackstagePlugin | ExtensionOverrides)[], +): RouteRefsById { + const routesById = new Map(); + const externalRoutesById = new Map(); + + for (const feature of features) { + if (feature.$$type !== '@backstage/BackstagePlugin') { + continue; + } + + for (const [name, ref] of Object.entries(feature.routes)) { + const refId = `plugin.${feature.id}.routes.${name}`; + if (routesById.has(refId)) { + throw new Error(`Unexpected duplicate route '${refId}'`); + } + + const internalRef = toInternalRouteRef(ref); + internalRef.setId(refId); + routesById.set(refId, ref); + } + for (const [name, ref] of Object.entries(feature.externalRoutes)) { + const refId = `plugin.${feature.id}.externalRoutes.${name}`; + if (externalRoutesById.has(refId)) { + throw new Error(`Unexpected duplicate external route '${refId}'`); + } + + const internalRef = toInternalExternalRouteRef(ref); + internalRef.setId(refId); + externalRoutesById.set(refId, ref); + } + } + + return { routes: routesById, externalRoutes: externalRoutesById }; +} From 2307fb17470e5a3039fcf8a8b42c317622293288 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 17:26:21 +0200 Subject: [PATCH 058/348] frontend-app-api: make it possible to bind routes through config Signed-off-by: Patrik Oldsberg --- packages/frontend-app-api/config.d.ts | 7 ++ .../src/routing/resolveRouteBindings.test.ts | 89 +++++++++++++++++-- .../src/routing/resolveRouteBindings.ts | 43 ++++++++- .../frontend-app-api/src/wiring/createApp.tsx | 10 ++- 4 files changed, 140 insertions(+), 9 deletions(-) diff --git a/packages/frontend-app-api/config.d.ts b/packages/frontend-app-api/config.d.ts index 5f5f877d3e..9ec020fa56 100644 --- a/packages/frontend-app-api/config.d.ts +++ b/packages/frontend-app-api/config.d.ts @@ -24,6 +24,13 @@ export interface Config { packages?: 'all' | { include?: string[]; exclude?: string[] }; }; + routes?: { + /** + * @deepVisibility frontend + */ + bindings?: { [externalRouteRefId: string]: string }; + }; + /** * @deepVisibility frontend */ diff --git a/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts b/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts index 9ea288c196..d80a02e34d 100644 --- a/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts +++ b/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts @@ -19,14 +19,21 @@ import { createRouteRef, } from '@backstage/frontend-plugin-api'; import { resolveRouteBindings } from './resolveRouteBindings'; +import { ConfigReader } from '@backstage/config'; + +const emptyIds = { routes: new Map(), externalRoutes: new Map() }; describe('resolveRouteBindings', () => { it('runs happy path', () => { const external = { myRoute: createExternalRouteRef() }; const ref = createRouteRef(); - const result = resolveRouteBindings(({ bind }) => { - bind(external, { myRoute: ref }); - }); + const result = resolveRouteBindings( + ({ bind }) => { + bind(external, { myRoute: ref }); + }, + new ConfigReader({}), + emptyIds, + ); expect(result.get(external.myRoute)).toBe(ref); }); @@ -35,9 +42,79 @@ describe('resolveRouteBindings', () => { const external = { myRoute: createExternalRouteRef() }; const ref = createRouteRef(); expect(() => - resolveRouteBindings(({ bind }) => { - bind(external, { someOtherRoute: ref } as any); - }), + resolveRouteBindings( + ({ bind }) => { + bind(external, { someOtherRoute: ref } as any); + }, + new ConfigReader({}), + emptyIds, + ), ).toThrow('Key someOtherRoute is not an existing external route'); }); + + it('reads bindings from config', () => { + const mySource = createExternalRouteRef(); + const myTarget = createRouteRef(); + const result = resolveRouteBindings( + () => {}, + new ConfigReader({ + app: { routes: { bindings: { mySource: 'myTarget' } } }, + }), + { + routes: new Map([['myTarget', myTarget]]), + externalRoutes: new Map([['mySource', mySource]]), + }, + ); + + expect(result.get(mySource)).toBe(myTarget); + }); + + it('throws on invalid config', () => { + expect(() => + resolveRouteBindings( + () => {}, + new ConfigReader({ app: { routes: { bindings: 'derp' } } }), + emptyIds, + ), + ).toThrow( + "Invalid type in config for key 'app.routes.bindings' in 'mock-config', got string, wanted object", + ); + + expect(() => + resolveRouteBindings( + () => {}, + new ConfigReader({ app: { routes: { bindings: { mySource: true } } } }), + emptyIds, + ), + ).toThrow( + "Invalid config at app.routes.bindings['mySource'], value must be a non-empty string", + ); + + expect(() => + resolveRouteBindings( + () => {}, + new ConfigReader({ + app: { routes: { bindings: { mySource: 'myTarget' } } }, + }), + emptyIds, + ), + ).toThrow( + "Invalid config at app.routes.bindings, 'mySource' is not a valid external route", + ); + + expect(() => + resolveRouteBindings( + () => {}, + new ConfigReader({ + app: { routes: { bindings: { mySource: 'myTarget' } } }, + }), + { + ...emptyIds, + externalRoutes: new Map([['mySource', createExternalRouteRef()]]), + }, + ), + ).toThrow( + "Invalid config at app.routes.bindings['mySource'], 'myTarget' is not a valid route", + ); + }); }); diff --git a/packages/frontend-app-api/src/routing/resolveRouteBindings.ts b/packages/frontend-app-api/src/routing/resolveRouteBindings.ts index 968da005ec..c98e36a75b 100644 --- a/packages/frontend-app-api/src/routing/resolveRouteBindings.ts +++ b/packages/frontend-app-api/src/routing/resolveRouteBindings.ts @@ -19,6 +19,8 @@ import { SubRouteRef, ExternalRouteRef, } from '@backstage/frontend-plugin-api'; +import { RouteRefsById } from './collectRouteIds'; +import { Config } from '@backstage/config'; /** * Extracts a union of the keys in a map whose value extends the given type @@ -73,7 +75,9 @@ export type AppRouteBinder = < /** @internal */ export function resolveRouteBindings( - bindRoutes?: (context: { bind: AppRouteBinder }) => void, + bindRoutes: ((context: { bind: AppRouteBinder }) => void) | undefined, + config: Config, + routesById: RouteRefsById, ): Map { const result = new Map(); @@ -100,5 +104,42 @@ export function resolveRouteBindings( bindRoutes({ bind }); } + const bindingsConfig = config.getOptionalConfig('app.routes.bindings'); + if (!bindingsConfig) { + return result; + } + + const bindings = bindingsConfig.get(); + if (bindings === null || typeof bindings !== 'object') { + throw new Error('Invalid config at app.routes.bindings, must be an object'); + } + + for (const [externalRefId, targetRefId] of Object.entries(bindings)) { + if (typeof targetRefId !== 'string' || targetRefId === '') { + throw new Error( + `Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string`, + ); + } + + const externalRef = routesById.externalRoutes.get(externalRefId); + if (!externalRef) { + throw new Error( + `Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`, + ); + } + // Route bindings defined in config have lower priority than those defined in code + if (result.has(externalRef)) { + continue; + } + const targetRef = routesById.routes.get(targetRefId); + if (!targetRef) { + throw new Error( + `Invalid config at app.routes.bindings['${externalRefId}'], '${targetRefId}' is not a valid route`, + ); + } + + result.set(externalRef, targetRef); + } + return result; } diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index 4842383096..87b2042d34 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -95,6 +95,7 @@ import { import { AppRouteBinder } from '../routing'; import { RoutingProvider } from '../routing/RoutingProvider'; import { resolveRouteBindings } from '../routing/resolveRouteBindings'; +import { collectRouteIds } from '../routing/collectRouteIds'; /** @public */ export interface ExtensionTreeNode { @@ -305,14 +306,19 @@ export function createApp(options: { ), ); + const routeIds = collectRouteIds(allFeatures); + const App = () => ( {/* TODO: set base path using the logic from AppRouter */} From 3f47f0d9b9f1b9b6ad2d635061cee804585b2752 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 17:26:56 +0200 Subject: [PATCH 059/348] app-next: bind page1 route through config Signed-off-by: Patrik Oldsberg --- packages/app-next/app-config.yaml | 3 +++ packages/app-next/src/App.tsx | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index a97c52f40f..eaaa2b0560 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -1,6 +1,9 @@ app: experimental: packages: 'all' # ✨ + routes: + bindings: + plugin.pages.externalRoutes.pageX: plugin.pages.routes.pageX extensions: - apis.plugin.graphiql.browse.gitlab: true diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 03fa03cfb3..92d71fee89 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -75,9 +75,10 @@ const app = createApp({ extensions: [entityPageExtension], }), ], - bindRoutes({ bind }) { - bind(pagesPlugin.externalRoutes, { pageX: pagesPlugin.routes.pageX }); - }, + /* Handled through config instead */ + // bindRoutes({ bind }) { + // bind(pagesPlugin.externalRoutes, { pageX: pagesPlugin.routes.pageX }); + // }, }); // const legacyApp = createLegacyApp({ plugins: [legacyGraphiqlPlugin] }); From 68fc9dc60e10fc684b9a4e975335d6f95edc8a05 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 17:35:39 +0200 Subject: [PATCH 060/348] changesets: added changesets for routing system refactor Signed-off-by: Patrik Oldsberg --- .changeset/eighty-chairs-camp.md | 5 +++++ .changeset/hungry-paws-dress.md | 8 ++++++++ .changeset/modern-ducks-battle.md | 5 +++++ .changeset/tricky-cups-hammer.md | 5 +++++ 4 files changed, 23 insertions(+) create mode 100644 .changeset/eighty-chairs-camp.md create mode 100644 .changeset/hungry-paws-dress.md create mode 100644 .changeset/modern-ducks-battle.md create mode 100644 .changeset/tricky-cups-hammer.md diff --git a/.changeset/eighty-chairs-camp.md b/.changeset/eighty-chairs-camp.md new file mode 100644 index 0000000000..6a240609d4 --- /dev/null +++ b/.changeset/eighty-chairs-camp.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': minor +--- + +Added `RouteRef`, `SubRouteRef`, `ExternalRouteRef`, and related types. All exports from this package that previously relied on the types with the same name from `@backstage/core-plugin-api` now use the new types instead. To convert and existing legacy route ref to be compatible with the APIs from this package, use the `convertLegacyRouteRef` utility from `@backstage/core-plugin-api/alpha`. diff --git a/.changeset/hungry-paws-dress.md b/.changeset/hungry-paws-dress.md new file mode 100644 index 0000000000..ede5358d58 --- /dev/null +++ b/.changeset/hungry-paws-dress.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-user-settings': patch +'@backstage/plugin-tech-radar': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-search': patch +--- + +Updated alpha exports according to routing changes in `@backstage/frontend-plugin-api`. diff --git a/.changeset/modern-ducks-battle.md b/.changeset/modern-ducks-battle.md new file mode 100644 index 0000000000..e8359cf4ac --- /dev/null +++ b/.changeset/modern-ducks-battle.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': minor +--- + +Added the ability to configure bound routes through `app.routes.bindings`. The routing system used by `createApp` has been replaced by one that only supports route refs of the new format from `@backstage/frontend-plugin-api`. The requirement for route refs to have the same ID as their associated extension has been removed. diff --git a/.changeset/tricky-cups-hammer.md b/.changeset/tricky-cups-hammer.md new file mode 100644 index 0000000000..4e1b6fe9ce --- /dev/null +++ b/.changeset/tricky-cups-hammer.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-plugin-api': patch +--- + +Added a new `/alpha` export `convertLegacyRouteRef`, which is a temporary utility to allow existing route refs to be used with the new experimental packages. From a285d8c00098197d5dbe57a9c2c3312eaebfda53 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 18:52:06 +0200 Subject: [PATCH 061/348] API report updates and frontend-*-api fixes Signed-off-by: Patrik Oldsberg --- .../app-next-example-plugin/api-report.md | 4 +- packages/frontend-app-api/api-report.md | 17 ++- packages/frontend-app-api/src/index.ts | 1 + packages/frontend-plugin-api/api-report.md | 140 +++++++++++++++++- .../src/routing/SubRouteRef.ts | 19 +-- .../src/wiring/createPlugin.ts | 4 +- .../frontend-plugin-api/src/wiring/index.ts | 2 + plugins/adr/alpha-api-report.md | 4 +- plugins/catalog/alpha-api-report.md | 4 +- plugins/explore/alpha-api-report.md | 4 +- plugins/graphiql/alpha-api-report.md | 11 +- plugins/search/alpha-api-report.md | 11 +- plugins/tech-radar/alpha-api-report.md | 11 +- plugins/techdocs/alpha-api-report.md | 4 +- plugins/user-settings/alpha-api-report.md | 15 +- 15 files changed, 203 insertions(+), 48 deletions(-) diff --git a/packages/app-next-example-plugin/api-report.md b/packages/app-next-example-plugin/api-report.md index 83449a102f..979abac30a 100644 --- a/packages/app-next-example-plugin/api-report.md +++ b/packages/app-next-example-plugin/api-report.md @@ -3,8 +3,8 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; +import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; +import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; diff --git a/packages/frontend-app-api/api-report.md b/packages/frontend-app-api/api-report.md index 74c34be5f4..11c9ac03c5 100644 --- a/packages/frontend-app-api/api-report.md +++ b/packages/frontend-app-api/api-report.md @@ -3,13 +3,28 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AppRouteBinder } from '@backstage/core-app-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Config } from '@backstage/config'; import { ConfigApi } from '@backstage/core-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionOverrides } from '@backstage/frontend-plugin-api'; +import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { RouteRef } from '@backstage/frontend-plugin-api'; +import { SubRouteRef } from '@backstage/frontend-plugin-api'; + +// @public +export type AppRouteBinder = < + TExternalRoutes extends { + [name: string]: ExternalRouteRef; + }, +>( + externalRoutes: TExternalRoutes, + targetRoutes: PartialKeys< + TargetRouteMap, + KeysWithType> + >, +) => void; // @public (undocumented) export function createApp(options: { diff --git a/packages/frontend-app-api/src/index.ts b/packages/frontend-app-api/src/index.ts index f2dfa0f029..ad82b4ceef 100644 --- a/packages/frontend-app-api/src/index.ts +++ b/packages/frontend-app-api/src/index.ts @@ -21,3 +21,4 @@ */ export * from './wiring'; +export * from './routing'; diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 071b617851..7753b1744e 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -7,15 +7,12 @@ import { AnyApiFactory } from '@backstage/core-plugin-api'; import { AnyApiRef } from '@backstage/core-plugin-api'; -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; import { AppTheme } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { JSX as JSX_2 } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; -import { RouteRef } from '@backstage/core-plugin-api'; import { z } from 'zod'; import { ZodSchema } from 'zod'; import { ZodTypeDef } from 'zod'; @@ -41,6 +38,23 @@ export type AnyExtensionInputMap = { >; }; +// @public (undocumented) +export type AnyExternalRoutes = { + [name in string]: ExternalRouteRef; +}; + +// @public +export type AnyRouteParams = + | { + [param in string]: string; + } + | undefined; + +// @public (undocumented) +export type AnyRoutes = { + [name in string]: RouteRef; +}; + // @public (undocumented) export interface BackstagePlugin< Routes extends AnyRoutes = AnyRoutes, @@ -79,7 +93,7 @@ export const coreExtensionData: { reactElement: ConfigurableExtensionDataRef; routePath: ConfigurableExtensionDataRef; apiFactory: ConfigurableExtensionDataRef; - routeRef: ConfigurableExtensionDataRef; + routeRef: ConfigurableExtensionDataRef, {}>; navTarget: ConfigurableExtensionDataRef; theme: ConfigurableExtensionDataRef; }; @@ -173,10 +187,35 @@ export function createExtensionOverrides( options: ExtensionOverridesOptions, ): ExtensionOverrides; +// @public +export function createExternalRouteRef< + TParams extends + | { + [param in TParamKeys]: string; + } + | undefined = undefined, + TOptional extends boolean = false, + TParamKeys extends string = string, +>(options?: { + readonly params?: string extends TParamKeys + ? (keyof TParams)[] + : TParamKeys[]; + optional?: TOptional; +}): ExternalRouteRef< + keyof TParams extends never + ? undefined + : string extends TParamKeys + ? TParams + : { + [param in TParamKeys]: string; + }, + TOptional +>; + // @public export function createNavItemExtension(options: { id: string; - routeRef: RouteRef; + routeRef: RouteRef; title: string; icon: IconComponent; }): Extension<{ @@ -215,17 +254,46 @@ export function createPageExtension< // @public (undocumented) export function createPlugin< - Routes extends AnyRoutes = AnyRoutes, - ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, + Routes extends AnyRoutes, + ExternalRoutes extends AnyExternalRoutes, >( options: PluginOptions, ): BackstagePlugin; +// @public +export function createRouteRef< + TParams extends + | { + [param in TParamKeys]: string; + } + | undefined = undefined, + TParamKeys extends string = string, +>(config?: { + readonly params: string extends TParamKeys ? (keyof TParams)[] : TParamKeys[]; +}): RouteRef< + keyof TParams extends never + ? undefined + : string extends TParamKeys + ? TParams + : { + [param in TParamKeys]: string; + } +>; + // @public (undocumented) export function createSchemaFromZod( schemaCreator: (zImpl: typeof z) => ZodSchema, ): PortableSchema; +// @public +export function createSubRouteRef< + Path extends string, + ParentParams extends AnyRouteParams = never, +>(config: { + path: Path; + parent: RouteRef; +}): MakeSubRouteRef, ParentParams>; + // @public (undocumented) export function createThemeExtension(theme: AppTheme): Extension; @@ -344,11 +412,24 @@ export interface ExtensionOverridesOptions { extensions: Extension[]; } +// @public +export interface ExternalRouteRef< + TParams extends AnyRouteParams = AnyRouteParams, + TOptional extends boolean = boolean, +> { + // (undocumented) + readonly $$type: '@backstage/ExternalRouteRef'; + // (undocumented) + readonly optional: TOptional; + // (undocumented) + readonly T: TParams; +} + // @public (undocumented) export type NavTarget = { title: string; icon: IconComponent; - routeRef: RouteRef<{}>; + routeRef: RouteRef; }; // @public (undocumented) @@ -371,4 +452,47 @@ export type PortableSchema = { parse: (input: unknown) => TOutput; schema: JsonObject; }; + +// @public +export type RouteFunc = ( + ...[params]: TParams extends undefined + ? readonly [] + : readonly [params: TParams] +) => string; + +// @public +export interface RouteRef { + // (undocumented) + readonly $$type: '@backstage/RouteRef'; + // (undocumented) + readonly T: TParams; +} + +// @public +export interface SubRouteRef { + // (undocumented) + readonly $$type: '@backstage/SubRouteRef'; + // (undocumented) + readonly path: string; + // (undocumented) + readonly T: TParams; +} + +// @public +export function useRouteRef< + TOptional extends boolean, + TParams extends AnyRouteParams, +>( + routeRef: ExternalRouteRef, +): TParams extends true ? RouteFunc | undefined : RouteFunc; + +// @public +export function useRouteRef( + routeRef: RouteRef | SubRouteRef, +): RouteFunc; + +// @public +export function useRouteRefParams( + _routeRef: RouteRef | SubRouteRef, +): Params; ``` diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts index b71ceb6a95..5c093afa7a 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts @@ -105,30 +105,27 @@ export class SubRouteRefImpl * Used in {@link PathParams} type declaration. * @ignore */ -export type ParamPart = S extends `:${infer Param}` - ? Param - : never; +type ParamPart = S extends `:${infer Param}` ? Param : never; /** * Used in {@link PathParams} type declaration. * @ignore */ -export type ParamNames = - S extends `${infer Part}/${infer Rest}` - ? ParamPart | ParamNames - : ParamPart; +type ParamNames = S extends `${infer Part}/${infer Rest}` + ? ParamPart | ParamNames + : ParamPart; /** * This utility type helps us infer a Param object type from a string path * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }` * @ignore */ -export type PathParams = { [name in ParamNames]: string }; +type PathParams = { [name in ParamNames]: string }; /** * Merges a param object type with an optional params type into a params object. * @ignore */ -export type MergeParams< +type MergeParams< P1 extends { [param in string]: string }, P2 extends AnyRouteParams, > = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2); @@ -137,7 +134,7 @@ export type MergeParams< * Convert empty params to undefined. * @ignore */ -export type TrimEmptyParams = +type TrimEmptyParams = keyof Params extends never ? undefined : Params; /** @@ -146,7 +143,7 @@ export type TrimEmptyParams = * * @ignore */ -export type MakeSubRouteRef< +type MakeSubRouteRef< Params extends { [param in string]: string }, ParentParams extends AnyRouteParams, > = keyof Params & keyof ParentParams extends never diff --git a/packages/frontend-plugin-api/src/wiring/createPlugin.ts b/packages/frontend-plugin-api/src/wiring/createPlugin.ts index 782e5134ec..cf18de2b5d 100644 --- a/packages/frontend-plugin-api/src/wiring/createPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createPlugin.ts @@ -17,10 +17,10 @@ import { Extension } from './createExtension'; import { ExternalRouteRef, RouteRef } from '../routing'; -/** @internal */ +/** @public */ export type AnyRoutes = { [name in string]: RouteRef }; -/** @internal */ +/** @public */ export type AnyExternalRoutes = { [name in string]: ExternalRouteRef }; /** @public */ diff --git a/packages/frontend-plugin-api/src/wiring/index.ts b/packages/frontend-plugin-api/src/wiring/index.ts index 4e4104de97..ec685d6c81 100644 --- a/packages/frontend-plugin-api/src/wiring/index.ts +++ b/packages/frontend-plugin-api/src/wiring/index.ts @@ -37,6 +37,8 @@ export { createPlugin, type BackstagePlugin, type PluginOptions, + type AnyRoutes, + type AnyExternalRoutes, } from './createPlugin'; export { createExtensionOverrides, diff --git a/plugins/adr/alpha-api-report.md b/plugins/adr/alpha-api-report.md index 6dd1c8043f..379b7e2ada 100644 --- a/plugins/adr/alpha-api-report.md +++ b/plugins/adr/alpha-api-report.md @@ -3,8 +3,8 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; +import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; +import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/alpha-api-report.md index 4582a13a5d..0ae94b81ae 100644 --- a/plugins/catalog/alpha-api-report.md +++ b/plugins/catalog/alpha-api-report.md @@ -3,8 +3,8 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; +import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; +import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; diff --git a/plugins/explore/alpha-api-report.md b/plugins/explore/alpha-api-report.md index 308cbac733..b4de3ef3db 100644 --- a/plugins/explore/alpha-api-report.md +++ b/plugins/explore/alpha-api-report.md @@ -3,8 +3,8 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; +import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; +import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; diff --git a/plugins/graphiql/alpha-api-report.md b/plugins/graphiql/alpha-api-report.md index 6c0ea02988..eca4a81c33 100644 --- a/plugins/graphiql/alpha-api-report.md +++ b/plugins/graphiql/alpha-api-report.md @@ -3,12 +3,12 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; +import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; import { GraphQLEndpoint } from '@backstage/plugin-graphiql'; import { PortableSchema } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) export function createEndpointExtension(options: { @@ -21,7 +21,12 @@ export function createEndpointExtension(options: { }): Extension; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin< + { + root: RouteRef; + }, + AnyExternalRoutes +>; export default _default; // @alpha (undocumented) diff --git a/plugins/search/alpha-api-report.md b/plugins/search/alpha-api-report.md index 58c963b1d6..cc4b68f86e 100644 --- a/plugins/search/alpha-api-report.md +++ b/plugins/search/alpha-api-report.md @@ -3,13 +3,18 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; +import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin< + { + root: RouteRef; + }, + AnyExternalRoutes +>; export default _default; // @alpha (undocumented) diff --git a/plugins/tech-radar/alpha-api-report.md b/plugins/tech-radar/alpha-api-report.md index 9245acfaf2..24846a1106 100644 --- a/plugins/tech-radar/alpha-api-report.md +++ b/plugins/tech-radar/alpha-api-report.md @@ -3,13 +3,18 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; +import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin< + { + root: RouteRef; + }, + AnyExternalRoutes +>; export default _default; // @alpha (undocumented) diff --git a/plugins/techdocs/alpha-api-report.md b/plugins/techdocs/alpha-api-report.md index 0bf8c25b33..5fd1374114 100644 --- a/plugins/techdocs/alpha-api-report.md +++ b/plugins/techdocs/alpha-api-report.md @@ -3,8 +3,8 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; +import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; +import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; diff --git a/plugins/user-settings/alpha-api-report.md b/plugins/user-settings/alpha-api-report.md index 8a3e109e5b..4ad22fa984 100644 --- a/plugins/user-settings/alpha-api-report.md +++ b/plugins/user-settings/alpha-api-report.md @@ -3,19 +3,20 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; +import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; -import { RouteRef } from '@backstage/core-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin< + { + root: RouteRef; + }, + AnyExternalRoutes +>; export default _default; -// @alpha (undocumented) -export const userSettingsRouteRef: RouteRef; - // @alpha (undocumented) export const userSettingsTranslationRef: TranslationRef< 'user-settings', From 5b665a3810a45987bc9b44e74b0fb14de4d66fe8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 19:56:51 +0200 Subject: [PATCH 062/348] frontend-plugin-api: rename AnyRouteParams -> AnyRouteRefParams Signed-off-by: Patrik Oldsberg --- .../src/routing/RouteResolver.ts | 4 ++-- .../extractRouteInfoFromInstanceTree.test.ts | 4 ++-- packages/frontend-plugin-api/api-report.md | 24 +++++++++++-------- .../src/routing/ExternalRouteRef.test.ts | 4 ++-- .../src/routing/ExternalRouteRef.ts | 8 +++---- .../src/routing/RouteRef.test.ts | 4 ++-- .../src/routing/RouteRef.ts | 10 ++++---- .../src/routing/SubRouteRef.test.ts | 4 ++-- .../src/routing/SubRouteRef.ts | 18 +++++++------- .../frontend-plugin-api/src/routing/index.ts | 2 +- .../frontend-plugin-api/src/routing/types.ts | 2 +- .../src/routing/useRouteRef.tsx | 12 +++++----- .../src/routing/useRouteRefParams.ts | 4 ++-- 13 files changed, 54 insertions(+), 46 deletions(-) diff --git a/packages/frontend-app-api/src/routing/RouteResolver.ts b/packages/frontend-app-api/src/routing/RouteResolver.ts index 9da5836be4..77336988e2 100644 --- a/packages/frontend-app-api/src/routing/RouteResolver.ts +++ b/packages/frontend-app-api/src/routing/RouteResolver.ts @@ -19,7 +19,7 @@ import { RouteRef, ExternalRouteRef, SubRouteRef, - AnyRouteParams, + AnyRouteRefParams, RouteFunc, } from '@backstage/frontend-plugin-api'; import mapValues from 'lodash/mapValues'; @@ -189,7 +189,7 @@ export class RouteResolver { private readonly appBasePath: string, // base path without a trailing slash ) {} - resolve( + resolve( anyRouteRef: | RouteRef | SubRouteRef diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts index 86a071df79..0de33b50f2 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts @@ -18,7 +18,7 @@ import React from 'react'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { extractRouteInfoFromInstanceTree } from './extractRouteInfoFromInstanceTree'; import { - AnyRouteParams, + AnyRouteRefParams, Extension, RouteRef, coreExtensionData, @@ -35,7 +35,7 @@ const ref2 = createRouteRef(); const ref3 = createRouteRef(); const ref4 = createRouteRef(); const ref5 = createRouteRef(); -const refOrder: RouteRef[] = [ref1, ref2, ref3, ref4, ref5]; +const refOrder: RouteRef[] = [ref1, ref2, ref3, ref4, ref5]; function createTestExtension(options: { id: string; diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 7753b1744e..9169d9c9e8 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -44,7 +44,7 @@ export type AnyExternalRoutes = { }; // @public -export type AnyRouteParams = +export type AnyRouteRefParams = | { [param in string]: string; } @@ -93,7 +93,7 @@ export const coreExtensionData: { reactElement: ConfigurableExtensionDataRef; routePath: ConfigurableExtensionDataRef; apiFactory: ConfigurableExtensionDataRef; - routeRef: ConfigurableExtensionDataRef, {}>; + routeRef: ConfigurableExtensionDataRef, {}>; navTarget: ConfigurableExtensionDataRef; theme: ConfigurableExtensionDataRef; }; @@ -288,7 +288,7 @@ export function createSchemaFromZod( // @public export function createSubRouteRef< Path extends string, - ParentParams extends AnyRouteParams = never, + ParentParams extends AnyRouteRefParams = never, >(config: { path: Path; parent: RouteRef; @@ -414,7 +414,7 @@ export interface ExtensionOverridesOptions { // @public export interface ExternalRouteRef< - TParams extends AnyRouteParams = AnyRouteParams, + TParams extends AnyRouteRefParams = AnyRouteRefParams, TOptional extends boolean = boolean, > { // (undocumented) @@ -454,14 +454,16 @@ export type PortableSchema = { }; // @public -export type RouteFunc = ( +export type RouteFunc = ( ...[params]: TParams extends undefined ? readonly [] : readonly [params: TParams] ) => string; // @public -export interface RouteRef { +export interface RouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> { // (undocumented) readonly $$type: '@backstage/RouteRef'; // (undocumented) @@ -469,7 +471,9 @@ export interface RouteRef { } // @public -export interface SubRouteRef { +export interface SubRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> { // (undocumented) readonly $$type: '@backstage/SubRouteRef'; // (undocumented) @@ -481,18 +485,18 @@ export interface SubRouteRef { // @public export function useRouteRef< TOptional extends boolean, - TParams extends AnyRouteParams, + TParams extends AnyRouteRefParams, >( routeRef: ExternalRouteRef, ): TParams extends true ? RouteFunc | undefined : RouteFunc; // @public -export function useRouteRef( +export function useRouteRef( routeRef: RouteRef | SubRouteRef, ): RouteFunc; // @public -export function useRouteRefParams( +export function useRouteRefParams( _routeRef: RouteRef | SubRouteRef, ): Params; ``` diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts index ad47941833..727dc1f53e 100644 --- a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts @@ -19,7 +19,7 @@ import { createExternalRouteRef, toInternalExternalRouteRef, } from './ExternalRouteRef'; -import { AnyRouteParams } from './types'; +import { AnyRouteRefParams } from './types'; describe('ExternalRouteRef', () => { it('should be created', () => { @@ -67,7 +67,7 @@ describe('ExternalRouteRef', () => { it('should properly infer and validate parameter types and assignments', () => { function checkRouteRef< - T extends AnyRouteParams, + T extends AnyRouteRefParams, TOptional extends boolean, TCheck extends TOptional, >( diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts index ad5ad05f05..c9aabdef27 100644 --- a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts @@ -16,7 +16,7 @@ import { RouteRefImpl } from './RouteRef'; import { describeParentCallSite } from './describeParentCallSite'; -import { AnyRouteParams } from './types'; +import { AnyRouteRefParams } from './types'; /** * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. @@ -28,7 +28,7 @@ import { AnyRouteParams } from './types'; * @public */ export interface ExternalRouteRef< - TParams extends AnyRouteParams = AnyRouteParams, + TParams extends AnyRouteRefParams = AnyRouteRefParams, TOptional extends boolean = boolean, > { readonly $$type: '@backstage/ExternalRouteRef'; @@ -38,7 +38,7 @@ export interface ExternalRouteRef< /** @internal */ export interface InternalExternalRouteRef< - TParams extends AnyRouteParams = AnyRouteParams, + TParams extends AnyRouteRefParams = AnyRouteRefParams, TOptional extends boolean = boolean, > extends ExternalRouteRef { readonly version: 'v1'; @@ -50,7 +50,7 @@ export interface InternalExternalRouteRef< /** @internal */ export function toInternalExternalRouteRef< - TParams extends AnyRouteParams = AnyRouteParams, + TParams extends AnyRouteRefParams = AnyRouteRefParams, TOptional extends boolean = boolean, >( resource: ExternalRouteRef, diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts index c8d7c22e35..de7a3de887 100644 --- a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { AnyRouteParams } from './types'; +import { AnyRouteRefParams } from './types'; import { RouteRef, createRouteRef, toInternalRouteRef } from './RouteRef'; describe('RouteRef', () => { @@ -54,7 +54,7 @@ describe('RouteRef', () => { }); it('should properly infer and validate parameter types and assignments', () => { - function checkRouteRef( + function checkRouteRef( _ref: RouteRef, _params: T extends undefined ? undefined : T, ) {} diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.ts b/packages/frontend-plugin-api/src/routing/RouteRef.ts index 1085644993..da562e5273 100644 --- a/packages/frontend-plugin-api/src/routing/RouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/RouteRef.ts @@ -15,7 +15,7 @@ */ import { describeParentCallSite } from './describeParentCallSite'; -import { AnyRouteParams } from './types'; +import { AnyRouteRefParams } from './types'; /** * Absolute route reference. @@ -26,14 +26,16 @@ import { AnyRouteParams } from './types'; * * @public */ -export interface RouteRef { +export interface RouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> { readonly $$type: '@backstage/RouteRef'; readonly T: TParams; } /** @internal */ export interface InternalRouteRef< - TParams extends AnyRouteParams = AnyRouteParams, + TParams extends AnyRouteRefParams = AnyRouteRefParams, > extends RouteRef { readonly version: 'v1'; getParams(): string[]; @@ -44,7 +46,7 @@ export interface InternalRouteRef< /** @internal */ export function toInternalRouteRef< - TParams extends AnyRouteParams = AnyRouteParams, + TParams extends AnyRouteRefParams = AnyRouteRefParams, >(resource: RouteRef): InternalRouteRef { const r = resource as InternalRouteRef; if (r.$$type !== '@backstage/RouteRef') { diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts index 5b1ef6d836..b04728c49b 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { AnyRouteParams } from './types'; +import { AnyRouteRefParams } from './types'; import { SubRouteRef, createSubRouteRef, @@ -96,7 +96,7 @@ describe('SubRouteRef', () => { }); it('should properly infer and parse path parameters', () => { - function checkSubRouteRef( + function checkSubRouteRef( _ref: SubRouteRef, _params: T extends undefined ? undefined : T, ) {} diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts index 5c093afa7a..74996ab4e7 100644 --- a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts @@ -15,7 +15,7 @@ */ import { RouteRef, toInternalRouteRef } from './RouteRef'; -import { AnyRouteParams } from './types'; +import { AnyRouteRefParams } from './types'; // Should match the pattern in react-router const PARAM_PATTERN = /^\w+$/; @@ -29,7 +29,9 @@ const PARAM_PATTERN = /^\w+$/; * * @public */ -export interface SubRouteRef { +export interface SubRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> { readonly $$type: '@backstage/SubRouteRef'; readonly T: TParams; @@ -39,7 +41,7 @@ export interface SubRouteRef { /** @internal */ export interface InternalSubRouteRef< - TParams extends AnyRouteParams = AnyRouteParams, + TParams extends AnyRouteRefParams = AnyRouteRefParams, > extends SubRouteRef { readonly version: 'v1'; @@ -50,7 +52,7 @@ export interface InternalSubRouteRef< /** @internal */ export function toInternalSubRouteRef< - TParams extends AnyRouteParams = AnyRouteParams, + TParams extends AnyRouteRefParams = AnyRouteRefParams, >(resource: SubRouteRef): InternalSubRouteRef { const r = resource as InternalSubRouteRef; if (r.$$type !== '@backstage/SubRouteRef') { @@ -68,7 +70,7 @@ export function isSubRouteRef(opaque: { } /** @internal */ -export class SubRouteRefImpl +export class SubRouteRefImpl implements SubRouteRef { readonly $$type = '@backstage/SubRouteRef'; @@ -127,7 +129,7 @@ type PathParams = { [name in ParamNames]: string }; */ type MergeParams< P1 extends { [param in string]: string }, - P2 extends AnyRouteParams, + P2 extends AnyRouteRefParams, > = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2); /** @@ -145,7 +147,7 @@ type TrimEmptyParams = */ type MakeSubRouteRef< Params extends { [param in string]: string }, - ParentParams extends AnyRouteParams, + ParentParams extends AnyRouteRefParams, > = keyof Params & keyof ParentParams extends never ? SubRouteRef>> : never; @@ -158,7 +160,7 @@ type MakeSubRouteRef< */ export function createSubRouteRef< Path extends string, - ParentParams extends AnyRouteParams = never, + ParentParams extends AnyRouteRefParams = never, >(config: { path: Path; parent: RouteRef; diff --git a/packages/frontend-plugin-api/src/routing/index.ts b/packages/frontend-plugin-api/src/routing/index.ts index d262bbed58..6c25f725b5 100644 --- a/packages/frontend-plugin-api/src/routing/index.ts +++ b/packages/frontend-plugin-api/src/routing/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export type { AnyRouteParams } from './types'; +export type { AnyRouteRefParams } from './types'; export { createRouteRef, type RouteRef } from './RouteRef'; export { createSubRouteRef, type SubRouteRef } from './SubRouteRef'; export { diff --git a/packages/frontend-plugin-api/src/routing/types.ts b/packages/frontend-plugin-api/src/routing/types.ts index 8fe0d7e8a4..3bf1323210 100644 --- a/packages/frontend-plugin-api/src/routing/types.ts +++ b/packages/frontend-plugin-api/src/routing/types.ts @@ -19,4 +19,4 @@ * * @public */ -export type AnyRouteParams = { [param in string]: string } | undefined; +export type AnyRouteRefParams = { [param in string]: string } | undefined; diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.tsx b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx index 3754d2e6d5..dfcb110930 100644 --- a/packages/frontend-plugin-api/src/routing/useRouteRef.tsx +++ b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx @@ -17,7 +17,7 @@ import { useMemo } from 'react'; import { matchRoutes, useLocation } from 'react-router-dom'; import { useVersionedContext } from '@backstage/version-bridge'; -import { AnyRouteParams } from './types'; +import { AnyRouteRefParams } from './types'; import { RouteRef } from './RouteRef'; import { SubRouteRef } from './SubRouteRef'; import { ExternalRouteRef } from './ExternalRouteRef'; @@ -35,7 +35,7 @@ import { ExternalRouteRef } from './ExternalRouteRef'; * * @public */ -export type RouteFunc = ( +export type RouteFunc = ( ...[params]: TParams extends undefined ? readonly [] : readonly [params: TParams] @@ -45,7 +45,7 @@ export type RouteFunc = ( * @internal */ export interface RouteResolver { - resolve( + resolve( anyRouteRef: | RouteRef | SubRouteRef @@ -67,7 +67,7 @@ export interface RouteResolver { */ export function useRouteRef< TOptional extends boolean, - TParams extends AnyRouteParams, + TParams extends AnyRouteRefParams, >( routeRef: ExternalRouteRef, ): TParams extends true ? RouteFunc | undefined : RouteFunc; @@ -83,7 +83,7 @@ export function useRouteRef< * @returns A function that will in turn return the concrete URL of the `routeRef`. * @public */ -export function useRouteRef( +export function useRouteRef( routeRef: RouteRef | SubRouteRef, ): RouteFunc; @@ -98,7 +98,7 @@ export function useRouteRef( * @returns A function that will in turn return the concrete URL of the `routeRef`. * @public */ -export function useRouteRef( +export function useRouteRef( routeRef: | RouteRef | SubRouteRef diff --git a/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts index dbe34a4d01..1bbd8ec6b8 100644 --- a/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts +++ b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts @@ -15,7 +15,7 @@ */ import { useParams } from 'react-router-dom'; -import { AnyRouteParams } from './types'; +import { AnyRouteRefParams } from './types'; import { RouteRef } from './RouteRef'; import { SubRouteRef } from './SubRouteRef'; @@ -24,7 +24,7 @@ import { SubRouteRef } from './SubRouteRef'; * @param _routeRef - Ref of the current route. * @public */ -export function useRouteRefParams( +export function useRouteRefParams( _routeRef: RouteRef | SubRouteRef, ): Params { return useParams() as Params; From cb6db75bc2f74253c716f895a7882edda0f17252 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 19:59:29 +0200 Subject: [PATCH 063/348] core-plugin-api: deprecate old routing types and introduce AnyRouteRefParams + report fixes Signed-off-by: Patrik Oldsberg --- .changeset/stale-rice-count.md | 5 +++ .changeset/tender-maps-type.md | 5 +++ packages/core-plugin-api/alpha-api-report.md | 22 +++++++++++ packages/core-plugin-api/api-report.md | 19 +++++---- .../src/routing/SubRouteRef.ts | 5 +++ .../src/routing/convertLegacyRouteRef.ts | 39 +++++++++++++------ packages/core-plugin-api/src/routing/index.ts | 1 + packages/core-plugin-api/src/routing/types.ts | 17 +++++++- 8 files changed, 93 insertions(+), 20 deletions(-) create mode 100644 .changeset/stale-rice-count.md create mode 100644 .changeset/tender-maps-type.md diff --git a/.changeset/stale-rice-count.md b/.changeset/stale-rice-count.md new file mode 100644 index 0000000000..3d2caf168d --- /dev/null +++ b/.changeset/stale-rice-count.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-plugin-api': patch +--- + +Deprecated several types related to the routing system that are scheduled to be removed, as well as several fields on the route ref types themselves. diff --git a/.changeset/tender-maps-type.md b/.changeset/tender-maps-type.md new file mode 100644 index 0000000000..11aa814a17 --- /dev/null +++ b/.changeset/tender-maps-type.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-plugin-api': minor +--- + +Introduced `AnyRouteRefParams` as a replacement for `AnyParams`, which is now deprecated. diff --git a/packages/core-plugin-api/alpha-api-report.md b/packages/core-plugin-api/alpha-api-report.md index ba3583142f..0284d691a9 100644 --- a/packages/core-plugin-api/alpha-api-report.md +++ b/packages/core-plugin-api/alpha-api-report.md @@ -3,8 +3,12 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AnyRouteRefParams } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; +import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { Observable } from '@backstage/types'; +import { RouteRef } from '@backstage/core-plugin-api'; +import { SubRouteRef } from '@backstage/core-plugin-api'; import { TranslationMessages as TranslationMessages_2 } from '@backstage/core-plugin-api/alpha'; import { TranslationRef as TranslationRef_2 } from '@backstage/core-plugin-api/alpha'; @@ -25,6 +29,24 @@ export type AppLanguageApi = { // @alpha (undocumented) export const appLanguageApiRef: ApiRef; +// @public +export function convertLegacyRouteRef( + ref: RouteRef, +): NewRouteRef; + +// @public +export function convertLegacyRouteRef( + ref: SubRouteRef, +): NewSubRouteRef; + +// @public +export function convertLegacyRouteRef< + TParams extends AnyRouteRefParams, + TOptional extends boolean, +>( + ref: ExternalRouteRef, +): NewExternalRouteRef; + // @alpha export function createTranslationMessages< TId extends string, diff --git a/packages/core-plugin-api/api-report.md b/packages/core-plugin-api/api-report.md index 7873b23f13..789fc2bfdc 100644 --- a/packages/core-plugin-api/api-report.md +++ b/packages/core-plugin-api/api-report.md @@ -95,8 +95,11 @@ export type AnyExternalRoutes = { [name: string]: ExternalRouteRef; }; +// @public @deprecated (undocumented) +export type AnyParams = AnyRouteRefParams; + // @public -export type AnyParams = +export type AnyRouteRefParams = | { [param in string]: string; } @@ -523,7 +526,7 @@ export type IdentityApi = { // @public export const identityApiRef: ApiRef; -// @public +// @public @deprecated export type MakeSubRouteRef< Params extends { [param in string]: string; @@ -533,7 +536,7 @@ export type MakeSubRouteRef< ? SubRouteRef>> : never; -// @public +// @public @deprecated export type MergeParams< P1 extends { [param in string]: string; @@ -606,30 +609,30 @@ export type OpenIdConnectApi = { getIdToken(options?: AuthRequestOptions): Promise; }; -// @public +// @public @deprecated export type OptionalParams< Params extends { [param in string]: string; }, > = Params[keyof Params] extends never ? undefined : Params; -// @public +// @public @deprecated export type ParamKeys = keyof Params extends never ? [] : (keyof Params)[]; -// @public +// @public @deprecated export type ParamNames = S extends `${infer Part}/${infer Rest}` ? ParamPart | ParamNames : ParamPart; -// @public +// @public @deprecated export type ParamPart = S extends `:${infer Param}` ? Param : never; -// @public +// @public @deprecated export type PathParams = { [name in ParamNames]: string; }; diff --git a/packages/core-plugin-api/src/routing/SubRouteRef.ts b/packages/core-plugin-api/src/routing/SubRouteRef.ts index 14a614c2ba..b08368d74e 100644 --- a/packages/core-plugin-api/src/routing/SubRouteRef.ts +++ b/packages/core-plugin-api/src/routing/SubRouteRef.ts @@ -51,6 +51,7 @@ export class SubRouteRefImpl /** * Used in {@link PathParams} type declaration. * @public + * @deprecated this type is deprecated and will be removed in the future */ export type ParamPart = S extends `:${infer Param}` ? Param @@ -59,6 +60,7 @@ export type ParamPart = S extends `:${infer Param}` /** * Used in {@link PathParams} type declaration. * @public + * @deprecated this type is deprecated and will be removed in the future */ export type ParamNames = S extends `${infer Part}/${infer Rest}` @@ -68,12 +70,14 @@ export type ParamNames = * This utility type helps us infer a Param object type from a string path * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }` * @public + * @deprecated this type is deprecated and will be removed in the future */ export type PathParams = { [name in ParamNames]: string }; /** * Merges a param object type with an optional params type into a params object. * @public + * @deprecated this type is deprecated and will be removed in the future */ export type MergeParams< P1 extends { [param in string]: string }, @@ -85,6 +89,7 @@ export type MergeParams< * The parameters types are merged together while ensuring that there is no overlap between the two. * * @public + * @deprecated this type is deprecated and will be removed in the future */ export type MakeSubRouteRef< Params extends { [param in string]: string }, diff --git a/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts b/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts index 9778625355..940a4174a9 100644 --- a/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts +++ b/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts @@ -14,12 +14,13 @@ * limitations under the License. */ +import { routeRefType } from './types'; import { - routeRefType, RouteRef as LegacyRouteRef, SubRouteRef as LegacySubRouteRef, ExternalRouteRef as LegacyExternalRouteRef, -} from './types'; + AnyRouteRefParams, +} from '@backstage/core-plugin-api'; // Relative imports to avoid dependency, at least for now @@ -28,7 +29,6 @@ import { RouteRef, SubRouteRef, ExternalRouteRef, - AnyRouteParams, createRouteRef, createSubRouteRef, createExternalRouteRef, @@ -40,6 +40,22 @@ import { toInternalSubRouteRef } from '../../../frontend-plugin-api/src/routing/ // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; +// TODO(Rugvip): Once this is moved to a compat package these aliases can be removed and imported from frontend- instead + +/** @ignore */ +type NewRouteRef = + RouteRef; + +/** @ignore */ +type NewSubRouteRef = + SubRouteRef; + +/** @ignore */ +type NewExternalRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, + TOptional extends boolean = boolean, +> = ExternalRouteRef; + /** * A temporary helper to convert a legacy route ref to the new system. * @@ -48,9 +64,9 @@ import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/rou * * In the future the legacy createRouteRef will instead create refs compatible with both systems. */ -export function convertLegacyRouteRef( +export function convertLegacyRouteRef( ref: LegacyRouteRef, -): RouteRef; +): NewRouteRef; /** * A temporary helper to convert a legacy sub route ref to the new system. @@ -60,9 +76,9 @@ export function convertLegacyRouteRef( * * In the future the legacy createSubRouteRef will instead create refs compatible with both systems. */ -export function convertLegacyRouteRef( +export function convertLegacyRouteRef( ref: LegacySubRouteRef, -): SubRouteRef; +): NewSubRouteRef; /** * A temporary helper to convert a legacy external route ref to the new system. @@ -73,17 +89,18 @@ export function convertLegacyRouteRef( * In the future the legacy createExternalRouteRef will instead create refs compatible with both systems. */ export function convertLegacyRouteRef< - TParams extends AnyRouteParams, + TParams extends AnyRouteRefParams, TOptional extends boolean, >( ref: LegacyExternalRouteRef, -): ExternalRouteRef; +): NewExternalRouteRef; + export function convertLegacyRouteRef( ref: LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef, -): RouteRef | SubRouteRef | ExternalRouteRef { +): NewRouteRef | NewSubRouteRef | NewExternalRouteRef { // Ref has already been converted if ('$$type' in ref) { - return ref as unknown as RouteRef | SubRouteRef | ExternalRouteRef; + return ref as unknown as NewRouteRef | NewSubRouteRef | NewExternalRouteRef; } const type = (ref as unknown as { [routeRefType]: unknown })[routeRefType]; diff --git a/packages/core-plugin-api/src/routing/index.ts b/packages/core-plugin-api/src/routing/index.ts index 01d69cd4b0..4f8b12ec73 100644 --- a/packages/core-plugin-api/src/routing/index.ts +++ b/packages/core-plugin-api/src/routing/index.ts @@ -16,6 +16,7 @@ export type { AnyParams, + AnyRouteRefParams, RouteRef, SubRouteRef, ExternalRouteRef, diff --git a/packages/core-plugin-api/src/routing/types.ts b/packages/core-plugin-api/src/routing/types.ts index 80653518bb..32f26f19c1 100644 --- a/packages/core-plugin-api/src/routing/types.ts +++ b/packages/core-plugin-api/src/routing/types.ts @@ -21,12 +21,19 @@ import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; * * @public */ -export type AnyParams = { [param in string]: string } | undefined; +export type AnyRouteRefParams = { [param in string]: string } | undefined; + +/** + * @deprecated use {@link AnyRouteRefParams} instead + * @public + */ +export type AnyParams = AnyRouteRefParams; /** * Type describing the key type of a route parameter mapping. * * @public + * @deprecated this type is deprecated and will be removed in the future */ export type ParamKeys = keyof Params extends never ? [] @@ -36,6 +43,7 @@ export type ParamKeys = keyof Params extends never * Optional route params. * * @public + * @deprecated this type is deprecated and will be removed in the future */ export type OptionalParams = Params[keyof Params] extends never ? undefined : Params; @@ -81,8 +89,10 @@ export const routeRefType: unique symbol = getOrCreateGlobalSingleton( * @public */ export type RouteRef = { + /** @deprecated access to this property will be removed in the future */ $$routeRefType: 'absolute'; // See routeRefType above + /** @deprecated access to this property will be removed in the future */ params: ParamKeys; }; @@ -96,12 +106,15 @@ export type RouteRef = { * @public */ export type SubRouteRef = { + /** @deprecated access to this property will be removed in the future */ $$routeRefType: 'sub'; // See routeRefType above + /** @deprecated access to this property will be removed in the future */ parent: RouteRef; path: string; + /** @deprecated access to this property will be removed in the future */ params: ParamKeys; }; @@ -118,8 +131,10 @@ export type ExternalRouteRef< Params extends AnyParams = any, Optional extends boolean = any, > = { + /** @deprecated access to this property will be removed in the future */ $$routeRefType: 'external'; // See routeRefType above + /** @deprecated access to this property will be removed in the future */ params: ParamKeys; optional?: Optional; From 10d75752ddb48226c4afa20b7d161a225fb49771 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 20:07:54 +0200 Subject: [PATCH 064/348] techdocs: migrate alpha exports to new routing API Signed-off-by: Patrik Oldsberg --- .changeset/hungry-paws-dress.md | 1 + plugins/techdocs/alpha-api-report.md | 14 ++++++++++++-- plugins/techdocs/src/alpha.tsx | 9 +++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/.changeset/hungry-paws-dress.md b/.changeset/hungry-paws-dress.md index ede5358d58..b227a77e72 100644 --- a/.changeset/hungry-paws-dress.md +++ b/.changeset/hungry-paws-dress.md @@ -1,5 +1,6 @@ --- '@backstage/plugin-user-settings': patch +'@backstage/plugin-techdocs': patch '@backstage/plugin-tech-radar': patch '@backstage/plugin-graphiql': patch '@backstage/plugin-search': patch diff --git a/plugins/techdocs/alpha-api-report.md b/plugins/techdocs/alpha-api-report.md index 5fd1374114..bc6b8926cf 100644 --- a/plugins/techdocs/alpha-api-report.md +++ b/plugins/techdocs/alpha-api-report.md @@ -4,12 +4,22 @@ ```ts import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; -import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin< + { + root: RouteRef; + docRoot: RouteRef<{ + name: string; + kind: string; + namespace: string; + }>; + }, + AnyExternalRoutes +>; export default _default; // @alpha (undocumented) diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx index 2f991f2fcc..f4d4da6e93 100644 --- a/plugins/techdocs/src/alpha.tsx +++ b/plugins/techdocs/src/alpha.tsx @@ -35,6 +35,7 @@ import { techdocsStorageApiRef, } from '@backstage/plugin-techdocs-react'; import { TechDocsClient, TechDocsStorageClient } from './client'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; const rootRouteRef = createRouteRef({ id: 'plugin.techdocs.indexPage', @@ -76,7 +77,7 @@ export const TechDocsSearchResultListItemExtension = const TechDocsIndexPage = createPageExtension({ id: 'plugin.techdocs.indexPage', defaultPath: '/docs', - routeRef: rootRouteRef, + routeRef: convertLegacyRouteRef(rootRouteRef), loader: () => import('./home/components/TechDocsIndexPage').then(m => ( @@ -94,7 +95,7 @@ const TechDocsReaderPage = createPageExtension({ import('./reader/components/TechDocsReaderPage').then(m => ( )), - routeRef: rootDocsRouteRef, + routeRef: convertLegacyRouteRef(rootDocsRouteRef), defaultPath: '/docs/:namespace/:kind/:name/*', }); @@ -153,4 +154,8 @@ export default createPlugin({ techDocsStorage, TechDocsSearchResultListItemExtension, ], + routes: { + root: convertLegacyRouteRef(rootRouteRef), + docRoot: convertLegacyRouteRef(rootDocsRouteRef), + }, }); From 6c8834add07174637cc9153ed26c1cad598c1693 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 20:36:21 +0200 Subject: [PATCH 065/348] frontend-plugin-api: add missing tlr dep Signed-off-by: Patrik Oldsberg --- packages/frontend-plugin-api/package.json | 1 + yarn.lock | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index e996881611..8d90a84d71 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -27,6 +27,7 @@ "@backstage/frontend-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.1", "history": "^5.3.0" }, diff --git a/yarn.lock b/yarn.lock index 4e47f15fd3..492c512e76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4236,6 +4236,7 @@ __metadata: "@backstage/types": "workspace:^" "@backstage/version-bridge": "workspace:^" "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.1 "@types/react": ^16.13.1 || ^17.0.0 history: ^5.3.0 From c4c13a6cb11b542d82070fc71dfe927725acccde Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Oct 2023 12:50:36 +0200 Subject: [PATCH 066/348] frontend-plugin-api: default plugin routes to empty Signed-off-by: Patrik Oldsberg --- packages/app-next-example-plugin/api-report.md | 4 +--- packages/frontend-plugin-api/api-report.md | 4 ++-- packages/frontend-plugin-api/src/wiring/createPlugin.ts | 4 ++-- plugins/adr/alpha-api-report.md | 4 +--- plugins/catalog/alpha-api-report.md | 4 +--- plugins/explore/alpha-api-report.md | 4 +--- plugins/graphiql/alpha-api-report.md | 3 +-- plugins/search/alpha-api-report.md | 3 +-- plugins/tech-radar/alpha-api-report.md | 3 +-- plugins/techdocs/alpha-api-report.md | 3 +-- plugins/user-settings/alpha-api-report.md | 3 +-- 11 files changed, 13 insertions(+), 26 deletions(-) diff --git a/packages/app-next-example-plugin/api-report.md b/packages/app-next-example-plugin/api-report.md index 979abac30a..c89a7b599b 100644 --- a/packages/app-next-example-plugin/api-report.md +++ b/packages/app-next-example-plugin/api-report.md @@ -3,13 +3,11 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; -import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; // @public (undocumented) -const examplePlugin: BackstagePlugin; +const examplePlugin: BackstagePlugin<{}, {}>; export default examplePlugin; // @public (undocumented) diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 9169d9c9e8..3ed5965c99 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -254,8 +254,8 @@ export function createPageExtension< // @public (undocumented) export function createPlugin< - Routes extends AnyRoutes, - ExternalRoutes extends AnyExternalRoutes, + Routes extends AnyRoutes = {}, + ExternalRoutes extends AnyExternalRoutes = {}, >( options: PluginOptions, ): BackstagePlugin; diff --git a/packages/frontend-plugin-api/src/wiring/createPlugin.ts b/packages/frontend-plugin-api/src/wiring/createPlugin.ts index cf18de2b5d..84edd954ef 100644 --- a/packages/frontend-plugin-api/src/wiring/createPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createPlugin.ts @@ -48,8 +48,8 @@ export interface BackstagePlugin< /** @public */ export function createPlugin< - Routes extends AnyRoutes, - ExternalRoutes extends AnyExternalRoutes, + Routes extends AnyRoutes = {}, + ExternalRoutes extends AnyExternalRoutes = {}, >( options: PluginOptions, ): BackstagePlugin { diff --git a/plugins/adr/alpha-api-report.md b/plugins/adr/alpha-api-report.md index 379b7e2ada..5740556904 100644 --- a/plugins/adr/alpha-api-report.md +++ b/plugins/adr/alpha-api-report.md @@ -3,8 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; -import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; @@ -26,7 +24,7 @@ export const adrTranslationRef: TranslationRef< >; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin<{}, {}>; export default _default; // (No @packageDocumentation comment for this package) diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/alpha-api-report.md index 0ae94b81ae..db76a2e0f3 100644 --- a/plugins/catalog/alpha-api-report.md +++ b/plugins/catalog/alpha-api-report.md @@ -3,8 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; -import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; @@ -17,7 +15,7 @@ export const CatalogSearchResultListItemExtension: Extension<{ }>; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin<{}, {}>; export default _default; // @alpha (undocumented) diff --git a/plugins/explore/alpha-api-report.md b/plugins/explore/alpha-api-report.md index b4de3ef3db..8670338f3e 100644 --- a/plugins/explore/alpha-api-report.md +++ b/plugins/explore/alpha-api-report.md @@ -3,13 +3,11 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; -import { AnyRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin<{}, {}>; export default _default; // @alpha (undocumented) diff --git a/plugins/graphiql/alpha-api-report.md b/plugins/graphiql/alpha-api-report.md index eca4a81c33..3362cf0a59 100644 --- a/plugins/graphiql/alpha-api-report.md +++ b/plugins/graphiql/alpha-api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; import { GraphQLEndpoint } from '@backstage/plugin-graphiql'; @@ -25,7 +24,7 @@ const _default: BackstagePlugin< { root: RouteRef; }, - AnyExternalRoutes + {} >; export default _default; diff --git a/plugins/search/alpha-api-report.md b/plugins/search/alpha-api-report.md index cc4b68f86e..99f3d07b57 100644 --- a/plugins/search/alpha-api-report.md +++ b/plugins/search/alpha-api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -13,7 +12,7 @@ const _default: BackstagePlugin< { root: RouteRef; }, - AnyExternalRoutes + {} >; export default _default; diff --git a/plugins/tech-radar/alpha-api-report.md b/plugins/tech-radar/alpha-api-report.md index 24846a1106..da8f12cf0e 100644 --- a/plugins/tech-radar/alpha-api-report.md +++ b/plugins/tech-radar/alpha-api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -13,7 +12,7 @@ const _default: BackstagePlugin< { root: RouteRef; }, - AnyExternalRoutes + {} >; export default _default; diff --git a/plugins/techdocs/alpha-api-report.md b/plugins/techdocs/alpha-api-report.md index bc6b8926cf..2b3a934e34 100644 --- a/plugins/techdocs/alpha-api-report.md +++ b/plugins/techdocs/alpha-api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -18,7 +17,7 @@ const _default: BackstagePlugin< namespace: string; }>; }, - AnyExternalRoutes + {} >; export default _default; diff --git a/plugins/user-settings/alpha-api-report.md b/plugins/user-settings/alpha-api-report.md index 4ad22fa984..f375eadbee 100644 --- a/plugins/user-settings/alpha-api-report.md +++ b/plugins/user-settings/alpha-api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; @@ -13,7 +12,7 @@ const _default: BackstagePlugin< { root: RouteRef; }, - AnyExternalRoutes + {} >; export default _default; From 332a3702b345d6328e1f30ba760b9569d54f72f6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Oct 2023 12:54:45 +0200 Subject: [PATCH 067/348] frontend-app-api: cleanup route binding config reading Signed-off-by: Patrik Oldsberg --- .../frontend-app-api/src/routing/resolveRouteBindings.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/frontend-app-api/src/routing/resolveRouteBindings.ts b/packages/frontend-app-api/src/routing/resolveRouteBindings.ts index c98e36a75b..f5a2e5bd94 100644 --- a/packages/frontend-app-api/src/routing/resolveRouteBindings.ts +++ b/packages/frontend-app-api/src/routing/resolveRouteBindings.ts @@ -21,6 +21,7 @@ import { } from '@backstage/frontend-plugin-api'; import { RouteRefsById } from './collectRouteIds'; import { Config } from '@backstage/config'; +import { JsonObject } from '@backstage/types'; /** * Extracts a union of the keys in a map whose value extends the given type @@ -109,11 +110,7 @@ export function resolveRouteBindings( return result; } - const bindings = bindingsConfig.get(); - if (bindings === null || typeof bindings !== 'object') { - throw new Error('Invalid config at app.routes.bindings, must be an object'); - } - + const bindings = bindingsConfig.get(); for (const [externalRefId, targetRefId] of Object.entries(bindings)) { if (typeof targetRefId !== 'string' || targetRefId === '') { throw new Error( From 95415da622aa4058e3ad9fc0d8f89edb18f6c6df Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 26 Sep 2023 14:39:19 +0200 Subject: [PATCH 068/348] feat: started to promote the bare minmum Signed-off-by: blam --- plugins/scaffolder-react/src/alpha.ts | 2 + .../scaffolder-react/src/extensions/index.tsx | 22 +- .../scaffolder-react/src/extensions/rjsf.ts | 292 ++++++++++++++++++ .../scaffolder-react/src/extensions/types.ts | 65 ++-- .../src/{next => legacy}/extensions/index.tsx | 23 +- .../src/legacy/extensions/types.ts | 62 ++++ plugins/scaffolder-react/src/legacy/index.ts | 16 + .../src/next/components/Form/Form.tsx | 24 +- .../next/components/Stepper/Stepper.test.tsx | 2 +- .../src/next/components/Stepper/Stepper.tsx | 2 +- .../Stepper/createAsyncValidators.test.ts | 2 +- .../Stepper/createAsyncValidators.ts | 2 +- .../src/next/extensions/types.ts | 84 ----- plugins/scaffolder-react/src/next/index.ts | 1 - 14 files changed, 460 insertions(+), 139 deletions(-) create mode 100644 plugins/scaffolder-react/src/extensions/rjsf.ts rename plugins/scaffolder-react/src/{next => legacy}/extensions/index.tsx (70%) create mode 100644 plugins/scaffolder-react/src/legacy/extensions/types.ts create mode 100644 plugins/scaffolder-react/src/legacy/index.ts delete mode 100644 plugins/scaffolder-react/src/next/extensions/types.ts diff --git a/plugins/scaffolder-react/src/alpha.ts b/plugins/scaffolder-react/src/alpha.ts index 731b8e07d9..f60ced6b35 100644 --- a/plugins/scaffolder-react/src/alpha.ts +++ b/plugins/scaffolder-react/src/alpha.ts @@ -16,3 +16,5 @@ export * from './next'; export type { FormProps } from './next'; + +export * from './legacy'; diff --git a/plugins/scaffolder-react/src/extensions/index.tsx b/plugins/scaffolder-react/src/extensions/index.tsx index d70f5e36c5..395a15f902 100644 --- a/plugins/scaffolder-react/src/extensions/index.tsx +++ b/plugins/scaffolder-react/src/extensions/index.tsx @@ -14,23 +14,16 @@ * limitations under the License. */ -import React from 'react'; import { - CustomFieldExtensionSchema, CustomFieldValidator, FieldExtensionOptions, FieldExtensionComponentProps, + FieldExtensionUiSchema, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; +import { UIOptionsType } from '@rjsf/utils'; import { FIELD_EXTENSION_KEY, FIELD_EXTENSION_WRAPPER_KEY } from './keys'; -/** - * The type used to wrap up the Layout and embed the input props - * - * @public - */ -export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; - /** * Method for creating field extensions that can be used in the scaffolder * frontend form. @@ -38,7 +31,7 @@ export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; */ export function createScaffolderFieldExtension< TReturnValue = unknown, - TInputProps = unknown, + TInputProps extends UIOptionsType = {}, >( options: FieldExtensionOptions, ): Extension> { @@ -72,9 +65,16 @@ attachComponentData( true, ); +/** + * The type used to wrap up the Layout and embed the input props + * + * @public + */ +export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; + export type { - CustomFieldExtensionSchema, CustomFieldValidator, FieldExtensionOptions, FieldExtensionComponentProps, + FieldExtensionUiSchema, }; diff --git a/plugins/scaffolder-react/src/extensions/rjsf.ts b/plugins/scaffolder-react/src/extensions/rjsf.ts new file mode 100644 index 0000000000..edacbc26aa --- /dev/null +++ b/plugins/scaffolder-react/src/extensions/rjsf.ts @@ -0,0 +1,292 @@ +/* + * Copyright 2023 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 { ComponentType, ElementType, FormEvent, ReactNode, Ref } from 'react'; +import { + ErrorSchema, + FormContextType, + GenericObjectType, + IdSchema, + Registry, + RJSFSchema, + StrictRJSFSchema, + UiSchema, + ValidatorType, + TemplatesType, + RegistryWidgetsType, + RJSFValidationError, + CustomValidator, + Experimental_DefaultFormStateBehavior, + ErrorTransformer, +} from '@rjsf/utils'; +import { HTMLAttributes } from 'react'; +import Form, { IChangeEvent } from '@rjsf/core-v5'; + +/** + * The props for the `Field` components + * @public + */ +export interface ScaffolderRJSFFieldProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> extends GenericObjectType, + Pick< + HTMLAttributes, + Exclude< + keyof HTMLAttributes, + 'onBlur' | 'onFocus' | 'onChange' + > + > { + /** The JSON subschema object for this field */ + schema: S; + /** The uiSchema for this field */ + uiSchema: UiSchema; + /** The tree of unique ids for every child field */ + idSchema: IdSchema; + /** The data for this field */ + formData: T; + /** The tree of errors for this field and its children */ + errorSchema?: ErrorSchema; + /** The field change event handler; called with the updated form data and an optional `ErrorSchema` */ + onChange: ( + newFormData: T | undefined, + es?: ErrorSchema, + id?: string, + ) => any; + /** The input blur event handler; call it with the field id and value */ + onBlur: (id: string, value: any) => void; + /** The input focus event handler; call it with the field id and value */ + onFocus: (id: string, value: any) => void; + /** The `formContext` object that you passed to `Form` */ + formContext?: F; + /** A boolean value stating if the field should autofocus */ + autofocus?: boolean; + /** A boolean value stating if the field is disabled */ + disabled: boolean; + /** A boolean value stating if the field is hiding its errors */ + hideError?: boolean; + /** A boolean value stating if the field is read-only */ + readonly: boolean; + /** The required status of this field */ + required?: boolean; + /** The unique name of the field, usually derived from the name of the property in the JSONSchema */ + name: string; + /** To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids; + * Default is `root` + */ + idPrefix?: string; + /** To avoid using a path separator that is present in field names, it is possible to change the separator used for + * ids (Default is `_`) + */ + idSeparator?: string; + /** An array of strings listing all generated error messages from encountered errors for this field */ + rawErrors: string[]; + /** The `registry` object */ + registry: Registry; +} + +/** + * The properties that are passed to the `Form` + * @public + */ +export interface ScaffolderRJSFFormProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> { + /** The JSON schema object for the form */ + schema: S; + /** An implementation of the `ValidatorType` interface that is needed for form validation to work */ + validator: ValidatorType; + /** The optional children for the form, if provided, it will replace the default `SubmitButton` */ + children?: ReactNode; + /** The uiSchema for the form */ + uiSchema?: UiSchema; + /** The data for the form, used to prefill a form with existing data */ + formData?: T; + /** You can provide a `formContext` object to the form, which is passed down to all fields and widgets. Useful for + * implementing context aware fields and widgets. + * + * NOTE: Setting `{readonlyAsDisabled: false}` on the formContext will make the antd theme treat readOnly fields as + * disabled. + */ + formContext?: F; + /** To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids; + * Default is `root` + */ + idPrefix?: string; + /** To avoid using a path separator that is present in field names, it is possible to change the separator used for + * ids (Default is `_`) + */ + idSeparator?: string; + /** It's possible to disable the whole form by setting the `disabled` prop. The `disabled` prop is then forwarded down + * to each field of the form. If you just want to disable some fields, see the `ui:disabled` parameter in `uiSchema` + */ + disabled?: boolean; + /** It's possible to make the whole form read-only by setting the `readonly` prop. The `readonly` prop is then + * forwarded down to each field of the form. If you just want to make some fields read-only, see the `ui:readonly` + * parameter in `uiSchema` + */ + readonly?: boolean; + /** The dictionary of registered fields in the form */ + fields?: ScaffolderRJSFRegistryFieldsType; + /** The dictionary of registered templates in the form; Partial allows a subset to be provided beyond the defaults */ + templates?: Partial, 'ButtonTemplates'>> & { + ButtonTemplates?: Partial['ButtonTemplates']>; + }; + /** The dictionary of registered widgets in the form */ + widgets?: RegistryWidgetsType; + /** If you plan on being notified every time the form data are updated, you can pass an `onChange` handler, which will + * receive the same args as `onSubmit` any time a value is updated in the form. Can also return the `id` of the field + * that caused the change + */ + onChange?: (data: IChangeEvent, id?: string) => void; + /** To react when submitted form data are invalid, pass an `onError` handler. It will be passed the list of + * encountered errors + */ + onError?: (errors: RJSFValidationError[]) => void; + /** You can pass a function as the `onSubmit` prop of your `Form` component to listen to when the form is submitted + * and its data are valid. It will be passed a result object having a `formData` attribute, which is the valid form + * data you're usually after. The original event will also be passed as a second parameter + */ + onSubmit?: (data: IChangeEvent, event: FormEvent) => void; + /** Sometimes you may want to trigger events or modify external state when a field has been touched, so you can pass + * an `onBlur` handler, which will receive the id of the input that was blurred and the field value + */ + onBlur?: (id: string, data: any) => void; + /** Sometimes you may want to trigger events or modify external state when a field has been focused, so you can pass + * an `onFocus` handler, which will receive the id of the input that is focused and the field value + */ + onFocus?: (id: string, data: any) => void; + /** The value of this prop will be passed to the `accept-charset` HTML attribute on the form */ + acceptcharset?: string; + /** The value of this prop will be passed to the `action` HTML attribute on the form + * + * NOTE: this just renders the `action` attribute in the HTML markup. There is no real network request being sent to + * this `action` on submit. Instead, react-jsonschema-form catches the submit event with `event.preventDefault()` + * and then calls the `onSubmit` function, where you could send a request programmatically with `fetch` or similar. + */ + action?: string; + /** The value of this prop will be passed to the `autocomplete` HTML attribute on the form */ + autoComplete?: string; + /** The value of this prop will be passed to the `class` HTML attribute on the form */ + className?: string; + /** The value of this prop will be passed to the `enctype` HTML attribute on the form */ + enctype?: string; + /** The value of this prop will be passed to the `id` HTML attribute on the form */ + id?: string; + /** The value of this prop will be passed to the `name` HTML attribute on the form */ + name?: string; + /** The value of this prop will be passed to the `method` HTML attribute on the form */ + method?: string; + /** It's possible to change the default `form` tag name to a different HTML tag, which can be helpful if you are + * nesting forms. However, native browser form behaviour, such as submitting when the `Enter` key is pressed, may no + * longer work + */ + tagName?: ElementType; + /** The value of this prop will be passed to the `target` HTML attribute on the form */ + target?: string; + /** Formerly the `validate` prop; Takes a function that specifies custom validation rules for the form */ + customValidate?: CustomValidator; + /** This prop allows passing in custom errors that are augmented with the existing JSON Schema errors on the form; it + * can be used to implement asynchronous validation + */ + extraErrors?: ErrorSchema; + /** If set to true, turns off HTML5 validation on the form; Set to `false` by default */ + noHtml5Validate?: boolean; + /** If set to true, turns off all validation. Set to `false` by default + * + * @deprecated - In a future release, this switch may be replaced by making `validator` prop optional + */ + noValidate?: boolean; + /** If set to true, the form will perform validation and show any validation errors whenever the form data is changed, + * rather than just on submit + */ + liveValidate?: boolean; + /** If `omitExtraData` and `liveOmit` are both set to true, then extra form data values that are not in any form field + * will be removed whenever `onChange` is called. Set to `false` by default + */ + liveOmit?: boolean; + /** If set to true, then extra form data values that are not in any form field will be removed whenever `onSubmit` is + * called. Set to `false` by default. + */ + omitExtraData?: boolean; + /** When this prop is set to `top` or 'bottom', a list of errors (or the custom error list defined in the `ErrorList`) will also + * show. When set to false, only inline input validation errors will be shown. Set to `top` by default + */ + showErrorList?: false | 'top' | 'bottom'; + /** A function can be passed to this prop in order to make modifications to the default errors resulting from JSON + * Schema validation + */ + transformErrors?: ErrorTransformer; + /** If set to true, then the first field with an error will receive the focus when the form is submitted with errors + */ + focusOnFirstError?: boolean | ((error: RJSFValidationError) => void); + /** Optional string translation function, if provided, allows users to change the translation of the RJSF internal + * strings. Some strings contain replaceable parameter values as indicated by `%1`, `%2`, etc. The number after the + * `%` indicates the order of the parameter. The ordering of parameters is important because some languages may choose + * to put the second parameter before the first in its translation. + */ + translateString?: Registry['translateString']; + /** Optional configuration object with flags, if provided, allows users to override default form state behavior + * Currently only affecting minItems on array fields and handling of setting defaults based on the value of + * `emptyObjectFields` + */ + experimental_defaultFormStateBehavior?: Experimental_DefaultFormStateBehavior; + /** + * _internalFormWrapper is currently used by the semantic-ui theme to provide a custom wrapper around `
` + * that supports the proper rendering of those themes. To use this prop, one must pass a component that takes two + * props: `children` and `as`. That component, at minimum, should render the `children` inside of a tag + * unless `as` is provided, in which case, use the `as` prop in place of ``. + * i.e.: + * ``` + * export default function InternalForm({ children, as }) { + * const FormTag = as || 'form'; + * return {children}; + * } + * ``` + * + * Use at your own risk as this prop is private and may change at any time without notice. + */ + _internalFormWrapper?: ElementType; + /** Support receiving a React ref to the Form + */ + ref?: Ref>; +} + +/** + * The set of `Fields` stored in the `Registry` + * @public + */ +export type ScaffolderRJSFRegistryFieldsType< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = { + /** A `Field` indexed by `name` */ + [name: string]: ScaffolderRJSFField; +}; + +/** + * The `Field` type for Field Extensions + * @public + */ +export type ScaffolderRJSFField< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = ComponentType>; diff --git a/plugins/scaffolder-react/src/extensions/types.ts b/plugins/scaffolder-react/src/extensions/types.ts index 5d560a20bc..b77dc39c73 100644 --- a/plugins/scaffolder-react/src/extensions/types.ts +++ b/plugins/scaffolder-react/src/extensions/types.ts @@ -14,19 +14,23 @@ * limitations under the License. */ import { ApiHolder } from '@backstage/core-plugin-api'; -import { FieldValidation, FieldProps } from '@rjsf/core'; +import { PropsWithChildren } from 'react'; +import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; +import { UiSchema, UIOptionsType, FieldValidation } from '@rjsf/utils'; +import { ScaffolderRJSFFieldProps } from './rjsf'; /** - * Field validation type for Custom Field Extensions. + * Type for Field Extension Props for RJSF v5 * * @public */ -export type CustomFieldValidator = ( - data: TFieldReturnValue, - field: FieldValidation, - context: { apiHolder: ApiHolder }, -) => void | Promise; +export interface FieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = {}, +> extends PropsWithChildren> { + uiSchema: FieldExtensionUiSchema; +} /** * Type for the Custom Field Extension schema. @@ -38,6 +42,32 @@ export type CustomFieldExtensionSchema = { uiOptions?: JSONSchema7; }; +/** + * Type for Field Extension UiSchema + * + * @public + */ +export interface FieldExtensionUiSchema + extends UiSchema { + 'ui:options'?: TUiOptions & UIOptionsType; +} + +/** + * Field validation type for Custom Field Extensions. + * + * @public + */ +export type CustomFieldValidator = ( + data: TFieldReturnValue, + field: FieldValidation, + context: { + apiHolder: ApiHolder; + formData: JsonObject; + schema: JsonObject; + uiSchema?: FieldExtensionUiSchema; + }, +) => void | Promise; + /** * Type for the Custom Field Extension with the * name and components and validation function. @@ -46,27 +76,12 @@ export type CustomFieldExtensionSchema = { */ export type FieldExtensionOptions< TFieldReturnValue = unknown, - TInputProps = unknown, + TUiOptions = unknown, > = { name: string; component: ( - props: FieldExtensionComponentProps, + props: FieldExtensionComponentProps, ) => JSX.Element | null; - validation?: CustomFieldValidator; + validation?: CustomFieldValidator; schema?: CustomFieldExtensionSchema; }; - -/** - * Type for field extensions and being able to type - * incoming props easier. - * - * @public - */ -export interface FieldExtensionComponentProps< - TFieldReturnValue, - TUiOptions = unknown, -> extends FieldProps { - uiSchema: FieldProps['uiSchema'] & { - 'ui:options'?: TUiOptions; - }; -} diff --git a/plugins/scaffolder-react/src/next/extensions/index.tsx b/plugins/scaffolder-react/src/legacy/extensions/index.tsx similarity index 70% rename from plugins/scaffolder-react/src/next/extensions/index.tsx rename to plugins/scaffolder-react/src/legacy/extensions/index.tsx index 70751936c5..449aa74c22 100644 --- a/plugins/scaffolder-react/src/next/extensions/index.tsx +++ b/plugins/scaffolder-react/src/legacy/extensions/index.tsx @@ -15,26 +15,24 @@ */ import { - NextCustomFieldValidator, - NextFieldExtensionOptions, - NextFieldExtensionComponentProps, - NextFieldExtensionUiSchema, + CustomFieldValidator, + FieldExtensionOptions, + FieldExtensionComponentProps, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; -import { UIOptionsType } from '@rjsf/utils'; import { FIELD_EXTENSION_KEY } from '../../extensions/keys'; -import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; +import { FieldExtensionComponent } from '../../extensions'; /** * Method for creating field extensions that can be used in the scaffolder * frontend form. * @alpha */ -export function createNextScaffolderFieldExtension< +export function createLegacyScaffolderFieldExtension< TReturnValue = unknown, - TInputProps extends UIOptionsType = {}, + TInputProps = unknown, >( - options: NextFieldExtensionOptions, + options: FieldExtensionOptions, ): Extension> { return { expose() { @@ -52,8 +50,7 @@ export function createNextScaffolderFieldExtension< } export type { - NextCustomFieldValidator, - NextFieldExtensionOptions, - NextFieldExtensionComponentProps, - NextFieldExtensionUiSchema, + CustomFieldValidator, + FieldExtensionOptions, + FieldExtensionComponentProps, }; diff --git a/plugins/scaffolder-react/src/legacy/extensions/types.ts b/plugins/scaffolder-react/src/legacy/extensions/types.ts new file mode 100644 index 0000000000..1c94626b03 --- /dev/null +++ b/plugins/scaffolder-react/src/legacy/extensions/types.ts @@ -0,0 +1,62 @@ +/* + * 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 { ApiHolder } from '@backstage/core-plugin-api'; +import { FieldValidation, FieldProps } from '@rjsf/core'; +import { CustomFieldExtensionSchema } from '../../extensions/types'; + +/** + * Field validation type for Custom Field Extensions. + * + * @alpha + */ +export type CustomFieldValidator = ( + data: TFieldReturnValue, + field: FieldValidation, + context: { apiHolder: ApiHolder }, +) => void | Promise; + +/** + * Type for the Custom Field Extension with the + * name and components and validation function. + * + * @alpha + */ +export type FieldExtensionOptions< + TFieldReturnValue = unknown, + TInputProps = unknown, +> = { + name: string; + component: ( + props: FieldExtensionComponentProps, + ) => JSX.Element | null; + validation?: CustomFieldValidator; + schema?: CustomFieldExtensionSchema; +}; + +/** + * Type for field extensions and being able to type + * incoming props easier. + * + * @alpha + */ +export interface FieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = unknown, +> extends FieldProps { + uiSchema: FieldProps['uiSchema'] & { + 'ui:options'?: TUiOptions; + }; +} diff --git a/plugins/scaffolder-react/src/legacy/index.ts b/plugins/scaffolder-react/src/legacy/index.ts new file mode 100644 index 0000000000..c539a8ba60 --- /dev/null +++ b/plugins/scaffolder-react/src/legacy/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './extensions'; diff --git a/plugins/scaffolder-react/src/next/components/Form/Form.tsx b/plugins/scaffolder-react/src/next/components/Form/Form.tsx index 790c9027fe..adfb8db930 100644 --- a/plugins/scaffolder-react/src/next/components/Form/Form.tsx +++ b/plugins/scaffolder-react/src/next/components/Form/Form.tsx @@ -19,6 +19,7 @@ import React from 'react'; import { PropsWithChildren } from 'react'; import { FieldTemplate } from './FieldTemplate'; import { DescriptionFieldTemplate } from './DescriptionFieldTemplate'; +import { FieldProps } from '@rjsf/utils'; // TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly // which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because @@ -30,10 +31,31 @@ const WrappedForm = withTheme(require('@rjsf/material-ui-v5').Theme); * @alpha */ export const Form = (props: PropsWithChildren) => { + // This is where we unbreak the changes from RJSF, and make it work with our custom fields so we don't pass on this + // breaking change to our users. We will look more into a better API for this in scaffolderv2. + const wrappedFields = Object.fromEntries( + Object.entries(props.fields ?? {}).map(([key, Component]) => [ + key, + (wrapperProps: FieldProps) => { + return ( + + ); + }, + ]), + ); + const templates = { FieldTemplate, DescriptionFieldTemplate, ...props.templates, }; - return ; + + return ( + + ); }; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx index 6183f32a6c..2dd3825cea 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx @@ -20,7 +20,7 @@ import { renderInTestApp } from '@backstage/test-utils'; import { act, fireEvent } from '@testing-library/react'; import type { RJSFValidationError } from '@rjsf/utils'; import { JsonValue } from '@backstage/types'; -import { NextFieldExtensionComponentProps } from '../../extensions'; +import { NextFieldExtensionComponentProps } from '../../../extensions'; import { LayoutTemplate } from '../../../layouts'; describe('Stepper', () => { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index e15953bf1f..3d2e1233c0 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -26,7 +26,7 @@ import { import { type IChangeEvent } from '@rjsf/core-v5'; import { ErrorSchema } from '@rjsf/utils'; import React, { useCallback, useMemo, useState, type ReactNode } from 'react'; -import { NextFieldExtensionOptions } from '../../extensions'; +import { NextFieldExtensionOptions } from '../../../extensions'; import { createAsyncValidators, type FormValidation, diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index 3633410769..65e7a5b4fd 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { JsonObject } from '@backstage/types'; -import { NextCustomFieldValidator } from '../../extensions'; +import { NextCustomFieldValidator } from '../../../extensions'; import { createAsyncValidators } from './createAsyncValidators'; describe('createAsyncValidators', () => { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index ceef701255..5531ff26b4 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -19,7 +19,7 @@ import type { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { createFieldValidation, extractSchemaFromStep } from '../../lib'; -import { NextCustomFieldValidator } from '../../extensions'; +import { NextCustomFieldValidator } from '../../../extensions'; import { isObject } from './utils'; import { NextFieldExtensionUiSchema } from '../../extensions/types'; diff --git a/plugins/scaffolder-react/src/next/extensions/types.ts b/plugins/scaffolder-react/src/next/extensions/types.ts deleted file mode 100644 index 803dcb2be6..0000000000 --- a/plugins/scaffolder-react/src/next/extensions/types.ts +++ /dev/null @@ -1,84 +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 { ApiHolder } from '@backstage/core-plugin-api'; -import { - UIOptionsType, - FieldProps as FieldPropsV5, - UiSchema as UiSchemaV5, - FieldValidation as FieldValidationV5, -} from '@rjsf/utils'; -import { PropsWithChildren } from 'react'; -import { JsonObject } from '@backstage/types'; -import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react'; - -/** - * Type for Field Extension Props for RJSF v5 - * - * @alpha - */ -export interface NextFieldExtensionComponentProps< - TFieldReturnValue, - TUiOptions = {}, -> extends PropsWithChildren> { - uiSchema?: NextFieldExtensionUiSchema; -} - -/** - * Type for Field Extension UiSchema - * - * @alpha - */ -export interface NextFieldExtensionUiSchema - extends UiSchemaV5 { - 'ui:options'?: TUiOptions & UIOptionsType; -} - -/** - * Field validation type for Custom Field Extensions. - * - * @alpha - */ -export type NextCustomFieldValidator< - TFieldReturnValue, - TUiOptions = unknown, -> = ( - data: TFieldReturnValue, - field: FieldValidationV5, - context: { - apiHolder: ApiHolder; - formData: JsonObject; - schema: JsonObject; - uiSchema?: NextFieldExtensionUiSchema; - }, -) => void | Promise; - -/** - * Type for the Custom Field Extension with the - * name and components and validation function. - * - * @alpha - */ -export type NextFieldExtensionOptions< - TFieldReturnValue = unknown, - TUiOptions = unknown, -> = { - name: string; - component: ( - props: NextFieldExtensionComponentProps, - ) => JSX.Element | null; - validation?: NextCustomFieldValidator; - schema?: CustomFieldExtensionSchema; -}; diff --git a/plugins/scaffolder-react/src/next/index.ts b/plugins/scaffolder-react/src/next/index.ts index a18649f506..5e4c9f91c1 100644 --- a/plugins/scaffolder-react/src/next/index.ts +++ b/plugins/scaffolder-react/src/next/index.ts @@ -14,7 +14,6 @@ * limitations under the License. */ export * from './components'; -export * from './extensions'; export * from './types'; export * from './lib'; export * from './hooks'; From 48db8c25ebc94a96079ae388a051493745d168c4 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 28 Sep 2023 13:14:35 +0200 Subject: [PATCH 069/348] feat: started some more work on getting this into shape Signed-off-by: blam --- .../src/components/ReviewStep.tsx | 15 + .../scaffolder-react/src/components/index.ts | 16 ++ .../src/{next => components}/types.ts | 36 ++- .../scaffolder-react/src/extensions/index.tsx | 4 + plugins/scaffolder-react/src/index.ts | 1 + .../src/legacy/extensions/index.tsx | 14 +- .../src/legacy/extensions/types.ts | 10 +- .../src/next/components/Stepper/Stepper.tsx | 51 ++-- .../TemplateGroups/TemplateGroups.tsx | 11 +- .../src/next/components/Workflow/Workflow.tsx | 6 +- plugins/scaffolder/src/alpha.ts | 4 +- .../OngoingTask/ContextMenu.tsx | 0 .../OngoingTask/OngoingTask.test.tsx | 0 .../OngoingTask/OngoingTask.tsx | 0 .../{next => components}/OngoingTask/index.ts | 0 .../Router/Router.test.tsx | 9 +- .../{next => components}/Router/Router.tsx | 57 ++-- .../src/{next => components}/Router/index.ts | 3 +- .../CustomFieldExplorer.tsx | 205 -------------- .../TemplateEditorPage/TemplateEditor.tsx | 94 ------- .../TemplateEditorPage/TemplateEditorForm.tsx | 260 ------------------ .../TemplateEditorPage.test.tsx | 58 ---- .../TemplateFormPreviewer.tsx | 223 --------------- .../fields/EntityNamePicker/validation.ts | 2 +- .../fields/EntityPicker/EntityPicker.test.tsx | 3 +- .../fields/RepoUrlPicker/validation.ts | 2 +- plugins/scaffolder/src/components/index.ts | 9 +- plugins/scaffolder/src/components/types.ts | 22 -- .../FieldOverrides/DescriptionField.tsx | 0 .../MultistepJsonForm/FieldOverrides/index.ts | 0 .../MultistepJsonForm.test.tsx | 0 .../MultistepJsonForm/MultistepJsonForm.tsx | 6 +- .../MultistepJsonForm/ReviewStep.tsx | 2 +- .../MultistepJsonForm/index.ts | 0 .../MultistepJsonForm/schema.test.ts | 0 .../MultistepJsonForm/schema.ts | 0 .../src/{components => legacy}/Router.tsx | 26 +- .../ScaffolderPage/ScaffolderPage.tsx | 2 +- .../ScaffolderPageContextMenu.test.tsx | 0 .../ScaffolderPageContextMenu.tsx | 0 .../ScaffolderPage/index.ts | 0 .../TaskPage/IconLink.test.tsx | 0 .../TaskPage/IconLink.tsx | 0 .../TaskPage/TaskErrors.tsx | 0 .../TaskPage/TaskPage.tsx | 4 +- .../TaskPage/TaskPageLinks.test.tsx | 0 .../TaskPage/TaskPageLinks.tsx | 0 .../{components => legacy}/TaskPage/index.ts | 0 .../TemplateCard/TemplateCard.tsx | 0 .../TemplateCard/index.ts | 0 .../TemplateEditorPage/TemplateEditorPage.tsx | 16 +- .../TemplateEditorPage/index.ts | 3 +- .../TemplateList/TemplateList.test.tsx | 0 .../TemplateList/TemplateList.tsx | 0 .../TemplateList/index.ts | 0 .../TemplatePage/TemplatePage.test.tsx | 0 .../TemplatePage/TemplatePage.tsx | 6 +- .../TemplatePage/createValidator.test.ts | 84 +++--- .../TemplatePage/createValidator.ts | 4 +- .../TemplatePage/index.ts | 0 plugins/scaffolder/src/legacy/index.ts | 16 ++ .../CustomFieldExplorer.tsx | 13 +- .../DirectoryEditorContext.tsx | 0 .../TemplateEditorPage/DryRunContext.test.tsx | 0 .../TemplateEditorPage/DryRunContext.tsx | 0 .../DryRunResults/DryRunResults.test.tsx | 0 .../DryRunResults/DryRunResults.tsx | 0 .../DryRunResults/DryRunResultsList.test.tsx | 0 .../DryRunResults/DryRunResultsList.tsx | 0 .../DryRunResults/DryRunResultsSplitView.tsx | 0 .../DryRunResults/DryRunResultsView.test.tsx | 0 .../DryRunResults/DryRunResultsView.tsx | 6 +- .../TemplateEditorPage/DryRunResults/index.ts | 0 .../TemplateEditorPage/TemplateEditor.tsx | 14 +- .../TemplateEditorBrowser.test.tsx | 0 .../TemplateEditorBrowser.tsx | 0 .../TemplateEditorPage/TemplateEditorForm.tsx | 12 +- .../TemplateEditorIntro.tsx | 0 .../TemplateEditorPage/TemplateEditorPage.tsx | 10 +- .../TemplateEditorTextArea.tsx | 0 .../TemplateFormPreviewer.tsx | 10 +- .../TemplateListPage/TemplateListPage.tsx | 2 +- .../TemplateWizardPage/TemplateWizardPage.tsx | 18 +- plugins/scaffolder/src/next/index.ts | 1 - plugins/scaffolder/src/plugin.tsx | 6 +- 85 files changed, 311 insertions(+), 1065 deletions(-) create mode 100644 plugins/scaffolder-react/src/components/ReviewStep.tsx create mode 100644 plugins/scaffolder-react/src/components/index.ts rename plugins/scaffolder-react/src/{next => components}/types.ts (50%) rename plugins/scaffolder/src/{next => components}/OngoingTask/ContextMenu.tsx (100%) rename plugins/scaffolder/src/{next => components}/OngoingTask/OngoingTask.test.tsx (100%) rename plugins/scaffolder/src/{next => components}/OngoingTask/OngoingTask.tsx (100%) rename plugins/scaffolder/src/{next => components}/OngoingTask/index.ts (100%) rename plugins/scaffolder/src/{next => components}/Router/Router.test.tsx (94%) rename plugins/scaffolder/src/{next => components}/Router/Router.tsx (77%) rename plugins/scaffolder/src/{next => components}/Router/index.ts (87%) delete mode 100644 plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx delete mode 100644 plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx delete mode 100644 plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx delete mode 100644 plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.test.tsx delete mode 100644 plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx rename plugins/scaffolder/src/{components => legacy}/MultistepJsonForm/FieldOverrides/DescriptionField.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/MultistepJsonForm/FieldOverrides/index.ts (100%) rename plugins/scaffolder/src/{components => legacy}/MultistepJsonForm/MultistepJsonForm.test.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/MultistepJsonForm/MultistepJsonForm.tsx (98%) rename plugins/scaffolder/src/{components => legacy}/MultistepJsonForm/ReviewStep.tsx (98%) rename plugins/scaffolder/src/{components => legacy}/MultistepJsonForm/index.ts (100%) rename plugins/scaffolder/src/{components => legacy}/MultistepJsonForm/schema.test.ts (100%) rename plugins/scaffolder/src/{components => legacy}/MultistepJsonForm/schema.ts (100%) rename plugins/scaffolder/src/{components => legacy}/Router.tsx (91%) rename plugins/scaffolder/src/{components => legacy}/ScaffolderPage/ScaffolderPage.tsx (98%) rename plugins/scaffolder/src/{components => legacy}/ScaffolderPage/ScaffolderPageContextMenu.test.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/ScaffolderPage/ScaffolderPageContextMenu.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/ScaffolderPage/index.ts (100%) rename plugins/scaffolder/src/{components => legacy}/TaskPage/IconLink.test.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/TaskPage/IconLink.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/TaskPage/TaskErrors.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/TaskPage/TaskPage.tsx (99%) rename plugins/scaffolder/src/{components => legacy}/TaskPage/TaskPageLinks.test.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/TaskPage/TaskPageLinks.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/TaskPage/index.ts (100%) rename plugins/scaffolder/src/{components => legacy}/TemplateCard/TemplateCard.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/TemplateCard/index.ts (100%) rename plugins/scaffolder/src/{components => legacy}/TemplateEditorPage/TemplateEditorPage.tsx (82%) rename plugins/scaffolder/src/{components => legacy}/TemplateEditorPage/index.ts (93%) rename plugins/scaffolder/src/{components => legacy}/TemplateList/TemplateList.test.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/TemplateList/TemplateList.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/TemplateList/index.ts (100%) rename plugins/scaffolder/src/{components => legacy}/TemplatePage/TemplatePage.test.tsx (100%) rename plugins/scaffolder/src/{components => legacy}/TemplatePage/TemplatePage.tsx (97%) rename plugins/scaffolder/src/{components => legacy}/TemplatePage/createValidator.test.ts (73%) rename plugins/scaffolder/src/{components => legacy}/TemplatePage/createValidator.ts (95%) rename plugins/scaffolder/src/{components => legacy}/TemplatePage/index.ts (100%) create mode 100644 plugins/scaffolder/src/legacy/index.ts rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DirectoryEditorContext.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunContext.test.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunContext.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunResults/DryRunResults.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx (96%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/DryRunResults/index.ts (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/TemplateEditorBrowser.test.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/TemplateEditorBrowser.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/TemplateEditorIntro.tsx (100%) rename plugins/scaffolder/src/{components => next}/TemplateEditorPage/TemplateEditorTextArea.tsx (100%) diff --git a/plugins/scaffolder-react/src/components/ReviewStep.tsx b/plugins/scaffolder-react/src/components/ReviewStep.tsx new file mode 100644 index 0000000000..eb2f165350 --- /dev/null +++ b/plugins/scaffolder-react/src/components/ReviewStep.tsx @@ -0,0 +1,15 @@ +/* + * Copyright 2023 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. + */ diff --git a/plugins/scaffolder-react/src/components/index.ts b/plugins/scaffolder-react/src/components/index.ts new file mode 100644 index 0000000000..92cb965d75 --- /dev/null +++ b/plugins/scaffolder-react/src/components/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './types'; diff --git a/plugins/scaffolder-react/src/next/types.ts b/plugins/scaffolder-react/src/components/types.ts similarity index 50% rename from plugins/scaffolder-react/src/next/types.ts rename to plugins/scaffolder-react/src/components/types.ts index 192fdf4146..f6e186a56f 100644 --- a/plugins/scaffolder-react/src/next/types.ts +++ b/plugins/scaffolder-react/src/components/types.ts @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2023 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. @@ -14,18 +14,42 @@ * limitations under the License. */ +import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; +import { UiSchema } from '@rjsf/utils'; +import { JsonObject } from '@backstage/types'; -// TODO(Rugvip): The FormProps type is actually supposed to be alpha, but since we want to -// refer to it from @backstage/plugin-scaffolder, it needs to be public for now. -// Once we support internal alpha re-exports this should be switched to an alpha export. +/** @public */ +export type TemplateGroupFilter = { + title?: React.ReactNode; + filter: (entity: TemplateEntityV1beta3) => boolean; +}; /** - * Any `@rjsf/core` form properties that are publicly exposed to the `NextScaffolderpage` + * Any `@rjsf/core` form properties that are publicly exposed to the `ScaffolderPage` * - * @alpha + * @public */ export type FormProps = Pick< SchemaFormProps, 'transformErrors' | 'noHtml5Validate' >; + +/** + * The props for the Last Step in scaffolder template form. + * Which represents the summary of the input provided by the end user. + * + * @public + */ +export type ReviewStepProps = { + disableButtons: boolean; + formData: JsonObject; + handleBack: () => void; + handleReset: () => void; + handleCreate: () => void; + steps: { + uiSchema: UiSchema; + mergedSchema: JsonObject; + schema: JsonObject; + }[]; +}; diff --git a/plugins/scaffolder-react/src/extensions/index.tsx b/plugins/scaffolder-react/src/extensions/index.tsx index 395a15f902..5372a8cf7e 100644 --- a/plugins/scaffolder-react/src/extensions/index.tsx +++ b/plugins/scaffolder-react/src/extensions/index.tsx @@ -19,6 +19,7 @@ import { FieldExtensionOptions, FieldExtensionComponentProps, FieldExtensionUiSchema, + CustomFieldExtensionSchema, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; import { UIOptionsType } from '@rjsf/utils'; @@ -77,4 +78,7 @@ export type { FieldExtensionOptions, FieldExtensionComponentProps, FieldExtensionUiSchema, + CustomFieldExtensionSchema, }; + +export * from './rjsf'; diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts index 1b20c19414..70560cc694 100644 --- a/plugins/scaffolder-react/src/index.ts +++ b/plugins/scaffolder-react/src/index.ts @@ -15,6 +15,7 @@ */ export * from './extensions'; +export * from './components'; export * from './types'; export * from './secrets'; export * from './api'; diff --git a/plugins/scaffolder-react/src/legacy/extensions/index.tsx b/plugins/scaffolder-react/src/legacy/extensions/index.tsx index 449aa74c22..5276d9d31c 100644 --- a/plugins/scaffolder-react/src/legacy/extensions/index.tsx +++ b/plugins/scaffolder-react/src/legacy/extensions/index.tsx @@ -15,9 +15,9 @@ */ import { - CustomFieldValidator, - FieldExtensionOptions, - FieldExtensionComponentProps, + LegacyCustomFieldValidator, + LegacyFieldExtensionOptions, + LegacyFieldExtensionComponentProps, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; import { FIELD_EXTENSION_KEY } from '../../extensions/keys'; @@ -32,7 +32,7 @@ export function createLegacyScaffolderFieldExtension< TReturnValue = unknown, TInputProps = unknown, >( - options: FieldExtensionOptions, + options: LegacyFieldExtensionOptions, ): Extension> { return { expose() { @@ -50,7 +50,7 @@ export function createLegacyScaffolderFieldExtension< } export type { - CustomFieldValidator, - FieldExtensionOptions, - FieldExtensionComponentProps, + LegacyCustomFieldValidator, + LegacyFieldExtensionOptions, + LegacyFieldExtensionComponentProps, }; diff --git a/plugins/scaffolder-react/src/legacy/extensions/types.ts b/plugins/scaffolder-react/src/legacy/extensions/types.ts index 1c94626b03..80b2903b09 100644 --- a/plugins/scaffolder-react/src/legacy/extensions/types.ts +++ b/plugins/scaffolder-react/src/legacy/extensions/types.ts @@ -22,7 +22,7 @@ import { CustomFieldExtensionSchema } from '../../extensions/types'; * * @alpha */ -export type CustomFieldValidator = ( +export type LegacyCustomFieldValidator = ( data: TFieldReturnValue, field: FieldValidation, context: { apiHolder: ApiHolder }, @@ -34,15 +34,15 @@ export type CustomFieldValidator = ( * * @alpha */ -export type FieldExtensionOptions< +export type LegacyFieldExtensionOptions< TFieldReturnValue = unknown, TInputProps = unknown, > = { name: string; component: ( - props: FieldExtensionComponentProps, + props: LegacyFieldExtensionComponentProps, ) => JSX.Element | null; - validation?: CustomFieldValidator; + validation?: LegacyCustomFieldValidator; schema?: CustomFieldExtensionSchema; }; @@ -52,7 +52,7 @@ export type FieldExtensionOptions< * * @alpha */ -export interface FieldExtensionComponentProps< +export interface LegacyFieldExtensionComponentProps< TFieldReturnValue, TUiOptions = unknown, > extends FieldProps { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 3d2e1233c0..9bb8084ac3 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -25,8 +25,13 @@ import { } from '@material-ui/core'; import { type IChangeEvent } from '@rjsf/core-v5'; import { ErrorSchema } from '@rjsf/utils'; -import React, { useCallback, useMemo, useState, type ReactNode } from 'react'; -import { NextFieldExtensionOptions } from '../../../extensions'; +import React, { + useCallback, + useMemo, + useState, + type ReactNode, + ComponentType, +} from 'react'; import { createAsyncValidators, type FormValidation, @@ -35,7 +40,6 @@ import { ReviewState, type ReviewStateProps } from '../ReviewState'; import { useTemplateSchema } from '../../hooks/useTemplateSchema'; import validator from '@rjsf/validator-ajv8'; import { useFormDataFromQuery } from '../../hooks'; -import { FormProps } from '../../types'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; import { hasErrors } from './utils'; import * as FieldOverrides from './FieldOverrides'; @@ -43,7 +47,10 @@ import { Form } from '../Form'; import { TemplateParameterSchema, LayoutOptions, + FieldExtensionOptions, + FormProps, } from '@backstage/plugin-scaffolder-react'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles(theme => ({ backButton: { @@ -66,12 +73,13 @@ const useStyles = makeStyles(theme => ({ */ export type StepperProps = { manifest: TemplateParameterSchema; - extensions: NextFieldExtensionOptions[]; + extensions: FieldExtensionOptions[]; templateName?: string; - FormProps?: FormProps; + formProps?: FormProps; initialState?: Record; onCreate: (values: Record) => Promise; components?: { + ReviewStepComponent?: ComponentType; ReviewStateComponent?: (props: ReviewStateProps) => JSX.Element; createButtonText?: ReactNode; reviewButtonText?: ReactNode; @@ -87,6 +95,7 @@ export const Stepper = (stepperProps: StepperProps) => { const { layouts = [], components = {}, ...props } = stepperProps; const { ReviewStateComponent = ReviewState, + ReviewStepComponent, createButtonText = 'Create', reviewButtonText = 'Review', } = components; @@ -128,6 +137,13 @@ export const Stepper = (stepperProps: StepperProps) => { [setFormState], ); + const handleCreate = useCallback(() => { + props.onCreate(formState); + const name = + typeof formState.name === 'string' ? formState.name : undefined; + analytics.captureEvent('create', name ?? props.templateName ?? 'unknown'); + }, [props, formState, analytics]); + const currentStep = useTransformSchemaToProps(steps[activeStep], { layouts }); const handleNext = async ({ @@ -171,6 +187,7 @@ export const Stepper = (stepperProps: StepperProps) => {
+ {/* eslint-disable-next-line no-nested-ternary */} {activeStep < steps.length ? ( { fields={{ ...FieldOverrides, ...extensions }} showErrorList={false} onChange={handleChange} - {...(props.FormProps ?? {})} + {...(props.formProps ?? {})} >
+ ) : // TODO: potentially move away from this pattern, deprecate? + ReviewStepComponent ? ( + {}} + steps={steps} + handleCreate={handleCreate} + /> ) : ( <> @@ -217,17 +244,7 @@ export const Stepper = (stepperProps: StepperProps) => { diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx index f0f06b3410..ec08505c06 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx @@ -23,15 +23,8 @@ import { import { Progress, Link } from '@backstage/core-components'; import { Typography } from '@material-ui/core'; import { errorApiRef, IconComponent, useApi } from '@backstage/core-plugin-api'; -import { TemplateGroup } from '@backstage/plugin-scaffolder-react/alpha'; - -/** - * @alpha - */ -export type TemplateGroupFilter = { - title?: React.ReactNode; - filter: (entity: TemplateEntityV1beta3) => boolean; -}; +import { TemplateGroupFilter } from '../../../components'; +import { TemplateGroup } from '../TemplateGroup/TemplateGroup'; /** * @alpha diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index 228f5cefd9..c0d6b40333 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -27,6 +27,7 @@ import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema'; import { Stepper, type StepperProps } from '../Stepper/Stepper'; import { SecretsContextProvider } from '../../../secrets/SecretsContext'; +import { ReviewStepProps } from '../../../components'; const useStyles = makeStyles(() => ({ markdown: { @@ -48,11 +49,14 @@ export type WorkflowProps = { description?: string; namespace: string; templateName: string; + components?: { + ReviewStepComponent?: React.ComponentType; + }; onError(error: Error | undefined): JSX.Element | null; } & Pick< StepperProps, | 'extensions' - | 'FormProps' + | 'formProps' | 'components' | 'onCreate' | 'initialState' diff --git a/plugins/scaffolder/src/alpha.ts b/plugins/scaffolder/src/alpha.ts index d2bd762190..92ec945de4 100644 --- a/plugins/scaffolder/src/alpha.ts +++ b/plugins/scaffolder/src/alpha.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -export { NextScaffolderPage } from './plugin'; export { - type NextRouterProps, type FormProps, type TemplateListPageProps, type TemplateWizardPageProps, } from './next'; + +export * from './legacy'; diff --git a/plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx b/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx similarity index 100% rename from plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx rename to plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.test.tsx b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.test.tsx similarity index 100% rename from plugins/scaffolder/src/next/OngoingTask/OngoingTask.test.tsx rename to plugins/scaffolder/src/components/OngoingTask/OngoingTask.test.tsx diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx similarity index 100% rename from plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx rename to plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx diff --git a/plugins/scaffolder/src/next/OngoingTask/index.ts b/plugins/scaffolder/src/components/OngoingTask/index.ts similarity index 100% rename from plugins/scaffolder/src/next/OngoingTask/index.ts rename to plugins/scaffolder/src/components/OngoingTask/index.ts diff --git a/plugins/scaffolder/src/next/Router/Router.test.tsx b/plugins/scaffolder/src/components/Router/Router.test.tsx similarity index 94% rename from plugins/scaffolder/src/next/Router/Router.test.tsx rename to plugins/scaffolder/src/components/Router/Router.test.tsx index 3d52dd0dd0..2dc67a76be 100644 --- a/plugins/scaffolder/src/next/Router/Router.test.tsx +++ b/plugins/scaffolder/src/components/Router/Router.test.tsx @@ -14,8 +14,6 @@ * limitations under the License. */ import React from 'react'; -import { TemplateListPage } from '../TemplateListPage'; -import { TemplateWizardPage } from '../TemplateWizardPage'; import { Router } from './Router'; import { renderInTestApp } from '@backstage/test-utils'; import { @@ -27,6 +25,7 @@ import { createScaffolderLayout, ScaffolderLayouts, } from '@backstage/plugin-scaffolder-react'; +import { TemplateListPage, TemplateWizardPage } from '../../next'; jest.mock('../TemplateListPage', () => ({ TemplateListPage: jest.fn(() => null), @@ -52,7 +51,7 @@ describe('Router', () => { const { getByText } = await renderInTestApp( <>foobar, + EXPERIMENTAL_TemplateListPageComponent: () => <>foobar, }} />, { @@ -77,7 +76,7 @@ describe('Router', () => { const { getByText } = await renderInTestApp( <>foobar, + EXPERIMENTAL_TemplateWizardPageComponent: () => <>foobar, }} />, { @@ -93,7 +92,7 @@ describe('Router', () => { await renderInTestApp( ; TemplateCardComponent?: React.ComponentType<{ template: TemplateEntityV1beta3; }>; TaskPageComponent?: React.ComponentType>; - TemplateOutputsComponent?: React.ComponentType<{ + EXPERIMENTAL_TemplateOutputsComponent?: React.ComponentType<{ output?: ScaffolderTaskOutput; }>; - TemplateListPageComponent?: React.ComponentType; - TemplateWizardPageComponent?: React.ComponentType; + EXPERIMENTAL_TemplateListPageComponent?: React.ComponentType; + EXPERIMENTAL_TemplateWizardPageComponent?: React.ComponentType; }; groups?: TemplateGroupFilter[]; templateFilter?: (entity: TemplateEntityV1beta3) => boolean; - // todo(blam): rename this to formProps - FormProps?: FormProps; + formProps?: FormProps; contextMenu?: { /** Whether to show a link to the template editor */ editor?: boolean; @@ -82,21 +87,24 @@ export type NextRouterProps = { /** * The Scaffolder Router * - * @alpha + * @public */ -export const Router = (props: PropsWithChildren) => { +export const Router = (props: PropsWithChildren) => { const { components: { TemplateCardComponent, - TemplateOutputsComponent, TaskPageComponent = OngoingTask, - TemplateListPageComponent = TemplateListPage, - TemplateWizardPageComponent = TemplateWizardPage, + ReviewStepComponent, + EXPERIMENTAL_TemplateOutputsComponent: TemplateOutputsComponent, + EXPERIMENTAL_TemplateListPageComponent: + TemplateListPageComponent = TemplateListPage, + EXPERIMENTAL_TemplateWizardPageComponent: + TemplateWizardPageComponent = TemplateWizardPage, } = {}, } = props; const outlet = useOutlet() || props.children; const customFieldExtensions = - useCustomFieldExtensions(outlet); + useCustomFieldExtensions(outlet); const fieldExtensions = [ ...customFieldExtensions, @@ -106,7 +114,7 @@ export const Router = (props: PropsWithChildren) => { customFieldExtension => customFieldExtension.name === name, ), ), - ] as NextFieldExtensionOptions[]; + ] as FieldExtensionOptions[]; const customLayouts = useCustomLayouts(outlet); @@ -130,7 +138,8 @@ export const Router = (props: PropsWithChildren) => { } diff --git a/plugins/scaffolder/src/next/Router/index.ts b/plugins/scaffolder/src/components/Router/index.ts similarity index 87% rename from plugins/scaffolder/src/next/Router/index.ts rename to plugins/scaffolder/src/components/Router/index.ts index dac1db7b3a..afe51fbdc9 100644 --- a/plugins/scaffolder/src/next/Router/index.ts +++ b/plugins/scaffolder/src/components/Router/index.ts @@ -13,5 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { Router } from './Router'; -export type { NextRouterProps } from './Router'; +export { Router, type RouterProps } from './Router'; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx deleted file mode 100644 index e470267b23..0000000000 --- a/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { StreamLanguage } from '@codemirror/language'; -import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; -import { - Button, - Card, - CardContent, - CardHeader, - FormControl, - IconButton, - InputLabel, - makeStyles, - MenuItem, - Select, -} from '@material-ui/core'; -import CloseIcon from '@material-ui/icons/Close'; -import { ISubmitEvent, withTheme } from '@rjsf/core'; -import { Theme as MuiTheme } from '@rjsf/material-ui'; -import CodeMirror from '@uiw/react-codemirror'; -import React, { useCallback, useMemo, useState } from 'react'; -import yaml from 'yaml'; -import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; -import * as fieldOverrides from '../MultistepJsonForm/FieldOverrides'; -import { TemplateEditorForm } from './TemplateEditorForm'; - -const Form = withTheme(MuiTheme); - -const useStyles = makeStyles(theme => ({ - root: { - gridArea: 'pageContent', - display: 'grid', - gridTemplateAreas: ` - "controls controls" - "fieldForm preview" - `, - gridTemplateRows: 'auto 1fr', - gridTemplateColumns: '1fr 1fr', - }, - controls: { - gridArea: 'controls', - display: 'flex', - flexFlow: 'row nowrap', - alignItems: 'center', - margin: theme.spacing(1), - }, - fieldForm: { - gridArea: 'fieldForm', - }, - preview: { - gridArea: 'preview', - }, -})); - -export const CustomFieldExplorer = ({ - customFieldExtensions = [], - onClose, -}: { - customFieldExtensions?: FieldExtensionOptions[]; - onClose?: () => void; -}) => { - const classes = useStyles(); - const fieldOptions = customFieldExtensions.filter(field => !!field.schema); - const [selectedField, setSelectedField] = useState(fieldOptions[0]); - const [fieldFormState, setFieldFormState] = useState({}); - const [formState, setFormState] = useState({}); - const [refreshKey, setRefreshKey] = useState(Date.now()); - const sampleFieldTemplate = useMemo( - () => - yaml.stringify({ - parameters: [ - { - title: `${selectedField.name} Example`, - properties: { - [selectedField.name]: { - type: selectedField.schema?.returnValue?.type, - 'ui:field': selectedField.name, - 'ui:options': fieldFormState, - }, - }, - }, - ], - }), - [fieldFormState, selectedField], - ); - - const fieldComponents = useMemo(() => { - return Object.fromEntries( - customFieldExtensions.map(({ name, component }) => [name, component]), - ); - }, [customFieldExtensions]); - - const handleSelectionChange = useCallback( - (selection: FieldExtensionOptions) => { - setSelectedField(selection); - setFieldFormState({}); - setFormState({}); - }, - [setFieldFormState, setFormState, setSelectedField], - ); - - const handleFieldConfigChange = useCallback( - (state: {}) => { - setFieldFormState(state); - setFormState({}); - // Force TemplateEditorForm to re-render since some fields - // may not be responsive to ui:option changes - setRefreshKey(Date.now()); - }, - [setFieldFormState, setRefreshKey], - ); - - return ( -
-
- - - Choose Custom Field Extension - - - - - - - -
-
- - - -
) => - handleFieldConfigChange(e.formData) - } - schema={selectedField.schema?.uiOptions || {}} - > - -
-
-
-
-
- - - - - - - null} - /> -
-
- ); -}; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx deleted file mode 100644 index e07434aff7..0000000000 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { makeStyles } from '@material-ui/core'; -import React, { useState } from 'react'; -import type { - FieldExtensionOptions, - LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; -import { TemplateDirectoryAccess } from '../../lib/filesystem'; -import { DirectoryEditorProvider } from './DirectoryEditorContext'; -import { DryRunProvider } from './DryRunContext'; -import { DryRunResults } from './DryRunResults'; -import { TemplateEditorBrowser } from './TemplateEditorBrowser'; -import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from './TemplateEditorTextArea'; - -const useStyles = makeStyles({ - // Reset and fix sizing to make sure scrolling behaves correctly - root: { - gridArea: 'pageContent', - - display: 'grid', - gridTemplateAreas: ` - "browser editor preview" - "results results results" - `, - gridTemplateColumns: '1fr 3fr 2fr', - gridTemplateRows: '1fr auto', - }, - browser: { - gridArea: 'browser', - overflow: 'auto', - }, - editor: { - gridArea: 'editor', - overflow: 'auto', - }, - preview: { - gridArea: 'preview', - overflow: 'auto', - }, - results: { - gridArea: 'results', - }, -}); - -export const TemplateEditor = (props: { - directory: TemplateDirectoryAccess; - fieldExtensions?: FieldExtensionOptions[]; - layouts?: LayoutOptions[]; - onClose?: () => void; -}) => { - const classes = useStyles(); - - const [errorText, setErrorText] = useState(); - - return ( - - -
-
- -
-
- -
-
- -
-
- -
-
-
-
- ); -}; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx deleted file mode 100644 index 2a726110b8..0000000000 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { useApiHolder } from '@backstage/core-plugin-api'; -import { JsonObject, JsonValue } from '@backstage/types'; -import { makeStyles } from '@material-ui/core/styles'; -import React, { Component, ReactNode, useMemo, useState } from 'react'; -import useDebounce from 'react-use/lib/useDebounce'; -import yaml from 'yaml'; -import type { - FieldExtensionOptions, - LayoutOptions, - TemplateParameterSchema, -} from '@backstage/plugin-scaffolder-react'; -import { MultistepJsonForm } from '../MultistepJsonForm'; -import { createValidator } from '../TemplatePage'; -import { useDirectoryEditor } from './DirectoryEditorContext'; -import { useDryRun } from './DryRunContext'; - -const useStyles = makeStyles({ - containerWrapper: { - position: 'relative', - width: '100%', - height: '100%', - }, - container: { - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - overflow: 'auto', - }, -}); - -interface ErrorBoundaryProps { - invalidator: unknown; - setErrorText(errorText: string | undefined): void; - children: ReactNode; -} - -interface ErrorBoundaryState { - shouldRender: boolean; -} - -class ErrorBoundary extends Component { - state = { - shouldRender: true, - }; - - componentDidUpdate(prevProps: { invalidator: unknown }) { - if (prevProps.invalidator !== this.props.invalidator) { - this.setState({ shouldRender: true }); - } - } - - componentDidCatch(error: Error) { - this.props.setErrorText(error.message); - this.setState({ shouldRender: false }); - } - - render() { - return this.state.shouldRender ? this.props.children : null; - } -} - -interface TemplateEditorFormProps { - content?: string; - /** Setting this to true will cause the content to be parsed as if it is the template entity spec */ - contentIsSpec?: boolean; - data: JsonObject; - onUpdate: (data: JsonObject) => void; - setErrorText: (errorText?: string) => void; - - onDryRun?: (data: JsonObject) => Promise; - fieldExtensions?: FieldExtensionOptions[]; - layouts?: LayoutOptions[]; -} - -function isJsonObject(value: JsonValue | undefined): value is JsonObject { - return typeof value === 'object' && value !== null && !Array.isArray(value); -} - -/** Shows the a template form that is parsed from the provided content */ -export function TemplateEditorForm(props: TemplateEditorFormProps) { - const { - content, - contentIsSpec, - data, - onUpdate, - onDryRun, - setErrorText, - fieldExtensions = [], - layouts = [], - } = props; - const classes = useStyles(); - const apiHolder = useApiHolder(); - - const [steps, setSteps] = useState(); - - const fields = useMemo(() => { - return Object.fromEntries( - fieldExtensions.map(({ name, component }) => [name, component]), - ); - }, [fieldExtensions]); - - useDebounce( - () => { - try { - if (!content) { - setSteps(undefined); - return; - } - const parsed: JsonValue = yaml - .parseAllDocuments(content) - .filter(c => c) - .map(c => c.toJSON())[0]; - - if (!isJsonObject(parsed)) { - setSteps(undefined); - return; - } - - let rootObj = parsed; - if (!contentIsSpec) { - const isTemplate = - String(parsed.kind).toLocaleLowerCase('en-US') === 'template'; - if (!isTemplate) { - setSteps(undefined); - return; - } - - rootObj = isJsonObject(parsed.spec) ? parsed.spec : {}; - } - - const { parameters } = rootObj; - - if (!Array.isArray(parameters)) { - setErrorText('Template parameters must be an array'); - setSteps(undefined); - return; - } - - const fieldValidators = Object.fromEntries( - fieldExtensions.map(({ name, validation }) => [name, validation]), - ); - - setErrorText(); - setSteps( - parameters.flatMap(param => - isJsonObject(param) - ? [ - { - title: String(param.title), - schema: param, - validate: createValidator(param, fieldValidators, { - apiHolder, - }), - }, - ] - : [], - ), - ); - } catch (e) { - setErrorText(e.message); - } - }, - 250, - [contentIsSpec, content, apiHolder], - ); - - if (!steps) { - return null; - } - - return ( -
-
- - onUpdate(e.formData)} - onReset={() => onUpdate({})} - finishButtonLabel={onDryRun && 'Try It'} - onFinish={onDryRun && (() => onDryRun(data))} - layouts={layouts} - /> - -
-
- ); -} - -/** A version of the TemplateEditorForm that is connected to the DirectoryEditor and DryRun contexts */ -export function TemplateEditorFormDirectoryEditorDryRun( - props: Pick< - TemplateEditorFormProps, - 'setErrorText' | 'fieldExtensions' | 'layouts' - >, -) { - const { setErrorText, fieldExtensions = [], layouts } = props; - const dryRun = useDryRun(); - - const directoryEditor = useDirectoryEditor(); - const { selectedFile } = directoryEditor; - - const [data, setData] = useState({}); - - const handleDryRun = async () => { - if (!selectedFile) { - return; - } - - try { - await dryRun.execute({ - templateContent: selectedFile.content, - values: data, - files: directoryEditor.files, - }); - setErrorText(); - } catch (e) { - setErrorText(String(e.cause || e)); - throw e; - } - }; - - const content = - selectedFile && selectedFile.path.match(/\.ya?ml$/) - ? selectedFile.content - : undefined; - - return ( - - ); -} - -TemplateEditorForm.DirectoryEditorDryRun = - TemplateEditorFormDirectoryEditorDryRun; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.test.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.test.tsx deleted file mode 100644 index bf9cd8c464..0000000000 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.test.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React from 'react'; -import { TemplateEditorPage } from './TemplateEditorPage'; - -describe('TemplateEditorPage', () => { - it('renders without exploding', async () => { - await renderInTestApp(); - - expect(screen.getByText('Load Template Directory')).toBeInTheDocument(); - expect(screen.getByText('Edit Template Form')).toBeInTheDocument(); - }); - - it('template directory loading should not be supported in Jest', async () => { - await renderInTestApp(); - - expect( - screen.getByRole('button', { name: /Load Template Directory/ }), - ).toBeDisabled(); - }); - - it('should be able to continue to form preview', async () => { - await renderInTestApp( - - - , - ); - - await userEvent.click(screen.getByText('Edit Template Form')); - - expect(screen.getByLabelText('Load Existing Template')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx deleted file mode 100644 index 9442394177..0000000000 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Entity } from '@backstage/catalog-model'; -import { alertApiRef, useApi } from '@backstage/core-plugin-api'; -import { - catalogApiRef, - humanizeEntityRef, -} from '@backstage/plugin-catalog-react'; -import { - FormControl, - IconButton, - InputLabel, - LinearProgress, - makeStyles, - MenuItem, - Select, -} from '@material-ui/core'; -import CloseIcon from '@material-ui/icons/Close'; -import React, { useCallback, useState } from 'react'; -import useAsync from 'react-use/lib/useAsync'; -import yaml from 'yaml'; -import { - type FieldExtensionOptions, - type LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; -import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from './TemplateEditorTextArea'; - -const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI -parameters: - - title: Fill in some steps - required: - - name - properties: - name: - title: Name - type: string - description: Unique name of the component - owner: - title: Owner - type: string - description: Owner of the component - ui:field: OwnerPicker - ui:options: - catalogFilter: - kind: Group - - title: Choose a location - required: - - repoUrl - properties: - repoUrl: - title: Repository Location - type: string - ui:field: RepoUrlPicker - ui:options: - allowedHosts: - - github.com -steps: - - id: fetch-base - name: Fetch Base - action: fetch:template - input: - url: ./template - values: - name: \${{parameters.name}} -`; - -type TemplateOption = { - label: string; - value: Entity; -}; - -const useStyles = makeStyles(theme => ({ - root: { - gridArea: 'pageContent', - display: 'grid', - gridTemplateAreas: ` - "controls controls" - "textArea preview" - `, - gridTemplateRows: 'auto 1fr', - gridTemplateColumns: '1fr 1fr', - }, - controls: { - gridArea: 'controls', - display: 'flex', - flexFlow: 'row nowrap', - alignItems: 'center', - margin: theme.spacing(1), - }, - textArea: { - gridArea: 'textArea', - }, - preview: { - gridArea: 'preview', - }, -})); - -export const TemplateFormPreviewer = ({ - defaultPreviewTemplate = EXAMPLE_TEMPLATE_PARAMS_YAML, - customFieldExtensions = [], - onClose, - layouts = [], -}: { - defaultPreviewTemplate?: string; - customFieldExtensions?: FieldExtensionOptions[]; - onClose?: () => void; - layouts?: LayoutOptions[]; -}) => { - const classes = useStyles(); - const alertApi = useApi(alertApiRef); - const catalogApi = useApi(catalogApiRef); - const [selectedTemplate, setSelectedTemplate] = useState(''); - const [errorText, setErrorText] = useState(); - const [templateOptions, setTemplateOptions] = useState([]); - const [templateYaml, setTemplateYaml] = useState(defaultPreviewTemplate); - const [formState, setFormState] = useState({}); - - const { loading } = useAsync( - () => - catalogApi - .getEntities({ - filter: { kind: 'template' }, - fields: [ - 'kind', - 'metadata.namespace', - 'metadata.name', - 'metadata.title', - 'spec.parameters', - 'spec.steps', - 'spec.output', - ], - }) - .then(({ items }) => - setTemplateOptions( - items.map(template => ({ - label: - template.metadata.title ?? - humanizeEntityRef(template, { defaultKind: 'template' }), - value: template, - })), - ), - ) - .catch(e => - alertApi.post({ - message: `Error loading exisiting templates: ${e.message}`, - severity: 'error', - }), - ), - [catalogApi], - ); - - const handleSelectChange = useCallback( - // TODO(Rugvip): Afaik this should be Entity, but didn't want to make runtime changes while fixing types - (selected: any) => { - setSelectedTemplate(selected); - setTemplateYaml(yaml.stringify(selected.spec)); - }, - [setTemplateYaml], - ); - - return ( - <> - {loading && } -
-
- - - Load Existing Template - - - - - - - -
-
- -
-
- -
-
- - ); -}; diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts index d116bef228..9302e9abc1 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; export const entityNamePickerValidation = ( diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index cbc587a732..300e23ee89 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -18,11 +18,12 @@ import { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { FieldProps } from '@rjsf/core'; + import { fireEvent, screen } from '@testing-library/react'; import React from 'react'; import { EntityPicker } from './EntityPicker'; import { EntityPickerProps } from './schema'; +import { FieldProps } from '@rjsf/utils'; const makeEntity = (kind: string, namespace: string, name: string): Entity => ({ apiVersion: 'scaffolder.backstage.io/v1beta3', diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts index 99847f9e3b..55ba92abdc 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { ApiHolder } from '@backstage/core-plugin-api'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; diff --git a/plugins/scaffolder/src/components/index.ts b/plugins/scaffolder/src/components/index.ts index a5c17b8ab0..fd8c11e2da 100644 --- a/plugins/scaffolder/src/components/index.ts +++ b/plugins/scaffolder/src/components/index.ts @@ -15,7 +15,12 @@ */ export * from './fields'; export type { RepoUrlPickerUiOptions } from './fields'; + export { TemplateTypePicker } from './TemplateTypePicker'; -export { TaskPage, type TaskPageProps } from './TaskPage'; + export type { RouterProps } from './Router'; -export type { ReviewStepProps } from './types'; +export { OngoingTask as TaskPage } from './OngoingTask'; + +export type { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; + +export type { TaskPageProps } from '../legacy/TaskPage'; diff --git a/plugins/scaffolder/src/components/types.ts b/plugins/scaffolder/src/components/types.ts index f5989a2ae1..b1e99a84e6 100644 --- a/plugins/scaffolder/src/components/types.ts +++ b/plugins/scaffolder/src/components/types.ts @@ -13,25 +13,3 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import { UiSchema } from '@rjsf/utils'; -import { JsonObject } from '@backstage/types'; - -/** - * The props for the Last Step in scaffolder template form. - * Which represents the summary of the input provided by the end user. - * - * @public - */ -export type ReviewStepProps = { - disableButtons: boolean; - formData: JsonObject; - handleBack: () => void; - handleReset: () => void; - handleCreate: () => void; - steps: { - uiSchema: UiSchema; - mergedSchema: JsonObject; - schema: JsonObject; - }[]; -}; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/DescriptionField.tsx similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx rename to plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/DescriptionField.tsx diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/index.ts b/plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/index.ts similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/index.ts rename to plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/index.ts diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.test.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.test.tsx rename to plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.test.tsx diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx similarity index 98% rename from plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx rename to plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx index d8299a9b5f..eddbbff4bf 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx @@ -35,11 +35,13 @@ import React, { ComponentType, useState } from 'react'; import { transformSchemaToProps } from './schema'; import cloneDeep from 'lodash/cloneDeep'; import * as fieldOverrides from './FieldOverrides'; -import { ReviewStepProps } from '../types'; import { ReviewStep } from './ReviewStep'; import { extractSchemaFromStep } from '@backstage/plugin-scaffolder-react/alpha'; import { selectedTemplateRouteRef } from '../../routes'; -import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { + LayoutOptions, + ReviewStepProps, +} from '@backstage/plugin-scaffolder-react'; const Form = withTheme(MuiTheme); diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/ReviewStep.tsx similarity index 98% rename from plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx rename to plugins/scaffolder/src/legacy/MultistepJsonForm/ReviewStep.tsx index 112b96bdf1..7d9e81d91b 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx +++ b/plugins/scaffolder/src/legacy/MultistepJsonForm/ReviewStep.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { Content, StructuredMetadataTable } from '@backstage/core-components'; import { UiSchema } from '@rjsf/core'; import { JsonObject } from '@backstage/types'; -import { ReviewStepProps } from '../types'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; export function getReviewData( formData: Record, diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/index.ts b/plugins/scaffolder/src/legacy/MultistepJsonForm/index.ts similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/index.ts rename to plugins/scaffolder/src/legacy/MultistepJsonForm/index.ts diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts b/plugins/scaffolder/src/legacy/MultistepJsonForm/schema.test.ts similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts rename to plugins/scaffolder/src/legacy/MultistepJsonForm/schema.test.ts diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts b/plugins/scaffolder/src/legacy/MultistepJsonForm/schema.ts similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/schema.ts rename to plugins/scaffolder/src/legacy/MultistepJsonForm/schema.ts diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/legacy/Router.tsx similarity index 91% rename from plugins/scaffolder/src/components/Router.tsx rename to plugins/scaffolder/src/legacy/Router.tsx index 3ceda359cc..ac183b9470 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/legacy/Router.tsx @@ -21,18 +21,17 @@ import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { ScaffolderPage } from './ScaffolderPage'; import { TemplatePage } from './TemplatePage'; import { TaskPage } from './TaskPage'; -import { ActionsPage } from './ActionsPage'; -import { TemplateEditorPage } from './TemplateEditorPage'; +import { ActionsPage } from '../components/ActionsPage'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../extensions/default'; import { useRouteRef, useRouteRefParams } from '@backstage/core-plugin-api'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; import { - FieldExtensionOptions, + ReviewStepProps, SecretsContextProvider, useCustomFieldExtensions, useCustomLayouts, } from '@backstage/plugin-scaffolder-react'; -import { ListTasksPage } from './ListTasksPage'; -import { ReviewStepProps } from './types'; +import { ListTasksPage } from '../components/ListTasksPage'; import { actionsRouteRef, editRouteRef, @@ -41,12 +40,13 @@ import { scaffolderTaskRouteRef, selectedTemplateRouteRef, } from '../routes'; +import { TemplateEditorPage } from './TemplateEditorPage'; /** * The props for the entrypoint `ScaffolderPage` component the plugin. - * @public + * @alpha */ -export type RouterProps = { +export type LegacyRouterProps = { components?: { ReviewStepComponent?: ComponentType; TemplateCardComponent?: @@ -77,11 +77,11 @@ export type RouterProps = { }; /** - * The main entrypoint `Router` for the `ScaffolderPlugin`. + * The legacy router * - * @public + * @alpha */ -export const Router = (props: RouterProps) => { +export const LegacyRouter = (props: LegacyRouterProps) => { const { groups, templateFilter, @@ -95,7 +95,9 @@ export const Router = (props: RouterProps) => { const outlet = useOutlet(); const TaskPageElement = TaskPageComponent ?? TaskPage; - const customFieldExtensions = useCustomFieldExtensions(outlet); + const customFieldExtensions = + useCustomFieldExtensions(outlet); + const fieldExtensions = [ ...customFieldExtensions, ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter( @@ -104,7 +106,7 @@ export const Router = (props: RouterProps) => { customFieldExtension => customFieldExtension.name === name, ), ), - ] as FieldExtensionOptions[]; + ] as LegacyFieldExtensionOptions[]; const customLayouts = useCustomLayouts(outlet); diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPage.tsx similarity index 98% rename from plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx rename to plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPage.tsx index 40435573e9..54122eddf0 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPage.tsx @@ -34,11 +34,11 @@ import { } from '@backstage/plugin-catalog-react'; import React, { ComponentType } from 'react'; import { TemplateList } from '../TemplateList'; -import { TemplateTypePicker } from '../TemplateTypePicker'; import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha'; import { usePermission } from '@backstage/plugin-permission-react'; import { ScaffolderPageContextMenu } from './ScaffolderPageContextMenu'; import { registerComponentRouteRef } from '../../routes'; +import { TemplateTypePicker } from '../../components'; export type ScaffolderPageProps = { TemplateCardComponent?: diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx rename to plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.test.tsx diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.tsx similarity index 100% rename from plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx rename to plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.tsx diff --git a/plugins/scaffolder/src/components/ScaffolderPage/index.ts b/plugins/scaffolder/src/legacy/ScaffolderPage/index.ts similarity index 100% rename from plugins/scaffolder/src/components/ScaffolderPage/index.ts rename to plugins/scaffolder/src/legacy/ScaffolderPage/index.ts diff --git a/plugins/scaffolder/src/components/TaskPage/IconLink.test.tsx b/plugins/scaffolder/src/legacy/TaskPage/IconLink.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/IconLink.test.tsx rename to plugins/scaffolder/src/legacy/TaskPage/IconLink.test.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/IconLink.tsx b/plugins/scaffolder/src/legacy/TaskPage/IconLink.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/IconLink.tsx rename to plugins/scaffolder/src/legacy/TaskPage/IconLink.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/TaskErrors.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskErrors.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/TaskErrors.tsx rename to plugins/scaffolder/src/legacy/TaskPage/TaskErrors.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx similarity index 99% rename from plugins/scaffolder/src/components/TaskPage/TaskPage.tsx rename to plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx index 78cdc5d935..7ba7c2c9f7 100644 --- a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx @@ -237,7 +237,7 @@ const hasLinks = ({ links = [] }: ScaffolderTaskOutput): boolean => * TaskPageProps for constructing a TaskPage * @param loadingText - Optional loading text shown before a task begins executing. * - * @public + * @deprecated - this is a useless type that is no longer used. */ export type TaskPageProps = { loadingText?: string; @@ -246,7 +246,7 @@ export type TaskPageProps = { /** * TaskPage for showing the status of the taskId provided as a param * - * @public + * @alpha */ export const TaskPage = (props: TaskPageProps) => { const { loadingText } = props; diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.test.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskPageLinks.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/TaskPageLinks.test.tsx rename to plugins/scaffolder/src/legacy/TaskPage/TaskPageLinks.test.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskPageLinks.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx rename to plugins/scaffolder/src/legacy/TaskPage/TaskPageLinks.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/index.ts b/plugins/scaffolder/src/legacy/TaskPage/index.ts similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/index.ts rename to plugins/scaffolder/src/legacy/TaskPage/index.ts diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/legacy/TemplateCard/TemplateCard.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx rename to plugins/scaffolder/src/legacy/TemplateCard/TemplateCard.tsx diff --git a/plugins/scaffolder/src/components/TemplateCard/index.ts b/plugins/scaffolder/src/legacy/TemplateCard/index.ts similarity index 100% rename from plugins/scaffolder/src/components/TemplateCard/index.ts rename to plugins/scaffolder/src/legacy/TemplateCard/index.ts diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx similarity index 82% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx rename to plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx index ebb763e145..e65869ad0e 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx @@ -19,14 +19,12 @@ import { TemplateDirectoryAccess, WebFileSystemAccess, } from '../../lib/filesystem'; -import { CustomFieldExplorer } from './CustomFieldExplorer'; -import { TemplateEditorIntro } from './TemplateEditorIntro'; -import { TemplateEditor } from './TemplateEditor'; -import { TemplateFormPreviewer } from './TemplateFormPreviewer'; -import { - type FieldExtensionOptions, - type LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; +import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; +import { CustomFieldExplorer } from '../../next/TemplateEditorPage/CustomFieldExplorer'; +import { TemplateFormPreviewer } from '../../next/TemplateEditorPage/TemplateFormPreviewer'; +import { TemplateEditor } from '../../next/TemplateEditorPage/TemplateEditor'; +import { TemplateEditorIntro } from '../../next/TemplateEditorPage/TemplateEditorIntro'; type Selection = | { @@ -42,7 +40,7 @@ type Selection = interface TemplateEditorPageProps { defaultPreviewTemplate?: string; - customFieldExtensions?: FieldExtensionOptions[]; + customFieldExtensions?: LegacyFieldExtensionOptions[]; layouts?: LayoutOptions[]; } diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/index.ts b/plugins/scaffolder/src/legacy/TemplateEditorPage/index.ts similarity index 93% rename from plugins/scaffolder/src/components/TemplateEditorPage/index.ts rename to plugins/scaffolder/src/legacy/TemplateEditorPage/index.ts index 7ec6bddb64..7de0d3c679 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/index.ts +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2023 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. @@ -13,5 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - export { TemplateEditorPage } from './TemplateEditorPage'; diff --git a/plugins/scaffolder/src/components/TemplateList/TemplateList.test.tsx b/plugins/scaffolder/src/legacy/TemplateList/TemplateList.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateList/TemplateList.test.tsx rename to plugins/scaffolder/src/legacy/TemplateList/TemplateList.test.tsx diff --git a/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx b/plugins/scaffolder/src/legacy/TemplateList/TemplateList.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateList/TemplateList.tsx rename to plugins/scaffolder/src/legacy/TemplateList/TemplateList.tsx diff --git a/plugins/scaffolder/src/components/TemplateList/index.ts b/plugins/scaffolder/src/legacy/TemplateList/index.ts similarity index 100% rename from plugins/scaffolder/src/components/TemplateList/index.ts rename to plugins/scaffolder/src/legacy/TemplateList/index.ts diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx rename to plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.test.tsx diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx similarity index 97% rename from plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx rename to plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx index c615649f93..a5cac1ef54 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx @@ -20,10 +20,10 @@ import React, { ComponentType, useCallback, useState } from 'react'; import { Navigate, useNavigate } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; import { - type FieldExtensionOptions, type LayoutOptions, scaffolderApiRef, useTemplateSecrets, + ReviewStepProps, } from '@backstage/plugin-scaffolder-react'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from './createValidator'; @@ -38,12 +38,12 @@ import { useRouteRefParams, } from '@backstage/core-plugin-api'; import { stringifyEntityRef } from '@backstage/catalog-model'; -import { ReviewStepProps } from '../types'; import { rootRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, } from '../../routes'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; const useTemplateParameterSchema = (templateRef: string) => { const scaffolderApi = useApi(scaffolderApiRef); @@ -56,7 +56,7 @@ const useTemplateParameterSchema = (templateRef: string) => { type Props = { ReviewStepComponent?: ComponentType; - customFieldExtensions?: FieldExtensionOptions[]; + customFieldExtensions?: LegacyFieldExtensionOptions[]; layouts?: LayoutOptions[]; headerOptions?: { pageTitleOverride?: string; diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.test.ts similarity index 73% rename from plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts rename to plugins/scaffolder/src/legacy/TemplatePage/createValidator.test.ts index 1858e40241..117b54b0d2 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.test.ts @@ -15,7 +15,7 @@ */ import { createValidator } from './createValidator'; -import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; +import { LegacyCustomFieldValidator } from '@backstage/plugin-scaffolder-react/alpha'; import { ApiHolder } from '@backstage/core-plugin-api'; import { FieldValidation, FormValidation } from '@rjsf/core'; @@ -26,49 +26,51 @@ type CustomLinkType = { }; describe('createValidator', () => { - const validators: Record> = - { - CustomPicker: ( - value: unknown, - fieldValidation: FieldValidation, - _context: { apiHolder: ApiHolder }, - ) => { - if (!value || !(value as { value?: unknown }).value) { - fieldValidation.addError('Error !'); - } - }, - CustomLink: ( - values: unknown, - fieldValidation: FieldValidation, - _context: { apiHolder: ApiHolder }, - ) => { - const input = values as CustomLinkType[]; - for (const item of input) { - const validGitlabUrlRegex = - /gitlab\.(?:stg\.)?spotify\.com\?owner=.*&repo=.*/; + const validators: Record< + string, + undefined | LegacyCustomFieldValidator + > = { + CustomPicker: ( + value: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { + if (!value || !(value as { value?: unknown }).value) { + fieldValidation.addError('Error !'); + } + }, + CustomLink: ( + values: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { + const input = values as CustomLinkType[]; + for (const item of input) { + const validGitlabUrlRegex = + /gitlab\.(?:stg\.)?spotify\.com\?owner=.*&repo=.*/; - if (!item || !validGitlabUrlRegex.test(item.url)) { - fieldValidation.addError( - `Make sure to put in a valid gitlab clone url.`, - ); - } + if (!item || !validGitlabUrlRegex.test(item.url)) { + fieldValidation.addError( + `Make sure to put in a valid gitlab clone url.`, + ); } - }, - TagPicker: ( - values: unknown, - fieldValidation: FieldValidation, - _context: { apiHolder: ApiHolder }, - ) => { - const input = values as string[]; - for (const item of input) { - if (!/^[a-z0-9-]+$/.test(item)) { - fieldValidation.addError( - 'A tag name can only contain lowercase letters, numeric characters or dashes', - ); - } + } + }, + TagPicker: ( + values: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { + const input = values as string[]; + for (const item of input) { + if (!/^[a-z0-9-]+$/.test(item)) { + fieldValidation.addError( + 'A tag name can only contain lowercase letters, numeric characters or dashes', + ); } - }, - }; + } + }, + }; const apiHolderMock: jest.Mocked = { get: jest.fn().mockImplementation(() => { diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts similarity index 95% rename from plugins/scaffolder/src/components/TemplatePage/createValidator.ts rename to plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts index 8bfe8c8313..04325ce5e5 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; +import { LegacyCustomFieldValidator } from '@backstage/plugin-scaffolder-react/alpha'; import { FormValidation } from '@rjsf/core'; import { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; @@ -29,7 +29,7 @@ function isArray(obj: unknown): obj is JsonObject { export const createValidator = ( rootSchema: JsonObject, - validators: Record>, + validators: Record>, context: { apiHolder: ApiHolder; }, diff --git a/plugins/scaffolder/src/components/TemplatePage/index.ts b/plugins/scaffolder/src/legacy/TemplatePage/index.ts similarity index 100% rename from plugins/scaffolder/src/components/TemplatePage/index.ts rename to plugins/scaffolder/src/legacy/TemplatePage/index.ts diff --git a/plugins/scaffolder/src/legacy/index.ts b/plugins/scaffolder/src/legacy/index.ts new file mode 100644 index 0000000000..83b5717fbe --- /dev/null +++ b/plugins/scaffolder/src/legacy/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 { LegacyRouter, type LegacyRouterProps } from './Router'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx index 15298dff8a..af195b866a 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx @@ -31,12 +31,10 @@ import CloseIcon from '@material-ui/icons/Close'; import CodeMirror from '@uiw/react-codemirror'; import React, { useCallback, useMemo, useState } from 'react'; import yaml from 'yaml'; -import { - NextFieldExtensionOptions, - Form, -} from '@backstage/plugin-scaffolder-react/alpha'; +import { Form } from '@backstage/plugin-scaffolder-react/alpha'; import { TemplateEditorForm } from './TemplateEditorForm'; import validator from '@rjsf/validator-ajv8'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles(theme => ({ root: { @@ -68,7 +66,7 @@ export const CustomFieldExplorer = ({ customFieldExtensions = [], onClose, }: { - customFieldExtensions?: NextFieldExtensionOptions[]; + customFieldExtensions?: FieldExtensionOptions[]; onClose?: () => void; }) => { const classes = useStyles(); @@ -102,7 +100,7 @@ export const CustomFieldExplorer = ({ }, [customFieldExtensions]); const handleSelectionChange = useCallback( - (selection: NextFieldExtensionOptions) => { + (selection: FieldExtensionOptions) => { setSelectedField(selection); setFieldFormState({}); }, @@ -131,7 +129,7 @@ export const CustomFieldExplorer = ({ label="Choose Custom Field Extension" labelId="select-field-label" onChange={e => - handleSelectionChange(e.target.value as NextFieldExtensionOptions) + handleSelectionChange(e.target.value as FieldExtensionOptions) } > {fieldOptions.map((option, idx) => ( @@ -152,6 +150,7 @@ export const CustomFieldExplorer = ({
[]; + fieldExtensions?: FieldExtensionOptions[]; layouts?: LayoutOptions[]; onClose?: () => void; }) => { diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorBrowser.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorBrowser.test.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorBrowser.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorBrowser.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx index 898487e200..15c53d6d81 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx @@ -22,13 +22,11 @@ import yaml from 'yaml'; import { LayoutOptions, TemplateParameterSchema, + FieldExtensionOptions, } from '@backstage/plugin-scaffolder-react'; -import { - NextFieldExtensionOptions, - Stepper, -} from '@backstage/plugin-scaffolder-react/alpha'; -import { useDryRun } from '../../components/TemplateEditorPage/DryRunContext'; -import { useDirectoryEditor } from '../../components/TemplateEditorPage/DirectoryEditorContext'; +import { Stepper } from '@backstage/plugin-scaffolder-react/alpha'; +import { useDryRun } from './DryRunContext'; +import { useDirectoryEditor } from './DirectoryEditorContext'; const useStyles = makeStyles({ containerWrapper: { @@ -83,7 +81,7 @@ interface TemplateEditorFormProps { contentIsSpec?: boolean; setErrorText: (errorText?: string) => void; onDryRun?: (data: JsonObject) => Promise; - fieldExtensions?: NextFieldExtensionOptions[]; + fieldExtensions?: FieldExtensionOptions[]; layouts?: LayoutOptions[]; } diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorIntro.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorIntro.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx index 9863e99c73..aab693e590 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx @@ -22,9 +22,11 @@ import { import { CustomFieldExplorer } from './CustomFieldExplorer'; import { TemplateEditor } from './TemplateEditor'; import { TemplateFormPreviewer } from './TemplateFormPreviewer'; -import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; -import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; -import { TemplateEditorIntro } from '../../components/TemplateEditorPage/TemplateEditorIntro'; +import { + FieldExtensionOptions, + type LayoutOptions, +} from '@backstage/plugin-scaffolder-react'; +import { TemplateEditorIntro } from './TemplateEditorIntro'; type Selection = | { @@ -40,7 +42,7 @@ type Selection = interface TemplateEditorPageProps { defaultPreviewTemplate?: string; - customFieldExtensions?: NextFieldExtensionOptions[]; + customFieldExtensions?: FieldExtensionOptions[]; layouts?: LayoutOptions[]; } diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorTextArea.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorTextArea.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx index 75d8c511b1..c253bc0a5f 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -32,10 +32,12 @@ import CloseIcon from '@material-ui/icons/Close'; import React, { useCallback, useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import yaml from 'yaml'; -import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; -import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; +import { + LayoutOptions, + FieldExtensionOptions, +} from '@backstage/plugin-scaffolder-react'; import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea'; +import { TemplateEditorTextArea } from './TemplateEditorTextArea'; const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI parameters: @@ -114,7 +116,7 @@ export const TemplateFormPreviewer = ({ layouts = [], }: { defaultPreviewTemplate?: string; - customFieldExtensions?: NextFieldExtensionOptions[]; + customFieldExtensions?: FieldExtensionOptions[]; onClose?: () => void; layouts?: LayoutOptions[]; }) => { diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index 863d3009e1..44390bc03c 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -38,7 +38,6 @@ import { import { ScaffolderPageContextMenu, TemplateCategoryPicker, - TemplateGroupFilter, TemplateGroups, } from '@backstage/plugin-scaffolder-react/alpha'; @@ -52,6 +51,7 @@ import { viewTechDocRouteRef, } from '../../routes'; import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; /** * @alpha diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index a7133ae8c7..464e23a201 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -26,12 +26,10 @@ import { scaffolderApiRef, useTemplateSecrets, type LayoutOptions, + FieldExtensionOptions, + ReviewStepProps, } from '@backstage/plugin-scaffolder-react'; -import { - FormProps, - Workflow, - NextFieldExtensionOptions, -} from '@backstage/plugin-scaffolder-react/alpha'; +import { FormProps, Workflow } from '@backstage/plugin-scaffolder-react/alpha'; import { JsonValue } from '@backstage/types'; import { Header, Page } from '@backstage/core-components'; @@ -45,9 +43,12 @@ import { * @alpha */ export type TemplateWizardPageProps = { - customFieldExtensions: NextFieldExtensionOptions[]; + customFieldExtensions: FieldExtensionOptions[]; + components?: { + ReviewStepComponent?: React.ComponentType; + }; layouts?: LayoutOptions[]; - FormProps?: FormProps; + formProps?: FormProps; }; export const TemplateWizardPage = (props: TemplateWizardPageProps) => { @@ -90,9 +91,10 @@ export const TemplateWizardPage = (props: TemplateWizardPageProps) => { namespace={namespace} templateName={templateName} onCreate={onCreate} + components={props.components} onError={onError} extensions={props.customFieldExtensions} - FormProps={props.FormProps} + formProps={props.formProps} layouts={props.layouts} /> diff --git a/plugins/scaffolder/src/next/index.ts b/plugins/scaffolder/src/next/index.ts index 6cef3eaa03..2ae1b7b6c7 100644 --- a/plugins/scaffolder/src/next/index.ts +++ b/plugins/scaffolder/src/next/index.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './Router'; export * from './TemplateListPage'; export * from './TemplateWizardPage'; export * from './types'; diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index ad9e70d843..fdde81695d 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -217,10 +217,10 @@ export const EntityTagsPickerFieldExtension = scaffolderPlugin.provide( * @alpha * The Router and main entrypoint to the Alpha Scaffolder plugin. */ -export const NextScaffolderPage = scaffolderPlugin.provide( +export const LegacyScaffolderPage = scaffolderPlugin.provide( createRoutableExtension({ - name: 'NextScaffolderPage', - component: () => import('./next/Router').then(m => m.Router), + name: 'LegacyScaffolderPage', + component: () => import('./legacy/Router').then(m => m.LegacyRouter), mountPoint: rootRouteRef, }), ); From f0e021aeddbb4e08c095b8b0a2178aa584b3d14d Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 28 Sep 2023 13:50:23 +0200 Subject: [PATCH 070/348] chore: fixing some more work Signed-off-by: blam --- packages/app/src/App.tsx | 12 +- .../scaffolder/customScaffolderExtensions.tsx | 8 +- plugins/scaffolder-react/src/alpha.ts | 2 - .../src/next/components/Form/Form.tsx | 5 +- .../next/components/Stepper/Stepper.test.tsx | 8 +- .../Stepper/createAsyncValidators.test.ts | 24 +- .../Stepper/createAsyncValidators.ts | 12 +- plugins/scaffolder-react/src/next/index.ts | 1 - plugins/scaffolder/dev/index.tsx | 10 +- .../fields/EntityPicker/EntityPicker.test.tsx | 6 +- .../MyGroupsPicker/MyGroupsPicker.test.tsx | 6 +- .../fields/OwnerPicker/OwnerPicker.test.tsx | 4 +- .../RepoUrlPicker/RepoUrlPicker.test.tsx | 2 +- .../CustomFieldExplorer.tsx | 195 +++++++++++++++ .../TemplateEditorPage/TemplateEditor.tsx | 92 +++++++ .../TemplateEditorPage/TemplateEditorForm.tsx | 236 ++++++++++++++++++ .../TemplateEditorPage/TemplateEditorPage.tsx | 6 +- .../TemplateFormPreviewer.tsx | 217 ++++++++++++++++ plugins/scaffolder/src/legacy/index.ts | 1 + .../TemplateEditorBrowser.tsx | 2 +- .../TemplateWizardPage/TemplateWizardPage.tsx | 3 +- 21 files changed, 792 insertions(+), 60 deletions(-) create mode 100644 plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx create mode 100644 plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditor.tsx create mode 100644 plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx create mode 100644 plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index f2b7d66b21..cc3787a8bc 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -64,7 +64,7 @@ import { GcpProjectsPage } from '@backstage/plugin-gcp-projects'; import { HomepageCompositionRoot, VisitListener } from '@backstage/plugin-home'; import { LighthousePage } from '@backstage/plugin-lighthouse'; import { NewRelicPage } from '@backstage/plugin-newrelic'; -import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha'; +import { LegacyScaffolderPage } from '@backstage/plugin-scaffolder/alpha'; import { ScaffolderPage, scaffolderPlugin } from '@backstage/plugin-scaffolder'; import { ScaffolderFieldExtensions, @@ -236,11 +236,11 @@ const routes = ( - + - + - + - + diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index b15d12979a..e236e01d79 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -17,10 +17,6 @@ import React from 'react'; import type { FieldValidation } from '@rjsf/utils'; import { scaffolderPlugin } from '@backstage/plugin-scaffolder'; import { TextField } from '@material-ui/core'; -import { - NextFieldExtensionComponentProps, - createNextScaffolderFieldExtension, -} from '@backstage/plugin-scaffolder-react/alpha'; import { createScaffolderFieldExtension, FieldExtensionComponentProps, @@ -67,7 +63,7 @@ export const LowerCaseValuePickerFieldExtension = scaffolderPlugin.provide( ); const MockDelayComponent = ( - props: NextFieldExtensionComponentProps<{ test?: string }>, + props: FieldExtensionComponentProps<{ test?: string }>, ) => { const { onChange, formData, rawErrors = [] } = props; return ( @@ -83,7 +79,7 @@ const MockDelayComponent = ( }; export const DelayingComponentFieldExtension = scaffolderPlugin.provide( - createNextScaffolderFieldExtension({ + createScaffolderFieldExtension({ name: 'DelayingComponent', component: MockDelayComponent, validation: async ( diff --git a/plugins/scaffolder-react/src/alpha.ts b/plugins/scaffolder-react/src/alpha.ts index f60ced6b35..224ee97c06 100644 --- a/plugins/scaffolder-react/src/alpha.ts +++ b/plugins/scaffolder-react/src/alpha.ts @@ -15,6 +15,4 @@ */ export * from './next'; -export type { FormProps } from './next'; - export * from './legacy'; diff --git a/plugins/scaffolder-react/src/next/components/Form/Form.tsx b/plugins/scaffolder-react/src/next/components/Form/Form.tsx index adfb8db930..ec644333b9 100644 --- a/plugins/scaffolder-react/src/next/components/Form/Form.tsx +++ b/plugins/scaffolder-react/src/next/components/Form/Form.tsx @@ -14,12 +14,13 @@ * limitations under the License. */ -import { FormProps, withTheme } from '@rjsf/core-v5'; +import { withTheme } from '@rjsf/core-v5'; import React from 'react'; import { PropsWithChildren } from 'react'; import { FieldTemplate } from './FieldTemplate'; import { DescriptionFieldTemplate } from './DescriptionFieldTemplate'; import { FieldProps } from '@rjsf/utils'; +import { ScaffolderRJSFFormProps } from '../../../extensions'; // TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly // which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because @@ -30,7 +31,7 @@ const WrappedForm = withTheme(require('@rjsf/material-ui-v5').Theme); * The Form component * @alpha */ -export const Form = (props: PropsWithChildren) => { +export const Form = (props: PropsWithChildren) => { // This is where we unbreak the changes from RJSF, and make it work with our custom fields so we don't pass on this // breaking change to our users. We will look more into a better API for this in scaffolderv2. const wrappedFields = Object.fromEntries( diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx index 2dd3825cea..24126152ed 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx @@ -20,7 +20,7 @@ import { renderInTestApp } from '@backstage/test-utils'; import { act, fireEvent } from '@testing-library/react'; import type { RJSFValidationError } from '@rjsf/utils'; import { JsonValue } from '@backstage/types'; -import { NextFieldExtensionComponentProps } from '../../../extensions'; +import { FieldExtensionComponentProps } from '../../../extensions'; import { LayoutTemplate } from '../../../layouts'; describe('Stepper', () => { @@ -115,7 +115,7 @@ describe('Stepper', () => { it('should merge nested formData correctly in multiple steps', async () => { const Repo = ({ onChange, - }: NextFieldExtensionComponentProps<{ repository: string }, any>) => ( + }: FieldExtensionComponentProps<{ repository: string }, any>) => ( { const Owner = ({ onChange, - }: NextFieldExtensionComponentProps<{ owner: string }, any>) => ( + }: FieldExtensionComponentProps<{ owner: string }, any>) => ( { manifest={manifest} extensions={[]} onCreate={jest.fn()} - FormProps={{ transformErrors }} + formProps={{ transformErrors }} />, ); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index 65e7a5b4fd..f4dab376bc 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { JsonObject } from '@backstage/types'; -import { NextCustomFieldValidator } from '../../../extensions'; +import { CustomFieldValidator } from '../../../extensions'; import { createAsyncValidators } from './createAsyncValidators'; describe('createAsyncValidators', () => { @@ -158,16 +158,13 @@ describe('createAsyncValidators', () => { }, }; - const NameField: NextCustomFieldValidator = ( - value, - { addError }, - ) => { + const NameField: CustomFieldValidator = (value, { addError }) => { if (!value) { addError('something is broken here!'); } }; - const AddressField: NextCustomFieldValidator<{ + const AddressField: CustomFieldValidator<{ street?: string; postcode?: string; }> = (value, { addError }) => { @@ -183,8 +180,8 @@ describe('createAsyncValidators', () => { const validate = createAsyncValidators( schema, { - NameField: NameField as NextCustomFieldValidator, - AddressField: AddressField as NextCustomFieldValidator, + NameField: NameField as CustomFieldValidator, + AddressField: AddressField as CustomFieldValidator, }, { apiHolder: { get: jest.fn() }, @@ -298,7 +295,7 @@ describe('createAsyncValidators', () => { }, }; - const AddressField: NextCustomFieldValidator<{ + const AddressField: CustomFieldValidator<{ street?: string; postcode?: string; }> = (value, { addError }) => { @@ -311,18 +308,15 @@ describe('createAsyncValidators', () => { } }; - const NameField: NextCustomFieldValidator = ( - value, - { addError }, - ) => { + const NameField: CustomFieldValidator = (value, { addError }) => { if (!value) { addError('something is broken here!'); } }; const validators = { - AddressField: AddressField as NextCustomFieldValidator, - NameField: NameField as NextCustomFieldValidator, + AddressField: AddressField as CustomFieldValidator, + NameField: NameField as CustomFieldValidator, }; const validate = createAsyncValidators(schema, validators, { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 5531ff26b4..a606f01d6b 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -19,9 +19,11 @@ import type { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { createFieldValidation, extractSchemaFromStep } from '../../lib'; -import { NextCustomFieldValidator } from '../../../extensions'; +import { + CustomFieldValidator, + FieldExtensionUiSchema, +} from '../../../extensions'; import { isObject } from './utils'; -import { NextFieldExtensionUiSchema } from '../../extensions/types'; /** * @internal @@ -34,7 +36,7 @@ export const createAsyncValidators = ( rootSchema: JsonObject, validators: Record< string, - undefined | NextCustomFieldValidator + undefined | CustomFieldValidator >, context: { apiHolder: ApiHolder; @@ -53,7 +55,7 @@ export const createAsyncValidators = ( key: string, value: JsonValue | undefined, schema: JsonObject, - uiSchema: NextFieldExtensionUiSchema, + uiSchema: FieldExtensionUiSchema, ) => { const validator = validators[validatorName]; if (validator) { @@ -82,7 +84,7 @@ export const createAsyncValidators = ( const doValidateItem = async ( propValue: JsonObject, itemSchema: JsonObject, - itemUiSchema: NextFieldExtensionUiSchema, + itemUiSchema: FieldExtensionUiSchema, ) => { await validateForm( propValue['ui:field'] as string, diff --git a/plugins/scaffolder-react/src/next/index.ts b/plugins/scaffolder-react/src/next/index.ts index 5e4c9f91c1..f13bb76d7a 100644 --- a/plugins/scaffolder-react/src/next/index.ts +++ b/plugins/scaffolder-react/src/next/index.ts @@ -14,6 +14,5 @@ * limitations under the License. */ export * from './components'; -export * from './types'; export * from './lib'; export * from './hooks'; diff --git a/plugins/scaffolder/dev/index.tsx b/plugins/scaffolder/dev/index.tsx index 68c59eec2d..b683345ff5 100644 --- a/plugins/scaffolder/dev/index.tsx +++ b/plugins/scaffolder/dev/index.tsx @@ -24,7 +24,7 @@ import { } from '@backstage/plugin-catalog-react'; import React from 'react'; import { scaffolderApiRef, ScaffolderClient } from '../src'; -import { NextScaffolderPage, ScaffolderPage } from '../src/plugin'; +import { ScaffolderPage, LegacyScaffolderPage } from '../src/plugin'; import { discoveryApiRef, fetchApiRef, @@ -69,9 +69,9 @@ createDevApp() element: , }) .addPage({ - path: '/next-create', + path: '/legacy-create', title: 'Create (next)', - element: , + element: , }) .addPage({ path: '/create-groups', @@ -92,10 +92,10 @@ createDevApp() ), }) .addPage({ - path: '/next-create-groups', + path: '/legacy-create-groups', title: 'Groups (next)', element: ( - e.metadata.tags?.includes('techdocs') || false, diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index 300e23ee89..4329b2208b 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -23,7 +23,7 @@ import { fireEvent, screen } from '@testing-library/react'; import React from 'react'; import { EntityPicker } from './EntityPicker'; import { EntityPickerProps } from './schema'; -import { FieldProps } from '@rjsf/utils'; +import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react'; const makeEntity = (kind: string, namespace: string, name: string): Entity => ({ apiVersion: 'scaffolder.backstage.io/v1beta3', @@ -40,7 +40,7 @@ describe('', () => { const rawErrors: string[] = []; const formData = undefined; - let props: FieldProps; + let props: FieldProps; const catalogApi: jest.Mocked = { getLocationById: jest.fn(), @@ -77,7 +77,7 @@ describe('', () => { uiSchema, rawErrors, formData, - } as unknown as FieldProps; + } as unknown as FieldProps; catalogApi.getEntities.mockResolvedValue({ items: entities }); }); diff --git a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx index 099d6fa6ed..be59d4d1cf 100644 --- a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx @@ -17,7 +17,6 @@ import React from 'react'; import { render, waitFor } from '@testing-library/react'; import { CatalogApi } from '@backstage/catalog-client'; -import { FieldProps } from '@rjsf/core'; import { MyGroupsPicker } from './MyGroupsPicker'; import { TestApiProvider } from '@backstage/test-utils'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; @@ -29,6 +28,7 @@ import { identityApiRef, } from '@backstage/core-plugin-api'; import userEvent from '@testing-library/user-event'; +import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react'; // Create a mock IdentityApi const mockIdentityApi: IdentityApi = { @@ -109,7 +109,7 @@ describe('', () => { onChange, schema, required, - } as unknown as FieldProps; + } as unknown as FieldProps; render( ', () => { onChange, schema, required, - } as unknown as FieldProps; + } as unknown as FieldProps; const { queryByText, getByRole } = render( ', () => { const rawErrors: string[] = []; const formData = undefined; - let props: FieldProps; + let props: FieldProps; const catalogApi: jest.Mocked = { getLocationById: jest.fn(), diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index 4b44a4fa3e..e9c52907f9 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; import { RepoUrlPicker } from './RepoUrlPicker'; -import Form from '@rjsf/core'; +import { Form } from '@backstage/plu'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { scmIntegrationsApiRef, diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx new file mode 100644 index 0000000000..c790dbd72c --- /dev/null +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx @@ -0,0 +1,195 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { StreamLanguage } from '@codemirror/language'; +import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; +import { + Button, + Card, + CardContent, + CardHeader, + FormControl, + IconButton, + InputLabel, + makeStyles, + MenuItem, + Select, +} from '@material-ui/core'; +import CloseIcon from '@material-ui/icons/Close'; +import CodeMirror from '@uiw/react-codemirror'; +import React, { useCallback, useMemo, useState } from 'react'; +import yaml from 'yaml'; +import { Form } from '@backstage/plugin-scaffolder-react/alpha'; +import { TemplateEditorForm } from './TemplateEditorForm'; +import validator from '@rjsf/validator-ajv8'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; + +const useStyles = makeStyles(theme => ({ + root: { + gridArea: 'pageContent', + display: 'grid', + gridTemplateAreas: ` + "controls controls" + "fieldForm preview" + `, + gridTemplateRows: 'auto 1fr', + gridTemplateColumns: '1fr 1fr', + }, + controls: { + gridArea: 'controls', + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + margin: theme.spacing(1), + }, + fieldForm: { + gridArea: 'fieldForm', + }, + preview: { + gridArea: 'preview', + }, +})); + +export const CustomFieldExplorer = ({ + customFieldExtensions = [], + onClose, +}: { + customFieldExtensions?: LegacyFieldExtensionOptions[]; + onClose?: () => void; +}) => { + const classes = useStyles(); + const fieldOptions = customFieldExtensions.filter(field => !!field.schema); + const [selectedField, setSelectedField] = useState(fieldOptions[0]); + const [fieldFormState, setFieldFormState] = useState({}); + const [refreshKey, setRefreshKey] = useState(Date.now()); + const sampleFieldTemplate = useMemo( + () => + yaml.stringify({ + parameters: [ + { + title: `${selectedField.name} Example`, + properties: { + [selectedField.name]: { + type: selectedField.schema?.returnValue?.type, + 'ui:field': selectedField.name, + 'ui:options': fieldFormState, + }, + }, + }, + ], + }), + [fieldFormState, selectedField], + ); + + const fieldComponents = useMemo(() => { + return Object.fromEntries( + customFieldExtensions.map(({ name, component }) => [name, component]), + ); + }, [customFieldExtensions]); + + const handleSelectionChange = useCallback( + selection => { + setSelectedField(selection); + setFieldFormState({}); + }, + [setFieldFormState, setSelectedField], + ); + + const handleFieldConfigChange = useCallback( + state => { + setFieldFormState(state); + // Force TemplateEditorForm to re-render since some fields + // may not be responsive to ui:option changes + setRefreshKey(Date.now()); + }, + [setFieldFormState, setRefreshKey], + ); + + return ( +
+
+ + + Choose Custom Field Extension + + + + + + + +
+
+ + + + handleFieldConfigChange(e.formData)} + validator={validator} + schema={selectedField.schema?.uiOptions || {}} + > + + + + +
+
+ + + + + + + null} + /> +
+
+ ); +}; diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditor.tsx new file mode 100644 index 0000000000..f6e7b38d7d --- /dev/null +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditor.tsx @@ -0,0 +1,92 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { makeStyles } from '@material-ui/core'; +import React, { useState } from 'react'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; +import { TemplateDirectoryAccess } from '../../lib/filesystem'; +import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { DirectoryEditorProvider } from '../../next/TemplateEditorPage/DirectoryEditorContext'; +import { DryRunProvider } from '../../next/TemplateEditorPage/DryRunContext'; +import { TemplateEditorBrowser } from '../../next/TemplateEditorPage/TemplateEditorBrowser'; +import { TemplateEditorTextArea } from '../../next/TemplateEditorPage/TemplateEditorTextArea'; +import { TemplateEditorForm } from './TemplateEditorForm'; +import { DryRunResults } from '../../next/TemplateEditorPage/DryRunResults'; + +const useStyles = makeStyles({ + // Reset and fix sizing to make sure scrolling behaves correctly + root: { + gridArea: 'pageContent', + + display: 'grid', + gridTemplateAreas: ` + "browser editor preview" + "results results results" + `, + gridTemplateColumns: '1fr 3fr 2fr', + gridTemplateRows: '1fr auto', + }, + browser: { + gridArea: 'browser', + overflow: 'auto', + }, + editor: { + gridArea: 'editor', + overflow: 'auto', + }, + preview: { + gridArea: 'preview', + overflow: 'auto', + }, + results: { + gridArea: 'results', + }, +}); + +export const TemplateEditor = (props: { + directory: TemplateDirectoryAccess; + fieldExtensions?: LegacyFieldExtensionOptions[]; + layouts?: LayoutOptions[]; + onClose?: () => void; +}) => { + const classes = useStyles(); + + const [errorText, setErrorText] = useState(); + + return ( + + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ ); +}; diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx new file mode 100644 index 0000000000..80121c40db --- /dev/null +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx @@ -0,0 +1,236 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { useApiHolder } from '@backstage/core-plugin-api'; +import { JsonObject, JsonValue } from '@backstage/types'; +import { makeStyles } from '@material-ui/core/styles'; +import React, { Component, ReactNode, useState } from 'react'; +import useDebounce from 'react-use/lib/useDebounce'; +import yaml from 'yaml'; +import { + FieldExtensionOptions, + LayoutOptions, + TemplateParameterSchema, +} from '@backstage/plugin-scaffolder-react'; +import { + Stepper, + LegacyFieldExtensionOptions, +} from '@backstage/plugin-scaffolder-react/alpha'; +import { useDryRun } from '../../next/TemplateEditorPage/DryRunContext'; +import { useDirectoryEditor } from '../../next/TemplateEditorPage/DirectoryEditorContext'; + +const useStyles = makeStyles({ + containerWrapper: { + position: 'relative', + width: '100%', + height: '100%', + }, + container: { + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + overflow: 'auto', + }, +}); + +interface ErrorBoundaryProps { + invalidator: unknown; + setErrorText(errorText: string | undefined): void; + children: ReactNode; +} + +interface ErrorBoundaryState { + shouldRender: boolean; +} + +class ErrorBoundary extends Component { + state = { + shouldRender: true, + }; + + componentDidUpdate(prevProps: { invalidator: unknown }) { + if (prevProps.invalidator !== this.props.invalidator) { + this.setState({ shouldRender: true }); + } + } + + componentDidCatch(error: Error) { + this.props.setErrorText(error.message); + this.setState({ shouldRender: false }); + } + + render() { + return this.state.shouldRender ? this.props.children : null; + } +} + +interface TemplateEditorFormProps { + content?: string; + /** Setting this to true will cause the content to be parsed as if it is the template entity spec */ + contentIsSpec?: boolean; + setErrorText: (errorText?: string) => void; + onDryRun?: (data: JsonObject) => Promise; + fieldExtensions?: LegacyFieldExtensionOptions[]; + layouts?: LayoutOptions[]; +} + +function isJsonObject(value: JsonValue | undefined): value is JsonObject { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +/** Shows the a template form that is parsed from the provided content */ +export function TemplateEditorForm(props: TemplateEditorFormProps) { + const { + content, + contentIsSpec, + onDryRun, + setErrorText, + fieldExtensions = [], + layouts = [], + } = props; + const classes = useStyles(); + const apiHolder = useApiHolder(); + + const [steps, setSteps] = useState(); + + useDebounce( + () => { + try { + if (!content) { + setSteps(undefined); + return; + } + const parsed: JsonValue = yaml.parse(content); + + if (!isJsonObject(parsed)) { + setSteps(undefined); + return; + } + + let rootObj = parsed; + if (!contentIsSpec) { + const isTemplate = + String(parsed.kind).toLocaleLowerCase('en-US') === 'template'; + if (!isTemplate) { + setSteps(undefined); + return; + } + + rootObj = isJsonObject(parsed.spec) ? parsed.spec : {}; + } + + const { parameters } = rootObj; + + if (!Array.isArray(parameters)) { + setErrorText('Template parameters must be an array'); + setSteps(undefined); + return; + } + + setErrorText(); + setSteps( + parameters.flatMap(param => + isJsonObject(param) + ? [ + { + title: String(param.title), + schema: param, + }, + ] + : [], + ), + ); + } catch (e) { + setErrorText(e.message); + } + }, + 250, + [contentIsSpec, content, apiHolder], + ); + + if (!steps) { + return null; + } + + return ( +
+
+ + { + await onDryRun?.(data); + }} + layouts={layouts} + components={{ createButtonText: onDryRun && 'Try It' }} + /> + +
+
+ ); +} + +/** A version of the TemplateEditorForm that is connected to the DirectoryEditor and DryRun contexts */ +export function TemplateEditorFormDirectoryEditorDryRun( + props: Pick< + TemplateEditorFormProps, + 'setErrorText' | 'fieldExtensions' | 'layouts' + >, +) { + const { setErrorText, fieldExtensions = [], layouts } = props; + const dryRun = useDryRun(); + + const directoryEditor = useDirectoryEditor(); + const { selectedFile } = directoryEditor; + + const handleDryRun = async (values: JsonObject) => { + if (!selectedFile) { + return; + } + + try { + await dryRun.execute({ + templateContent: selectedFile.content, + values, + files: directoryEditor.files, + }); + setErrorText(); + } catch (e) { + setErrorText(String(e.cause || e)); + throw e; + } + }; + + const content = + selectedFile && selectedFile.path.match(/\.ya?ml$/) + ? selectedFile.content + : undefined; + + return ( + + ); +} + +TemplateEditorForm.DirectoryEditorDryRun = + TemplateEditorFormDirectoryEditorDryRun; diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx index e65869ad0e..127c73dcf5 100644 --- a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx @@ -21,10 +21,10 @@ import { } from '../../lib/filesystem'; import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; -import { CustomFieldExplorer } from '../../next/TemplateEditorPage/CustomFieldExplorer'; -import { TemplateFormPreviewer } from '../../next/TemplateEditorPage/TemplateFormPreviewer'; -import { TemplateEditor } from '../../next/TemplateEditorPage/TemplateEditor'; import { TemplateEditorIntro } from '../../next/TemplateEditorPage/TemplateEditorIntro'; +import { TemplateEditor } from './TemplateEditor'; +import { TemplateFormPreviewer } from './TemplateFormPreviewer'; +import { CustomFieldExplorer } from './CustomFieldExplorer'; type Selection = | { diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx new file mode 100644 index 0000000000..21df43cf8c --- /dev/null +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -0,0 +1,217 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Entity } from '@backstage/catalog-model'; +import { alertApiRef, useApi } from '@backstage/core-plugin-api'; +import { + catalogApiRef, + humanizeEntityRef, +} from '@backstage/plugin-catalog-react'; +import { + FormControl, + IconButton, + InputLabel, + LinearProgress, + makeStyles, + MenuItem, + Select, +} from '@material-ui/core'; +import CloseIcon from '@material-ui/icons/Close'; +import React, { useCallback, useState } from 'react'; +import useAsync from 'react-use/lib/useAsync'; +import yaml from 'yaml'; +import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; +import { TemplateEditorTextArea } from '../../next/TemplateEditorPage/TemplateEditorTextArea'; +import { TemplateEditorForm } from './TemplateEditorForm'; + +const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI +parameters: + - title: Fill in some steps + required: + - name + properties: + name: + title: Name + type: string + description: Unique name of the component + owner: + title: Owner + type: string + description: Owner of the component + ui:field: OwnerPicker + ui:options: + catalogFilter: + kind: Group + - title: Choose a location + required: + - repoUrl + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + allowedHosts: + - github.com +steps: + - id: fetch-base + name: Fetch Base + action: fetch:template + input: + url: ./template + values: + name: \${{parameters.name}} +`; + +type TemplateOption = { + label: string; + value: Entity; +}; + +const useStyles = makeStyles(theme => ({ + root: { + gridArea: 'pageContent', + display: 'grid', + gridTemplateAreas: ` + "controls controls" + "textArea preview" + `, + gridTemplateRows: 'auto 1fr', + gridTemplateColumns: '1fr 1fr', + }, + controls: { + gridArea: 'controls', + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + margin: theme.spacing(1), + }, + textArea: { + gridArea: 'textArea', + }, + preview: { + gridArea: 'preview', + }, +})); + +export const TemplateFormPreviewer = ({ + defaultPreviewTemplate = EXAMPLE_TEMPLATE_PARAMS_YAML, + customFieldExtensions = [], + onClose, + layouts = [], +}: { + defaultPreviewTemplate?: string; + customFieldExtensions?: LegacyFieldExtensionOptions[]; + onClose?: () => void; + layouts?: LayoutOptions[]; +}) => { + const classes = useStyles(); + const alertApi = useApi(alertApiRef); + const catalogApi = useApi(catalogApiRef); + const [selectedTemplate, setSelectedTemplate] = useState(''); + const [errorText, setErrorText] = useState(); + const [templateOptions, setTemplateOptions] = useState([]); + const [templateYaml, setTemplateYaml] = useState(defaultPreviewTemplate); + + const { loading } = useAsync( + () => + catalogApi + .getEntities({ + filter: { kind: 'template' }, + fields: [ + 'kind', + 'metadata.namespace', + 'metadata.name', + 'metadata.title', + 'spec.parameters', + 'spec.steps', + 'spec.output', + ], + }) + .then(({ items }) => + setTemplateOptions( + items.map(template => ({ + label: + template.metadata.title ?? + humanizeEntityRef(template, { defaultKind: 'template' }), + value: template, + })), + ), + ) + .catch(e => + alertApi.post({ + message: `Error loading exisiting templates: ${e.message}`, + severity: 'error', + }), + ), + [catalogApi], + ); + + const handleSelectChange = useCallback( + selected => { + setSelectedTemplate(selected); + setTemplateYaml(yaml.stringify(selected.spec)); + }, + [setTemplateYaml], + ); + + return ( + <> + {loading && } +
+
+ + + Load Existing Template + + + + + + + +
+
+ +
+
+ +
+
+ + ); +}; diff --git a/plugins/scaffolder/src/legacy/index.ts b/plugins/scaffolder/src/legacy/index.ts index 83b5717fbe..2393be0f69 100644 --- a/plugins/scaffolder/src/legacy/index.ts +++ b/plugins/scaffolder/src/legacy/index.ts @@ -14,3 +14,4 @@ * limitations under the License. */ export { LegacyRouter, type LegacyRouterProps } from './Router'; +export { LegacyScaffolderPage } from '../plugin'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx index 177ad11c2b..996da98d4a 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx @@ -18,8 +18,8 @@ import CloseIcon from '@material-ui/icons/Close'; import RefreshIcon from '@material-ui/icons/Refresh'; import SaveIcon from '@material-ui/icons/Save'; import React from 'react'; -import { FileBrowser } from '../FileBrowser'; import { useDirectoryEditor } from './DirectoryEditorContext'; +import { FileBrowser } from '../../components/FileBrowser'; const useStyles = makeStyles(theme => ({ button: { diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index 464e23a201..3b14f2c07f 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -26,10 +26,11 @@ import { scaffolderApiRef, useTemplateSecrets, type LayoutOptions, + FormProps, FieldExtensionOptions, ReviewStepProps, } from '@backstage/plugin-scaffolder-react'; -import { FormProps, Workflow } from '@backstage/plugin-scaffolder-react/alpha'; +import { Workflow } from '@backstage/plugin-scaffolder-react/alpha'; import { JsonValue } from '@backstage/types'; import { Header, Page } from '@backstage/core-components'; From 660db1f39a16302a9ff16bbc8a09528d6ba7ac59 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 28 Sep 2023 13:59:54 +0200 Subject: [PATCH 071/348] chore: completeing props Signed-off-by: blam --- .../src/components/Router/Router.tsx | 6 ++++ .../MyGroupsPicker/MyGroupsPicker.test.tsx | 2 +- .../RepoUrlPicker/RepoUrlPicker.test.tsx | 30 +++++++++++++++---- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/plugins/scaffolder/src/components/Router/Router.tsx b/plugins/scaffolder/src/components/Router/Router.tsx index ad72170bba..83c26c9130 100644 --- a/plugins/scaffolder/src/components/Router/Router.tsx +++ b/plugins/scaffolder/src/components/Router/Router.tsx @@ -73,6 +73,12 @@ export type RouterProps = { }; groups?: TemplateGroupFilter[]; templateFilter?: (entity: TemplateEntityV1beta3) => boolean; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; + defaultPreviewTemplate?: string; formProps?: FormProps; contextMenu?: { /** Whether to show a link to the template editor */ diff --git a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx index be59d4d1cf..521c4029b3 100644 --- a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx @@ -238,7 +238,7 @@ describe('', () => { onChange, schema, required, - } as unknown as FieldProps; + } as unknown as FieldProps; const { getByRole } = render( { >
as ScaffolderRJSFField, + }} onSubmit={onSubmit} /> @@ -109,12 +115,15 @@ describe('RepoUrlPicker', () => { > , + }} /> , @@ -144,6 +153,7 @@ describe('RepoUrlPicker', () => { > { }, }, }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField, + }} /> @@ -206,6 +218,7 @@ describe('RepoUrlPicker', () => { > { }, }, }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField, + }} /> @@ -259,6 +274,7 @@ describe('RepoUrlPicker', () => { > { }, }, }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField, + }} /> From 91642181e79f31201174846600b6d0f03ff6c3c8 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 28 Sep 2023 14:03:45 +0200 Subject: [PATCH 072/348] feat: started some API report tweaks Signed-off-by: blam --- plugins/scaffolder-react/alpha-api-report.md | 108 +++++----- plugins/scaffolder-react/api-report.md | 197 ++++++++++++++++-- .../src/components/ReviewStep.tsx | 15 -- 3 files changed, 242 insertions(+), 78 deletions(-) delete mode 100644 plugins/scaffolder-react/src/components/ReviewStep.tsx diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index 11bb2c10c4..89ba75e8ef 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -6,39 +6,63 @@ /// import { ApiHolder } from '@backstage/core-plugin-api'; -import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react'; +import { ComponentType } from 'react'; +import { CustomValidator } from '@rjsf/utils'; import { Dispatch } from 'react'; +import { ElementType } from 'react'; +import { ErrorSchema } from '@rjsf/utils'; +import { ErrorTransformer } from '@rjsf/utils'; +import { Experimental_DefaultFormStateBehavior } from '@rjsf/utils'; import { Extension } from '@backstage/core-plugin-api'; -import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; -import { FieldProps } from '@rjsf/utils'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; +import { FieldProps } from '@rjsf/core'; import { FieldValidation } from '@rjsf/utils'; -import { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { FieldValidation as FieldValidation_2 } from '@rjsf/core'; +import { default as Form_2 } from '@rjsf/core-v5'; +import { FormContextType } from '@rjsf/utils'; +import { FormEvent } from 'react'; +import { FormProps } from '@backstage/plugin-scaffolder-react'; +import { GenericObjectType } from '@rjsf/utils'; +import { HTMLAttributes } from 'react'; +import { IChangeEvent } from '@rjsf/core-v5'; import { IconComponent } from '@backstage/core-plugin-api'; +import { IdSchema } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; +import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; +import { Ref } from 'react'; +import { Registry } from '@rjsf/utils'; +import { RegistryWidgetsType } from '@rjsf/utils'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; +import { RJSFSchema } from '@rjsf/utils'; +import { RJSFValidationError } from '@rjsf/utils'; import { ScaffolderStep } from '@backstage/plugin-scaffolder-react'; import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; import { SetStateAction } from 'react'; +import { StrictRJSFSchema } from '@rjsf/utils'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; -import { UIOptionsType } from '@rjsf/utils'; +import { TemplatesType } from '@rjsf/utils'; import { UiSchema } from '@rjsf/utils'; +import { ValidatorType } from '@rjsf/utils'; // @alpha export const createFieldValidation: () => FieldValidation; +// Warning: (ae-forgotten-export) The symbol "FieldExtensionComponent" needs to be exported by the entry point alpha.d.ts +// // @alpha -export function createNextScaffolderFieldExtension< +export function createLegacyScaffolderFieldExtension< TReturnValue = unknown, - TInputProps extends UIOptionsType = {}, + TInputProps = unknown, >( - options: NextFieldExtensionOptions, + options: LegacyFieldExtensionOptions, ): Extension>; // @alpha @@ -55,61 +79,46 @@ export const extractSchemaFromStep: (inputStep: JsonObject) => { schema: JsonObject; }; +// Warning: (ae-forgotten-export) The symbol "ScaffolderRJSFFormProps" needs to be exported by the entry point alpha.d.ts +// // @alpha export const Form: ( - props: PropsWithChildren, + props: PropsWithChildren, ) => React_2.JSX.Element; // @alpha -export type FormProps = Pick< - FormProps_2, - 'transformErrors' | 'noHtml5Validate' ->; - -// @alpha -export type NextCustomFieldValidator< - TFieldReturnValue, - TUiOptions = unknown, -> = ( +export type LegacyCustomFieldValidator = ( data: TFieldReturnValue, - field: FieldValidation, + field: FieldValidation_2, context: { apiHolder: ApiHolder; - formData: JsonObject; - schema: JsonObject; - uiSchema?: NextFieldExtensionUiSchema; }, ) => void | Promise; // @alpha -export interface NextFieldExtensionComponentProps< +export interface LegacyFieldExtensionComponentProps< TFieldReturnValue, - TUiOptions = {}, -> extends PropsWithChildren> { + TUiOptions = unknown, +> extends FieldProps { // (undocumented) - uiSchema?: NextFieldExtensionUiSchema; + uiSchema: FieldProps['uiSchema'] & { + 'ui:options'?: TUiOptions; + }; } // @alpha -export type NextFieldExtensionOptions< +export type LegacyFieldExtensionOptions< TFieldReturnValue = unknown, - TUiOptions = unknown, + TInputProps = unknown, > = { name: string; component: ( - props: NextFieldExtensionComponentProps, + props: LegacyFieldExtensionComponentProps, ) => JSX.Element | null; - validation?: NextCustomFieldValidator; + validation?: LegacyCustomFieldValidator; schema?: CustomFieldExtensionSchema; }; -// @alpha -export interface NextFieldExtensionUiSchema - extends UiSchema { - // (undocumented) - 'ui:options'?: TUiOptions & UIOptionsType; -} - // @alpha export interface ParsedTemplateSchema { // (undocumented) @@ -176,12 +185,13 @@ export const Stepper: (stepperProps: StepperProps) => React_2.JSX.Element; // @alpha export type StepperProps = { manifest: TemplateParameterSchema; - extensions: NextFieldExtensionOptions[]; + extensions: FieldExtensionOptions[]; templateName?: string; - FormProps?: FormProps; + formProps?: FormProps; initialState?: Record; onCreate: (values: Record) => Promise; components?: { + ReviewStepComponent?: ComponentType; ReviewStateComponent?: (props: ReviewStateProps) => JSX.Element; createButtonText?: ReactNode; reviewButtonText?: ReactNode; @@ -236,12 +246,6 @@ export const TemplateGroup: ( props: TemplateGroupProps, ) => React_2.JSX.Element | null; -// @alpha (undocumented) -export type TemplateGroupFilter = { - title?: React_2.ReactNode; - filter: (entity: TemplateEntityV1beta3) => boolean; -}; - // @alpha export interface TemplateGroupProps { // (undocumented) @@ -276,6 +280,8 @@ export interface TemplateGroupsProps { text: string; url: string; }[]; + // Warning: (ae-forgotten-export) The symbol "TemplateGroupFilter" needs to be exported by the entry point alpha.d.ts + // // (undocumented) groups: TemplateGroupFilter[]; // (undocumented) @@ -314,16 +320,24 @@ export type WorkflowProps = { description?: string; namespace: string; templateName: string; + components?: { + ReviewStepComponent?: React_2.ComponentType; + }; onError(error: Error | undefined): JSX.Element | null; } & Pick< StepperProps, | 'extensions' - | 'FormProps' + | 'formProps' | 'components' | 'onCreate' | 'initialState' | 'layouts' >; +// Warnings were encountered during analysis: +// +// src/legacy/extensions/types.d.ts:23:5 - (ae-forgotten-export) The symbol "CustomFieldExtensionSchema" needs to be exported by the entry point alpha.d.ts +// src/next/components/Workflow/Workflow.d.ts:13:9 - (ae-forgotten-export) The symbol "ReviewStepProps_2" needs to be exported by the entry point alpha.d.ts + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index da95e6746e..057bb3a059 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -7,18 +7,42 @@ import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; +import { ComponentType } from 'react'; +import { CustomValidator } from '@rjsf/utils'; +import { ElementType } from 'react'; +import { ErrorSchema } from '@rjsf/utils'; +import { ErrorTransformer } from '@rjsf/utils'; +import { Experimental_DefaultFormStateBehavior } from '@rjsf/utils'; import { Extension } from '@backstage/core-plugin-api'; -import { FieldProps } from '@rjsf/core'; -import { FieldValidation } from '@rjsf/core'; -import type { FormProps } from '@rjsf/core-v5'; +import { FieldValidation } from '@rjsf/utils'; +import Form from '@rjsf/core-v5'; +import { FormContextType } from '@rjsf/utils'; +import { FormEvent } from 'react'; +import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { GenericObjectType } from '@rjsf/utils'; +import { HTMLAttributes } from 'react'; +import { IChangeEvent } from '@rjsf/core-v5'; +import { IdSchema } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; import { Observable } from '@backstage/types'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; +import { ReactNode } from 'react'; +import { Ref } from 'react'; +import { Registry } from '@rjsf/utils'; +import { RegistryWidgetsType } from '@rjsf/utils'; +import { RJSFSchema } from '@rjsf/utils'; +import { RJSFValidationError } from '@rjsf/utils'; +import { StrictRJSFSchema } from '@rjsf/utils'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; +import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TemplatesType } from '@rjsf/utils'; +import { UIOptionsType } from '@rjsf/utils'; +import { UiSchema } from '@rjsf/utils'; +import { ValidatorType } from '@rjsf/utils'; // @public export type Action = { @@ -40,7 +64,7 @@ export type ActionExample = { // @public export function createScaffolderFieldExtension< TReturnValue = unknown, - TInputProps = unknown, + TInputProps extends UIOptionsType = {}, >( options: FieldExtensionOptions, ): Extension>; @@ -57,11 +81,14 @@ export type CustomFieldExtensionSchema = { }; // @public -export type CustomFieldValidator = ( +export type CustomFieldValidator = ( data: TFieldReturnValue, field: FieldValidation, context: { apiHolder: ApiHolder; + formData: JsonObject; + schema: JsonObject; + uiSchema?: FieldExtensionUiSchema; }, ) => void | Promise; @@ -71,27 +98,38 @@ export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; // @public export interface FieldExtensionComponentProps< TFieldReturnValue, - TUiOptions = unknown, -> extends FieldProps { + TUiOptions = {}, +> extends PropsWithChildren> { // (undocumented) - uiSchema: FieldProps['uiSchema'] & { - 'ui:options'?: TUiOptions; - }; + uiSchema: FieldExtensionUiSchema; } // @public export type FieldExtensionOptions< TFieldReturnValue = unknown, - TInputProps = unknown, + TUiOptions = unknown, > = { name: string; component: ( - props: FieldExtensionComponentProps, + props: FieldExtensionComponentProps, ) => JSX.Element | null; - validation?: CustomFieldValidator; + validation?: CustomFieldValidator; schema?: CustomFieldExtensionSchema; }; +// @public +export interface FieldExtensionUiSchema + extends UiSchema { + // (undocumented) + 'ui:options'?: TUiOptions & UIOptionsType; +} + +// @public +export type FormProps = Pick< + FormProps_2, + 'transformErrors' | 'noHtml5Validate' +>; + // @public export type LayoutComponent<_TInputProps> = () => null; @@ -105,7 +143,7 @@ export interface LayoutOptions

{ // @public export type LayoutTemplate = NonNullable< - FormProps['uiSchema'] + FormProps_2['uiSchema'] >['ui:ObjectFieldTemplate']; // @public @@ -124,6 +162,20 @@ export type LogEvent = { taskId: string; }; +// @public +export type ReviewStepProps = { + disableButtons: boolean; + formData: JsonObject; + handleBack: () => void; + handleReset: () => void; + handleCreate: () => void; + steps: { + uiSchema: UiSchema; + mergedSchema: JsonObject; + schema: JsonObject; + }[]; +}; + // @public export interface ScaffolderApi { cancelTask(taskId: string): Promise; @@ -186,8 +238,8 @@ export interface ScaffolderDryRunResponse { } // @public -export const ScaffolderFieldExtensions: React_2.ComponentType< - React_2.PropsWithChildren<{}> +export const ScaffolderFieldExtensions: React.ComponentType< + React.PropsWithChildren<{}> >; // @public @@ -226,6 +278,113 @@ export type ScaffolderOutputText = { content?: string; }; +// @public +export type ScaffolderRJSFField< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = ComponentType>; + +// @public +export interface ScaffolderRJSFFieldProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> extends GenericObjectType, + Pick< + HTMLAttributes, + Exclude< + keyof HTMLAttributes, + 'onBlur' | 'onFocus' | 'onChange' + > + > { + autofocus?: boolean; + disabled: boolean; + errorSchema?: ErrorSchema; + formContext?: F; + formData: T; + hideError?: boolean; + idPrefix?: string; + idSchema: IdSchema; + idSeparator?: string; + name: string; + onBlur: (id: string, value: any) => void; + onChange: ( + newFormData: T | undefined, + es?: ErrorSchema, + id?: string, + ) => any; + onFocus: (id: string, value: any) => void; + rawErrors: string[]; + readonly: boolean; + registry: Registry; + required?: boolean; + schema: S; + uiSchema: UiSchema; +} + +// @public +export interface ScaffolderRJSFFormProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> { + acceptcharset?: string; + action?: string; + autoComplete?: string; + children?: ReactNode; + className?: string; + customValidate?: CustomValidator; + disabled?: boolean; + enctype?: string; + experimental_defaultFormStateBehavior?: Experimental_DefaultFormStateBehavior; + extraErrors?: ErrorSchema; + fields?: ScaffolderRJSFRegistryFieldsType; + focusOnFirstError?: boolean | ((error: RJSFValidationError) => void); + formContext?: F; + formData?: T; + id?: string; + idPrefix?: string; + idSeparator?: string; + _internalFormWrapper?: ElementType; + liveOmit?: boolean; + liveValidate?: boolean; + method?: string; + name?: string; + noHtml5Validate?: boolean; + // @deprecated + noValidate?: boolean; + omitExtraData?: boolean; + onBlur?: (id: string, data: any) => void; + onChange?: (data: IChangeEvent, id?: string) => void; + onError?: (errors: RJSFValidationError[]) => void; + onFocus?: (id: string, data: any) => void; + onSubmit?: (data: IChangeEvent, event: FormEvent) => void; + readonly?: boolean; + ref?: Ref>; + schema: S; + showErrorList?: false | 'top' | 'bottom'; + tagName?: ElementType; + target?: string; + templates?: Partial, 'ButtonTemplates'>> & { + ButtonTemplates?: Partial['ButtonTemplates']>; + }; + transformErrors?: ErrorTransformer; + translateString?: Registry['translateString']; + uiSchema?: UiSchema; + validator: ValidatorType; + widgets?: RegistryWidgetsType; +} + +// @public +export type ScaffolderRJSFRegistryFieldsType< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = { + [name: string]: ScaffolderRJSFField; +}; + // @public export interface ScaffolderScaffoldOptions { // (undocumented) @@ -313,6 +472,12 @@ export type TaskStream = { output?: ScaffolderTaskOutput; }; +// @public (undocumented) +export type TemplateGroupFilter = { + title?: React.ReactNode; + filter: (entity: TemplateEntityV1beta3) => boolean; +}; + // @public export type TemplateParameterSchema = { title: string; diff --git a/plugins/scaffolder-react/src/components/ReviewStep.tsx b/plugins/scaffolder-react/src/components/ReviewStep.tsx deleted file mode 100644 index eb2f165350..0000000000 --- a/plugins/scaffolder-react/src/components/ReviewStep.tsx +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2023 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. - */ From 03b0e226487808437050f2f2989431ea1107c8c2 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 2 Oct 2023 10:24:21 +0200 Subject: [PATCH 073/348] chore: woops Signed-off-by: blam --- .../TemplateEditorPage/TemplateEditorForm.tsx | 57 +++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx index 80121c40db..766581e311 100644 --- a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx @@ -16,20 +16,19 @@ import { useApiHolder } from '@backstage/core-plugin-api'; import { JsonObject, JsonValue } from '@backstage/types'; import { makeStyles } from '@material-ui/core/styles'; -import React, { Component, ReactNode, useState } from 'react'; +import React, { Component, ReactNode, useMemo, useState } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import yaml from 'yaml'; import { - FieldExtensionOptions, LayoutOptions, TemplateParameterSchema, } from '@backstage/plugin-scaffolder-react'; -import { - Stepper, - LegacyFieldExtensionOptions, -} from '@backstage/plugin-scaffolder-react/alpha'; + import { useDryRun } from '../../next/TemplateEditorPage/DryRunContext'; import { useDirectoryEditor } from '../../next/TemplateEditorPage/DirectoryEditorContext'; +import { MultistepJsonForm } from '../MultistepJsonForm'; +import { createValidator } from '../TemplatePage'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; const useStyles = makeStyles({ containerWrapper: { @@ -82,7 +81,10 @@ interface TemplateEditorFormProps { content?: string; /** Setting this to true will cause the content to be parsed as if it is the template entity spec */ contentIsSpec?: boolean; + data: JsonObject; + onUpdate: (data: JsonObject) => void; setErrorText: (errorText?: string) => void; + onDryRun?: (data: JsonObject) => Promise; fieldExtensions?: LegacyFieldExtensionOptions[]; layouts?: LayoutOptions[]; @@ -97,6 +99,8 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { const { content, contentIsSpec, + data, + onUpdate, onDryRun, setErrorText, fieldExtensions = [], @@ -107,6 +111,12 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { const [steps, setSteps] = useState(); + const fields = useMemo(() => { + return Object.fromEntries( + fieldExtensions.map(({ name, component }) => [name, component]), + ); + }, [fieldExtensions]); + useDebounce( () => { try { @@ -114,7 +124,10 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { setSteps(undefined); return; } - const parsed: JsonValue = yaml.parse(content); + const parsed: JsonValue = yaml + .parseAllDocuments(content) + .filter(c => c) + .map(c => c.toJSON())[0]; if (!isJsonObject(parsed)) { setSteps(undefined); @@ -141,6 +154,10 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { return; } + const fieldValidators = Object.fromEntries( + fieldExtensions.map(({ name, validation }) => [name, validation]), + ); + setErrorText(); setSteps( parameters.flatMap(param => @@ -149,6 +166,9 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { { title: String(param.title), schema: param, + validate: createValidator(param, fieldValidators, { + apiHolder, + }), }, ] : [], @@ -170,14 +190,15 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) {

- { - await onDryRun?.(data); - }} + onUpdate(e.formData)} + onReset={() => onUpdate({})} + finishButtonLabel={onDryRun && 'Try It'} + onFinish={onDryRun && (() => onDryRun(data))} layouts={layouts} - components={{ createButtonText: onDryRun && 'Try It' }} />
@@ -198,7 +219,9 @@ export function TemplateEditorFormDirectoryEditorDryRun( const directoryEditor = useDirectoryEditor(); const { selectedFile } = directoryEditor; - const handleDryRun = async (values: JsonObject) => { + const [data, setData] = useState({}); + + const handleDryRun = async () => { if (!selectedFile) { return; } @@ -206,7 +229,7 @@ export function TemplateEditorFormDirectoryEditorDryRun( try { await dryRun.execute({ templateContent: selectedFile.content, - values, + values: data, files: directoryEditor.files, }); setErrorText(); @@ -227,6 +250,8 @@ export function TemplateEditorFormDirectoryEditorDryRun( fieldExtensions={fieldExtensions} setErrorText={setErrorText} content={content} + data={data} + onUpdate={setData} layouts={layouts} /> ); From 6bfa4894a89fbd5627a0b3aa4b3137a2a5ed0985 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 2 Oct 2023 10:41:26 +0200 Subject: [PATCH 074/348] chore: fixing some missing features that got accidentally replaced Signed-off-by: blam --- .../Stepper/createAsyncValidators.ts | 1 + .../src/next/components/Stepper/index.ts | 1 + .../CustomFieldExplorer.tsx | 8 +++-- .../TemplateEditorPage/TemplateEditorForm.tsx | 2 +- .../TemplateFormPreviewer.tsx | 3 ++ .../TemplateEditorPage/TemplateEditorForm.tsx | 36 ++++++++++++++----- 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index a606f01d6b..8eb665911d 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -32,6 +32,7 @@ export type FormValidation = { [name: string]: FieldValidation | FormValidation; }; +/** @alpha */ export const createAsyncValidators = ( rootSchema: JsonObject, validators: Record< diff --git a/plugins/scaffolder-react/src/next/components/Stepper/index.ts b/plugins/scaffolder-react/src/next/components/Stepper/index.ts index daa47f078e..ebf0f7e902 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/index.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/index.ts @@ -14,3 +14,4 @@ * limitations under the License. */ export { Stepper, type StepperProps } from './Stepper'; +export { createAsyncValidators } from './createAsyncValidators'; diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx index c790dbd72c..de0c243e42 100644 --- a/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx @@ -74,6 +74,7 @@ export const CustomFieldExplorer = ({ const [selectedField, setSelectedField] = useState(fieldOptions[0]); const [fieldFormState, setFieldFormState] = useState({}); const [refreshKey, setRefreshKey] = useState(Date.now()); + const [formState, setFormState] = useState({}); const sampleFieldTemplate = useMemo( () => yaml.stringify({ @@ -103,8 +104,9 @@ export const CustomFieldExplorer = ({ selection => { setSelectedField(selection); setFieldFormState({}); + setFormState({}); }, - [setFieldFormState, setSelectedField], + [setFieldFormState, setSelectedField, setFormState], ); const handleFieldConfigChange = useCallback( @@ -149,7 +151,7 @@ export const CustomFieldExplorer = ({ onUpdate(e.formData)} onReset={() => onUpdate({})} - finishButtonLabel={onDryRun && 'Try It'} + finishButtonLabel={onDryRun && 'Try iIt'} onFinish={onDryRun && (() => onDryRun(data))} layouts={layouts} /> diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx index 21df43cf8c..b83acf85a5 100644 --- a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -125,6 +125,7 @@ export const TemplateFormPreviewer = ({ const [errorText, setErrorText] = useState(); const [templateOptions, setTemplateOptions] = useState([]); const [templateYaml, setTemplateYaml] = useState(defaultPreviewTemplate); + const [formState, setFormState] = useState({}); const { loading } = useAsync( () => @@ -204,6 +205,8 @@ export const TemplateFormPreviewer = ({
void; + onDryRun?: (data: JsonObject) => Promise; fieldExtensions?: FieldExtensionOptions[]; layouts?: LayoutOptions[]; @@ -104,6 +108,12 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { const [steps, setSteps] = useState(); + const fields = useMemo(() => { + return Object.fromEntries( + fieldExtensions.map(({ name, component }) => [name, component]), + ); + }, [fieldExtensions]); + useDebounce( () => { try { @@ -111,7 +121,10 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { setSteps(undefined); return; } - const parsed: JsonValue = yaml.parse(content); + const parsed: JsonValue = yaml + .parseAllDocuments(content) + .filter(c => c) + .map(c => c.toJSON())[0]; if (!isJsonObject(parsed)) { setSteps(undefined); @@ -138,6 +151,10 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { return; } + const fieldValidators = Object.fromEntries( + fieldExtensions.map(({ name, validation }) => [name, validation]), + ); + setErrorText(); setSteps( parameters.flatMap(param => @@ -146,6 +163,9 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { { title: String(param.title), schema: param, + validate: createAsyncValidators(param, fieldValidators, { + apiHolder, + }), }, ] : [], @@ -170,11 +190,11 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { { - await onDryRun?.(data); + components={fields} + onCreate={async options => { + await onDryRun?.(options); }} layouts={layouts} - components={{ createButtonText: onDryRun && 'Try It' }} />
@@ -195,7 +215,7 @@ export function TemplateEditorFormDirectoryEditorDryRun( const directoryEditor = useDirectoryEditor(); const { selectedFile } = directoryEditor; - const handleDryRun = async (values: JsonObject) => { + const handleDryRun = async (data: JsonObject) => { if (!selectedFile) { return; } @@ -203,7 +223,7 @@ export function TemplateEditorFormDirectoryEditorDryRun( try { await dryRun.execute({ templateContent: selectedFile.content, - values, + values: data, files: directoryEditor.files, }); setErrorText(); From da462fffc70688766cd70ab51c32d195b7074380 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 2 Oct 2023 11:52:49 +0200 Subject: [PATCH 075/348] feat: make things nice here Signed-off-by: blam --- plugins/scaffolder-react/alpha-api-report.md | 56 +++++++--------- .../src/legacy/extensions/index.tsx | 2 +- .../src/legacy/extensions/types.ts | 2 +- .../src/next/components/Form/Form.tsx | 2 +- .../Stepper/createAsyncValidators.ts | 6 +- .../src/next/components/Stepper/index.ts | 5 +- .../TemplateGroups/TemplateGroups.tsx | 2 +- .../src/next/components/Workflow/Workflow.tsx | 2 +- plugins/scaffolder/alpha-api-report.md | 59 ++++++++++------- plugins/scaffolder/api-report.md | 64 +++++++++---------- .../components/OngoingTask/OngoingTask.tsx | 3 + .../src/components/Router/Router.tsx | 5 +- .../src/legacy/TaskPage/TaskPage.tsx | 2 +- 13 files changed, 106 insertions(+), 104 deletions(-) diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index 89ba75e8ef..cb45773f06 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -7,56 +7,50 @@ import { ApiHolder } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; -import { CustomValidator } from '@rjsf/utils'; +import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react'; +import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; import { Dispatch } from 'react'; -import { ElementType } from 'react'; -import { ErrorSchema } from '@rjsf/utils'; -import { ErrorTransformer } from '@rjsf/utils'; -import { Experimental_DefaultFormStateBehavior } from '@rjsf/utils'; import { Extension } from '@backstage/core-plugin-api'; +import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; import { FieldProps } from '@rjsf/core'; import { FieldValidation } from '@rjsf/utils'; import { FieldValidation as FieldValidation_2 } from '@rjsf/core'; -import { default as Form_2 } from '@rjsf/core-v5'; -import { FormContextType } from '@rjsf/utils'; -import { FormEvent } from 'react'; import { FormProps } from '@backstage/plugin-scaffolder-react'; -import { GenericObjectType } from '@rjsf/utils'; -import { HTMLAttributes } from 'react'; -import { IChangeEvent } from '@rjsf/core-v5'; import { IconComponent } from '@backstage/core-plugin-api'; -import { IdSchema } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; -import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; -import { Ref } from 'react'; -import { Registry } from '@rjsf/utils'; -import { RegistryWidgetsType } from '@rjsf/utils'; import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; -import { RJSFSchema } from '@rjsf/utils'; -import { RJSFValidationError } from '@rjsf/utils'; +import { ScaffolderRJSFFormProps } from '@backstage/plugin-scaffolder-react'; import { ScaffolderStep } from '@backstage/plugin-scaffolder-react'; import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; import { SetStateAction } from 'react'; -import { StrictRJSFSchema } from '@rjsf/utils'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; -import { TemplatesType } from '@rjsf/utils'; import { UiSchema } from '@rjsf/utils'; -import { ValidatorType } from '@rjsf/utils'; + +// @alpha (undocumented) +export const createAsyncValidators: ( + rootSchema: JsonObject, + validators: Record< + string, + undefined | CustomFieldValidator + >, + context: { + apiHolder: ApiHolder; + }, +) => (formData: JsonObject) => Promise; // @alpha export const createFieldValidation: () => FieldValidation; -// Warning: (ae-forgotten-export) The symbol "FieldExtensionComponent" needs to be exported by the entry point alpha.d.ts -// // @alpha export function createLegacyScaffolderFieldExtension< TReturnValue = unknown, @@ -79,13 +73,16 @@ export const extractSchemaFromStep: (inputStep: JsonObject) => { schema: JsonObject; }; -// Warning: (ae-forgotten-export) The symbol "ScaffolderRJSFFormProps" needs to be exported by the entry point alpha.d.ts -// // @alpha export const Form: ( props: PropsWithChildren, ) => React_2.JSX.Element; +// @alpha (undocumented) +export type FormValidation = { + [name: string]: FieldValidation | FormValidation; +}; + // @alpha export type LegacyCustomFieldValidator = ( data: TFieldReturnValue, @@ -280,8 +277,6 @@ export interface TemplateGroupsProps { text: string; url: string; }[]; - // Warning: (ae-forgotten-export) The symbol "TemplateGroupFilter" needs to be exported by the entry point alpha.d.ts - // // (undocumented) groups: TemplateGroupFilter[]; // (undocumented) @@ -321,7 +316,7 @@ export type WorkflowProps = { namespace: string; templateName: string; components?: { - ReviewStepComponent?: React_2.ComponentType; + ReviewStepComponent?: React_2.ComponentType; }; onError(error: Error | undefined): JSX.Element | null; } & Pick< @@ -334,10 +329,5 @@ export type WorkflowProps = { | 'layouts' >; -// Warnings were encountered during analysis: -// -// src/legacy/extensions/types.d.ts:23:5 - (ae-forgotten-export) The symbol "CustomFieldExtensionSchema" needs to be exported by the entry point alpha.d.ts -// src/next/components/Workflow/Workflow.d.ts:13:9 - (ae-forgotten-export) The symbol "ReviewStepProps_2" needs to be exported by the entry point alpha.d.ts - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/scaffolder-react/src/legacy/extensions/index.tsx b/plugins/scaffolder-react/src/legacy/extensions/index.tsx index 5276d9d31c..870d797fc4 100644 --- a/plugins/scaffolder-react/src/legacy/extensions/index.tsx +++ b/plugins/scaffolder-react/src/legacy/extensions/index.tsx @@ -21,7 +21,7 @@ import { } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; import { FIELD_EXTENSION_KEY } from '../../extensions/keys'; -import { FieldExtensionComponent } from '../../extensions'; +import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; /** * Method for creating field extensions that can be used in the scaffolder diff --git a/plugins/scaffolder-react/src/legacy/extensions/types.ts b/plugins/scaffolder-react/src/legacy/extensions/types.ts index 80b2903b09..9adf1b74f6 100644 --- a/plugins/scaffolder-react/src/legacy/extensions/types.ts +++ b/plugins/scaffolder-react/src/legacy/extensions/types.ts @@ -15,7 +15,7 @@ */ import { ApiHolder } from '@backstage/core-plugin-api'; import { FieldValidation, FieldProps } from '@rjsf/core'; -import { CustomFieldExtensionSchema } from '../../extensions/types'; +import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react'; /** * Field validation type for Custom Field Extensions. diff --git a/plugins/scaffolder-react/src/next/components/Form/Form.tsx b/plugins/scaffolder-react/src/next/components/Form/Form.tsx index ec644333b9..b9f4fa4531 100644 --- a/plugins/scaffolder-react/src/next/components/Form/Form.tsx +++ b/plugins/scaffolder-react/src/next/components/Form/Form.tsx @@ -20,7 +20,7 @@ import { PropsWithChildren } from 'react'; import { FieldTemplate } from './FieldTemplate'; import { DescriptionFieldTemplate } from './DescriptionFieldTemplate'; import { FieldProps } from '@rjsf/utils'; -import { ScaffolderRJSFFormProps } from '../../../extensions'; +import { ScaffolderRJSFFormProps } from '@backstage/plugin-scaffolder-react'; // TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly // which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 8eb665911d..f50f44d8f5 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -22,12 +22,10 @@ import { createFieldValidation, extractSchemaFromStep } from '../../lib'; import { CustomFieldValidator, FieldExtensionUiSchema, -} from '../../../extensions'; +} from '@backstage/plugin-scaffolder-react'; import { isObject } from './utils'; -/** - * @internal - */ +/** @alpha */ export type FormValidation = { [name: string]: FieldValidation | FormValidation; }; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/index.ts b/plugins/scaffolder-react/src/next/components/Stepper/index.ts index ebf0f7e902..5f33c2ff78 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/index.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/index.ts @@ -14,4 +14,7 @@ * limitations under the License. */ export { Stepper, type StepperProps } from './Stepper'; -export { createAsyncValidators } from './createAsyncValidators'; +export { + createAsyncValidators, + type FormValidation, +} from './createAsyncValidators'; diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx index ec08505c06..800ec67a16 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx @@ -23,7 +23,7 @@ import { import { Progress, Link } from '@backstage/core-components'; import { Typography } from '@material-ui/core'; import { errorApiRef, IconComponent, useApi } from '@backstage/core-plugin-api'; -import { TemplateGroupFilter } from '../../../components'; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; import { TemplateGroup } from '../TemplateGroup/TemplateGroup'; /** diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index c0d6b40333..e7c56378a7 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -27,7 +27,7 @@ import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema'; import { Stepper, type StepperProps } from '../Stepper/Stepper'; import { SecretsContextProvider } from '../../../secrets/SecretsContext'; -import { ReviewStepProps } from '../../../components'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles(() => ({ markdown: { diff --git a/plugins/scaffolder/alpha-api-report.md b/plugins/scaffolder/alpha-api-report.md index 8cacf6105e..bf9fc5782d 100644 --- a/plugins/scaffolder/alpha-api-report.md +++ b/plugins/scaffolder/alpha-api-report.md @@ -5,50 +5,58 @@ ```ts /// -import { FormProps as FormProps_2 } from '@backstage/plugin-scaffolder-react/alpha'; -import type { FormProps as FormProps_3 } from '@rjsf/core-v5'; +import { ComponentType } from 'react'; +import { Entity } from '@backstage/catalog-model'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; +import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { FormProps as FormProps_3 } from '@backstage/plugin-scaffolder-react'; import { JSX as JSX_2 } from 'react'; import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; -import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; -import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react/alpha'; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; // @alpha @deprecated export type FormProps = Pick< - FormProps_3, + FormProps_2, 'transformErrors' | 'noHtml5Validate' >; // @alpha -export type NextRouterProps = { +export const LegacyRouter: (props: LegacyRouterProps) => React_2.JSX.Element; + +// @alpha +export type LegacyRouterProps = { components?: { - TemplateCardComponent?: React_2.ComponentType<{ - template: TemplateEntityV1beta3; - }>; - TaskPageComponent?: React_2.ComponentType>; - TemplateOutputsComponent?: React_2.ComponentType<{ - output?: ScaffolderTaskOutput; - }>; - TemplateListPageComponent?: React_2.ComponentType; - TemplateWizardPageComponent?: React_2.ComponentType; + ReviewStepComponent?: ComponentType; + TemplateCardComponent?: + | ComponentType<{ + template: TemplateEntityV1beta3; + }> + | undefined; + TaskPageComponent?: ComponentType>; }; - groups?: TemplateGroupFilter[]; + groups?: Array<{ + title?: React_2.ReactNode; + filter: (entity: Entity) => boolean; + }>; templateFilter?: (entity: TemplateEntityV1beta3) => boolean; - FormProps?: FormProps_2; + defaultPreviewTemplate?: string; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; contextMenu?: { editor?: boolean; actions?: boolean; - tasks?: boolean; }; }; // @alpha -export const NextScaffolderPage: ( - props: PropsWithChildren, -) => JSX_2.Element; +export const LegacyScaffolderPage: (props: LegacyRouterProps) => JSX_2.Element; // @alpha (undocumented) export type TemplateListPageProps = { @@ -66,9 +74,12 @@ export type TemplateListPageProps = { // @alpha (undocumented) export type TemplateWizardPageProps = { - customFieldExtensions: NextFieldExtensionOptions[]; + customFieldExtensions: FieldExtensionOptions[]; + components?: { + ReviewStepComponent?: React_2.ComponentType; + }; layouts?: LayoutOptions[]; - FormProps?: FormProps_2; + formProps?: FormProps_3; }; // (No @packageDocumentation comment for this package) diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index ddda40d95f..6f8479990b 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -14,15 +14,14 @@ import { createScaffolderLayout as createScaffolderLayout_2 } from '@backstage/p import { CustomFieldExtensionSchema as CustomFieldExtensionSchema_2 } from '@backstage/plugin-scaffolder-react'; import { CustomFieldValidator as CustomFieldValidator_2 } from '@backstage/plugin-scaffolder-react'; import { DiscoveryApi } from '@backstage/core-plugin-api'; -import { Entity } from '@backstage/catalog-model'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { FetchApi } from '@backstage/core-plugin-api'; import { FieldExtensionComponent as FieldExtensionComponent_2 } from '@backstage/plugin-scaffolder-react'; import { FieldExtensionComponentProps as FieldExtensionComponentProps_2 } from '@backstage/plugin-scaffolder-react'; import { FieldExtensionOptions as FieldExtensionOptions_2 } from '@backstage/plugin-scaffolder-react'; -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; +import { FormProps } from '@backstage/plugin-scaffolder-react'; import { IdentityApi } from '@backstage/core-plugin-api'; -import { JsonObject } from '@backstage/types'; import { JSX as JSX_2 } from 'react'; import { LayoutOptions as LayoutOptions_2 } from '@backstage/plugin-scaffolder-react'; import { LayoutTemplate as LayoutTemplate_2 } from '@backstage/plugin-scaffolder-react'; @@ -33,6 +32,7 @@ import { PathParams } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; import { RouteRef } from '@backstage/core-plugin-api'; import { ScaffolderApi as ScaffolderApi_2 } from '@backstage/plugin-scaffolder-react'; import { ScaffolderDryRunOptions as ScaffolderDryRunOptions_2 } from '@backstage/plugin-scaffolder-react'; @@ -50,8 +50,10 @@ import { ScaffolderUseTemplateSecrets as ScaffolderUseTemplateSecrets_2 } from ' import { ScmIntegrationRegistry } from '@backstage/integration'; import { SubRouteRef } from '@backstage/core-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; +import { TemplateListPageProps } from '@backstage/plugin-scaffolder/alpha'; import { TemplateParameterSchema as TemplateParameterSchema_2 } from '@backstage/plugin-scaffolder-react'; -import { UiSchema } from '@rjsf/utils'; +import { TemplateWizardPageProps } from '@backstage/plugin-scaffolder/alpha'; import { z } from 'zod'; // @public @deprecated (undocumented) @@ -419,19 +421,7 @@ export const RepoUrlPickerFieldSchema: FieldSchema< export type RepoUrlPickerUiOptions = typeof RepoUrlPickerFieldSchema.uiOptionsType; -// @public -export type ReviewStepProps = { - disableButtons: boolean; - formData: JsonObject; - handleBack: () => void; - handleReset: () => void; - handleCreate: () => void; - steps: { - uiSchema: UiSchema; - mergedSchema: JsonObject; - schema: JsonObject; - }[]; -}; +export { ReviewStepProps }; // @public @deprecated (undocumented) export const rootRouteRef: RouteRef; @@ -439,28 +429,30 @@ export const rootRouteRef: RouteRef; // @public export type RouterProps = { components?: { - ReviewStepComponent?: ComponentType; - TemplateCardComponent?: - | ComponentType<{ - template: TemplateEntityV1beta3; - }> - | undefined; - TaskPageComponent?: ComponentType>; + ReviewStepComponent?: React_2.ComponentType; + TemplateCardComponent?: React_2.ComponentType<{ + template: TemplateEntityV1beta3; + }>; + TaskPageComponent?: React_2.ComponentType>; + EXPERIMENTAL_TemplateOutputsComponent?: React_2.ComponentType<{ + output?: ScaffolderTaskOutput_2; + }>; + EXPERIMENTAL_TemplateListPageComponent?: React_2.ComponentType; + EXPERIMENTAL_TemplateWizardPageComponent?: React_2.ComponentType; }; - groups?: Array<{ - title?: React_2.ReactNode; - filter: (entity: Entity) => boolean; - }>; + groups?: TemplateGroupFilter[]; templateFilter?: (entity: TemplateEntityV1beta3) => boolean; - defaultPreviewTemplate?: string; headerOptions?: { pageTitleOverride?: string; title?: string; subtitle?: string; }; + defaultPreviewTemplate?: string; + formProps?: FormProps; contextMenu?: { editor?: boolean; actions?: boolean; + tasks?: boolean; }; }; @@ -537,7 +529,9 @@ export const ScaffolderLayouts: ComponentType<{ export type ScaffolderOutputlink = ScaffolderOutputLink; // @public -export const ScaffolderPage: (props: RouterProps) => JSX_2.Element; +export const ScaffolderPage: ( + props: PropsWithChildren, +) => JSX_2.Element; // @public export const scaffolderPlugin: BackstagePlugin< @@ -585,10 +579,14 @@ export type ScaffolderTaskStatus = ScaffolderTaskStatus_2; // @public @deprecated (undocumented) export type ScaffolderUseTemplateSecrets = ScaffolderUseTemplateSecrets_2; -// @public -export const TaskPage: (props: TaskPageProps) => React_2.JSX.Element; +// @public (undocumented) +export const TaskPage: (props: { + TemplateOutputsComponent?: React_2.ComponentType<{ + output?: ScaffolderTaskOutput_2; + }>; +}) => React_2.JSX.Element; -// @public +// @public @deprecated export type TaskPageProps = { loadingText?: string; }; diff --git a/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx index b483cd27cb..cc988599a0 100644 --- a/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx @@ -51,6 +51,9 @@ const useStyles = makeStyles(theme => ({ }, })); +/** + * @public + */ export const OngoingTask = (props: { TemplateOutputsComponent?: React.ComponentType<{ output?: ScaffolderTaskOutput; diff --git a/plugins/scaffolder/src/components/Router/Router.tsx b/plugins/scaffolder/src/components/Router/Router.tsx index 83c26c9130..dede51d676 100644 --- a/plugins/scaffolder/src/components/Router/Router.tsx +++ b/plugins/scaffolder/src/components/Router/Router.tsx @@ -45,11 +45,10 @@ import { ActionsPage } from '../../components/ActionsPage'; import { ListTasksPage } from '../../components/ListTasksPage'; import { - TemplateListPage, TemplateListPageProps, - TemplateWizardPage, TemplateWizardPageProps, -} from '../../next'; +} from '@backstage/plugin-scaffolder/alpha'; +import { TemplateListPage, TemplateWizardPage } from '../../next'; import { OngoingTask } from '../OngoingTask'; import { TemplateEditorPage } from '../../next/TemplateEditorPage'; diff --git a/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx index 7ba7c2c9f7..846e5a861f 100644 --- a/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx @@ -236,7 +236,7 @@ const hasLinks = ({ links = [] }: ScaffolderTaskOutput): boolean => /** * TaskPageProps for constructing a TaskPage * @param loadingText - Optional loading text shown before a task begins executing. - * + * @public * @deprecated - this is a useless type that is no longer used. */ export type TaskPageProps = { From c04f436b616ef6936ebc9716dee9cb16a00efe4c Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 2 Oct 2023 13:51:29 +0200 Subject: [PATCH 076/348] feat: fixing tests Signed-off-by: blam --- .../components/TemplateGroups/TemplateGroups.test.tsx | 4 ++-- .../scaffolder/src/components/Router/Router.test.tsx | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.test.tsx index 894c6ea4d0..66c9d01ffd 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.test.tsx @@ -18,7 +18,7 @@ jest.mock('@backstage/plugin-catalog-react', () => ({ useEntityList: jest.fn(), })); -jest.mock('@backstage/plugin-scaffolder-react/alpha', () => ({ +jest.mock('../TemplateGroup/TemplateGroup', () => ({ TemplateGroup: jest.fn(() => null), })); @@ -27,7 +27,7 @@ import { useEntityList } from '@backstage/plugin-catalog-react'; import { TemplateGroups } from './TemplateGroups'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { errorApiRef } from '@backstage/core-plugin-api'; -import { TemplateGroup } from '@backstage/plugin-scaffolder-react/alpha'; +import { TemplateGroup } from '../TemplateGroup/TemplateGroup'; describe('TemplateGroups', () => { beforeEach(() => jest.clearAllMocks()); diff --git a/plugins/scaffolder/src/components/Router/Router.test.tsx b/plugins/scaffolder/src/components/Router/Router.test.tsx index 2dc67a76be..8c301b55fb 100644 --- a/plugins/scaffolder/src/components/Router/Router.test.tsx +++ b/plugins/scaffolder/src/components/Router/Router.test.tsx @@ -27,12 +27,9 @@ import { } from '@backstage/plugin-scaffolder-react'; import { TemplateListPage, TemplateWizardPage } from '../../next'; -jest.mock('../TemplateListPage', () => ({ - TemplateListPage: jest.fn(() => null), -})); - -jest.mock('../TemplateWizardPage', () => ({ +jest.mock('../../next', () => ({ TemplateWizardPage: jest.fn(() => null), + TemplateListPage: jest.fn(() => null), })); describe('Router', () => { @@ -104,9 +101,9 @@ describe('Router', () => { const mock = TemplateWizardPage as jest.Mock; - const [{ FormProps }] = mock.mock.calls[0]; + const [{ formProps }] = mock.mock.calls[0]; - expect(FormProps).toEqual({ + expect(formProps).toEqual({ transformErrors: transformErrorsMock, noHtml5Validate: true, }); From 72b7dc147f8b54f400b643182b233ab2cf651672 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 Oct 2023 07:56:03 +0200 Subject: [PATCH 077/348] feat: fix code review Signed-off-by: blam Signed-off-by: Patrik Oldsberg --- .../src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx | 3 +-- .../src/legacy/TemplateEditorPage/TemplateEditorForm.tsx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index 36fef1c91e..da86e6e4b8 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -79,8 +79,7 @@ describe('RepoUrlPicker', () => { schema={{ type: 'string' }} uiSchema={{ 'ui:field': 'RepoUrlPicker' }} fields={{ - RepoUrlPicker: - RepoUrlPicker as ScaffolderRJSFField as ScaffolderRJSFField, + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField, }} onSubmit={onSubmit} /> diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx index 34e1b05c98..766581e311 100644 --- a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx @@ -196,7 +196,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { formData={data} onChange={e => onUpdate(e.formData)} onReset={() => onUpdate({})} - finishButtonLabel={onDryRun && 'Try iIt'} + finishButtonLabel={onDryRun && 'Try It'} onFinish={onDryRun && (() => onDryRun(data))} layouts={layouts} /> From fadd3ca42af8840fd308c033eeab8fccda8ed63c Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 Oct 2023 08:22:41 +0200 Subject: [PATCH 078/348] chore: remove old rjsf Signed-off-by: blam --- plugins/home/package.json | 4 +- .../CustomHomepage/WidgetSettingsOverlay.tsx | 5 +- plugins/scaffolder-react/alpha-api-report.md | 9 ++- plugins/scaffolder-react/api-report.md | 6 +- plugins/scaffolder-react/package.json | 6 +- .../scaffolder-react/src/components/types.ts | 2 +- .../scaffolder-react/src/extensions/rjsf.ts | 2 +- .../src/layouts/createScaffolderLayout.ts | 2 +- .../src/legacy/extensions/types.ts | 11 +-- .../src/next/components/Form/Form.tsx | 8 +-- .../src/next/components/Stepper/Stepper.tsx | 2 +- plugins/scaffolder/alpha-api-report.md | 2 +- plugins/scaffolder/package.json | 4 +- .../EntityNamePicker/validation.test.ts | 2 +- .../fields/RepoUrlPicker/validation.test.ts | 2 +- .../FieldOverrides/DescriptionField.tsx | 2 +- .../MultistepJsonForm/MultistepJsonForm.tsx | 2 + .../legacy/MultistepJsonForm/ReviewStep.tsx | 2 +- .../src/legacy/MultistepJsonForm/schema.ts | 6 +- .../TemplateEditorPage/TemplateEditorForm.tsx | 2 +- .../src/legacy/TemplatePage/TemplatePage.tsx | 2 +- .../TemplatePage/createValidator.test.ts | 8 +-- .../legacy/TemplatePage/createValidator.ts | 4 +- plugins/scaffolder/src/next/types.ts | 2 +- yarn.lock | 70 ++++--------------- 25 files changed, 62 insertions(+), 105 deletions(-) diff --git a/plugins/home/package.json b/plugins/home/package.json index 58b25eb22c..a239f1b17e 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -46,8 +46,8 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@rjsf/core-v5": "npm:@rjsf/core@5.13.0", - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.13.0", + "@rjsf/core": "5.13.0", + "@rjsf/material-ui": "5.13.0", "@rjsf/utils": "5.13.0", "@rjsf/validator-ajv8": "5.13.0", "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx b/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx index 2c3a1d9ab9..aec4b3dcf2 100644 --- a/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx +++ b/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx @@ -27,10 +27,11 @@ import SettingsIcon from '@material-ui/icons/Settings'; import DeleteIcon from '@material-ui/icons/Delete'; import React from 'react'; import { Widget } from './types'; -import { withTheme } from '@rjsf/core-v5'; +import { withTheme } from '@rjsf/core'; +import { Theme as MuiTheme } from '@rjsf/material-ui'; import validator from '@rjsf/validator-ajv8'; -const Form = withTheme(require('@rjsf/material-ui-v5').Theme); +const Form = withTheme(MuiTheme); const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index cb45773f06..a31d9b1d60 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -13,9 +13,7 @@ import { Dispatch } from 'react'; import { Extension } from '@backstage/core-plugin-api'; import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; -import { FieldProps } from '@rjsf/core'; import { FieldValidation } from '@rjsf/utils'; -import { FieldValidation as FieldValidation_2 } from '@rjsf/core'; import { FormProps } from '@backstage/plugin-scaffolder-react'; import { IconComponent } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; @@ -26,6 +24,7 @@ import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderRJSFFieldProps } from '@backstage/plugin-scaffolder-react'; import { ScaffolderRJSFFormProps } from '@backstage/plugin-scaffolder-react'; import { ScaffolderStep } from '@backstage/plugin-scaffolder-react'; import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; @@ -86,7 +85,7 @@ export type FormValidation = { // @alpha export type LegacyCustomFieldValidator = ( data: TFieldReturnValue, - field: FieldValidation_2, + field: FieldValidation, context: { apiHolder: ApiHolder; }, @@ -96,9 +95,9 @@ export type LegacyCustomFieldValidator = ( export interface LegacyFieldExtensionComponentProps< TFieldReturnValue, TUiOptions = unknown, -> extends FieldProps { +> extends ScaffolderRJSFFieldProps { // (undocumented) - uiSchema: FieldProps['uiSchema'] & { + uiSchema: ScaffolderRJSFFieldProps['uiSchema'] & { 'ui:options'?: TUiOptions; }; } diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 057bb3a059..6acc2f9812 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -15,13 +15,13 @@ import { ErrorTransformer } from '@rjsf/utils'; import { Experimental_DefaultFormStateBehavior } from '@rjsf/utils'; import { Extension } from '@backstage/core-plugin-api'; import { FieldValidation } from '@rjsf/utils'; -import Form from '@rjsf/core-v5'; +import Form from '@rjsf/core'; import { FormContextType } from '@rjsf/utils'; import { FormEvent } from 'react'; -import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import type { FormProps as FormProps_2 } from '@rjsf/core'; import { GenericObjectType } from '@rjsf/utils'; import { HTMLAttributes } from 'react'; -import { IChangeEvent } from '@rjsf/core-v5'; +import { IChangeEvent } from '@rjsf/core'; import { IdSchema } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 05dccfa1fe..df4a3c867f 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -60,10 +60,8 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@react-hookz/web": "^20.0.0", - "@rjsf/core": "^3.2.1", - "@rjsf/core-v5": "npm:@rjsf/core@5.13.0", - "@rjsf/material-ui": "^3.2.1", - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.13.0", + "@rjsf/core": "5.13.0", + "@rjsf/material-ui": "5.13.0", "@rjsf/utils": "5.13.0", "@rjsf/validator-ajv8": "5.13.0", "@types/json-schema": "^7.0.9", diff --git a/plugins/scaffolder-react/src/components/types.ts b/plugins/scaffolder-react/src/components/types.ts index f6e186a56f..597998bac4 100644 --- a/plugins/scaffolder-react/src/components/types.ts +++ b/plugins/scaffolder-react/src/components/types.ts @@ -15,7 +15,7 @@ */ import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; +import type { FormProps as SchemaFormProps } from '@rjsf/core'; import { UiSchema } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; diff --git a/plugins/scaffolder-react/src/extensions/rjsf.ts b/plugins/scaffolder-react/src/extensions/rjsf.ts index edacbc26aa..cacedad080 100644 --- a/plugins/scaffolder-react/src/extensions/rjsf.ts +++ b/plugins/scaffolder-react/src/extensions/rjsf.ts @@ -33,7 +33,7 @@ import { ErrorTransformer, } from '@rjsf/utils'; import { HTMLAttributes } from 'react'; -import Form, { IChangeEvent } from '@rjsf/core-v5'; +import Form, { IChangeEvent } from '@rjsf/core'; /** * The props for the `Field` components diff --git a/plugins/scaffolder-react/src/layouts/createScaffolderLayout.ts b/plugins/scaffolder-react/src/layouts/createScaffolderLayout.ts index 6b2ae1b33b..d950285a7d 100644 --- a/plugins/scaffolder-react/src/layouts/createScaffolderLayout.ts +++ b/plugins/scaffolder-react/src/layouts/createScaffolderLayout.ts @@ -16,7 +16,7 @@ import { LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from './keys'; import { attachComponentData, Extension } from '@backstage/core-plugin-api'; -import type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; +import type { FormProps as SchemaFormProps } from '@rjsf/core'; import React from 'react'; /** diff --git a/plugins/scaffolder-react/src/legacy/extensions/types.ts b/plugins/scaffolder-react/src/legacy/extensions/types.ts index 9adf1b74f6..54c38ad2cd 100644 --- a/plugins/scaffolder-react/src/legacy/extensions/types.ts +++ b/plugins/scaffolder-react/src/legacy/extensions/types.ts @@ -14,8 +14,11 @@ * limitations under the License. */ import { ApiHolder } from '@backstage/core-plugin-api'; -import { FieldValidation, FieldProps } from '@rjsf/core'; -import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react'; +import { FieldValidation } from '@rjsf/utils'; +import { + CustomFieldExtensionSchema, + ScaffolderRJSFFieldProps, +} from '@backstage/plugin-scaffolder-react'; /** * Field validation type for Custom Field Extensions. @@ -55,8 +58,8 @@ export type LegacyFieldExtensionOptions< export interface LegacyFieldExtensionComponentProps< TFieldReturnValue, TUiOptions = unknown, -> extends FieldProps { - uiSchema: FieldProps['uiSchema'] & { +> extends ScaffolderRJSFFieldProps { + uiSchema: ScaffolderRJSFFieldProps['uiSchema'] & { 'ui:options'?: TUiOptions; }; } diff --git a/plugins/scaffolder-react/src/next/components/Form/Form.tsx b/plugins/scaffolder-react/src/next/components/Form/Form.tsx index b9f4fa4531..7398e0bb2e 100644 --- a/plugins/scaffolder-react/src/next/components/Form/Form.tsx +++ b/plugins/scaffolder-react/src/next/components/Form/Form.tsx @@ -14,18 +14,16 @@ * limitations under the License. */ -import { withTheme } from '@rjsf/core-v5'; +import { withTheme } from '@rjsf/core'; import React from 'react'; import { PropsWithChildren } from 'react'; import { FieldTemplate } from './FieldTemplate'; import { DescriptionFieldTemplate } from './DescriptionFieldTemplate'; import { FieldProps } from '@rjsf/utils'; import { ScaffolderRJSFFormProps } from '@backstage/plugin-scaffolder-react'; +import { Theme as MuiTheme } from '@rjsf/material-ui'; -// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly -// which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because -// of the re-writing we're doing. Once we've migrated, we can import this the exact same as before. -const WrappedForm = withTheme(require('@rjsf/material-ui-v5').Theme); +const WrappedForm = withTheme(MuiTheme); /** * The Form component diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 9bb8084ac3..1e43eba770 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -23,7 +23,7 @@ import { makeStyles, LinearProgress, } from '@material-ui/core'; -import { type IChangeEvent } from '@rjsf/core-v5'; +import { type IChangeEvent } from '@rjsf/core'; import { ErrorSchema } from '@rjsf/utils'; import React, { useCallback, diff --git a/plugins/scaffolder/alpha-api-report.md b/plugins/scaffolder/alpha-api-report.md index bf9fc5782d..55d14bff75 100644 --- a/plugins/scaffolder/alpha-api-report.md +++ b/plugins/scaffolder/alpha-api-report.md @@ -8,7 +8,7 @@ import { ComponentType } from 'react'; import { Entity } from '@backstage/catalog-model'; import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; -import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import type { FormProps as FormProps_2 } from '@rjsf/core'; import { FormProps as FormProps_3 } from '@backstage/plugin-scaffolder-react'; import { JSX as JSX_2 } from 'react'; import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 5cfc038e77..f6ca5b5003 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -68,8 +68,8 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@react-hookz/web": "^20.0.0", - "@rjsf/core": "^3.2.1", - "@rjsf/material-ui": "^3.2.1", + "@rjsf/core": "5.13.0", + "@rjsf/material-ui": "5.13.0", "@rjsf/utils": "5.13.0", "@rjsf/validator-ajv8": "5.13.0", "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts index 290650387e..7201c9c4b3 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; import { entityNamePickerValidation } from './validation'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts index 45e44b4072..b9c481957c 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts @@ -15,7 +15,7 @@ */ import { repoPickerValidation } from './validation'; -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/core-app-api'; import { ApiHolder } from '@backstage/core-plugin-api'; diff --git a/plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/DescriptionField.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/DescriptionField.tsx index 3c592860ef..eded38beee 100644 --- a/plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/DescriptionField.tsx +++ b/plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/DescriptionField.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { MarkdownContent } from '@backstage/core-components'; -import { FieldProps } from '@rjsf/core'; +import { FieldProps } from '@rjsf/utils'; export const DescriptionField = ({ description }: FieldProps) => description && ; diff --git a/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx index eddbbff4bf..c9a9be50e0 100644 --- a/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx @@ -36,6 +36,7 @@ import { transformSchemaToProps } from './schema'; import cloneDeep from 'lodash/cloneDeep'; import * as fieldOverrides from './FieldOverrides'; import { ReviewStep } from './ReviewStep'; +import validator from '@rjsf/validator-ajv8'; import { extractSchemaFromStep } from '@backstage/plugin-scaffolder-react/alpha'; import { selectedTemplateRouteRef } from '../../routes'; import { @@ -180,6 +181,7 @@ export const MultistepJsonForm = (props: MultistepJsonFormProps) => { ['ObjectFieldTemplate']; + uiSchema['ui:ObjectFieldTemplate'] = Layout; } } diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx index 766581e311..df05efc921 100644 --- a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx @@ -192,7 +192,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { onUpdate(e.formData)} onReset={() => onUpdate({})} diff --git a/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx index a5cac1ef54..ffb754bae3 100644 --- a/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx @@ -162,7 +162,7 @@ export const TemplatePage = ({ { /* THEN */ expect(result).not.toBeNull(); - expect(result.p1.addError).toHaveBeenCalledTimes(1); + expect(result.p1?.addError).toHaveBeenCalledTimes(1); }); it('should call validator for array property from a custom field extension', () => { @@ -146,7 +146,7 @@ describe('createValidator', () => { /* THEN */ expect(result).not.toBeNull(); - expect(result.tags.addError).toHaveBeenCalledTimes(1); + expect(result.tags?.addError).toHaveBeenCalledTimes(1); }); it('should call validator for array object property from a custom field extension', () => { @@ -195,6 +195,6 @@ describe('createValidator', () => { /* THEN */ expect(result).not.toBeNull(); - expect(result.links.addError).toHaveBeenCalledTimes(1); + expect(result.links?.addError).toHaveBeenCalledTimes(1); }); }); diff --git a/plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts index 04325ce5e5..ae0b834fe9 100644 --- a/plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts @@ -15,7 +15,7 @@ */ import { LegacyCustomFieldValidator } from '@backstage/plugin-scaffolder-react/alpha'; -import { FormValidation } from '@rjsf/core'; +import { FieldValidation, FormValidation } from '@rjsf/utils'; import { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; @@ -56,7 +56,7 @@ export const createValidator = ( if (fieldName && typeof validators[fieldName] === 'function') { validators[fieldName]!( propData as JsonObject[], - propValidation, + propValidation as FieldValidation, context, ); } diff --git a/plugins/scaffolder/src/next/types.ts b/plugins/scaffolder/src/next/types.ts index c2ee473d54..80e01042f2 100644 --- a/plugins/scaffolder/src/next/types.ts +++ b/plugins/scaffolder/src/next/types.ts @@ -20,7 +20,7 @@ * It exists already in the `scaffolder-react` plugin, so you may have to update both files. */ -import type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; +import type { FormProps as SchemaFormProps } from '@rjsf/core'; /** * Any `@rjsf/core` form properties that are publicly exposed to the `NextScaffolderPage` diff --git a/yarn.lock b/yarn.lock index 492c512e76..a6f75ec491 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7216,8 +7216,8 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@rjsf/core-v5": "npm:@rjsf/core@5.13.0" - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.13.0" + "@rjsf/core": 5.13.0 + "@rjsf/material-ui": 5.13.0 "@rjsf/utils": 5.13.0 "@rjsf/validator-ajv8": 5.13.0 "@testing-library/dom": ^9.0.0 @@ -8663,10 +8663,8 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@react-hookz/web": ^20.0.0 - "@rjsf/core": ^3.2.1 - "@rjsf/core-v5": "npm:@rjsf/core@5.13.0" - "@rjsf/material-ui": ^3.2.1 - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.13.0" + "@rjsf/core": 5.13.0 + "@rjsf/material-ui": 5.13.0 "@rjsf/utils": 5.13.0 "@rjsf/validator-ajv8": 5.13.0 "@testing-library/dom": ^9.0.0 @@ -8729,8 +8727,8 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@react-hookz/web": ^20.0.0 - "@rjsf/core": ^3.2.1 - "@rjsf/material-ui": ^3.2.1 + "@rjsf/core": 5.13.0 + "@rjsf/material-ui": 5.13.0 "@rjsf/utils": 5.13.0 "@rjsf/validator-ajv8": 5.13.0 "@testing-library/dom": ^9.0.0 @@ -14621,7 +14619,7 @@ __metadata: languageName: node linkType: hard -"@rjsf/core-v5@npm:@rjsf/core@5.13.0": +"@rjsf/core@npm:5.13.0": version: 5.13.0 resolution: "@rjsf/core@npm:5.13.0" dependencies: @@ -14637,26 +14635,7 @@ __metadata: languageName: node linkType: hard -"@rjsf/core@npm:^3.2.1": - version: 3.2.1 - resolution: "@rjsf/core@npm:3.2.1" - 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: ^5.0.0 - lodash: ^4.17.15 - nanoid: ^3.1.23 - prop-types: ^15.7.2 - react-is: ^16.9.0 - peerDependencies: - react: ">=16" - checksum: 2142d4a31229ea242b79aca4ed93e2fe89e75f15ce93111457c3017d3ab295cae8f53e4dd870c619afa571959d00f46b3c19085c6a336f522c891fc07ecc46f1 - languageName: node - linkType: hard - -"@rjsf/material-ui-v5@npm:@rjsf/material-ui@5.13.0": +"@rjsf/material-ui@npm:5.13.0": version: 5.13.0 resolution: "@rjsf/material-ui@npm:5.13.0" peerDependencies: @@ -14669,18 +14648,6 @@ __metadata: languageName: node linkType: hard -"@rjsf/material-ui@npm:^3.2.1": - version: 3.2.1 - resolution: "@rjsf/material-ui@npm:3.2.1" - peerDependencies: - "@material-ui/core": ^4.2.0 - "@material-ui/icons": ^4.2.1 - "@rjsf/core": ^3.0.0 - react: ">=16" - checksum: bd25cd9f2e2d568c653755e7268fe3e53279e1ae675e39bccd85f65557623d2052b706763e017a949f897751e25a16d0f2c8b995508bb56907be6786b09e2b1e - languageName: node - linkType: hard - "@rjsf/utils@npm:5.13.0": version: 5.13.0 resolution: "@rjsf/utils@npm:5.13.0" @@ -19611,7 +19578,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.10.1, ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5, ajv@npm:^6.5.5, ajv@npm:^6.7.0, ajv@npm:~6.12.6": +"ajv@npm:^6.10.1, ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5, ajv@npm:^6.5.5, ajv@npm:~6.12.6": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -22270,7 +22237,7 @@ __metadata: languageName: node linkType: hard -"compute-lcm@npm:^1.1.0, compute-lcm@npm:^1.1.2": +"compute-lcm@npm:^1.1.2": version: 1.1.2 resolution: "compute-lcm@npm:1.1.2" dependencies: @@ -22536,7 +22503,7 @@ __metadata: languageName: node linkType: hard -"core-js-pure@npm:^3.23.3, core-js-pure@npm:^3.30.2, core-js-pure@npm:^3.6.5": +"core-js-pure@npm:^3.23.3, core-js-pure@npm:^3.30.2": version: 3.31.0 resolution: "core-js-pure@npm:3.31.0" checksum: 2bc5d2f6c3c9732fd5c066529b8d41fae9c746206ddf7614712dc4120a9efd47bf894df4fc600fde8c04324171c1999869798b48b23fca128eff5f09f58cd2f6 @@ -30316,17 +30283,6 @@ __metadata: languageName: node linkType: hard -"json-schema-merge-allof@npm:^0.6.0": - version: 0.6.0 - resolution: "json-schema-merge-allof@npm:0.6.0" - dependencies: - compute-lcm: ^1.1.0 - json-schema-compare: ^0.2.2 - lodash: ^4.17.4 - checksum: 2008aede3f5d05d7870e7d5e554e5c6a5b451cfff1357d34d3d8b34e2ba57468a97c76aa5b967bdb411d91b98c734f19f350de578d25b2a0a27cd4e1ca92bd1d - languageName: node - linkType: hard - "json-schema-merge-allof@npm:^0.8.1": version: 0.8.1 resolution: "json-schema-merge-allof@npm:0.8.1" @@ -33243,7 +33199,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.1.23, nanoid@npm:^3.3.6": +"nanoid@npm:^3.3.6": version: 3.3.6 resolution: "nanoid@npm:3.3.6" bin: @@ -36760,7 +36716,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.6.3, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6, react-is@npm:^16.9.0": +"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.6.3, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f From d4f2e21386c5accffca1bef534d5c4cc3e5aff83 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 Oct 2023 08:48:15 +0200 Subject: [PATCH 079/348] chore: fix Signed-off-by: blam --- plugins/scaffolder-react/src/next/components/Form/Form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-react/src/next/components/Form/Form.tsx b/plugins/scaffolder-react/src/next/components/Form/Form.tsx index 7398e0bb2e..85e75e2c0d 100644 --- a/plugins/scaffolder-react/src/next/components/Form/Form.tsx +++ b/plugins/scaffolder-react/src/next/components/Form/Form.tsx @@ -40,7 +40,7 @@ export const Form = (props: PropsWithChildren) => { ); From 445d7a305813c179bc16fa72a19f695ae9a175d2 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 Oct 2023 08:51:49 +0200 Subject: [PATCH 080/348] chore: fix Signed-off-by: blam --- .../src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx | 3 +-- .../src/next/TemplateEditorPage/CustomFieldExplorer.tsx | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx index de0c243e42..0ba5db560a 100644 --- a/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx @@ -150,8 +150,7 @@ export const CustomFieldExplorer = ({ Date: Tue, 17 Oct 2023 12:51:07 +0200 Subject: [PATCH 081/348] scaffolder: type fix in MultistepJsonForm Signed-off-by: Patrik Oldsberg --- .../src/legacy/MultistepJsonForm/MultistepJsonForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx index c9a9be50e0..312522bc88 100644 --- a/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx @@ -29,7 +29,7 @@ import { useRouteRefParams, useApi, } from '@backstage/core-plugin-api'; -import { FormProps, IChangeEvent, ISubmitEvent, withTheme } from '@rjsf/core'; +import { FormProps, IChangeEvent, withTheme } from '@rjsf/core'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { ComponentType, useState } from 'react'; import { transformSchemaToProps } from './schema'; @@ -189,7 +189,7 @@ export const MultistepJsonForm = (props: MultistepJsonFormProps) => { formData={formData} formContext={{ formData }} onChange={onChange} - onSubmit={(e: ISubmitEvent) => { + onSubmit={(e: IChangeEvent) => { if (e.errors.length === 0) handleNext(); }} {...formProps} From 62735024ad86a6e26f66e205e09a54525bcb9167 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 13:10:14 +0200 Subject: [PATCH 082/348] docs/features/techdocs: wrap file extensions in code blocks Signed-off-by: Patrik Oldsberg --- docs/features/techdocs/how-to-guides.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 6a70e9e2aa..29f985904f 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -548,7 +548,7 @@ title Login Sequence #### Referenced PlantUML Diagram Example -Here, the markdown file refers to another file (_.puml or _.pu) which contains the diagram description. +Here, the markdown file refers to another file (`*.puml` or `*.pu`) which contains the diagram description. ````md ```plantuml From 7c53e2edb718e9fe71fd983d50f5355b76fd7ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 17 Oct 2023 13:25:33 +0200 Subject: [PATCH 083/348] enter pre mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/pre.json | 256 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 .changeset/pre.json diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 0000000000..4a9428d0cd --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,256 @@ +{ + "mode": "pre", + "tag": "next", + "initialVersions": { + "example-app": "0.2.88", + "@backstage/app-defaults": "1.4.4", + "example-app-next": "0.0.2", + "app-next-example-plugin": "0.0.2", + "example-backend": "0.2.88", + "@backstage/backend-app-api": "0.5.6", + "@backstage/backend-common": "0.19.8", + "@backstage/backend-defaults": "0.2.6", + "@backstage/backend-dev-utils": "0.1.2", + "example-backend-next": "0.0.16", + "@backstage/backend-openapi-utils": "0.0.5", + "@backstage/backend-plugin-api": "0.6.6", + "@backstage/backend-plugin-manager": "0.0.2", + "@backstage/backend-tasks": "0.5.11", + "@backstage/backend-test-utils": "0.2.7", + "@backstage/catalog-client": "1.4.5", + "@backstage/catalog-model": "1.4.3", + "@backstage/cli": "0.23.0", + "@backstage/cli-common": "0.1.13", + "@backstage/cli-node": "0.1.5", + "@backstage/codemods": "0.1.46", + "@backstage/config": "1.1.1", + "@backstage/config-loader": "1.5.1", + "@backstage/core-app-api": "1.11.0", + "@backstage/core-components": "0.13.6", + "@backstage/core-plugin-api": "1.7.0", + "@backstage/create-app": "0.5.6", + "@backstage/dev-utils": "1.0.22", + "e2e-test": "0.2.8", + "@backstage/e2e-test-utils": "0.1.0", + "@backstage/errors": "1.2.3", + "@backstage/eslint-plugin": "0.1.3", + "@backstage/frontend-app-api": "0.2.0", + "@backstage/frontend-plugin-api": "0.2.0", + "@backstage/integration": "1.7.1", + "@backstage/integration-aws-node": "0.1.7", + "@backstage/integration-react": "1.1.20", + "@backstage/release-manifests": "0.0.10", + "@backstage/repo-tools": "0.3.5", + "@techdocs/cli": "1.6.0", + "techdocs-cli-embedded-app": "0.2.87", + "@backstage/test-utils": "1.4.4", + "@backstage/theme": "0.4.3", + "@backstage/types": "1.1.1", + "@backstage/version-bridge": "1.0.6", + "@backstage/plugin-adr": "0.6.8", + "@backstage/plugin-adr-backend": "0.4.3", + "@backstage/plugin-adr-common": "0.2.16", + "@backstage/plugin-airbrake": "0.3.25", + "@backstage/plugin-airbrake-backend": "0.3.3", + "@backstage/plugin-allure": "0.1.41", + "@backstage/plugin-analytics-module-ga": "0.1.34", + "@backstage/plugin-analytics-module-ga4": "0.1.5", + "@backstage/plugin-analytics-module-newrelic-browser": "0.0.3", + "@backstage/plugin-apache-airflow": "0.2.16", + "@backstage/plugin-api-docs": "0.9.12", + "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.4", + "@backstage/plugin-apollo-explorer": "0.1.16", + "@backstage/plugin-app-backend": "0.3.54", + "@backstage/plugin-app-node": "0.1.6", + "@backstage/plugin-auth-backend": "0.19.3", + "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.2.0", + "@backstage/plugin-auth-backend-module-github-provider": "0.1.3", + "@backstage/plugin-auth-backend-module-gitlab-provider": "0.1.3", + "@backstage/plugin-auth-backend-module-google-provider": "0.1.3", + "@backstage/plugin-auth-backend-module-microsoft-provider": "0.1.0", + "@backstage/plugin-auth-backend-module-oauth2-provider": "0.1.3", + "@backstage/plugin-auth-backend-module-pinniped-provider": "0.1.0", + "@backstage/plugin-auth-node": "0.4.0", + "@backstage/plugin-azure-devops": "0.3.7", + "@backstage/plugin-azure-devops-backend": "0.4.3", + "@backstage/plugin-azure-devops-common": "0.3.1", + "@backstage/plugin-azure-sites": "0.1.14", + "@backstage/plugin-azure-sites-backend": "0.1.16", + "@backstage/plugin-azure-sites-common": "0.1.1", + "@backstage/plugin-badges": "0.2.49", + "@backstage/plugin-badges-backend": "0.3.3", + "@backstage/plugin-bazaar": "0.2.17", + "@backstage/plugin-bazaar-backend": "0.3.3", + "@backstage/plugin-bitbucket-cloud-common": "0.2.13", + "@backstage/plugin-bitrise": "0.1.52", + "@backstage/plugin-catalog": "1.14.0", + "@backstage/plugin-catalog-backend": "1.14.0", + "@backstage/plugin-catalog-backend-module-aws": "0.3.0", + "@backstage/plugin-catalog-backend-module-azure": "0.1.25", + "@backstage/plugin-catalog-backend-module-bitbucket": "0.2.21", + "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.21", + "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.19", + "@backstage/plugin-catalog-backend-module-gcp": "0.1.6", + "@backstage/plugin-catalog-backend-module-gerrit": "0.1.22", + "@backstage/plugin-catalog-backend-module-github": "0.4.4", + "@backstage/plugin-catalog-backend-module-github-org": "0.1.0", + "@backstage/plugin-catalog-backend-module-gitlab": "0.3.3", + "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.4.10", + "@backstage/plugin-catalog-backend-module-ldap": "0.5.21", + "@backstage/plugin-catalog-backend-module-msgraph": "0.5.13", + "@backstage/plugin-catalog-backend-module-openapi": "0.1.23", + "@backstage/plugin-catalog-backend-module-puppetdb": "0.1.11", + "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.1.3", + "@backstage/plugin-catalog-backend-module-unprocessed": "0.3.3", + "@backstage/plugin-catalog-common": "1.0.17", + "@backstage/plugin-catalog-graph": "0.2.37", + "@backstage/plugin-catalog-graphql": "0.4.0", + "@backstage/plugin-catalog-import": "0.10.1", + "@backstage/plugin-catalog-node": "1.4.7", + "@backstage/plugin-catalog-react": "1.8.5", + "@backstage/plugin-catalog-unprocessed-entities": "0.1.4", + "@backstage/plugin-cicd-statistics": "0.1.27", + "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.21", + "@backstage/plugin-circleci": "0.3.25", + "@backstage/plugin-cloudbuild": "0.3.25", + "@backstage/plugin-code-climate": "0.1.25", + "@backstage/plugin-code-coverage": "0.2.18", + "@backstage/plugin-code-coverage-backend": "0.2.20", + "@backstage/plugin-codescene": "0.1.18", + "@backstage/plugin-config-schema": "0.1.46", + "@backstage/plugin-cost-insights": "0.12.14", + "@backstage/plugin-cost-insights-common": "0.1.2", + "@backstage/plugin-devtools": "0.1.5", + "@backstage/plugin-devtools-backend": "0.2.3", + "@backstage/plugin-devtools-common": "0.1.5", + "@backstage/plugin-dynatrace": "7.0.5", + "@backstage/plugin-entity-feedback": "0.2.8", + "@backstage/plugin-entity-feedback-backend": "0.2.3", + "@backstage/plugin-entity-feedback-common": "0.1.3", + "@backstage/plugin-entity-validation": "0.1.10", + "@backstage/plugin-events-backend": "0.2.15", + "@backstage/plugin-events-backend-module-aws-sqs": "0.2.9", + "@backstage/plugin-events-backend-module-azure": "0.1.16", + "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.16", + "@backstage/plugin-events-backend-module-gerrit": "0.1.16", + "@backstage/plugin-events-backend-module-github": "0.1.16", + "@backstage/plugin-events-backend-module-gitlab": "0.1.16", + "@backstage/plugin-events-backend-test-utils": "0.1.16", + "@backstage/plugin-events-node": "0.2.15", + "@internal/plugin-todo-list": "1.0.18", + "@internal/plugin-todo-list-backend": "1.0.18", + "@internal/plugin-todo-list-common": "1.0.14", + "@backstage/plugin-explore": "0.4.11", + "@backstage/plugin-explore-backend": "0.0.16", + "@backstage/plugin-explore-common": "0.0.2", + "@backstage/plugin-explore-react": "0.0.32", + "@backstage/plugin-firehydrant": "0.2.9", + "@backstage/plugin-fossa": "0.2.57", + "@backstage/plugin-gcalendar": "0.3.19", + "@backstage/plugin-gcp-projects": "0.3.42", + "@backstage/plugin-git-release-manager": "0.3.38", + "@backstage/plugin-github-actions": "0.6.6", + "@backstage/plugin-github-deployments": "0.1.56", + "@backstage/plugin-github-issues": "0.2.14", + "@backstage/plugin-github-pull-requests-board": "0.1.19", + "@backstage/plugin-gitops-profiles": "0.3.41", + "@backstage/plugin-gocd": "0.1.31", + "@backstage/plugin-graphiql": "0.2.55", + "@backstage/plugin-graphql-backend": "0.2.0", + "@backstage/plugin-graphql-voyager": "0.1.8", + "@backstage/plugin-home": "0.5.9", + "@backstage/plugin-home-react": "0.1.4", + "@backstage/plugin-ilert": "0.2.14", + "@backstage/plugin-jenkins": "0.9.0", + "@backstage/plugin-jenkins-backend": "0.3.0", + "@backstage/plugin-jenkins-common": "0.1.20", + "@backstage/plugin-kafka": "0.3.25", + "@backstage/plugin-kafka-backend": "0.3.3", + "@backstage/plugin-kubernetes": "0.11.0", + "@backstage/plugin-kubernetes-backend": "0.13.0", + "@backstage/plugin-kubernetes-cluster": "0.0.1", + "@backstage/plugin-kubernetes-common": "0.7.0", + "@backstage/plugin-kubernetes-node": "0.1.0", + "@backstage/plugin-kubernetes-react": "0.1.0", + "@backstage/plugin-lighthouse": "0.4.10", + "@backstage/plugin-lighthouse-backend": "0.3.3", + "@backstage/plugin-lighthouse-common": "0.1.4", + "@backstage/plugin-linguist": "0.1.10", + "@backstage/plugin-linguist-backend": "0.5.3", + "@backstage/plugin-linguist-common": "0.1.2", + "@backstage/plugin-microsoft-calendar": "0.1.8", + "@backstage/plugin-newrelic": "0.3.41", + "@backstage/plugin-newrelic-dashboard": "0.3.0", + "@backstage/plugin-nomad": "0.1.6", + "@backstage/plugin-nomad-backend": "0.1.8", + "@backstage/plugin-octopus-deploy": "0.2.7", + "@backstage/plugin-opencost": "0.2.1", + "@backstage/plugin-org": "0.6.15", + "@backstage/plugin-org-react": "0.1.14", + "@backstage/plugin-pagerduty": "0.6.6", + "@backstage/plugin-periskop": "0.1.23", + "@backstage/plugin-periskop-backend": "0.2.3", + "@backstage/plugin-permission-backend": "0.5.29", + "@backstage/plugin-permission-backend-module-allow-all-policy": "0.1.3", + "@backstage/plugin-permission-common": "0.7.9", + "@backstage/plugin-permission-node": "0.7.17", + "@backstage/plugin-permission-react": "0.4.16", + "@backstage/plugin-playlist": "0.1.17", + "@backstage/plugin-playlist-backend": "0.3.10", + "@backstage/plugin-playlist-common": "0.1.11", + "@backstage/plugin-proxy-backend": "0.4.3", + "@backstage/plugin-puppetdb": "0.1.8", + "@backstage/plugin-rollbar": "0.4.25", + "@backstage/plugin-rollbar-backend": "0.1.51", + "@backstage/plugin-scaffolder": "1.15.1", + "@backstage/plugin-scaffolder-backend": "1.18.0", + "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.2.7", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.30", + "@backstage/plugin-scaffolder-backend-module-gitlab": "0.2.9", + "@backstage/plugin-scaffolder-backend-module-rails": "0.4.23", + "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.14", + "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.27", + "@backstage/plugin-scaffolder-common": "1.4.2", + "@backstage/plugin-scaffolder-node": "0.2.6", + "@backstage/plugin-scaffolder-react": "1.5.6", + "@backstage/plugin-search": "1.4.1", + "@backstage/plugin-search-backend": "1.4.6", + "@backstage/plugin-search-backend-module-catalog": "0.1.10", + "@backstage/plugin-search-backend-module-elasticsearch": "1.3.9", + "@backstage/plugin-search-backend-module-explore": "0.1.10", + "@backstage/plugin-search-backend-module-pg": "0.5.15", + "@backstage/plugin-search-backend-module-techdocs": "0.1.10", + "@backstage/plugin-search-backend-node": "1.2.10", + "@backstage/plugin-search-common": "1.2.7", + "@backstage/plugin-search-react": "1.7.1", + "@backstage/plugin-sentry": "0.5.10", + "@backstage/plugin-shortcuts": "0.3.15", + "@backstage/plugin-sonarqube": "0.7.6", + "@backstage/plugin-sonarqube-backend": "0.2.8", + "@backstage/plugin-sonarqube-react": "0.1.9", + "@backstage/plugin-splunk-on-call": "0.4.14", + "@backstage/plugin-stack-overflow": "0.1.21", + "@backstage/plugin-stack-overflow-backend": "0.2.10", + "@backstage/plugin-stackstorm": "0.1.7", + "@backstage/plugin-tech-insights": "0.3.17", + "@backstage/plugin-tech-insights-backend": "0.5.20", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.38", + "@backstage/plugin-tech-insights-common": "0.2.12", + "@backstage/plugin-tech-insights-node": "0.4.12", + "@backstage/plugin-tech-radar": "0.6.9", + "@backstage/plugin-techdocs": "1.8.0", + "@backstage/plugin-techdocs-addons-test-utils": "1.0.22", + "@backstage/plugin-techdocs-backend": "1.8.0", + "@backstage/plugin-techdocs-module-addons-contrib": "1.1.1", + "@backstage/plugin-techdocs-node": "1.9.0", + "@backstage/plugin-techdocs-react": "1.1.12", + "@backstage/plugin-todo": "0.2.28", + "@backstage/plugin-todo-backend": "0.3.4", + "@backstage/plugin-user-settings": "0.7.11", + "@backstage/plugin-user-settings-backend": "0.2.4", + "@backstage/plugin-vault": "0.1.20", + "@backstage/plugin-vault-backend": "0.3.11", + "@backstage/plugin-xcmetrics": "0.2.44" + }, + "changesets": [] +} From 5faf1e186a7a40014939ec858178edf4e154c0c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:33:48 +0000 Subject: [PATCH 084/348] build(deps): bump @babel/traverse from 7.22.11 to 7.23.2 Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.22.11 to 7.23.2. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse) --- updated-dependencies: - dependency-name: "@babel/traverse" dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 108 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 98 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6ced2641d6..b948d90768 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1810,6 +1810,16 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.22.13": + version: 7.22.13 + resolution: "@babel/code-frame@npm:7.22.13" + dependencies: + "@babel/highlight": ^7.22.13 + chalk: ^2.4.2 + checksum: 22e342c8077c8b77eeb11f554ecca2ba14153f707b85294fcf6070b6f6150aae88a7b7436dd88d8c9289970585f3fe5b9b941c5aa3aa26a6d5a8ef3f292da058 + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.18.8, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": version: 7.22.9 resolution: "@babel/compat-data@npm:7.22.9" @@ -1852,6 +1862,18 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/generator@npm:7.23.0" + dependencies: + "@babel/types": ^7.23.0 + "@jridgewell/gen-mapping": ^0.3.2 + "@jridgewell/trace-mapping": ^0.3.17 + jsesc: ^2.5.1 + checksum: 8efe24adad34300f1f8ea2add420b28171a646edc70f2a1b3e1683842f23b8b7ffa7e35ef0119294e1901f45bfea5b3dc70abe1f10a1917ccdfb41bed69be5f1 + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:^7.16.0, @babel/helper-annotate-as-pure@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" @@ -1930,6 +1952,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-environment-visitor@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-environment-visitor@npm:7.22.20" + checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 + languageName: node + linkType: hard + "@babel/helper-environment-visitor@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-environment-visitor@npm:7.22.5" @@ -1947,6 +1976,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" + dependencies: + "@babel/template": ^7.22.15 + "@babel/types": ^7.23.0 + checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10 + languageName: node + linkType: hard + "@babel/helper-hoist-variables@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-hoist-variables@npm:7.22.5" @@ -2065,6 +2104,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-validator-identifier@npm:7.22.5" @@ -2112,6 +2158,17 @@ __metadata: languageName: node linkType: hard +"@babel/highlight@npm:^7.22.13": + version: 7.22.20 + resolution: "@babel/highlight@npm:7.22.20" + dependencies: + "@babel/helper-validator-identifier": ^7.22.20 + chalk: ^2.4.2 + js-tokens: ^4.0.0 + checksum: 84bd034dca309a5e680083cd827a766780ca63cef37308404f17653d32366ea76262bd2364b2d38776232f2d01b649f26721417d507e8b4b6da3e4e739f6d134 + languageName: node + linkType: hard + "@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.15, @babel/parser@npm:^7.22.11, @babel/parser@npm:^7.22.5": version: 7.22.11 resolution: "@babel/parser@npm:7.22.11" @@ -2121,6 +2178,15 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/parser@npm:7.23.0" + bin: + parser: ./bin/babel-parser.js + checksum: 453fdf8b9e2c2b7d7b02139e0ce003d1af21947bbc03eb350fb248ee335c9b85e4ab41697ddbdd97079698de825a265e45a0846bb2ed47a2c7c1df833f42a354 + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.22.5" @@ -3325,21 +3391,32 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.22.11, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.2": - version: 7.22.11 - resolution: "@babel/traverse@npm:7.22.11" +"@babel/template@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/template@npm:7.22.15" dependencies: - "@babel/code-frame": ^7.22.10 - "@babel/generator": ^7.22.10 - "@babel/helper-environment-visitor": ^7.22.5 - "@babel/helper-function-name": ^7.22.5 + "@babel/code-frame": ^7.22.13 + "@babel/parser": ^7.22.15 + "@babel/types": ^7.22.15 + checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.22.11, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.2": + version: 7.23.2 + resolution: "@babel/traverse@npm:7.23.2" + dependencies: + "@babel/code-frame": ^7.22.13 + "@babel/generator": ^7.23.0 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 "@babel/helper-hoist-variables": ^7.22.5 "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/parser": ^7.22.11 - "@babel/types": ^7.22.11 + "@babel/parser": ^7.23.0 + "@babel/types": ^7.23.0 debug: ^4.1.0 globals: ^11.1.0 - checksum: 4ad62d548ca8b95dbf45bae16cc167428f174f3c837d55a5878b1f17bdbc8b384d6df741dc7c461b62c04d881cf25644d3ab885909ba46e3ac43224e2b15b504 + checksum: 26a1eea0dde41ab99dde8b9773a013a0dc50324e5110a049f5d634e721ff08afffd54940b3974a20308d7952085ac769689369e9127dea655f868c0f6e1ab35d languageName: node linkType: hard @@ -3354,6 +3431,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.22.15, @babel/types@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/types@npm:7.23.0" + dependencies: + "@babel/helper-string-parser": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 + to-fast-properties: ^2.0.0 + checksum: 215fe04bd7feef79eeb4d33374b39909ce9cad1611c4135a4f7fdf41fe3280594105af6d7094354751514625ea92d0875aba355f53e86a92600f290e77b0e604 + languageName: node + linkType: hard + "@backstage/app-defaults@workspace:^, @backstage/app-defaults@workspace:packages/app-defaults": version: 0.0.0-use.local resolution: "@backstage/app-defaults@workspace:packages/app-defaults" From d9b752bdd761a29ffb1f2ee8df72930262edcf1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 17 Oct 2023 13:54:31 +0200 Subject: [PATCH 085/348] dedup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- yarn.lock | 106 +++++------------------------------------------------- 1 file changed, 9 insertions(+), 97 deletions(-) diff --git a/yarn.lock b/yarn.lock index b948d90768..9b1dfe3754 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1800,17 +1800,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.22.10, @babel/code-frame@npm:^7.22.5, @babel/code-frame@npm:^7.8.3": - version: 7.22.10 - resolution: "@babel/code-frame@npm:7.22.10" - dependencies: - "@babel/highlight": ^7.22.10 - chalk: ^2.4.2 - checksum: 89a06534ad19759da6203a71bad120b1d7b2ddc016c8e07d4c56b35dea25e7396c6da60a754e8532a86733092b131ae7f661dbe6ba5d165ea777555daa2ed3c9 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.22.13": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.22.10, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.8.3": version: 7.22.13 resolution: "@babel/code-frame@npm:7.22.13" dependencies: @@ -1850,19 +1840,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.22.10, @babel/generator@npm:^7.7.2": - version: 7.22.10 - resolution: "@babel/generator@npm:7.22.10" - dependencies: - "@babel/types": ^7.22.10 - "@jridgewell/gen-mapping": ^0.3.2 - "@jridgewell/trace-mapping": ^0.3.17 - jsesc: ^2.5.1 - checksum: 59a79730abdff9070692834bd3af179e7a9413fa2ff7f83dff3eb888765aeaeb2bfc7b0238a49613ed56e1af05956eff303cc139f2407eda8df974813e486074 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.23.0": +"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.22.10, @babel/generator@npm:^7.23.0, @babel/generator@npm:^7.7.2": version: 7.23.0 resolution: "@babel/generator@npm:7.23.0" dependencies: @@ -1952,31 +1930,14 @@ __metadata: languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.22.20": +"@babel/helper-environment-visitor@npm:^7.22.20, @babel/helper-environment-visitor@npm:^7.22.5": version: 7.22.20 resolution: "@babel/helper-environment-visitor@npm:7.22.20" checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-environment-visitor@npm:7.22.5" - checksum: 248532077d732a34cd0844eb7b078ff917c3a8ec81a7f133593f71a860a582f05b60f818dc5049c2212e5baa12289c27889a4b81d56ef409b4863db49646c4b1 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-function-name@npm:7.22.5" - dependencies: - "@babel/template": ^7.22.5 - "@babel/types": ^7.22.5 - checksum: 6b1f6ce1b1f4e513bf2c8385a557ea0dd7fa37971b9002ad19268ca4384bbe90c09681fe4c076013f33deabc63a53b341ed91e792de741b4b35e01c00238177a - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.23.0": +"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": version: 7.23.0 resolution: "@babel/helper-function-name@npm:7.23.0" dependencies: @@ -2104,20 +2065,13 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.20": +"@babel/helper-validator-identifier@npm:^7.22.20, @babel/helper-validator-identifier@npm:^7.22.5": version: 7.22.20 resolution: "@babel/helper-validator-identifier@npm:7.22.20" checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-validator-identifier@npm:7.22.5" - checksum: 7f0f30113474a28298c12161763b49de5018732290ca4de13cdaefd4fd0d635a6fe3f6686c37a02905fb1e64f21a5ee2b55140cf7b070e729f1bd66866506aea - languageName: node - linkType: hard - "@babel/helper-validator-option@npm:^7.16.7, @babel/helper-validator-option@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-validator-option@npm:7.22.5" @@ -2147,18 +2101,7 @@ __metadata: languageName: node linkType: hard -"@babel/highlight@npm:^7.0.0, @babel/highlight@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/highlight@npm:7.22.10" - dependencies: - "@babel/helper-validator-identifier": ^7.22.5 - chalk: ^2.4.2 - js-tokens: ^4.0.0 - checksum: f714a1e1a72dd9d72f6383f4f30fd342e21a8df32d984a4ea8f5eab691bb6ba6db2f8823d4b4cf135d98869e7a98925b81306aa32ee3c429f8cfa52c75889e1b - languageName: node - linkType: hard - -"@babel/highlight@npm:^7.22.13": +"@babel/highlight@npm:^7.0.0, @babel/highlight@npm:^7.22.13": version: 7.22.20 resolution: "@babel/highlight@npm:7.22.20" dependencies: @@ -2169,16 +2112,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.15, @babel/parser@npm:^7.22.11, @babel/parser@npm:^7.22.5": - version: 7.22.11 - resolution: "@babel/parser@npm:7.22.11" - bin: - parser: ./bin/babel-parser.js - checksum: 332079ed09794d3685343e9fc39c6a12dcb6ea589119f2135952cdef2424296786bb609a33f6dfa9be271797bbf8339f1865118418ea50b32a0c701734c96664 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.15, @babel/parser@npm:^7.22.11, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0": version: 7.23.0 resolution: "@babel/parser@npm:7.23.0" bin: @@ -3380,18 +3314,7 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.18.10, @babel/template@npm:^7.22.5, @babel/template@npm:^7.3.3": - version: 7.22.5 - resolution: "@babel/template@npm:7.22.5" - dependencies: - "@babel/code-frame": ^7.22.5 - "@babel/parser": ^7.22.5 - "@babel/types": ^7.22.5 - checksum: c5746410164039aca61829cdb42e9a55410f43cace6f51ca443313f3d0bdfa9a5a330d0b0df73dc17ef885c72104234ae05efede37c1cc8a72dc9f93425977a3 - languageName: node - linkType: hard - -"@babel/template@npm:^7.22.15": +"@babel/template@npm:^7.18.10, @babel/template@npm:^7.22.15, @babel/template@npm:^7.22.5, @babel/template@npm:^7.3.3": version: 7.22.15 resolution: "@babel/template@npm:7.22.15" dependencies: @@ -3420,18 +3343,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.20.0, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.11, @babel/types@npm:^7.22.5, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.22.11 - resolution: "@babel/types@npm:7.22.11" - dependencies: - "@babel/helper-string-parser": ^7.22.5 - "@babel/helper-validator-identifier": ^7.22.5 - to-fast-properties: ^2.0.0 - checksum: 431a6446896adb62c876d0fe75263835735d3c974aae05356a87eb55f087c20a777028cf08eadcace7993e058bbafe3b21ce2119363222c6cef9eedd7a204810 - languageName: node - linkType: hard - -"@babel/types@npm:^7.22.15, @babel/types@npm:^7.23.0": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.20.0, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.11, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": version: 7.23.0 resolution: "@babel/types@npm:7.23.0" dependencies: From 3fdffbb69919dc894bc5be4b2d559bc77997bf6d Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 17 Oct 2023 14:09:02 +0200 Subject: [PATCH 086/348] chore: add missing changeset Signed-off-by: blam --- .changeset/fair-parrots-lick.md | 5 +++++ .changeset/violet-lamps-appear.md | 12 ++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 .changeset/fair-parrots-lick.md create mode 100644 .changeset/violet-lamps-appear.md diff --git a/.changeset/fair-parrots-lick.md b/.changeset/fair-parrots-lick.md new file mode 100644 index 0000000000..dffe6be1e2 --- /dev/null +++ b/.changeset/fair-parrots-lick.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Remove the duplicate versions of `@rjsf/*` as they're no longer needed diff --git a/.changeset/violet-lamps-appear.md b/.changeset/violet-lamps-appear.md new file mode 100644 index 0000000000..23536fb728 --- /dev/null +++ b/.changeset/violet-lamps-appear.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-scaffolder': minor +'@backstage/plugin-scaffolder-react': minor +--- + +Release design improvements for the `Scaffolder` plugin and support v5 of `@rjsf/*` libraries. + +This change should be non-breaking. If you're seeing typescript issues after migrating please [open an issue](https://github.com/backstage/backstage/issues/new/choose) + +The `next` versions like `createNextFieldExtension` and `NextScaffolderPage` have been promoted to the public interface under `createScaffolderFieldExtension` and `ScaffolderPage`, so any older imports which are no longer found will need updating from `@backstage/plugin-scaffolder/alpha` or `@backstage/plugin-scaffolder-react/alpha` will need to be imported from `@backstage/plugin-scaffolder` and `@backstage/plugin-scaffolder-react` respectively. + +The legacy versions are now available in `/alpha` under `createLegacyFieldExtension` and `LegacyScaffolderPage` if you're running into issues, but be aware that these will be removed in a next mainline release. From 154f6e4490cbd5df6398b80aced03efa727cebbd Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 11 Oct 2023 20:02:41 +0200 Subject: [PATCH 087/348] home: add support for new backend system Signed-off-by: Vincenzo Scamporlino --- plugins/home/alpha-api-report.md | 13 ++++++++ plugins/home/package.json | 16 ++++++++++ plugins/home/src/alpha.tsx | 53 ++++++++++++++++++++++++++++++++ yarn.lock | 1 + 4 files changed, 83 insertions(+) create mode 100644 plugins/home/alpha-api-report.md create mode 100644 plugins/home/src/alpha.tsx diff --git a/plugins/home/alpha-api-report.md b/plugins/home/alpha-api-report.md new file mode 100644 index 0000000000..3ae9f14973 --- /dev/null +++ b/plugins/home/alpha-api-report.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/plugin-home" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +const _default: BackstagePlugin; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/home/package.json b/plugins/home/package.json index a239f1b17e..2bd22ee549 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -23,6 +23,21 @@ "backstage", "homepage" ], + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.tsx", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.tsx" + ], + "package.json": [ + "package.json" + ] + } + }, "sideEffects": false, "scripts": { "build": "backstage-cli package build", @@ -39,6 +54,7 @@ "@backstage/core-app-api": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-home-react": "workspace:^", "@backstage/theme": "workspace:^", diff --git a/plugins/home/src/alpha.tsx b/plugins/home/src/alpha.tsx new file mode 100644 index 0000000000..d712769cb0 --- /dev/null +++ b/plugins/home/src/alpha.tsx @@ -0,0 +1,53 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; + +import { rootRouteRef } from './routes'; +import { + coreExtensionData, + createExtensionInput, + createPageExtension, + createPlugin, +} from '@backstage/frontend-plugin-api'; + +const HomepageCompositionRootExtension = createPageExtension({ + id: 'home', + defaultPath: '/home', + routeRef: rootRouteRef, + inputs: { + props: createExtensionInput( + { children: coreExtensionData.reactElement.optional() }, + // TODO(vinzscam): title + { + singleton: true, + optional: true, + }, + ), + }, + loader: ({ inputs }) => + import('./components/').then(m => ( + + )), +}); + +/** + * @alpha + */ +export default createPlugin({ + id: 'home', + extensions: [HomepageCompositionRootExtension], +}); diff --git a/yarn.lock b/yarn.lock index b2d6c3b2e7..d17dc58776 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7208,6 +7208,7 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-home-react": "workspace:^" "@backstage/test-utils": "workspace:^" From a9c4fb996f28cd1d44c1f6fc5029c6a84a6c9a72 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 11 Oct 2023 20:03:37 +0200 Subject: [PATCH 088/348] app-next: add home plugin Signed-off-by: Vincenzo Scamporlino --- packages/app-next/src/App.tsx | 19 ++++++++++++++++++- .../app-next/src/examples/pagesPlugin.tsx | 3 +++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 92d71fee89..b2ea86feb4 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -20,13 +20,18 @@ import { pagesPlugin } from './examples/pagesPlugin'; import graphiqlPlugin from '@backstage/plugin-graphiql/alpha'; import techRadarPlugin from '@backstage/plugin-tech-radar/alpha'; import userSettingsPlugin from '@backstage/plugin-user-settings/alpha'; +import homePlugin from '@backstage/plugin-home/alpha'; + import { + coreExtensionData, + createExtension, createExtensionOverrides, createPageExtension, } from '@backstage/frontend-plugin-api'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; import techdocsPlugin from '@backstage/plugin-techdocs/alpha'; import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { homePage } from './HomePage'; /* @@ -64,6 +69,17 @@ const entityPageExtension = createPageExtension({ loader: async () =>
Just a temporary mocked entity page
, }); +const homePageExtension = createExtension({ + id: 'myhomepage', + attachTo: { id: 'home', input: 'props' }, + output: { + children: coreExtensionData.reactElement, + }, + factory({ bind }) { + bind({ children: homePage }); + }, +}); + const app = createApp({ features: [ graphiqlPlugin, @@ -71,8 +87,9 @@ const app = createApp({ techRadarPlugin, techdocsPlugin, userSettingsPlugin, + homePlugin, createExtensionOverrides({ - extensions: [entityPageExtension], + extensions: [entityPageExtension, homePageExtension], }), ], /* Handled through config instead */ diff --git a/packages/app-next/src/examples/pagesPlugin.tsx b/packages/app-next/src/examples/pagesPlugin.tsx index 6e040c2faf..1e9409a5e4 100644 --- a/packages/app-next/src/examples/pagesPlugin.tsx +++ b/packages/app-next/src/examples/pagesPlugin.tsx @@ -48,6 +48,9 @@ const IndexPage = createPageExtension({
Page 1
+
+ Home +
GraphiQL
From 17c37fcbc57319874f88c645fde8c8c5ccbde868 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 11 Oct 2023 20:03:58 +0200 Subject: [PATCH 089/348] app-next: migrate current ejected homepage Signed-off-by: Vincenzo Scamporlino --- packages/app-next/src/HomePage.tsx | 119 +++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 packages/app-next/src/HomePage.tsx diff --git a/packages/app-next/src/HomePage.tsx b/packages/app-next/src/HomePage.tsx new file mode 100644 index 0000000000..cb31beb34a --- /dev/null +++ b/packages/app-next/src/HomePage.tsx @@ -0,0 +1,119 @@ +/* + * 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 { + ClockConfig, + CustomHomepageGrid, + HeaderWorldClock, + HomePageCompanyLogo, + HomePageRandomJoke, + HomePageStarredEntities, + HomePageToolkit, + HomePageTopVisited, + HomePageRecentlyVisited, + WelcomeTitle, +} from '@backstage/plugin-home'; +import { Content, Header, Page } from '@backstage/core-components'; +import { HomePageCalendar } from '@backstage/plugin-gcalendar'; +import { MicrosoftCalendarCard } from '@backstage/plugin-microsoft-calendar'; +import React from 'react'; +import HomeIcon from '@material-ui/icons/Home'; +import { HomePagePagerDutyCard } from '@backstage/plugin-pagerduty'; + +const clockConfigs: ClockConfig[] = [ + { + label: 'NYC', + timeZone: 'America/New_York', + }, + { + label: 'UTC', + timeZone: 'UTC', + }, + { + label: 'STO', + timeZone: 'Europe/Stockholm', + }, + { + label: 'TYO', + timeZone: 'Asia/Tokyo', + }, +]; + +const timeFormat: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + hour12: false, +}; + +const defaultConfig = [ + { + component: 'CompanyLogo', + x: 0, + y: 0, + width: 12, + height: 1, + movable: false, + resizable: false, + deletable: false, + }, + { + component: 'WelcomeTitle', + x: 0, + y: 1, + width: 12, + height: 1, + }, + { + component: 'HomePageSearchBar', + x: 0, + y: 2, + width: 12, + height: 2, + }, +]; + +export const homePage = ( + +
} pageTitleOverride="Home"> + +
+ + + + + + + + + + , + }, + ]} + /> + + + + +
+); From 7878eac0a796eb3be5de9d6782a441e4f84e5573 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 17 Oct 2023 15:30:16 +0200 Subject: [PATCH 090/348] home: customize title Signed-off-by: Vincenzo Scamporlino --- packages/app-next/src/App.tsx | 7 +++++-- plugins/home/alpha-api-report.md | 6 +++++- plugins/home/src/alpha.tsx | 22 ++++++++++++++++++---- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index b2ea86feb4..d64c4dbb15 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -20,7 +20,9 @@ import { pagesPlugin } from './examples/pagesPlugin'; import graphiqlPlugin from '@backstage/plugin-graphiql/alpha'; import techRadarPlugin from '@backstage/plugin-tech-radar/alpha'; import userSettingsPlugin from '@backstage/plugin-user-settings/alpha'; -import homePlugin from '@backstage/plugin-home/alpha'; +import homePlugin, { + titleExtensionDataRef, +} from '@backstage/plugin-home/alpha'; import { coreExtensionData, @@ -74,9 +76,10 @@ const homePageExtension = createExtension({ attachTo: { id: 'home', input: 'props' }, output: { children: coreExtensionData.reactElement, + title: titleExtensionDataRef, }, factory({ bind }) { - bind({ children: homePage }); + bind({ children: homePage, title: 'just a title' }); }, }); diff --git a/plugins/home/alpha-api-report.md b/plugins/home/alpha-api-report.md index 3ae9f14973..35ce0bb86c 100644 --- a/plugins/home/alpha-api-report.md +++ b/plugins/home/alpha-api-report.md @@ -4,10 +4,14 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin<{}, {}>; export default _default; +// @alpha (undocumented) +export const titleExtensionDataRef: ConfigurableExtensionDataRef; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/home/src/alpha.tsx b/plugins/home/src/alpha.tsx index d712769cb0..c8308f7c0a 100644 --- a/plugins/home/src/alpha.tsx +++ b/plugins/home/src/alpha.tsx @@ -16,22 +16,33 @@ import React from 'react'; -import { rootRouteRef } from './routes'; import { coreExtensionData, + createExtensionDataRef, createExtensionInput, createPageExtension, createPlugin, + createRouteRef, } from '@backstage/frontend-plugin-api'; +const rootRouteRef = createRouteRef(); + +/** + * @alpha + */ +export const titleExtensionDataRef = createExtensionDataRef('title'); + const HomepageCompositionRootExtension = createPageExtension({ id: 'home', defaultPath: '/home', routeRef: rootRouteRef, inputs: { props: createExtensionInput( - { children: coreExtensionData.reactElement.optional() }, - // TODO(vinzscam): title + { + children: coreExtensionData.reactElement.optional(), + title: titleExtensionDataRef.optional(), + }, + { singleton: true, optional: true, @@ -40,7 +51,10 @@ const HomepageCompositionRootExtension = createPageExtension({ }, loader: ({ inputs }) => import('./components/').then(m => ( - + )), }); From 1db998ce6b3711df262fd32cb7a7bdc38411aa5b Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Tue, 17 Oct 2023 13:35:37 -0400 Subject: [PATCH 091/348] Fix tests Signed-off-by: Sydney Achinger --- packages/app-defaults/src/setupTests.ts | 2 -- plugins/techdocs-module-addons-contrib/src/setupTests.ts | 2 ++ plugins/techdocs/src/setupTests.ts | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/app-defaults/src/setupTests.ts b/packages/app-defaults/src/setupTests.ts index 5f1220066f..963c0f188b 100644 --- a/packages/app-defaults/src/setupTests.ts +++ b/packages/app-defaults/src/setupTests.ts @@ -15,5 +15,3 @@ */ import '@testing-library/jest-dom'; - -Element.prototype.scroll = jest.fn(); diff --git a/plugins/techdocs-module-addons-contrib/src/setupTests.ts b/plugins/techdocs-module-addons-contrib/src/setupTests.ts index 326d2ed212..56b9b18321 100644 --- a/plugins/techdocs-module-addons-contrib/src/setupTests.ts +++ b/plugins/techdocs-module-addons-contrib/src/setupTests.ts @@ -14,3 +14,5 @@ * limitations under the License. */ import '@testing-library/jest-dom'; + +Element.prototype.scrollIntoView = jest.fn(); diff --git a/plugins/techdocs/src/setupTests.ts b/plugins/techdocs/src/setupTests.ts index 963c0f188b..6c7fc2d3e3 100644 --- a/plugins/techdocs/src/setupTests.ts +++ b/plugins/techdocs/src/setupTests.ts @@ -15,3 +15,5 @@ */ import '@testing-library/jest-dom'; + +Element.prototype.scrollIntoView = jest.fn(); From a65eed00a988b5041cfe94470b2bc39bebd8d076 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 17 Oct 2023 19:32:38 +0200 Subject: [PATCH 092/348] home: fix plugin lol Signed-off-by: Vincenzo Scamporlino --- plugins/home/package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/home/package.json b/plugins/home/package.json index 2bd22ee549..2612db5bbe 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -6,9 +6,7 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" }, "backstage": { "role": "frontend-plugin" From 49d3bd983325c179ea27b157cbf6cda053bf3191 Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Tue, 17 Oct 2023 15:12:15 -0400 Subject: [PATCH 093/348] Remove unnecessary dep from dep array. Signed-off-by: Sydney Achinger --- .../TechDocsReaderPageContent/TechDocsReaderPageContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx index b8570ba25d..32fe788716 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx @@ -91,7 +91,7 @@ export const TechDocsReaderPageContent = withTechDocsReaderProvider( } else { document?.querySelector('header')?.scrollIntoView(); } - }, [hashElement, isStyleLoading, dom]); + }, [hash, hashElement, isStyleLoading]); const handleAppend = useCallback( (newShadowRoot: ShadowRoot) => { From 4728b3960d0dcda08ab7bafc9b74ff5fb221a515 Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Tue, 17 Oct 2023 16:16:27 -0400 Subject: [PATCH 094/348] changeset Signed-off-by: Sydney Achinger --- .changeset/fresh-crews-promise.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/fresh-crews-promise.md diff --git a/.changeset/fresh-crews-promise.md b/.changeset/fresh-crews-promise.md new file mode 100644 index 0000000000..fc9859086a --- /dev/null +++ b/.changeset/fresh-crews-promise.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-techdocs': patch +--- + +Fixed navigation bug that caused users to not be scrolled to the top of a new page. Fixed navigation bug where using backwards and forwards browser navigation did not scroll users to the correct place on the TechDoc page. From 5b364984bf5e66d2555cf92bedf9069cbaf31ee7 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 17 Oct 2023 23:58:01 +0200 Subject: [PATCH 095/348] home: changeset Signed-off-by: Vincenzo Scamporlino --- .changeset/quick-pumpkins-shave.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/quick-pumpkins-shave.md diff --git a/.changeset/quick-pumpkins-shave.md b/.changeset/quick-pumpkins-shave.md new file mode 100644 index 0000000000..cbb4c48dce --- /dev/null +++ b/.changeset/quick-pumpkins-shave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Added experimental support for declarative integration via the `/alpha` subpath. From d0bd66e29bc110f238de4a6ce1b7317ea0d1b1a5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 00:12:31 +0200 Subject: [PATCH 096/348] .github/workflows: remove runner hardening from test runs Signed-off-by: Patrik Oldsberg --- .github/workflows/ci.yml | 5 ----- .github/workflows/deploy_packages.yml | 5 ----- 2 files changed, 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b08a28d786..81ea6f96d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -196,11 +196,6 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit - - uses: actions/checkout@v3.6.0 - name: fetch branch master run: git fetch origin master diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index a8a4315191..f5ebfd7ee2 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -60,11 +60,6 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - name: Harden Runner - uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 - with: - egress-policy: audit - - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} From ded2058de97400263dcd5e99f24e400d7ab0c5c8 Mon Sep 17 00:00:00 2001 From: Niklas Aronsson Date: Wed, 18 Oct 2023 09:10:42 +0200 Subject: [PATCH 097/348] scaffolder cookiecutter: remove usage of mock-fs Signed-off-by: Niklas Aronsson --- .../package.json | 3 +- .../src/actions/fetch/cookiecutter.test.ts | 28 ++++++------------- yarn.lock | 3 +- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 68bbd40294..b2d8016325 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -41,11 +41,10 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", - "@types/mock-fs": "^4.13.0", - "mock-fs": "^5.2.0", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts index f944b6e598..3872b2e302 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts @@ -22,8 +22,7 @@ import { import { ConfigReader } from '@backstage/config'; import { JsonObject } from '@backstage/types'; import { ScmIntegrations } from '@backstage/integration'; -import mockFs from 'mock-fs'; -import os from 'os'; +import { createMockDirectory } from '@backstage/backend-test-utils'; import { PassThrough } from 'stream'; import { createFetchCookiecutterAction } from './cookiecutter'; import { join } from 'path'; @@ -47,6 +46,7 @@ jest.mock( ); describe('fetch:cookiecutter', () => { + const mockDir = createMockDirectory(); const integrations = ScmIntegrations.fromConfig( new ConfigReader({ integrations: { @@ -58,7 +58,7 @@ describe('fetch:cookiecutter', () => { }), ); - const mockTmpDir = os.tmpdir(); + const mockTmpDir = mockDir.path; let mockContext: ActionContext<{ url: string; @@ -106,36 +106,26 @@ describe('fetch:cookiecutter', () => { output: jest.fn(), createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), }; - - // mock the temp directory - mockFs({ [mockTmpDir]: {} }); - mockFs({ [`${join(mockTmpDir, 'template')}`]: {} }); + mockDir.clear(); + mockDir.addContent({ template: {} }); commandExists.mockResolvedValue(null); // Mock when run container is called it creates some new files in the mock filesystem containerRunner.runContainer.mockImplementation(async () => { - mockFs({ - [`${join(mockTmpDir, 'intermediate')}`]: { - 'testfile.json': '{}', - }, + mockDir.addContent({ + 'intermediate/testfile.json': '{}', }); }); // Mock when executeShellCommand is called it creates some new files in the mock filesystem executeShellCommand.mockImplementation(async () => { - mockFs({ - [`${join(mockTmpDir, 'intermediate')}`]: { - 'testfile.json': '{}', - }, + mockDir.addContent({ + 'intermediate/testfile.json': '{}', }); }); }); - afterEach(() => { - mockFs.restore(); - }); - it('should throw an error when copyWithoutRender is not an array', async () => { (mockContext.input as any).copyWithoutRender = 'not an array'; diff --git a/yarn.lock b/yarn.lock index 9f79ca0ec4..8fc014912f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8710,6 +8710,7 @@ __metadata: resolution: "@backstage/plugin-scaffolder-backend-module-cookiecutter@workspace:plugins/scaffolder-backend-module-cookiecutter" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" @@ -8718,10 +8719,8 @@ __metadata: "@backstage/types": "workspace:^" "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 - "@types/mock-fs": ^4.13.0 command-exists: ^1.2.9 fs-extra: 10.1.0 - mock-fs: ^5.2.0 msw: ^1.0.0 winston: ^3.2.1 yn: ^4.0.0 From 71c97e7d73934a0fa7cbe839d9800d31f43537bd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 00:05:25 +0200 Subject: [PATCH 098/348] type fixes for React 18 Signed-off-by: Patrik Oldsberg --- .changeset/healthy-shirts-fold.md | 6 ++++++ .changeset/popular-bikes-do.md | 5 +++++ .changeset/pretty-swans-worry.md | 5 +++++ .changeset/sweet-buckets-fry.md | 5 +++++ .changeset/thick-dolphins-boil.md | 5 +++++ .changeset/wet-cows-brake.md | 5 +++++ .changeset/wild-geese-occur.md | 5 +++++ .../legacy/TemplateEditorPage/CustomFieldExplorer.tsx | 10 +++++++--- .../TemplateEditorPage/TemplateFormPreviewer.tsx | 3 ++- 9 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 .changeset/healthy-shirts-fold.md create mode 100644 .changeset/popular-bikes-do.md create mode 100644 .changeset/pretty-swans-worry.md create mode 100644 .changeset/sweet-buckets-fry.md create mode 100644 .changeset/thick-dolphins-boil.md create mode 100644 .changeset/wet-cows-brake.md create mode 100644 .changeset/wild-geese-occur.md diff --git a/.changeset/healthy-shirts-fold.md b/.changeset/healthy-shirts-fold.md new file mode 100644 index 0000000000..f2ac0a9e83 --- /dev/null +++ b/.changeset/healthy-shirts-fold.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog': patch +'@backstage/plugin-techdocs': patch +--- + +The `spec.lifecycle' field in entities will now always be rendered as a string. diff --git a/.changeset/popular-bikes-do.md b/.changeset/popular-bikes-do.md new file mode 100644 index 0000000000..b1cc5c2cdd --- /dev/null +++ b/.changeset/popular-bikes-do.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-code-coverage': patch +--- + +The warning for missing code coverage will now render the entity as a reference. diff --git a/.changeset/pretty-swans-worry.md b/.changeset/pretty-swans-worry.md new file mode 100644 index 0000000000..621ae98fe5 --- /dev/null +++ b/.changeset/pretty-swans-worry.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fixed the type declaration of `DependencyGraphProps`, the `defs` prop now expects `JSX.Element`s. diff --git a/.changeset/sweet-buckets-fry.md b/.changeset/sweet-buckets-fry.md new file mode 100644 index 0000000000..8f17617645 --- /dev/null +++ b/.changeset/sweet-buckets-fry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +The `spec.type` field in entities will now always be rendered as a string. diff --git a/.changeset/thick-dolphins-boil.md b/.changeset/thick-dolphins-boil.md new file mode 100644 index 0000000000..dd562e620c --- /dev/null +++ b/.changeset/thick-dolphins-boil.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +The `app.title` configuration is now properly required to be a string. diff --git a/.changeset/wet-cows-brake.md b/.changeset/wet-cows-brake.md new file mode 100644 index 0000000000..9e694d8452 --- /dev/null +++ b/.changeset/wet-cows-brake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +The filter options passed to `SearchResultGroupLayout` are now always explicitly rendered as strings by default. diff --git a/.changeset/wild-geese-occur.md b/.changeset/wild-geese-occur.md new file mode 100644 index 0000000000..b97620e7f5 --- /dev/null +++ b/.changeset/wild-geese-occur.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Minor internal code cleanup. diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx index 0ba5db560a..9107ac67eb 100644 --- a/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx @@ -101,7 +101,7 @@ export const CustomFieldExplorer = ({ }, [customFieldExtensions]); const handleSelectionChange = useCallback( - selection => { + (selection: LegacyFieldExtensionOptions) => { setSelectedField(selection); setFieldFormState({}); setFormState({}); @@ -110,7 +110,7 @@ export const CustomFieldExplorer = ({ ); const handleFieldConfigChange = useCallback( - state => { + (state: {}) => { setFieldFormState(state); // Force TemplateEditorForm to re-render since some fields // may not be responsive to ui:option changes @@ -130,7 +130,11 @@ export const CustomFieldExplorer = ({ value={selectedField} label="Choose Custom Field Extension" labelId="select-field-label" - onChange={e => handleSelectionChange(e.target.value)} + onChange={e => + handleSelectionChange( + e.target.value as LegacyFieldExtensionOptions, + ) + } > {fieldOptions.map((option, idx) => ( diff --git a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx index b83acf85a5..9e92d12d93 100644 --- a/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -162,7 +162,8 @@ export const TemplateFormPreviewer = ({ ); const handleSelectChange = useCallback( - selected => { + // TODO(Rugvip): Afaik this should be Entity, but didn't want to make runtime changes while fixing types + (selected: any) => { setSelectedTemplate(selected); setTemplateYaml(yaml.stringify(selected.spec)); }, From 4a0227ee3dcef507ef2d04d0c4e13d4ab6c10fe5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 00:25:28 +0200 Subject: [PATCH 099/348] switch to React 18 Signed-off-by: Patrik Oldsberg --- package.json | 4 +- packages/app-next/package.json | 4 +- packages/app/package.json | 4 +- .../techdocs-cli-embedded-app/package.json | 4 +- yarn.lock | 61 +++++++++---------- 5 files changed, 37 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index 80b3d4a374..5ff39c8770 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,8 @@ ] }, "resolutions": { - "@types/react": "^17", - "@types/react-dom": "^17", + "@types/react": "^18", + "@types/react-dom": "^18", "jest-haste-map@^29.4.3": "patch:jest-haste-map@npm%3A29.4.3#./.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch", "mock-fs@^5.2.0": "patch:mock-fs@npm%3A5.2.0#./.yarn/patches/mock-fs-npm-5.2.0-5103a7b507.patch" }, diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 0b0dcd7429..8a088bbed8 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -89,8 +89,8 @@ "app-next-example-plugin": "workspace:^", "history": "^5.0.0", "lodash": "^4.17.21", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.2", + "react-dom": "^18.0.2", "react-router": "^6.3.0", "react-router-dom": "^6.3.0", "react-use": "^17.2.4", diff --git a/packages/app/package.json b/packages/app/package.json index 59aa16734e..0201b43af5 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -94,8 +94,8 @@ "@roadiehq/backstage-plugin-github-pull-requests": "^2.2.7", "@roadiehq/backstage-plugin-travis-ci": "^2.0.5", "history": "^5.0.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.2", + "react-dom": "^18.0.2", "react-router": "^6.3.0", "react-router-dom": "^6.3.0", "react-use": "^17.2.4", diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 71e80fa2f0..fd3ca45114 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -29,8 +29,8 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "history": "^5.0.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.2", + "react-dom": "^18.0.2", "react-router-dom": "^6.3.0", "react-use": "^17.2.4" }, diff --git a/yarn.lock b/yarn.lock index b2d6c3b2e7..611ade7792 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18198,12 +18198,12 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^17": - version: 17.0.21 - resolution: "@types/react-dom@npm:17.0.21" +"@types/react-dom@npm:^18": + version: 18.2.13 + resolution: "@types/react-dom@npm:18.2.13" dependencies: - "@types/react": ^17 - checksum: a2e3f068c1374601856b63bc57f3f436cf6270c1ba5c5cef0776def6de296c8bdd31c39b5be9e9e77f4652e923bef1e71ae377a2b038f4a81bfd0fec8d10d0d0 + "@types/react": "*" + checksum: 22ba066b141dca5a5a9227fae0afc7c94b470fff8e8a38ade72649da57a8ea04d0cb2ba3e22005e7d8e772d49bddd28855b1dd98e6defd033bba6afb6edff883 languageName: node linkType: hard @@ -18300,14 +18300,14 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^17": - version: 17.0.68 - resolution: "@types/react@npm:17.0.68" +"@types/react@npm:^18": + version: 18.2.28 + resolution: "@types/react@npm:18.2.28" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: c6ca4415b53b1abe91162b29af541a1797a56a6f462ef796e8ebda3eaa4d0609205f4f17b3fce8d9a12235d4ffd8a67c47b5e018ed85c2f3bee0fba8f54638c1 + checksum: 81381bedeba83278f4c9febb0b83e0bd3f42a25897a50b9cb36ef53651d34b3d50f87ebf11211ea57ea575131f85d31e93e496ce46478a00b0f9bf7b26b5917a languageName: node linkType: hard @@ -25345,8 +25345,8 @@ __metadata: cross-env: ^7.0.0 history: ^5.0.0 lodash: ^4.17.21 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.2 + react-dom: ^18.0.2 react-router: ^6.3.0 react-router-dom: ^6.3.0 react-use: ^17.2.4 @@ -25456,8 +25456,8 @@ __metadata: "@types/zen-observable": ^0.8.0 cross-env: ^7.0.0 history: ^5.0.0 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.2 + react-dom: ^18.0.2 react-router: ^6.3.0 react-router-dom: ^6.3.0 react-use: ^17.2.4 @@ -36546,16 +36546,15 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^17.0.2": - version: 17.0.2 - resolution: "react-dom@npm:17.0.2" +"react-dom@npm:^18.0.2": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - scheduler: ^0.20.2 + scheduler: ^0.23.0 peerDependencies: - react: 17.0.2 - checksum: 1c1eaa3bca7c7228d24b70932e3d7c99e70d1d04e13bb0843bbf321582bc25d7961d6b8a6978a58a598af2af496d1cedcfb1bf65f6b0960a0a8161cb8dab743c + react: ^18.2.0 + checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc languageName: node linkType: hard @@ -37121,13 +37120,12 @@ __metadata: languageName: node linkType: hard -"react@npm:^17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" +"react@npm:^18.0.2": + version: 18.2.0 + resolution: "react@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b languageName: node linkType: hard @@ -38384,13 +38382,12 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.20.2": - version: 0.20.2 - resolution: "scheduler@npm:0.20.2" +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc + checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a languageName: node linkType: hard @@ -40245,8 +40242,8 @@ __metadata: "@types/react-dom": "*" cross-env: ^7.0.0 history: ^5.0.0 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.2 + react-dom: ^18.0.2 react-router-dom: ^6.3.0 react-use: ^17.2.4 languageName: unknown From 912a0766a542c88dae7bd063bd9e4c7edf5e7039 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 00:28:05 +0200 Subject: [PATCH 100/348] update react and react-dom peer dependency ranges to include 18 Signed-off-by: Patrik Oldsberg --- packages/app-defaults/package.json | 4 ++-- packages/app-next-example-plugin/package.json | 4 ++-- packages/core-app-api/package.json | 4 ++-- packages/core-components/package.json | 4 ++-- packages/core-plugin-api/package.json | 4 ++-- packages/frontend-app-api/package.json | 2 +- packages/frontend-plugin-api/package.json | 2 +- packages/integration-react/package.json | 4 ++-- packages/test-utils/package.json | 4 ++-- packages/theme/package.json | 4 ++-- packages/version-bridge/package.json | 4 ++-- plugins/adr/package.json | 4 ++-- plugins/airbrake/package.json | 4 ++-- plugins/allure/package.json | 4 ++-- plugins/analytics-module-ga/package.json | 4 ++-- plugins/analytics-module-ga4/package.json | 4 ++-- plugins/analytics-module-newrelic-browser/package.json | 2 +- plugins/apache-airflow/package.json | 4 ++-- plugins/api-docs-module-protoc-gen-doc/package.json | 4 ++-- plugins/api-docs/package.json | 4 ++-- plugins/apollo-explorer/package.json | 4 ++-- plugins/azure-devops/package.json | 4 ++-- plugins/azure-sites/package.json | 4 ++-- plugins/badges/package.json | 4 ++-- plugins/bazaar/package.json | 4 ++-- plugins/bitrise/package.json | 4 ++-- plugins/catalog-graph/package.json | 4 ++-- plugins/catalog-graphql/package.json | 4 ++-- plugins/catalog-import/package.json | 4 ++-- plugins/catalog-react/package.json | 4 ++-- plugins/catalog-unprocessed-entities/package.json | 4 ++-- plugins/catalog/package.json | 4 ++-- plugins/cicd-statistics-module-gitlab/package.json | 4 ++-- plugins/cicd-statistics/package.json | 4 ++-- plugins/circleci/package.json | 4 ++-- plugins/cloudbuild/package.json | 4 ++-- plugins/code-climate/package.json | 4 ++-- plugins/code-coverage/package.json | 4 ++-- plugins/codescene/package.json | 4 ++-- plugins/config-schema/package.json | 4 ++-- plugins/cost-insights/package.json | 4 ++-- plugins/devtools/package.json | 4 ++-- plugins/dynatrace/package.json | 4 ++-- plugins/entity-feedback/package.json | 4 ++-- plugins/entity-validation/package.json | 4 ++-- plugins/example-todo-list/package.json | 4 ++-- plugins/explore-react/package.json | 4 ++-- plugins/explore/package.json | 4 ++-- plugins/firehydrant/package.json | 4 ++-- plugins/fossa/package.json | 4 ++-- plugins/gcalendar/package.json | 4 ++-- plugins/gcp-projects/package.json | 4 ++-- plugins/git-release-manager/package.json | 4 ++-- plugins/github-actions/package.json | 4 ++-- plugins/github-deployments/package.json | 4 ++-- plugins/github-issues/package.json | 4 ++-- plugins/github-pull-requests-board/package.json | 4 ++-- plugins/gitops-profiles/package.json | 4 ++-- plugins/gocd/package.json | 4 ++-- plugins/graphiql/package.json | 4 ++-- plugins/graphql-voyager/package.json | 4 ++-- plugins/home-react/package.json | 4 ++-- plugins/home/package.json | 4 ++-- plugins/ilert/package.json | 4 ++-- plugins/jenkins/package.json | 4 ++-- plugins/kafka/package.json | 4 ++-- plugins/kubernetes-cluster/package.json | 4 ++-- plugins/kubernetes-react/package.json | 2 +- plugins/kubernetes/package.json | 4 ++-- plugins/lighthouse/package.json | 4 ++-- plugins/linguist/package.json | 4 ++-- plugins/microsoft-calendar/package.json | 4 ++-- plugins/newrelic-dashboard/package.json | 4 ++-- plugins/newrelic/package.json | 4 ++-- plugins/nomad/package.json | 4 ++-- plugins/octopus-deploy/package.json | 4 ++-- plugins/opencost/package.json | 2 +- plugins/org-react/package.json | 4 ++-- plugins/org/package.json | 4 ++-- plugins/pagerduty/package.json | 4 ++-- plugins/periskop/package.json | 4 ++-- plugins/permission-react/package.json | 4 ++-- plugins/playlist/package.json | 4 ++-- plugins/puppetdb/package.json | 4 ++-- plugins/rollbar/package.json | 4 ++-- plugins/scaffolder-react/package.json | 4 ++-- plugins/scaffolder/package.json | 4 ++-- plugins/search-react/package.json | 4 ++-- plugins/search/package.json | 4 ++-- plugins/sentry/package.json | 4 ++-- plugins/shortcuts/package.json | 4 ++-- plugins/sonarqube-react/package.json | 4 ++-- plugins/sonarqube/package.json | 4 ++-- plugins/splunk-on-call/package.json | 4 ++-- plugins/stack-overflow/package.json | 4 ++-- plugins/stackstorm/package.json | 4 ++-- plugins/tech-insights/package.json | 4 ++-- plugins/tech-radar/package.json | 4 ++-- plugins/techdocs-addons-test-utils/package.json | 4 ++-- plugins/techdocs-module-addons-contrib/package.json | 4 ++-- plugins/techdocs-react/package.json | 4 ++-- plugins/todo/package.json | 4 ++-- plugins/user-settings/package.json | 4 ++-- plugins/vault/package.json | 4 ++-- plugins/xcmetrics/package.json | 4 ++-- 105 files changed, 205 insertions(+), 205 deletions(-) diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 40507f0bb9..eb87496e80 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -42,8 +42,8 @@ "@material-ui/icons": "^4.9.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index 73666a569d..1e1b903271 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -39,8 +39,8 @@ "@material-ui/icons": "^4.9.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 3ae162315f..56cfc9d046 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -57,8 +57,8 @@ "zod": "^3.21.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 09b6dfb2b8..1f99a682e5 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -78,8 +78,8 @@ "zod": "^3.21.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 56362eac7b..4d6e010255 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -54,8 +54,8 @@ "i18next": "^22.4.15" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index ebd4291317..472b914b6e 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -49,7 +49,7 @@ "lodash": "^4.17.21" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" } } diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 8d90a84d71..4c9efdfaf6 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -35,7 +35,7 @@ "dist" ], "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "dependencies": { diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 9909350e91..d75c2e612c 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -38,8 +38,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 28aa1715e6..dd310800ad 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -62,8 +62,8 @@ }, "peerDependencies": { "@testing-library/react": "^12.1.3 || ^13.0.0 || ^14.0.0", - "react": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/theme/package.json b/packages/theme/package.json index 15046d057b..8b6bd081c1 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -40,8 +40,8 @@ "peerDependencies": { "@material-ui/core": "^4.12.2", "@types/react": "^16.13.1 || ^17.0.0", - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0" + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index 8424ac54fc..6b90502021 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -36,8 +36,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 8c20d7a93a..2a18953271 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -62,8 +62,8 @@ "remark-gfm": "^3.0.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 80cf3adc35..f9ae2838b0 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/allure/package.json b/plugins/allure/package.json index d351388326..165e00077a 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -42,8 +42,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 5d5a9505da..bab595e008 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -40,8 +40,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index a786986f5e..31ea10c681 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -37,8 +37,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index f42911a93c..0f90451257 100644 --- a/plugins/analytics-module-newrelic-browser/package.json +++ b/plugins/analytics-module-newrelic-browser/package.json @@ -30,7 +30,7 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0" + "react": "^16.13.1 || ^17 || ^18" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index e0cc0619b3..368e7a9466 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -40,8 +40,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/api-docs-module-protoc-gen-doc/package.json b/plugins/api-docs-module-protoc-gen-doc/package.json index ac1b941a7d..a569f5f02e 100644 --- a/plugins/api-docs-module-protoc-gen-doc/package.json +++ b/plugins/api-docs-module-protoc-gen-doc/package.json @@ -36,8 +36,8 @@ "grpc-docs": "^1.1.2" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 0f5e9214a3..a37bf50697 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -52,8 +52,8 @@ "swagger-ui-react": "^5.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 386eab6ab0..325de67864 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -40,8 +40,8 @@ "use-deep-compare-effect": "^1.8.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 2e88ac76ab..997eda7fce 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index 77bc1d3833..57bbba41dc 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/badges/package.json b/plugins/badges/package.json index ccd4e37db0..c63e1a876c 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 2c2f2ba1e8..4e04507e65 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -51,8 +51,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index fdf18f4380..d9a897de81 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -46,8 +46,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 52079e0fa1..e296a950c2 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 599ca62d2b..001dd72869 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -47,8 +47,8 @@ "winston": "^3.2.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index efb4922f6f..17cad0b813 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -56,8 +56,8 @@ "yaml": "^2.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 7c1dcb5551..bcd17be1c7 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -72,8 +72,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index 5bf8a0150c..7b691e6099 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 73440c6ba1..4c583a06b9 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -71,8 +71,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index c5d2332904..3aa76191f4 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -43,8 +43,8 @@ "p-limit": "^4.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index 4a1fcfd960..e5b30dc101 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -54,8 +54,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "files": [ diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 590385e7c2..0ac680e78d 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 3a2d3c8d95..5c56d69b10 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 21218a4850..4aa971e458 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 93b06e7c85..a8be86154c 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -47,8 +47,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 3eeb6452af..b2fcf79c01 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -42,8 +42,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 55b716f1f4..e21643a65f 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -45,8 +45,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 8f9bb07fc8..322604f07b 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -57,8 +57,8 @@ "yup": "^0.32.9" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index c1ad7b53fd..568e4f0d59 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -44,8 +44,8 @@ }, "peerDependencies": { "@types/react": "^16.13.1 || ^17.0.0", - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index 97c79f84f5..d05d8b5b3c 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -41,8 +41,8 @@ }, "peerDependencies": { "@backstage/plugin-catalog-react": "workspace:^", - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 876653986e..13688922fa 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index e47ff094bf..773266def5 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -51,8 +51,8 @@ "yaml": "^2.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 36eb464bb5..267fe620b1 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -39,8 +39,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index d9b9145c27..f69738543f 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -37,8 +37,8 @@ "@backstage/plugin-explore-common": "workspace:^" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 1b4dc7b3e0..ed06d1864c 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -66,8 +66,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 6cd468514a..c8bedae934 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 8851cfc766..68aad1a889 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 1b74941ce3..ea1b8e9663 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 0544c904a2..c48f3001dc 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -44,8 +44,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 1cb5f9e4f2..aba5730df4 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -45,8 +45,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index de8f2e64dc..e165baaac9 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -52,8 +52,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 75fef7213c..f9c199ca83 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index b728856388..20c459528f 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -45,8 +45,8 @@ "react-use": "^17.4.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 3246afce3c..7536050d0c 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -51,8 +51,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 4593ab1e1a..3cf144d9e6 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 809eca8a14..50cc2f4d9f 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index c2b71fc11c..b0a12a8b46 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -60,8 +60,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index f7b89a5b83..5dee6b50e6 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index 64a4bcf6f6..aef8dd9b43 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -42,8 +42,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/home/package.json b/plugins/home/package.json index a239f1b17e..178cb55a4c 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -59,8 +59,8 @@ "zod": "^3.21.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index fc860e10c4..2747b6321f 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 8153a8bec2..c1730953fb 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -49,8 +49,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 9068de9134..9671ef168a 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -44,8 +44,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index b54c32f214..e86fe015c9 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -57,8 +57,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index 59d4b15bee..961bb116cb 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -48,7 +48,7 @@ "xterm-addon-fit": "^0.8.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0" + "react": "^16.13.1 || ^17 || ^18" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index db8f6455ce..09527dd16a 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -62,8 +62,8 @@ "xterm-addon-fit": "^0.8.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index a63c6bab59..6195bb93d2 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index df1e1f962b..73140ec8dc 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -45,8 +45,8 @@ "slugify": "^1.6.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index 8b19d35ef0..0c64c7caa5 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -65,8 +65,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index bd24971549..7937c9f52b 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 3fb1326005..ef81addd78 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/nomad/package.json b/plugins/nomad/package.json index 3623019c4c..063f2f315b 100644 --- a/plugins/nomad/package.json +++ b/plugins/nomad/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 6c72fe2446..5ff787bf59 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/opencost/package.json b/plugins/opencost/package.json index a79b79c0b2..c9986d91f2 100644 --- a/plugins/opencost/package.json +++ b/plugins/opencost/package.json @@ -40,7 +40,7 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", "react-router-dom": "*" }, "devDependencies": { diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 9e49b7bda6..f0242f0514 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/org/package.json b/plugins/org/package.json index d5dca29faa..8ceca3911c 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -46,8 +46,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index d221a753e4..8c29120ad3 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index e1cd374cce..de2635fe41 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index 145b6f7d42..c96f5e448a 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -41,8 +41,8 @@ "swr": "^2.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 224705983b..a433f2eb13 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -51,8 +51,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index ae351f5df7..54510a7a5e 100644 --- a/plugins/puppetdb/package.json +++ b/plugins/puppetdb/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 316f9532a1..c68e56bafe 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index df4a3c867f..c9eb9b87cd 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -81,8 +81,8 @@ "zod-to-json-schema": "^3.20.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index f6ca5b5003..2db000c81c 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -92,8 +92,8 @@ "zod-to-json-schema": "^3.20.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index b4a370e639..ac74e8465f 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -62,8 +62,8 @@ "react-use": "^17.3.2" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/search/package.json b/plugins/search/package.json index fe84cbe0df..27064c7abf 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -66,8 +66,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index f0a47e966b..5b53004cd3 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 263b476c0e..48116dba8f 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -44,8 +44,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index c04fdf394c..9884fbb5c4 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -45,8 +45,8 @@ "@backstage/core-plugin-api": "workspace:^" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index b812b5dd8f..cecd69c4ff 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -53,8 +53,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index bef2ebbb52..d72183423a 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 74a30cfd73..ec68b0183b 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -46,8 +46,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index ac96d2dbc2..02bc0a924f 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 6539d74abb..1f3423119b 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index b7bb44bf81..9f1d327e65 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -59,8 +59,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index b59ffc537c..dec4ad257c 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -52,8 +52,8 @@ "testing-library__dom": "^7.29.4-beta.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 76f358a3a7..8b797caaf3 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -49,8 +49,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 17b681a68b..75e4d8947d 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -49,8 +49,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 0ce3e92315..a1760a94ed 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -44,8 +44,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 849785907d..fd514527f7 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -62,8 +62,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/vault/package.json b/plugins/vault/package.json index bd7dc3cd7f..70736e40d5 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 27216f5fc2..d09b93a6f2 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -44,8 +44,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17 || ^18", + "react-dom": "^16.13.1 || ^17 || ^18", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { From e9318414a0c737b7bc47d93678572cf2eec259d9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 00:34:01 +0200 Subject: [PATCH 101/348] update @testing-library/react to v13 Signed-off-by: Patrik Oldsberg --- packages/app-defaults/package.json | 2 +- packages/app-next/package.json | 2 +- packages/app/package.json | 2 +- packages/core-app-api/package.json | 2 +- packages/core-components/package.json | 2 +- packages/core-plugin-api/package.json | 2 +- packages/dev-utils/package.json | 2 +- packages/frontend-app-api/package.json | 2 +- packages/frontend-plugin-api/package.json | 2 +- packages/techdocs-cli-embedded-app/package.json | 2 +- packages/version-bridge/package.json | 2 +- plugins/adr/package.json | 2 +- plugins/airbrake/package.json | 2 +- plugins/allure/package.json | 2 +- plugins/analytics-module-ga/package.json | 2 +- plugins/analytics-module-ga4/package.json | 2 +- plugins/analytics-module-newrelic-browser/package.json | 2 +- plugins/apache-airflow/package.json | 2 +- plugins/api-docs/package.json | 2 +- plugins/apollo-explorer/package.json | 2 +- plugins/azure-devops/package.json | 2 +- plugins/azure-sites/package.json | 2 +- plugins/bitrise/package.json | 2 +- plugins/catalog-graph/package.json | 2 +- plugins/catalog-import/package.json | 2 +- plugins/catalog-react/package.json | 2 +- plugins/catalog-unprocessed-entities/package.json | 2 +- plugins/catalog/package.json | 2 +- plugins/circleci/package.json | 2 +- plugins/cloudbuild/package.json | 2 +- plugins/code-climate/package.json | 2 +- plugins/code-coverage/package.json | 2 +- plugins/codescene/package.json | 2 +- plugins/config-schema/package.json | 2 +- plugins/cost-insights/package.json | 2 +- plugins/devtools/package.json | 2 +- plugins/dynatrace/package.json | 2 +- plugins/entity-feedback/package.json | 2 +- plugins/entity-validation/package.json | 2 +- plugins/example-todo-list/package.json | 2 +- plugins/explore-react/package.json | 2 +- plugins/explore/package.json | 2 +- plugins/firehydrant/package.json | 2 +- plugins/fossa/package.json | 2 +- plugins/gcalendar/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/github-issues/package.json | 2 +- plugins/github-pull-requests-board/package.json | 2 +- plugins/gitops-profiles/package.json | 2 +- plugins/gocd/package.json | 2 +- plugins/graphiql/package.json | 2 +- plugins/graphql-voyager/package.json | 2 +- plugins/home-react/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-cluster/package.json | 2 +- plugins/kubernetes-react/package.json | 2 +- plugins/kubernetes/package.json | 2 +- plugins/lighthouse/package.json | 2 +- plugins/linguist/package.json | 2 +- plugins/microsoft-calendar/package.json | 2 +- plugins/newrelic/package.json | 2 +- plugins/nomad/package.json | 2 +- plugins/octopus-deploy/package.json | 2 +- plugins/opencost/package.json | 2 +- plugins/org-react/package.json | 2 +- plugins/org/package.json | 2 +- plugins/pagerduty/package.json | 2 +- plugins/periskop/package.json | 2 +- plugins/permission-react/package.json | 2 +- plugins/playlist/package.json | 2 +- plugins/puppetdb/package.json | 2 +- plugins/rollbar/package.json | 2 +- plugins/scaffolder-react/package.json | 2 +- plugins/scaffolder/package.json | 2 +- plugins/search-react/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/stack-overflow/package.json | 2 +- plugins/stackstorm/package.json | 2 +- plugins/tech-insights/package.json | 2 +- plugins/tech-radar/package.json | 2 +- plugins/techdocs-addons-test-utils/package.json | 4 ++-- plugins/techdocs-module-addons-contrib/package.json | 2 +- plugins/techdocs-react/package.json | 2 +- plugins/techdocs/package.json | 2 +- plugins/todo/package.json | 2 +- plugins/user-settings/package.json | 2 +- plugins/vault/package.json | 2 +- plugins/xcmetrics/package.json | 2 +- 98 files changed, 99 insertions(+), 99 deletions(-) diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index eb87496e80..6d35e1b125 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -50,7 +50,7 @@ "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@types/react": "^16.13.1 || ^17.0.0" }, "files": [ diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 8a088bbed8..a52ec7fd17 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -100,7 +100,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/jquery": "^3.3.34", "@types/react": "*", diff --git a/packages/app/package.json b/packages/app/package.json index 0201b43af5..696aca2288 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -106,7 +106,7 @@ "@playwright/test": "^1.32.3", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/jquery": "^3.3.34", "@types/react": "*", diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 56cfc9d046..a138b1fcbb 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -66,7 +66,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/zen-observable": "^0.8.0", diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 1f99a682e5..310a2cf231 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -88,7 +88,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/ansi-regex": "^5.0.0", diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 4d6e010255..12d02d2a07 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -64,7 +64,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0" }, diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 31e12b80cd..1356c16a2c 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "zen-observable": "^0.10.0" }, diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index 472b914b6e..7d48d5b524 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -26,7 +26,7 @@ "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3" + "@testing-library/react": "^13.4.0" }, "configSchema": "config.d.ts", "files": [ diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 4c9efdfaf6..2c81a747e1 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -27,7 +27,7 @@ "@backstage/frontend-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.1", "history": "^5.3.0" }, diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index fd3ca45114..046d4f6db0 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -38,7 +38,7 @@ "@backstage/cli": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/react": "*", "@types/react-dom": "*", diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index 6b90502021..9b219c34ee 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -43,7 +43,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0" }, "files": [ diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 2a18953271..7300f8e852 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -73,7 +73,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/git-url-parse": "^9.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index f9ae2838b0..c11f14761f 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -54,7 +54,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 165e00077a..f7cc3a03c0 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -53,7 +53,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index bab595e008..347fd39b76 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -51,7 +51,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "msw": "^1.0.0" diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index 31ea10c681..782c0657e3 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -48,7 +48,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/jest": "^28.1.3", "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index 0f90451257..13e8dae3ca 100644 --- a/plugins/analytics-module-newrelic-browser/package.json +++ b/plugins/analytics-module-newrelic-browser/package.json @@ -38,7 +38,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 368e7a9466..5d1b5507ed 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -51,7 +51,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index a37bf50697..fb49f16a7d 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -63,7 +63,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/swagger-ui-react": "^4.18.0", "cross-fetch": "^3.1.5", diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 325de67864..66aa47faf6 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -51,7 +51,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 997eda7fce..12c563c187 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index 57bbba41dc..a6dc40caf9 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index d9a897de81..dac5a0f497 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -57,7 +57,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/recharts": "^1.8.15", "msw": "^1.0.0" diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index e296a950c2..069f7519e8 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0" }, diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 17cad0b813..ace0d82613 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -67,7 +67,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index bcd17be1c7..9f959b94b4 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -84,7 +84,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/zen-observable": "^0.8.0", diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index 7b691e6099..dd3c3674b8 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -51,7 +51,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 4c583a06b9..96e4a02b45 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -83,7 +83,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0" }, "files": [ diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 0ac680e78d..ad347a5f87 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.25.1", "cross-fetch": "^3.1.5", diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 5c56d69b10..cbb707c099 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 4aa971e458..13a061310d 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -53,7 +53,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.27.1", "@types/luxon": "^3.0.0", diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index a8be86154c..5247f76d0c 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/highlightjs": "^10.1.0", "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index b2fcf79c01..bd59b6e15e 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -53,7 +53,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index e21643a65f..9c0fc4e89f 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 322604f07b..e131e2ef5c 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -68,7 +68,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/pluralize": "^0.0.31", "@types/recharts": "^1.8.14", diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index 568e4f0d59..4e09919e43 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -54,7 +54,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index d05d8b5b3c..9cd80c075a 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -52,7 +52,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "express": "^4.18.1", "msw": "^1.0.0" diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 13688922fa..01efea478f 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -54,7 +54,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index 773266def5..12f835d98b 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -62,7 +62,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 267fe620b1..ad49a18d7c 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -50,7 +50,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "msw": "^1.0.0" diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index f69738543f..14ec278cab 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -47,7 +47,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/explore/package.json b/plugins/explore/package.json index ed06d1864c..c828622466 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -78,7 +78,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index c8bedae934..1fdee999b3 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -54,7 +54,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 68aad1a889..80c662fb88 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index ea1b8e9663..c85e9b2ba6 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/dompurify": "^2.3.3", "@types/sanitize-html": "^2.6.2", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index c48f3001dc..d68e25a3f6 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index aba5730df4..a8b60322ec 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/recharts": "^1.8.15", diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index e165baaac9..efc202f42d 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -63,7 +63,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index f9c199ca83..7ebc23aff8 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index 20c459528f..e4a1c12c4a 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 7536050d0c..d771913b44 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 3cf144d9e6..594f38556c 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 50cc2f4d9f..c4651c6444 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/lodash": "^4.14.173", "@types/luxon": "^3.0.0", diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index b0a12a8b46..4dabd20c30 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -71,7 +71,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/codemirror": "^5.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index 5dee6b50e6..2e10fcfd2c 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -52,7 +52,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index aef8dd9b43..043f3a99ff 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -53,7 +53,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/react-grid-layout": "^1.3.2", "cross-fetch": "^3.1.5", diff --git a/plugins/home/package.json b/plugins/home/package.json index 178cb55a4c..cbe73eefa2 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -69,7 +69,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.0.0", "@types/react-grid-layout": "^1.3.2", diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 2747b6321f..66d33c5532 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index c1730953fb..eabdd05241 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -60,7 +60,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/testing-library__jest-dom": "^5.9.1", "cross-fetch": "^3.1.5", diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 9671ef168a..cd35228fbd 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "jest-when": "^3.1.0", diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index e86fe015c9..0048b694c3 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -68,7 +68,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index 961bb116cb..1846866349 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -55,7 +55,7 @@ "@backstage/core-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.1", "jest-websocket-mock": "^2.5.0", "msw": "^1.3.1" diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 09527dd16a..7cd0b6dff2 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -73,7 +73,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "jest-websocket-mock": "^2.4.1", diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 6195bb93d2..0a2a0e7c50 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index 73140ec8dc..f54672d2e6 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index 0c64c7caa5..b81f03c565 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -76,7 +76,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index ef81addd78..53e42830c1 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -57,7 +57,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/parse-link-header": "^2.0.1", "cross-fetch": "^3.1.5", diff --git a/plugins/nomad/package.json b/plugins/nomad/package.json index 063f2f315b..49dbb7692d 100644 --- a/plugins/nomad/package.json +++ b/plugins/nomad/package.json @@ -53,7 +53,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 5ff787bf59..824c3c2e78 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -52,7 +52,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/opencost/package.json b/plugins/opencost/package.json index c9986d91f2..51055a738f 100644 --- a/plugins/opencost/package.json +++ b/plugins/opencost/package.json @@ -49,7 +49,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index f0242f0514..fa6e9fcb39 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/org/package.json b/plugins/org/package.json index 8ceca3911c..2fe3728c51 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -61,7 +61,7 @@ "@backstage/types": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 8c29120ad3..8450056765 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index de2635fe41..29091fef1b 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -54,7 +54,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/luxon": "^3.0.0", "msw": "^1.0.0" diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index c96f5e448a..fa3d77fc36 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -49,7 +49,7 @@ "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3" + "@testing-library/react": "^13.4.0" }, "files": [ "dist" diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index a433f2eb13..45be0f4d7c 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -63,7 +63,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0", diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index 54510a7a5e..877cb2fe5f 100644 --- a/plugins/puppetdb/package.json +++ b/plugins/puppetdb/package.json @@ -58,7 +58,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.1" }, diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index c68e56bafe..6808f85c0d 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index c9eb9b87cd..d3874d1f75 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -93,7 +93,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.18.1", diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 2db000c81c..1dec7ba98f 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -104,7 +104,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.18.1", diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index ac74e8465f..7708d630c8 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -72,7 +72,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0" }, diff --git a/plugins/search/package.json b/plugins/search/package.json index 27064c7abf..23a6f991a8 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -77,7 +77,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "history": "^5.0.0", diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 5b53004cd3..55bcd6c779 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/luxon": "^3.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 48116dba8f..18e529f9c1 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/zen-observable": "^0.8.2", "msw": "^1.0.0" diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index cecd69c4ff..a06a9bfafd 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -64,7 +64,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index d72183423a..cc800a6db0 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/luxon": "^3.0.0", "msw": "^1.0.0" diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index ec68b0183b..173a940096 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -56,7 +56,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index 02bc0a924f..af5a926045 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 1f3423119b..3c881649b6 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 9f1d327e65..792052f090 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -70,7 +70,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/color": "^3.0.1", "@types/d3-force": "^3.0.0", diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index dec4ad257c..8d3ae34018 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -46,7 +46,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@types/react": "^16.13.1 || ^17.0.0", "react-use": "^17.2.4", "testing-library__dom": "^7.29.4-beta.1" @@ -61,7 +61,7 @@ "@backstage/dev-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 8b797caaf3..17fa38c85a 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "msw": "^1.0.0" diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 75e4d8947d..37df5a207d 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0" }, "files": [ diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index eb69181027..83603b0f6a 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -86,7 +86,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/dompurify": "^2.2.2", diff --git a/plugins/todo/package.json b/plugins/todo/package.json index a1760a94ed..546c6d7f65 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index fd514527f7..d8a60850f1 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -73,7 +73,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 70736e40d5..bdbd09da95 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index d09b93a6f2..56befd87c2 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "@types/luxon": "^3.0.0", "msw": "^1.0.0" From d60fbcb553a1999f03481f95219f66533e8b0743 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 00:39:17 +0200 Subject: [PATCH 102/348] remove usages of @testing-library/react-hooks Signed-off-by: Patrik Oldsberg --- packages/core-app-api/src/app/AppContext.test.tsx | 2 +- .../src/routing/RoutingProvider.beta.test.tsx | 2 +- .../src/routing/RoutingProvider.stable.test.tsx | 2 +- packages/core-components/package.json | 1 - .../src/components/AutoLogout/disconnectedUsers.test.ts | 2 +- .../core-components/src/components/Link/Link.test.tsx | 7 +++---- .../src/components/LogViewer/useLogViewerSearch.test.tsx | 2 +- .../components/LogViewer/useLogViewerSelection.test.tsx | 2 +- .../core-components/src/layout/Sidebar/Items.test.tsx | 2 +- .../src/layout/Sidebar/SidebarOpenStateContext.test.tsx | 2 +- .../src/layout/Sidebar/SidebarPinStateContext.test.tsx | 2 +- packages/core-plugin-api/package.json | 1 - .../src/analytics/AnalyticsContext.test.tsx | 2 +- .../core-plugin-api/src/analytics/useAnalytics.test.tsx | 2 +- packages/core-plugin-api/src/apis/system/useApi.test.tsx | 2 +- packages/core-plugin-api/src/app/useApp.test.tsx | 2 +- .../src/extensions/useElementFilter.test.tsx | 2 +- .../core-plugin-api/src/routing/useRouteRef.test.tsx | 2 +- .../src/translation/useTranslationRef.test.tsx | 2 +- packages/version-bridge/package.json | 3 +-- .../version-bridge/src/lib/VersionedContext.test.tsx | 2 +- plugins/catalog-graph/package.json | 1 - .../CatalogGraphPage/useCatalogGraphPage.test.ts | 2 +- .../EntityRelationsGraph/useEntityRelationGraph.test.ts | 2 +- .../useEntityRelationNodesAndEdges.test.ts | 2 +- .../EntityRelationsGraph/useEntityStore.test.ts | 2 +- plugins/catalog-import/package.json | 1 - .../PreviewCatalogInfoComponent.test.tsx | 2 +- .../PreviewPullRequestComponent.test.tsx | 2 +- .../src/components/useImportState.test.tsx | 2 +- plugins/catalog-react/package.json | 1 - .../EntityOwnerPicker/useFacetsEntities.test.ts | 2 +- .../EntityOwnerPicker/useQueryEntities.test.ts | 2 +- .../useUnregisterEntityDialogState.test.tsx | 6 +----- plugins/catalog-react/src/hooks/useEntity.test.tsx | 2 +- .../src/hooks/useEntityListProvider.test.tsx | 2 +- .../catalog-react/src/hooks/useEntityOwnership.test.tsx | 2 +- .../catalog-react/src/hooks/useEntityPermission.test.tsx | 2 +- .../catalog-react/src/hooks/useRelatedEntities.test.tsx | 2 +- .../catalog-react/src/hooks/useStarredEntities.test.tsx | 2 +- .../catalog-react/src/hooks/useStarredEntity.test.tsx | 2 +- plugins/entity-feedback/package.json | 1 - plugins/git-release-manager/package.json | 1 - .../hooks/useCreateReleaseCandidate.test.tsx | 2 +- .../src/features/Patch/hooks/usePatch.test.ts | 2 +- .../src/features/PromoteRc/hooks/usePromoteRc.test.ts | 2 +- .../src/hooks/useGetGitBatchInfo.test.ts | 2 +- .../src/hooks/useResponseSteps.test.ts | 6 +++--- plugins/home/package.json | 1 - plugins/kafka/package.json | 1 - .../useConsumerGroupsForEntity.test.tsx | 2 +- .../useConsumerGroupsOffsetsForEntity.test.tsx | 2 +- plugins/kubernetes-cluster/package.json | 1 - plugins/kubernetes-react/package.json | 1 - .../src/components/Pods/Events/useEvents.test.tsx | 2 +- .../src/hooks/useCustomResources.test.ts | 2 +- .../src/hooks/useIsPodExecTerminalSupported.test.ts | 2 +- .../src/hooks/useKubernetesObjects.test.ts | 2 +- .../src/hooks/useMatchingErrors.test.tsx | 2 +- .../kubernetes-react/src/hooks/usePodMetrics.test.tsx | 2 +- plugins/kubernetes/package.json | 1 - plugins/lighthouse/package.json | 1 - .../lighthouse/src/hooks/useWebsiteForEntity.test.tsx | 2 +- plugins/org/package.json | 1 - .../Cards/OwnershipCard/useGetEntities.test.ts | 2 +- plugins/playlist/package.json | 1 - .../CreatePlaylistButton/CreatePlaylistButton.test.tsx | 3 +-- .../EntityPlaylistDialog/EntityPlaylistDialog.test.tsx | 3 +-- .../PlaylistEditDialog/PlaylistEditDialog.test.tsx | 3 +-- .../components/PlaylistPage/AddEntitiesDrawer.test.tsx | 3 +-- .../PlaylistPage/PlaylistEntitiesTable.test.tsx | 3 +-- .../src/components/PlaylistPage/PlaylistHeader.test.tsx | 3 +-- .../src/components/PlaylistPage/PlaylistPage.test.tsx | 3 +-- .../PlaylistSortPicker/PlaylistSortPicker.test.tsx | 9 +++++++-- plugins/playlist/src/hooks/PlaylistListProvider.test.tsx | 2 +- plugins/rollbar/package.json | 1 - plugins/scaffolder-react/package.json | 1 - .../src/next/hooks/useTemplateSchema.test.tsx | 2 +- .../src/next/hooks/useTransformSchemaToProps.test.tsx | 2 +- .../scaffolder-react/src/secrets/SecretsContext.test.tsx | 2 +- plugins/scaffolder/package.json | 1 - plugins/search-react/package.json | 1 - .../src/components/SearchFilter/hooks.test.tsx | 2 +- plugins/search-react/src/context/SearchContext.test.tsx | 2 +- plugins/search/package.json | 1 - .../src/components/SearchModal/useSearchModal.test.tsx | 2 +- plugins/techdocs-react/package.json | 3 +-- plugins/techdocs-react/src/context.test.tsx | 2 +- plugins/techdocs-react/src/hooks.test.ts | 2 +- plugins/techdocs/package.json | 1 - .../components/TechDocsReaderPage/context.test.tsx | 2 +- .../src/reader/components/useReaderState.test.tsx | 2 +- .../src/reader/transformers/html/transformer.test.tsx | 2 +- .../src/reader/transformers/styles/transformer.test.ts | 2 +- 94 files changed, 83 insertions(+), 113 deletions(-) diff --git a/packages/core-app-api/src/app/AppContext.test.tsx b/packages/core-app-api/src/app/AppContext.test.tsx index ee7b90533f..a011b5966b 100644 --- a/packages/core-app-api/src/app/AppContext.test.tsx +++ b/packages/core-app-api/src/app/AppContext.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useVersionedContext } from '@backstage/version-bridge'; import { AppContext as AppContextV1 } from './types'; import { AppContextProvider } from './AppContext'; diff --git a/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx index 0f7a5cd3ad..84b7afeb09 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx @@ -17,7 +17,7 @@ import React, { PropsWithChildren, ReactElement } from 'react'; import { MemoryRouter, Routes } from 'react-router-dom'; import { render } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useVersionedContext } from '@backstage/version-bridge'; import { childDiscoverer, diff --git a/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx index 495fc20b15..23d556a79e 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx @@ -17,7 +17,7 @@ import React, { PropsWithChildren, ReactElement } from 'react'; import { MemoryRouter, Routes, Route, useOutlet } from 'react-router-dom'; import { render } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useVersionedContext } from '@backstage/version-bridge'; import { childDiscoverer, diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 310a2cf231..77df614044 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -89,7 +89,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/ansi-regex": "^5.0.0", "@types/classnames": "^2.2.9", diff --git a/packages/core-components/src/components/AutoLogout/disconnectedUsers.test.ts b/packages/core-components/src/components/AutoLogout/disconnectedUsers.test.ts index 87d6369eda..3d097dcc7f 100644 --- a/packages/core-components/src/components/AutoLogout/disconnectedUsers.test.ts +++ b/packages/core-components/src/components/AutoLogout/disconnectedUsers.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { act } from 'react-dom/test-utils'; import { diff --git a/packages/core-components/src/components/Link/Link.test.tsx b/packages/core-components/src/components/Link/Link.test.tsx index f88d830479..42668b54c9 100644 --- a/packages/core-components/src/components/Link/Link.test.tsx +++ b/packages/core-components/src/components/Link/Link.test.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ -import React from 'react'; -import { fireEvent, waitFor, screen } from '@testing-library/react'; +import React, { ComponentType } from 'react'; +import { fireEvent, waitFor, screen, renderHook } from '@testing-library/react'; import { MockAnalyticsApi, TestApiProvider, @@ -24,7 +24,6 @@ import { import { analyticsApiRef, configApiRef } from '@backstage/core-plugin-api'; import { isExternalUri, Link, useResolvedPath } from './Link'; import { Route, Routes } from 'react-router-dom'; -import { renderHook, WrapperComponent } from '@testing-library/react-hooks'; import { ConfigReader } from '@backstage/config'; describe('', () => { @@ -128,7 +127,7 @@ describe('', () => { }); describe('useResolvedPath', () => { - const wrapper: WrapperComponent> = ({ + const wrapper: ComponentType> = ({ children, }) => { const configApi = new ConfigReader({ diff --git a/packages/core-components/src/components/LogViewer/useLogViewerSearch.test.tsx b/packages/core-components/src/components/LogViewer/useLogViewerSearch.test.tsx index a64f22765b..1b54f552a5 100644 --- a/packages/core-components/src/components/LogViewer/useLogViewerSearch.test.tsx +++ b/packages/core-components/src/components/LogViewer/useLogViewerSearch.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { applySearchFilter, useLogViewerSearch } from './useLogViewerSearch'; import { AnsiLine } from './AnsiProcessor'; diff --git a/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx b/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx index a828818ed5..6c6f7da71b 100644 --- a/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx +++ b/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { TestApiProvider, MockErrorApi } from '@backstage/test-utils'; import { errorApiRef } from '@backstage/core-plugin-api'; import { AnsiLine } from './AnsiProcessor'; diff --git a/packages/core-components/src/layout/Sidebar/Items.test.tsx b/packages/core-components/src/layout/Sidebar/Items.test.tsx index 9479180180..6c959bfd0d 100644 --- a/packages/core-components/src/layout/Sidebar/Items.test.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.test.tsx @@ -26,7 +26,7 @@ import HomeIcon from '@material-ui/icons/Home'; import CreateComponentIcon from '@material-ui/icons/AddCircleOutline'; import { Sidebar } from './Bar'; import { SidebarItem, SidebarSearchField, SidebarExpandButton } from './Items'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { makeStyles } from '@material-ui/core/styles'; import { analyticsApiRef } from '@backstage/core-plugin-api'; diff --git a/packages/core-components/src/layout/Sidebar/SidebarOpenStateContext.test.tsx b/packages/core-components/src/layout/Sidebar/SidebarOpenStateContext.test.tsx index f1900f025c..8cc6f7858c 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarOpenStateContext.test.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarOpenStateContext.test.tsx @@ -16,7 +16,7 @@ import React, { ReactNode, useContext } from 'react'; import { renderWithEffects } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { LegacySidebarContext, SidebarOpenStateProvider, diff --git a/packages/core-components/src/layout/Sidebar/SidebarPinStateContext.test.tsx b/packages/core-components/src/layout/Sidebar/SidebarPinStateContext.test.tsx index 8bd1597725..8f6660707d 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarPinStateContext.test.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarPinStateContext.test.tsx @@ -16,7 +16,7 @@ import React, { ReactNode, useContext } from 'react'; import { renderWithEffects } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { LegacySidebarPinStateContext, SidebarPinStateProvider, diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 12d02d2a07..0e6e15f28b 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -65,7 +65,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0" }, "files": [ diff --git a/packages/core-plugin-api/src/analytics/AnalyticsContext.test.tsx b/packages/core-plugin-api/src/analytics/AnalyticsContext.test.tsx index 88e8afa6ef..c29ec5b3ca 100644 --- a/packages/core-plugin-api/src/analytics/AnalyticsContext.test.tsx +++ b/packages/core-plugin-api/src/analytics/AnalyticsContext.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { AnalyticsContext, useAnalyticsContext } from './AnalyticsContext'; const AnalyticsSpy = () => { diff --git a/packages/core-plugin-api/src/analytics/useAnalytics.test.tsx b/packages/core-plugin-api/src/analytics/useAnalytics.test.tsx index 22021026af..037e585430 100644 --- a/packages/core-plugin-api/src/analytics/useAnalytics.test.tsx +++ b/packages/core-plugin-api/src/analytics/useAnalytics.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useAnalytics } from './useAnalytics'; import { useApi } from '../apis'; diff --git a/packages/core-plugin-api/src/apis/system/useApi.test.tsx b/packages/core-plugin-api/src/apis/system/useApi.test.tsx index 6f473d8f59..4b9d80fb62 100644 --- a/packages/core-plugin-api/src/apis/system/useApi.test.tsx +++ b/packages/core-plugin-api/src/apis/system/useApi.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { createVersionedContextForTesting } from '@backstage/version-bridge'; import { createApiRef } from './ApiRef'; import { useApi } from './useApi'; diff --git a/packages/core-plugin-api/src/app/useApp.test.tsx b/packages/core-plugin-api/src/app/useApp.test.tsx index f2e330e847..34c956138e 100644 --- a/packages/core-plugin-api/src/app/useApp.test.tsx +++ b/packages/core-plugin-api/src/app/useApp.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { createVersionedContextForTesting } from '@backstage/version-bridge'; import { useApp } from './useApp'; diff --git a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx index 9a3760d019..720b7e6838 100644 --- a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx +++ b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx @@ -15,7 +15,7 @@ */ import React, { ReactNode } from 'react'; import { useElementFilter } from './useElementFilter'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { attachComponentData } from './componentData'; import { featureFlagsApiRef } from '../apis'; import { LocalStorageFeatureFlags } from '@backstage/core-app-api'; diff --git a/packages/core-plugin-api/src/routing/useRouteRef.test.tsx b/packages/core-plugin-api/src/routing/useRouteRef.test.tsx index 7a03a1cdc4..b302fa6441 100644 --- a/packages/core-plugin-api/src/routing/useRouteRef.test.tsx +++ b/packages/core-plugin-api/src/routing/useRouteRef.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React from 'react'; import { MemoryRouter, Router } from 'react-router-dom'; import { createVersionedContextForTesting } from '@backstage/version-bridge'; diff --git a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx index 19f0516906..8433fb0f69 100644 --- a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx +++ b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx @@ -20,7 +20,7 @@ import { TestApiProvider, withLogCollector, } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { createTranslationRef, TranslationRef } from './TranslationRef'; import { useTranslationRef } from './useTranslationRef'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index 9b219c34ee..80671efe05 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -43,8 +43,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0" + "@testing-library/react": "^13.4.0" }, "files": [ "dist" diff --git a/packages/version-bridge/src/lib/VersionedContext.test.tsx b/packages/version-bridge/src/lib/VersionedContext.test.tsx index 275e491324..4ffe3f45ca 100644 --- a/packages/version-bridge/src/lib/VersionedContext.test.tsx +++ b/packages/version-bridge/src/lib/VersionedContext.test.tsx @@ -15,7 +15,7 @@ */ import React, { useContext } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { createVersionedContext, createVersionedContextForTesting, diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 069f7519e8..d167dbaf3a 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -60,7 +60,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0" }, "files": [ diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts b/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts index 7a4d836365..a89fa353d6 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { RELATION_MEMBER_OF } from '@backstage/catalog-model'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { useLocation as useLocationMocked } from 'react-router-dom'; import { Direction } from '../EntityRelationsGraph'; import { useCatalogGraphPage } from './useCatalogGraphPage'; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts index 7e0cd411ce..420af5345c 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts @@ -19,7 +19,7 @@ import { RELATION_OWNER_OF, RELATION_PART_OF, } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { pick } from 'lodash'; import { useEntityRelationGraph } from './useEntityRelationGraph'; import { useEntityStore as useEntityStoreMocked } from './useEntityStore'; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts index c2ee918e5b..526588d598 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts @@ -21,7 +21,7 @@ import { RELATION_PART_OF, stringifyEntityRef, } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { filter, keyBy } from 'lodash'; import { useEntityRelationGraph as useEntityRelationGraphMocked } from './useEntityRelationGraph'; import { useEntityRelationNodesAndEdges } from './useEntityRelationNodesAndEdges'; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts index 802f993802..9e37aadbf5 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { useApi as useApiMocked } from '@backstage/core-plugin-api'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { useEntityStore } from './useEntityStore'; jest.mock('@backstage/core-plugin-api'); diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index ace0d82613..3db78446d3 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -68,7 +68,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx index 0a6960cdc7..4e737bd115 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx @@ -19,7 +19,7 @@ import { configApiRef } from '@backstage/core-plugin-api'; import { MockConfigApi, TestApiProvider } from '@backstage/test-utils'; import { makeStyles } from '@material-ui/core'; import { render, screen } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React from 'react'; import { PreviewCatalogInfoComponent } from './PreviewCatalogInfoComponent'; diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewPullRequestComponent.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewPullRequestComponent.test.tsx index d983b6d359..53485bedb5 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewPullRequestComponent.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewPullRequestComponent.test.tsx @@ -16,7 +16,7 @@ import { makeStyles } from '@material-ui/core'; import { render, screen } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React from 'react'; import { PreviewPullRequestComponent } from './PreviewPullRequestComponent'; diff --git a/plugins/catalog-import/src/components/useImportState.test.tsx b/plugins/catalog-import/src/components/useImportState.test.tsx index 155adb8290..2345b2d696 100644 --- a/plugins/catalog-import/src/components/useImportState.test.tsx +++ b/plugins/catalog-import/src/components/useImportState.test.tsx @@ -16,7 +16,7 @@ import { Entity, CompoundEntityRef } from '@backstage/catalog-model'; import { cleanup } from '@testing-library/react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { AnalyzeResult } from '../api'; import { diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 9f959b94b4..f0bf4e822b 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -85,7 +85,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/zen-observable": "^0.8.0", "react-test-renderer": "^16.13.1" diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts b/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts index 6f6da43307..8dbd382c25 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useFacetsEntities } from './useFacetsEntities'; import { CatalogApi } from '@backstage/catalog-client'; diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts b/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts index d974709d34..f2986d296a 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { CatalogApi } from '@backstage/catalog-client'; import { useQueryEntities } from './useQueryEntities'; diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx index 8591cdad93..f305e68791 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx @@ -17,11 +17,7 @@ import { CatalogApi, Location } from '@backstage/catalog-client'; import { Entity, ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model'; import { catalogApiRef } from '../../api'; -import { - act, - renderHook, - RenderHookResult, -} from '@testing-library/react-hooks'; +import { act, renderHook, RenderHookResult } from '@testing-library/react'; import React, { ReactNode } from 'react'; import { UseUnregisterEntityDialogState, diff --git a/plugins/catalog-react/src/hooks/useEntity.test.tsx b/plugins/catalog-react/src/hooks/useEntity.test.tsx index 8fc388654a..7f2a29efee 100644 --- a/plugins/catalog-react/src/hooks/useEntity.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntity.test.tsx @@ -15,7 +15,7 @@ */ import React, { PropsWithChildren } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useEntity, useAsyncEntity, diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index da27c61dcb..7e54a82e71 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -25,7 +25,7 @@ import { storageApiRef, } from '@backstage/core-plugin-api'; import { MockStorageApi, TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import qs from 'qs'; import React, { PropsWithChildren } from 'react'; import { MemoryRouter } from 'react-router-dom'; diff --git a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx index dc400b5c90..2fbc283cb4 100644 --- a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx @@ -18,7 +18,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { ComponentEntity, RELATION_OWNED_BY } from '@backstage/catalog-model'; import { IdentityApi, identityApiRef } from '@backstage/core-plugin-api'; import { TestApiProvider } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React from 'react'; import { catalogApiRef } from '../api'; import { useEntityOwnership } from './useEntityOwnership'; diff --git a/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx b/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx index aed6676838..0c389de747 100644 --- a/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx @@ -15,7 +15,7 @@ */ import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common/alpha'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useEntityPermission } from './useEntityPermission'; import { useAsyncEntity } from './useEntity'; import { usePermission } from '@backstage/plugin-permission-react'; diff --git a/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx b/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx index 8de7822d59..bd8116d6b3 100644 --- a/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { WrapperComponent, renderHook } from '@testing-library/react-hooks'; +import { WrapperComponent, renderHook } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { catalogApiRef } from '../api'; import { useRelatedEntities } from './useRelatedEntities'; diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx index f21b3cb710..cde574e558 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { starredEntitiesApiRef, diff --git a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx index d24b27f903..272ba05b01 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx @@ -16,7 +16,7 @@ import { Entity, CompoundEntityRef } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import Observable from 'zen-observable'; import { StarredEntitiesApi, starredEntitiesApiRef } from '../apis'; diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 01efea478f..1fb982f803 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -55,7 +55,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index a8b60322ec..5b9db4f4b5 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -57,7 +57,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/recharts": "^1.8.15", "msw": "^1.0.0" diff --git a/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx b/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx index 25a987df2a..4ca9afbaff 100644 --- a/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx +++ b/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { waitFor } from '@testing-library/react'; import { diff --git a/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts b/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts index 0bd7f27cdb..6d6b297d2a 100644 --- a/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts +++ b/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { waitFor } from '@testing-library/react'; import { diff --git a/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts b/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts index f4e0fcb081..bd69a3366f 100644 --- a/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts +++ b/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { waitFor } from '@testing-library/react'; import { diff --git a/plugins/git-release-manager/src/hooks/useGetGitBatchInfo.test.ts b/plugins/git-release-manager/src/hooks/useGetGitBatchInfo.test.ts index 8e89add810..d1bf28bccb 100644 --- a/plugins/git-release-manager/src/hooks/useGetGitBatchInfo.test.ts +++ b/plugins/git-release-manager/src/hooks/useGetGitBatchInfo.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { waitFor } from '@testing-library/react'; import { mockApiClient } from '../test-helpers/mock-api-client'; diff --git a/plugins/git-release-manager/src/hooks/useResponseSteps.test.ts b/plugins/git-release-manager/src/hooks/useResponseSteps.test.ts index 513c51758d..f5b5ac056c 100644 --- a/plugins/git-release-manager/src/hooks/useResponseSteps.test.ts +++ b/plugins/git-release-manager/src/hooks/useResponseSteps.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { useResponseSteps } from './useResponseSteps'; @@ -74,7 +74,7 @@ describe('useResponseSteps', () => { "icon": "failure", "message": Something went wrong - + { "icon": "failure", "message": Something went wrong - + { it('should allow the setting of secrets in the context', async () => { diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 1dec7ba98f..1ef6c70340 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -105,7 +105,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.18.1", "@types/json-schema": "^7.0.9", diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 7708d630c8..52277961d9 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -73,7 +73,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0" }, "files": [ diff --git a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx index 5135cd4ae6..567617fccf 100644 --- a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { ApiProvider } from '@backstage/core-app-api'; import { MockConfigApi, TestApiRegistry } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { searchApiRef } from '../../api'; import { SearchContextProvider, useSearch } from '../../context'; diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index df71a848b0..64c3cbbded 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -16,7 +16,7 @@ import { configApiRef } from '@backstage/core-plugin-api'; import { render, screen, waitFor } from '@testing-library/react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { MockConfigApi, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { diff --git a/plugins/search/package.json b/plugins/search/package.json index 23a6f991a8..c89c86e518 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -78,7 +78,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "history": "^5.0.0", "msw": "^1.0.0" diff --git a/plugins/search/src/components/SearchModal/useSearchModal.test.tsx b/plugins/search/src/components/SearchModal/useSearchModal.test.tsx index e21f864ac2..a78f9b92af 100644 --- a/plugins/search/src/components/SearchModal/useSearchModal.test.tsx +++ b/plugins/search/src/components/SearchModal/useSearchModal.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { useSearchModal } from './useSearchModal'; import { BrowserRouter, Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 37df5a207d..3abafb9ef1 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -58,8 +58,7 @@ "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0" + "@testing-library/react": "^13.4.0" }, "files": [ "alpha", diff --git a/plugins/techdocs-react/src/context.test.tsx b/plugins/techdocs-react/src/context.test.tsx index 4800204f36..7890e755b4 100644 --- a/plugins/techdocs-react/src/context.test.tsx +++ b/plugins/techdocs-react/src/context.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; diff --git a/plugins/techdocs-react/src/hooks.test.ts b/plugins/techdocs-react/src/hooks.test.ts index 2aa53b32d5..0cd55fa10f 100644 --- a/plugins/techdocs-react/src/hooks.test.ts +++ b/plugins/techdocs-react/src/hooks.test.ts @@ -19,7 +19,7 @@ import { useShadowRootElements, useShadowRootSelection, } from './hooks'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { fireEvent, waitFor } from '@testing-library/react'; const fireSelectionChangeEvent = (window: Window) => { diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 83603b0f6a..104f764d00 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -87,7 +87,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^13.4.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/dompurify": "^2.2.2", "@types/event-source-polyfill": "^1.0.0", diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx index 2380724960..e3d5a59587 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; diff --git a/plugins/techdocs/src/reader/components/useReaderState.test.tsx b/plugins/techdocs/src/reader/components/useReaderState.test.tsx index 5f3e2d9662..e3b60f6f25 100644 --- a/plugins/techdocs/src/reader/components/useReaderState.test.tsx +++ b/plugins/techdocs/src/reader/components/useReaderState.test.tsx @@ -16,7 +16,7 @@ import { NotFoundError } from '@backstage/errors'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import React from 'react'; import { techdocsStorageApiRef } from '../../api'; import { diff --git a/plugins/techdocs/src/reader/transformers/html/transformer.test.tsx b/plugins/techdocs/src/reader/transformers/html/transformer.test.tsx index 2b1f427be3..ed5fbba085 100644 --- a/plugins/techdocs/src/reader/transformers/html/transformer.test.tsx +++ b/plugins/techdocs/src/reader/transformers/html/transformer.test.tsx @@ -15,7 +15,7 @@ */ import React, { FC, PropsWithChildren } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { ConfigReader } from '@backstage/core-app-api'; import { ConfigApi, configApiRef } from '@backstage/core-plugin-api'; diff --git a/plugins/techdocs/src/reader/transformers/styles/transformer.test.ts b/plugins/techdocs/src/reader/transformers/styles/transformer.test.ts index 84ba16d6e6..90244e96ad 100644 --- a/plugins/techdocs/src/reader/transformers/styles/transformer.test.ts +++ b/plugins/techdocs/src/reader/transformers/styles/transformer.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useStylesTransformer } from './transformer'; describe('Transformers > Styles', () => { From 0935b0d60fc2a33de54e297d70b62f18148b1424 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 09:21:51 +0200 Subject: [PATCH 103/348] rtl 13 fixes for tests with type issues Signed-off-by: Patrik Oldsberg --- .../src/routing/RoutingProvider.beta.test.tsx | 4 +- .../routing/RoutingProvider.stable.test.tsx | 4 +- .../src/extensions/useElementFilter.test.tsx | 34 +- .../translation/useTranslationRef.test.tsx | 37 +- .../useEntityRelationNodesAndEdges.test.ts | 58 +- .../useEntityStore.test.ts | 10 +- .../useFacetsEntities.test.ts | 18 +- .../useQueryEntities.test.ts | 4 +- .../useUnregisterEntityDialogState.test.tsx | 67 +- .../src/hooks/useEntity.test.tsx | 14 +- .../src/hooks/useEntityListProvider.test.tsx | 69 +- .../src/hooks/useEntityOwnership.test.tsx | 14 +- .../src/hooks/useRelatedEntities.test.tsx | 10 +- .../src/hooks/useStarredEntities.test.tsx | 58 +- .../src/hooks/useStarredEntities.ts | 4 +- .../src/hooks/useStarredEntity.test.tsx | 16 +- .../hooks/useCreateReleaseCandidate.test.tsx | 6 +- .../src/features/Patch/hooks/usePatch.test.ts | 7 +- .../PromoteRc/hooks/usePromoteRc.test.ts | 7 +- .../useConsumerGroupsForEntity.test.tsx | 8 +- ...useConsumerGroupsOffsetsForEntity.test.tsx | 31 +- .../components/Pods/Events/useEvents.test.tsx | 8 +- .../src/hooks/useCustomResources.test.ts | 52 +- .../useIsPodExecTerminalSupported.test.ts | 11 +- .../src/hooks/useKubernetesObjects.test.ts | 65 +- .../src/hooks/useWebsiteForEntity.test.tsx | 14 +- .../OwnershipCard/useGetEntities.test.ts | 24 +- .../src/hooks/PlaylistListProvider.test.tsx | 43 +- .../components/SearchFilter/hooks.test.tsx | 139 ++-- .../src/context/SearchContext.test.tsx | 260 +++---- plugins/techdocs-react/src/context.test.tsx | 63 +- .../TechDocsReaderPage/context.test.tsx | 16 +- .../reader/components/useReaderState.test.tsx | 650 +++++++++--------- 33 files changed, 862 insertions(+), 963 deletions(-) diff --git a/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx index 84b7afeb09..ca089d0014 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx @@ -353,9 +353,7 @@ describe('v1 consumer', () => { initialProps: { routeRef: routeRef1 as AnyRouteRef, }, - wrapper: ({ - children, - }: React.PropsWithChildren<{ routeRef: AnyRouteRef }>) => ( + wrapper: ({ children }) => ( , string>([ diff --git a/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx index 23d556a79e..df0ce32e2b 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx @@ -385,9 +385,7 @@ describe('v1 consumer', () => { initialProps: { routeRef: routeRef1 as AnyRouteRef, }, - wrapper: ({ - children, - }: React.PropsWithChildren<{ routeRef: AnyRouteRef }>) => ( + wrapper: ({ children }) => ( , string>([ diff --git a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx index 720b7e6838..8597274e35 100644 --- a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx +++ b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx @@ -316,23 +316,23 @@ describe('useElementFilter', () => { ); - const { result } = renderHook( - props => - useElementFilter(props.tree, elements => - elements - .selectByComponentData({ - key: WRAPPING_COMPONENT_KEY, - withStrictError: 'Could not find component', - }) - .findComponentData({ key: INNER_COMPONENT_KEY }), - ), - { - initialProps: { tree }, - wrapper: Wrapper, - }, - ); - - expect(result.error?.message).toEqual('Could not find component'); + expect(() => + renderHook( + props => + useElementFilter(props.tree, elements => + elements + .selectByComponentData({ + key: WRAPPING_COMPONENT_KEY, + withStrictError: 'Could not find component', + }) + .findComponentData({ key: INNER_COMPONENT_KEY }), + ), + { + initialProps: { tree }, + wrapper: Wrapper, + }, + ), + ).toThrow('Could not find component'); }); it('should support fragments and text node iteration', () => { diff --git a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx index 8433fb0f69..dad4740d6c 100644 --- a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx +++ b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx @@ -20,7 +20,7 @@ import { TestApiProvider, withLogCollector, } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react'; +import { act, renderHook } from '@testing-library/react'; import { createTranslationRef, TranslationRef } from './TranslationRef'; import { useTranslationRef } from './useTranslationRef'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports @@ -91,14 +91,11 @@ describe('useTranslationRef', () => { ], }); - const { result, waitForNextUpdate } = renderHook( - () => useTranslationRef(plainRef), - { - wrapper: makeWrapper(translationApi), - }, - ); + const { result } = renderHook(() => useTranslationRef(plainRef), { + wrapper: makeWrapper(translationApi), + }); - await waitForNextUpdate(); + await act(async () => {}); const { t } = result.current; @@ -123,12 +120,9 @@ describe('useTranslationRef', () => { ], }); - const { result, waitForNextUpdate } = renderHook( - () => useTranslationRef(plainRef), - { - wrapper: makeWrapper(translationApi), - }, - ); + const { result } = renderHook(() => useTranslationRef(plainRef), { + wrapper: makeWrapper(translationApi), + }); const { t } = result.current; @@ -137,7 +131,7 @@ describe('useTranslationRef', () => { languageApi.setLanguage('de'); - await waitForNextUpdate(); + await act(async () => {}); const { t: t2 } = result.current; @@ -165,14 +159,11 @@ describe('useTranslationRef', () => { languageApi, }); - const { result, waitForNextUpdate } = renderHook( - () => useTranslationRef(resourceRef), - { - wrapper: makeWrapper(translationApi), - }, - ); + const { result } = renderHook(() => useTranslationRef(resourceRef), { + wrapper: makeWrapper(translationApi), + }); - await waitForNextUpdate(); + await act(async () => {}); const { t } = result.current; @@ -212,7 +203,7 @@ describe('useTranslationRef', () => { }); const { error } = await withLogCollector(['error'], async () => { - await rendered2.waitForNextUpdate(); + await act(rendered2.rerender); }); const msg = diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts index 526588d598..d17e8b1c9d 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts @@ -21,7 +21,7 @@ import { RELATION_PART_OF, stringifyEntityRef, } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { filter, keyBy } from 'lodash'; import { useEntityRelationGraph as useEntityRelationGraphMocked } from './useEntityRelationGraph'; import { useEntityRelationNodesAndEdges } from './useEntityRelationNodesAndEdges'; @@ -163,7 +163,7 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate unidirectional graph with merged relations', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], unidirectional: true, @@ -171,9 +171,9 @@ describe('useEntityRelationNodesAndEdges', () => { }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -236,7 +236,7 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate unidirectional graph', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], unidirectional: true, @@ -244,9 +244,9 @@ describe('useEntityRelationNodesAndEdges', () => { }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -309,7 +309,7 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate bidirectional graph with merged relations', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], unidirectional: false, @@ -317,9 +317,9 @@ describe('useEntityRelationNodesAndEdges', () => { }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -412,7 +412,7 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate bidirectional graph with all relations', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], unidirectional: false, @@ -420,9 +420,9 @@ describe('useEntityRelationNodesAndEdges', () => { }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -515,15 +515,15 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate graph with multiple root nodes', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c', 'b:d/c2'], }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -586,16 +586,16 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should filter by relation', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], relations: [RELATION_OWNER_OF], }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -646,16 +646,16 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should filter by kind', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], kinds: ['b'], }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts index 9e37aadbf5..0d75fabc3b 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { useApi as useApiMocked } from '@backstage/core-plugin-api'; -import { act, renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { useEntityStore } from './useEntityStore'; jest.mock('@backstage/core-plugin-api'); @@ -65,7 +65,7 @@ describe('useEntityStore', () => { catalogApi.getEntityByRef.mockResolvedValue(entity); - const { result, waitFor } = renderHook(() => useEntityStore()); + const { result } = renderHook(() => useEntityStore()); act(() => { result.current.requestEntities(['kind:namespace/name']); @@ -85,7 +85,7 @@ describe('useEntityStore', () => { const err = new Error('Hello World'); catalogApi.getEntityByRef.mockRejectedValue(err); - const { result, waitFor } = renderHook(() => useEntityStore()); + const { result } = renderHook(() => useEntityStore()); act(() => { result.current.requestEntities(['kind:namespace/name']); @@ -134,7 +134,7 @@ describe('useEntityStore', () => { catalogApi.getEntityByRef.mockResolvedValue(entity1); - const { result, waitFor } = renderHook(() => useEntityStore()); + const { result } = renderHook(() => useEntityStore()); act(() => { result.current.requestEntities(['kind:namespace/name1']); @@ -189,7 +189,7 @@ describe('useEntityStore', () => { catalogApi.getEntityByRef.mockResolvedValue(entity1); - const { result, waitFor } = renderHook(() => useEntityStore()); + const { result } = renderHook(() => useEntityStore()); act(() => { result.current.requestEntities(['kind:namespace/name1']); diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts b/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts index 8dbd382c25..1d0d1130a6 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { useFacetsEntities } from './useFacetsEntities'; import { CatalogApi } from '@backstage/catalog-client'; @@ -50,9 +50,7 @@ describe('useFacetsEntities', () => { }, }); - const { result, waitFor } = renderHook(() => - useFacetsEntities({ enabled: true }), - ); + const { result } = renderHook(() => useFacetsEntities({ enabled: true })); result.current[1]({ text: '' }); await waitFor(() => { @@ -91,9 +89,7 @@ describe('useFacetsEntities', () => { }, }); - const { result, waitFor } = renderHook(() => - useFacetsEntities({ enabled: true }), - ); + const { result } = renderHook(() => useFacetsEntities({ enabled: true })); result.current[1]({ text: '' }); await waitFor(() => { @@ -147,9 +143,7 @@ describe('useFacetsEntities', () => { }, }); - const { result, waitFor } = renderHook(() => - useFacetsEntities({ enabled: true }), - ); + const { result } = renderHook(() => useFacetsEntities({ enabled: true })); result.current[1]({ text: '' }, { limit: 2 }); await waitFor(() => { @@ -261,9 +255,7 @@ describe('useFacetsEntities', () => { }, }); - const { result, waitFor } = renderHook(() => - useFacetsEntities({ enabled: true }), - ); + const { result } = renderHook(() => useFacetsEntities({ enabled: true })); result.current[1]({ text: 'der ' }); await waitFor(() => { diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts b/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts index f2986d296a..64cc7769a6 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { CatalogApi } from '@backstage/catalog-client'; import { useQueryEntities } from './useQueryEntities'; @@ -62,7 +62,7 @@ describe('useQueryEntities', () => { totalItems: 2, }); - const { result, waitFor } = renderHook(() => useQueryEntities()); + const { result } = renderHook(() => useQueryEntities()); const [, fetch] = result.current!; fetch({ text: 'text' }); diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx index f305e68791..342fe4758d 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx @@ -17,12 +17,9 @@ import { CatalogApi, Location } from '@backstage/catalog-client'; import { Entity, ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model'; import { catalogApiRef } from '../../api'; -import { act, renderHook, RenderHookResult } from '@testing-library/react'; -import React, { ReactNode } from 'react'; -import { - UseUnregisterEntityDialogState, - useUnregisterEntityDialogState, -} from './useUnregisterEntityDialogState'; +import { act, renderHook } from '@testing-library/react'; +import React from 'react'; +import { useUnregisterEntityDialogState } from './useUnregisterEntityDialogState'; import { TestApiProvider } from '@backstage/test-utils'; function defer(): { promise: Promise; resolve: (value: T) => void } { @@ -81,26 +78,20 @@ describe('useUnregisterEntityDialogState', () => { }); it('goes through the happy unregister path', async () => { - let rendered: RenderHookResult< - { children?: ReactNode }, - UseUnregisterEntityDialogState - >; - act(() => { - rendered = renderHook(() => useUnregisterEntityDialogState(entity), { - wrapper: Wrapper, - }); + const rendered = renderHook(() => useUnregisterEntityDialogState(entity), { + wrapper: Wrapper, }); - expect(rendered!.result.current).toEqual({ type: 'loading' }); + expect(rendered.result.current).toEqual({ type: 'loading' }); resolveLocation({ type: 'url', target: 'https://example.com', id: 'x' }); resolveColocatedEntities([entity]); await act(async () => { - await rendered!.waitForNextUpdate(); + await rendered.rerender(); }); - expect(rendered!.result.current).toEqual({ + expect(rendered.result.current).toEqual({ type: 'unregister', location: 'url:https://example.com', colocatedEntities: [{ kind: 'Component', namespace: 'ns', name: 'n' }], @@ -113,23 +104,17 @@ describe('useUnregisterEntityDialogState', () => { entity.metadata.annotations![ANNOTATION_ORIGIN_LOCATION] = 'bootstrap:bootstrap'; - let rendered: RenderHookResult< - { children?: ReactNode }, - UseUnregisterEntityDialogState - >; - act(() => { - rendered = renderHook(() => useUnregisterEntityDialogState(entity), { - wrapper: Wrapper, - }); + const rendered = renderHook(() => useUnregisterEntityDialogState(entity), { + wrapper: Wrapper, }); resolveLocation({ type: 'bootstrap', target: 'bootstrap', id: 'x' }); resolveColocatedEntities([]); await act(async () => { - await rendered!.waitForNextUpdate(); + await rendered.rerender(); }); - expect(rendered!.result.current).toEqual({ + expect(rendered.result.current).toEqual({ type: 'bootstrap', location: 'bootstrap:bootstrap', deleteEntity: expect.any(Function), @@ -139,46 +124,34 @@ describe('useUnregisterEntityDialogState', () => { it('chooses only-delete when there was no location annotation', async () => { delete entity.metadata.annotations![ANNOTATION_ORIGIN_LOCATION]; - let rendered: RenderHookResult< - { children?: ReactNode }, - UseUnregisterEntityDialogState - >; - act(() => { - rendered = renderHook(() => useUnregisterEntityDialogState(entity), { - wrapper: Wrapper, - }); + const rendered = renderHook(() => useUnregisterEntityDialogState(entity), { + wrapper: Wrapper, }); resolveLocation(undefined); resolveColocatedEntities([]); await act(async () => { - await rendered!.waitForNextUpdate(); + await rendered.rerender(); }); - expect(rendered!.result.current).toEqual({ + expect(rendered.result.current).toEqual({ type: 'only-delete', deleteEntity: expect.any(Function), }); }); it('chooses only-delete when the location could not be found', async () => { - let rendered: RenderHookResult< - { children?: ReactNode }, - UseUnregisterEntityDialogState - >; - act(() => { - rendered = renderHook(() => useUnregisterEntityDialogState(entity), { - wrapper: Wrapper, - }); + const rendered = renderHook(() => useUnregisterEntityDialogState(entity), { + wrapper: Wrapper, }); resolveLocation(undefined); resolveColocatedEntities([]); await act(async () => { - await rendered!.waitForNextUpdate(); + await rendered.rerender(); }); - expect(rendered!.result.current).toEqual({ + expect(rendered.result.current).toEqual({ type: 'only-delete', deleteEntity: expect.any(Function), }); diff --git a/plugins/catalog-react/src/hooks/useEntity.test.tsx b/plugins/catalog-react/src/hooks/useEntity.test.tsx index 7f2a29efee..3b1190de2b 100644 --- a/plugins/catalog-react/src/hooks/useEntity.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntity.test.tsx @@ -31,13 +31,13 @@ const entity = { metadata: { name: 'my-entity' }, kind: 'MyKind' } as Entity; describe('useEntity', () => { it('should throw if no entity is provided', async () => { - const { result } = renderHook(() => useEntity(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - - ), - }); - - expect(result.error?.message).toMatch(/entity has not been loaded/); + expect(() => + renderHook(() => useEntity(), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + + ), + }), + ).toThrow(/entity has not been loaded/); }); it('should provide an entity', async () => { diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index 7e54a82e71..a3366506f8 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -25,7 +25,7 @@ import { storageApiRef, } from '@backstage/core-plugin-api'; import { MockStorageApi, TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import qs from 'qs'; import React, { PropsWithChildren } from 'react'; import { MemoryRouter } from 'react-router-dom'; @@ -119,10 +119,14 @@ describe('', () => { }); it('resolves backend filters', async () => { - const { result, waitForValueToChange } = renderHook(() => useEntityList(), { + const { result } = renderHook(() => useEntityList(), { wrapper, }); - await waitForValueToChange(() => result.current.backendEntities); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); + expect(result.current.backendEntities.length).toBe(2); expect(mockCatalogApi.getEntities).toHaveBeenCalledWith({ filter: { kind: 'component' }, @@ -130,13 +134,16 @@ describe('', () => { }); it('resolves frontend filters', async () => { - const { result, waitFor } = renderHook(() => useEntityList(), { + const { result } = renderHook(() => useEntityList(), { wrapper, initialProps: { userFilter: 'all', }, }); - await waitFor(() => !!result.current.entities.length); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); expect(result.current.backendEntities.length).toBe(2); act(() => @@ -160,13 +167,15 @@ describe('', () => { const query = qs.stringify({ filters: { kind: 'component', type: 'service' }, }); - const { result, waitFor } = renderHook(() => useEntityList(), { - wrapper, - initialProps: { - location: `/catalog?${query}`, - }, + const { result } = renderHook(() => useEntityList(), { + wrapper: ({ children }) => + wrapper({ location: `/catalog?${query}`, children }), + }); + await act(async () => {}); + + await waitFor(() => { + expect(result.current.queryParameters).toBeTruthy(); }); - await act(() => waitFor(() => !!result.current.queryParameters)); expect(result.current.queryParameters).toEqual({ kind: 'component', type: 'service', @@ -174,7 +183,7 @@ describe('', () => { }); it('does not fetch when only frontend filters change', async () => { - const { result, waitFor } = renderHook(() => useEntityList(), { + const { result } = renderHook(() => useEntityList(), { wrapper, }); @@ -200,32 +209,34 @@ describe('', () => { }); it('debounces multiple filter changes', async () => { - const { result, waitForNextUpdate, waitForValueToChange } = renderHook( - () => useEntityList(), - { - wrapper, - }, - ); - await waitForValueToChange(() => result.current.backendEntities); + const { result } = renderHook(() => useEntityList(), { + wrapper, + }); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); expect(result.current.backendEntities.length).toBe(2); expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); - act(() => { + await act(async () => { result.current.updateFilters({ kind: new EntityKindFilter('component') }); result.current.updateFilters({ type: new EntityTypeFilter('service') }); }); - await waitForNextUpdate(); - expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(2); + + await waitFor(() => { + expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(2); + }); }); it('returns an error on catalogApi failure', async () => { - const { result, waitForValueToChange, waitFor } = renderHook( - () => useEntityList(), - { - wrapper, - }, - ); - await waitForValueToChange(() => result.current.backendEntities); + const { result } = renderHook(() => useEntityList(), { + wrapper, + }); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); expect(result.current.backendEntities.length).toBe(2); mockCatalogApi.getEntities = jest.fn().mockRejectedValue('error'); diff --git a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx index 2fbc283cb4..6c9519eb08 100644 --- a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx @@ -18,7 +18,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { ComponentEntity, RELATION_OWNED_BY } from '@backstage/catalog-model'; import { IdentityApi, identityApiRef } from '@backstage/core-plugin-api'; import { TestApiProvider } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import React from 'react'; import { catalogApiRef } from '../api'; import { useEntityOwnership } from './useEntityOwnership'; @@ -83,19 +83,15 @@ describe('useEntityOwnership', () => { }); mockCatalogApi.getEntityByRef.mockResolvedValue(undefined); - const { result, waitForValueToChange } = renderHook( - () => useEntityOwnership(), - { - wrapper: Wrapper, - }, - ); + const { result } = renderHook(() => useEntityOwnership(), { + wrapper: Wrapper, + }); expect(result.current.loading).toBe(true); expect(result.current.isOwnedEntity(ownedEntity)).toBe(false); - await waitForValueToChange(() => result.current.loading); + await waitFor(() => expect(result.current.loading).toBe(false)); - expect(result.current.loading).toBe(false); expect(result.current.isOwnedEntity(ownedEntity)).toBe(true); }); }); diff --git a/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx b/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx index bd8116d6b3..092f8e164e 100644 --- a/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx @@ -16,8 +16,8 @@ import { Entity } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { WrapperComponent, renderHook } from '@testing-library/react'; -import React, { PropsWithChildren } from 'react'; +import { renderHook, waitFor } from '@testing-library/react'; +import React, { ComponentType, PropsWithChildren } from 'react'; import { catalogApiRef } from '../api'; import { useRelatedEntities } from './useRelatedEntities'; @@ -50,7 +50,7 @@ describe('useRelatedEntities', () => { getEntitiesByRefs: jest.fn(), }; - const wrapper: WrapperComponent> = ({ children }) => { + const wrapper: ComponentType> = ({ children }) => { return ( {children} @@ -70,7 +70,9 @@ describe('useRelatedEntities', () => { expect(rendered.result.current).toEqual({ loading: true }); - await rendered.waitForValueToChange(() => rendered.result.current.loading); + await waitFor(() => { + expect(rendered.result.current.loading).toBe(false); + }); expect(catalogApi.getEntitiesByRefs).toHaveBeenCalledWith({ entityRefs: ['group:default/the-owners-1', 'group:default/the-owners-2'], diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx index cde574e558..6c76e8eb24 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { starredEntitiesApiRef, @@ -56,12 +56,11 @@ describe('useStarredEntities', () => { }); it('should return an empty set', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, + }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.starredEntities.size).toBe(0); }); @@ -72,12 +71,11 @@ describe('useStarredEntities', () => { mockApi.toggleStarred(id); } - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, + }); - await waitForNextUpdate(); + await act(async () => {}); for (const item of expectedIds) { expect(result.current.starredEntities.has(item)).toBeTruthy(); @@ -85,12 +83,11 @@ describe('useStarredEntities', () => { }); it('should listen to changes when the storage is set elsewhere', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, + }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.starredEntities.size).toBe(0); expect(result.current.isStarredEntity(mockEntity)).toBeFalsy(); @@ -99,42 +96,37 @@ describe('useStarredEntities', () => { // catch when the hook re-renders with the latest data setTimeout(() => result.current.toggleStarredEntity(mockEntity), 1); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.starredEntities.size).toBe(1); + }); - expect(result.current.starredEntities.size).toBe(1); expect(result.current.isStarredEntity(mockEntity)).toBeTruthy(); }); it('should write new entries to the local store when adding a toggling entity', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); - - act(() => { - result.current.toggleStarredEntity(mockEntity); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, }); - await waitForNextUpdate(); + await act(async () => { + result.current.toggleStarredEntity(mockEntity); + }); expect(result.current.isStarredEntity(mockEntity)).toBeTruthy(); expect(result.current.isStarredEntity(secondMockEntity)).toBeFalsy(); }); it('should remove an existing entity when toggling entries', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, + }); - act(() => { + await act(async () => { result.current.toggleStarredEntity(mockEntity); result.current.toggleStarredEntity(secondMockEntity); result.current.toggleStarredEntity(mockEntity); }); - await waitForNextUpdate(); - expect(result.current.isStarredEntity(mockEntity)).toBeFalsy(); expect(result.current.isStarredEntity(secondMockEntity)).toBeTruthy(); }); diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.ts b/plugins/catalog-react/src/hooks/useStarredEntities.ts index 328a26e0f8..7e63aed10f 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.ts +++ b/plugins/catalog-react/src/hooks/useStarredEntities.ts @@ -20,7 +20,7 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { useApi } from '@backstage/core-plugin-api'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import useObservable from 'react-use/lib/useObservable'; import { starredEntitiesApiRef } from '../apis'; @@ -45,7 +45,7 @@ export function useStarredEntities(): { const starredEntitiesApi = useApi(starredEntitiesApiRef); const starredEntities = useObservable( - starredEntitiesApi.starredEntitie$(), + useMemo(() => starredEntitiesApi.starredEntitie$(), [starredEntitiesApi]), new Set(), ); diff --git a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx index 272ba05b01..e64a9bbdf8 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx @@ -16,7 +16,7 @@ import { Entity, CompoundEntityRef } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import Observable from 'zen-observable'; import { StarredEntitiesApi, starredEntitiesApiRef } from '../apis'; @@ -83,18 +83,16 @@ describe('useStarredEntity', () => { ); mockStarredEntitiesApi.toggleStarred.mockResolvedValue(); - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntity(entityOrRef), - { - wrapper, - }, - ); + const { result } = renderHook(() => useStarredEntity(entityOrRef), { + wrapper, + }); // the initial value will always be false because the observable triggers async expect(result.current.isStarredEntity).toBe(false); - await waitForNextUpdate(); - expect(result.current.isStarredEntity).toBe(true); + await waitFor(() => { + expect(result.current.isStarredEntity).toBe(true); + }); }); }); }); diff --git a/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx b/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx index 4ca9afbaff..c5490103cb 100644 --- a/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx +++ b/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ import { renderHook, act } from '@testing-library/react'; -import { waitFor } from '@testing-library/react'; import { mockCalverProject, @@ -48,10 +47,9 @@ describe('useCreateReleaseCandidate', () => { ); await act(async () => { - await waitFor(() => result.current.run()); + await result.current.run(); }); - expect(result.error).toEqual(undefined); expect(result.current.responseSteps).toHaveLength(6); }); @@ -67,7 +65,7 @@ describe('useCreateReleaseCandidate', () => { ); await act(async () => { - await waitFor(() => result.current.run()); + await result.current.run(); }); expect(result.current.responseSteps).toHaveLength(7); diff --git a/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts b/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts index 6d6b297d2a..3eeda0531f 100644 --- a/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts +++ b/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts @@ -15,7 +15,6 @@ */ import { renderHook, act } from '@testing-library/react'; -import { waitFor } from '@testing-library/react'; import { mockBumpedTag, @@ -50,10 +49,9 @@ describe('patch', () => { ); await act(async () => { - await waitFor(() => result.current.run(mockSelectedPatchCommit)); + await result.current.run(mockSelectedPatchCommit); }); - expect(result.error).toEqual(undefined); expect(result.current.responseSteps).toHaveLength(18); }); @@ -69,10 +67,9 @@ describe('patch', () => { ); await act(async () => { - await waitFor(() => result.current.run(mockSelectedPatchCommit)); + await result.current.run(mockSelectedPatchCommit); }); - expect(result.error).toEqual(undefined); expect(result.current.responseSteps).toHaveLength(19); expect(result.current).toMatchInlineSnapshot(` { diff --git a/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts b/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts index bd69a3366f..1b1bb54df0 100644 --- a/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts +++ b/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts @@ -15,8 +15,6 @@ */ import { renderHook, act } from '@testing-library/react'; -import { waitFor } from '@testing-library/react'; - import { mockCalverProject, mockReleaseCandidateCalver, @@ -50,10 +48,9 @@ describe('usePromoteRc', () => { ); await act(async () => { - await waitFor(() => result.current.run()); + await result.current.run(); }); - expect(result.error).toEqual(undefined); expect(result.current.responseSteps).toHaveLength(4); }); @@ -67,7 +64,7 @@ describe('usePromoteRc', () => { ); await act(async () => { - await waitFor(() => result.current.run()); + await result.current.run(); }); expect(result.current.responseSteps).toHaveLength(5); diff --git a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsForEntity.test.tsx b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsForEntity.test.tsx index ea99256bbf..026331c7d9 100644 --- a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsForEntity.test.tsx +++ b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsForEntity.test.tsx @@ -165,12 +165,8 @@ describe('useConsumerGroupOffsets', () => { lifecycle: 'development', }, }; - const { result } = subject(); - expect(() => result.current).toThrow(); - expect(result.error).toStrictEqual( - new Error( - `Failed to parse kafka consumer group annotation: got "dev/another,consumer"`, - ), + expect(() => subject()).toThrow( + `Failed to parse kafka consumer group annotation: got "dev/another,consumer"`, ); }); }); diff --git a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx index d18d1ae99d..2f3fc21f93 100644 --- a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx +++ b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { when } from 'jest-when'; import React, { PropsWithChildren } from 'react'; import { @@ -96,27 +96,28 @@ describe('useConsumerGroupOffsets', () => { .mockResolvedValue(consumerGroupOffsets); when(mockKafkaDashboardApi.getDashboardUrl).mockReturnValue({}); - const { result, waitForNextUpdate } = subject(); - await waitForNextUpdate(); - const [tableProps] = result.current; + const { result } = subject(); - expect(tableProps.consumerGroupsTopics).toStrictEqual([ - { - clusterId: 'prod', - consumerGroup: consumerGroupOffsets.consumerId, - dashboardUrl: undefined, - topics: consumerGroupOffsets.offsets, - }, - ]); + await waitFor(() => { + expect(result.current[0].consumerGroupsTopics).toStrictEqual([ + { + clusterId: 'prod', + consumerGroup: consumerGroupOffsets.consumerId, + dashboardUrl: undefined, + topics: consumerGroupOffsets.offsets, + }, + ]); + }); }); it('posts an error to the error api', async () => { const error = new Error('error!'); mockKafkaApi.getConsumerGroupOffsets.mockRejectedValueOnce(error); - const { waitForNextUpdate } = subject(); - await waitForNextUpdate(); + subject(); - expect(mockErrorApi.post).toHaveBeenCalledWith(error); + await waitFor(() => { + expect(mockErrorApi.post).toHaveBeenCalledWith(error); + }); }); }); diff --git a/plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx b/plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx index 535b8f5098..f98e4f5e6e 100644 --- a/plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx +++ b/plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import { useApi } from '@backstage/core-plugin-api'; -import { renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { useEvents } from './useEvents'; import { DateTime } from 'luxon'; @@ -49,7 +49,7 @@ describe('Events', () => { mockGetEventsByInvolvedObjectName.mockResolvedValue(response), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useEvents({ involvedObjectName: 'some-objecgt', namespace: 'some-namespace', @@ -59,7 +59,9 @@ describe('Events', () => { expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.loading).toEqual(false); + }); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); diff --git a/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts b/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts index 6efaa27a8b..ace954ec2d 100644 --- a/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts +++ b/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts @@ -16,7 +16,7 @@ import { useCustomResources } from './useCustomResources'; import { Entity } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { useApi } from '@backstage/core-plugin-api'; import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; import { generateAuth } from './auth'; @@ -97,13 +97,13 @@ describe('useCustomResources', () => { getCustomObjectsByEntity: mockGetCustomObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers), ); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); @@ -117,20 +117,20 @@ describe('useCustomResources', () => { getCustomObjectsByEntity: mockGetCustomObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expectMocksCalledCorrectly(2); + }); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - - expectMocksCalledCorrectly(2); }); it('should return error when getObjectsByEntity throws', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -139,11 +139,11 @@ describe('useCustomResources', () => { message: 'some error', }), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers), ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBe('some error'); expect(result.current.loading).toEqual(false); @@ -162,17 +162,19 @@ describe('useCustomResources', () => { mockGetCustomObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBe('generateAuth failed'); expect(result.current.loading).toEqual(false); expect(result.current.kubernetesObjects).toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + }); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); @@ -186,17 +188,19 @@ describe('useCustomResources', () => { .mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBe('failed to fetch'); expect(result.current.loading).toEqual(false); expect(result.current.kubernetesObjects).toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + }); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); @@ -212,17 +216,19 @@ describe('useCustomResources', () => { mockGetCustomObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeDefined(); + }); expect(result.current.error).toBe('generateAuth failed'); expect(result.current.loading).toEqual(false); @@ -236,17 +242,19 @@ describe('useCustomResources', () => { .mockRejectedValue({ message: 'failed to fetch' }), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeDefined(); + }); expect(result.current.error).toBe('failed to fetch'); expect(result.current.loading).toEqual(false); diff --git a/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts b/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts index 9f318f487d..93bfb6dd4d 100644 --- a/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts +++ b/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { useApi } from '@backstage/core-plugin-api'; -import { renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { useIsPodExecTerminalSupported } from './useIsPodExecTerminalSupported'; @@ -68,15 +68,14 @@ describe('useIsClusterShellEnabled', () => { async ({ testClusters, returnValue }) => { clusters = testClusters; - const { result, waitForNextUpdate } = renderHook(() => - useIsPodExecTerminalSupported(), - ); + const { result } = renderHook(() => useIsPodExecTerminalSupported()); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.loading).toEqual(false); + }); - expect(result.current.loading).toEqual(false); expect(result.current.value).toBe(returnValue); }, ); diff --git a/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts index 4c37c2fd30..9fa642e071 100644 --- a/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts +++ b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts @@ -16,7 +16,7 @@ import { useKubernetesObjects } from './useKubernetesObjects'; import { Entity } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { useApi } from '@backstage/core-plugin-api'; import { generateAuth } from './auth'; @@ -87,13 +87,13 @@ describe('useKubernetesObjects', () => { getObjectsByEntity: mockGetObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity), - ); + const { result } = renderHook(() => useKubernetesObjects(entity)); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.loading).toEqual(false); + }); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); @@ -107,14 +107,13 @@ describe('useKubernetesObjects', () => { getObjectsByEntity: mockGetObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await waitForNextUpdate(); expect(result.current.error).toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expectMocksCalledCorrectly(2); + }); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); @@ -129,11 +128,9 @@ describe('useKubernetesObjects', () => { message: 'some error', }), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity), - ); + const { result } = renderHook(() => useKubernetesObjects(entity)); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBe('some error'); expect(result.current.loading).toEqual(false); @@ -152,17 +149,17 @@ describe('useKubernetesObjects', () => { mockGetObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBe('generateAuth failed'); expect(result.current.loading).toEqual(false); expect(result.current.kubernetesObjects).toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + }); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); @@ -176,17 +173,17 @@ describe('useKubernetesObjects', () => { .mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBe('failed to fetch'); expect(result.current.loading).toEqual(false); expect(result.current.kubernetesObjects).toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + }); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); @@ -202,17 +199,17 @@ describe('useKubernetesObjects', () => { mockGetObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeDefined(); + }); expect(result.current.error).toBe('generateAuth failed'); expect(result.current.loading).toEqual(false); @@ -226,17 +223,17 @@ describe('useKubernetesObjects', () => { .mockRejectedValue({ message: 'failed to fetch' }), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeDefined(); + }); expect(result.current.error).toBe('failed to fetch'); expect(result.current.loading).toEqual(false); diff --git a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx index 1a44f1cd98..440eb6a6fa 100644 --- a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx +++ b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderHook } from '@testing-library/react'; +import { act, renderHook } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { WebsiteListResponse } from '@backstage/plugin-lighthouse-common'; import { lighthouseApiRef } from '../api'; @@ -77,8 +77,8 @@ describe('useWebsiteForEntity', () => { }); it('returns the lighthouse information for the website url in annotations', async () => { - const { result, waitForNextUpdate } = subject(); - await waitForNextUpdate(); + const { result } = subject(); + await act(async () => {}); expect(result.current?.value).toBe(website); }); @@ -92,8 +92,8 @@ describe('useWebsiteForEntity', () => { }); it('posts the error to the error api and returns the error to the caller', async () => { - const { result, waitForNextUpdate } = subject(); - await waitForNextUpdate(); + const { result } = subject(); + await act(async () => {}); expect(result.current?.error).toBe(error); expect(mockErrorApi.post).toHaveBeenCalledWith(error); }); @@ -109,8 +109,8 @@ describe('useWebsiteForEntity', () => { }); it('does not post the error to the error api and returns the error to the caller', async () => { - const { result, waitForNextUpdate } = subject(); - await waitForNextUpdate(); + const { result } = subject(); + await act(async () => {}); expect(result.current?.error).toBe(error); expect(mockErrorApi.post).not.toHaveBeenCalledWith(error); }); diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts index 5af495eaf4..cb02f94ac5 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts @@ -16,7 +16,7 @@ import { CompoundEntityRef, Entity } from '@backstage/catalog-model'; import { useGetEntities } from './useGetEntities'; import { CatalogApi } from '@backstage/catalog-client'; -import { renderHook } from '@testing-library/react'; +import { act, renderHook } from '@testing-library/react'; import { getEntityRelations } from '@backstage/plugin-catalog-react'; const givenParentGroup = 'team.squad1'; @@ -66,14 +66,11 @@ describe('useGetEntities', () => { describe('given aggregated relationsType', () => { const whenHookIsCalledWith = async (_entity: Entity) => { - const hook = renderHook( - ({ entity }) => useGetEntities(entity, 'aggregated'), - { - initialProps: { entity: _entity }, - }, - ); + renderHook(({ entity }) => useGetEntities(entity, 'aggregated'), { + initialProps: { entity: _entity }, + }); - await hook.waitForNextUpdate(); + await act(async () => {}); }; beforeEach(() => { @@ -207,14 +204,11 @@ describe('useGetEntities', () => { describe('given direct relationsType', () => { const whenHookIsCalledWith = async (_entity: Entity) => { - const hook = renderHook( - ({ entity }) => useGetEntities(entity, 'direct'), - { - initialProps: { entity: _entity }, - }, - ); + renderHook(({ entity }) => useGetEntities(entity, 'direct'), { + initialProps: { entity: _entity }, + }); - await hook.waitForNextUpdate(); + await act(async () => {}); }; it('given group entity should return directly owned entities', async () => { diff --git a/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx b/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx index c36aeaf417..dda09a0e04 100644 --- a/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx +++ b/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx @@ -22,7 +22,7 @@ import { } from '@backstage/core-plugin-api'; import { Playlist } from '@backstage/plugin-playlist-common'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import qs from 'qs'; import React, { PropsWithChildren } from 'react'; import { MemoryRouter } from 'react-router-dom'; @@ -114,23 +114,22 @@ describe('', () => { }); it('resolves backend filters', async () => { - const { result, waitForValueToChange } = renderHook( - () => usePlaylistList(), - { - wrapper, - }, - ); - await waitForValueToChange(() => result.current.backendPlaylists); - expect(result.current.backendPlaylists.length).toBe(2); + const { result } = renderHook(() => usePlaylistList(), { + wrapper, + }); + await waitFor(() => { + expect(result.current.backendPlaylists.length).toBe(2); + }); expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalled(); }); it('resolves frontend filters', async () => { - const { result, waitFor } = renderHook(() => usePlaylistList(), { + const { result } = renderHook(() => usePlaylistList(), { wrapper, }); - await waitFor(() => !!result.current.playlists.length); - expect(result.current.backendPlaylists.length).toBe(2); + await waitFor(() => { + expect(result.current.backendPlaylists.length).toBe(2); + }); act(() => result.current.updateFilters({ @@ -152,13 +151,15 @@ describe('', () => { const query = qs.stringify({ filters: { personal: 'all', owners: ['user:default/guest'] }, }); - const { result, waitFor } = renderHook(() => usePlaylistList(), { - wrapper, - initialProps: { - location: `/playlist?${query}`, - }, + const { result } = renderHook(() => usePlaylistList(), { + wrapper: ({ children }) => + wrapper({ location: `/playlist?${query}`, children }), + }); + await act(async () => {}); + + await waitFor(() => { + expect(result.current.queryParameters).toBeTruthy(); }); - await waitFor(() => !!result.current.queryParameters); expect(result.current.queryParameters).toEqual({ personal: 'all', owners: ['user:default/guest'], @@ -166,7 +167,7 @@ describe('', () => { }); it('does not fetch when only frontend filters change', async () => { - const { result, waitFor } = renderHook(() => usePlaylistList(), { + const { result } = renderHook(() => usePlaylistList(), { wrapper, }); @@ -191,7 +192,7 @@ describe('', () => { }); it('applies custom sorting', async () => { - const { result, waitFor } = renderHook(() => usePlaylistList(), { + const { result } = renderHook(() => usePlaylistList(), { wrapper, }); @@ -216,7 +217,7 @@ describe('', () => { it('returns an error on playlistApi failure', async () => { mockPlaylistApi.getAllPlaylists = jest.fn().mockRejectedValue('error'); - const { result, waitFor } = renderHook(() => usePlaylistList(), { + const { result } = renderHook(() => usePlaylistList(), { wrapper, }); await waitFor(() => { diff --git a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx index 567617fccf..3d61c11b79 100644 --- a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { ApiProvider } from '@backstage/core-app-api'; import { MockConfigApi, TestApiRegistry } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react'; +import { act, renderHook } from '@testing-library/react'; import { searchApiRef } from '../../api'; import { SearchContextProvider, useSearch } from '../../context'; @@ -67,7 +67,7 @@ describe('SearchFilter.hooks', () => { it('should set non-empty string value', async () => { const expectedFilter = 'someField'; const expectedValue = 'someValue'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, expectedValue); return useSearch(); @@ -77,7 +77,7 @@ describe('SearchFilter.hooks', () => { }, ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.filters[expectedFilter]).toEqual(expectedValue); }); @@ -85,7 +85,7 @@ describe('SearchFilter.hooks', () => { it('should set non-empty array value', async () => { const expectedFilter = 'someField'; const expectedValue = ['someValue', 'anotherValue']; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, expectedValue); return useSearch(); @@ -95,7 +95,7 @@ describe('SearchFilter.hooks', () => { }, ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.filters[expectedFilter]).toEqual(expectedValue); }); @@ -103,24 +103,25 @@ describe('SearchFilter.hooks', () => { it('should not set undefined value', async () => { const expectedFilter = 'someField'; const expectedValue = 'notEmpty'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, undefined); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - [expectedFilter]: expectedValue, + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + [expectedFilter]: expectedValue, + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.filters[expectedFilter]).toEqual(expectedValue); }); @@ -128,24 +129,25 @@ describe('SearchFilter.hooks', () => { it('should not set null value', async () => { const expectedFilter = 'someField'; const expectedValue = 'notEmpty'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, null); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - [expectedFilter]: expectedValue, + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + [expectedFilter]: expectedValue, + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.filters[expectedFilter]).toEqual(expectedValue); }); @@ -153,24 +155,25 @@ describe('SearchFilter.hooks', () => { it('should not set empty string value', async () => { const expectedFilter = 'someField'; const expectedValue = 'notEmpty'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, ''); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - [expectedFilter]: expectedValue, + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + [expectedFilter]: expectedValue, + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.filters[expectedFilter]).toEqual(expectedValue); }); @@ -178,24 +181,25 @@ describe('SearchFilter.hooks', () => { it('should not set empty array value', async () => { const expectedFilter = 'someField'; const expectedValue = ['not', 'empty']; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, []); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - [expectedFilter]: expectedValue, + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + [expectedFilter]: expectedValue, + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.filters[expectedFilter]).toEqual(expectedValue); }); @@ -203,24 +207,25 @@ describe('SearchFilter.hooks', () => { it('should not affect unrelated filters', async () => { const expectedFilter = 'someField'; const expectedValue = 'someValue'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, expectedValue); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - unrelatedField: 'unrelatedValue', + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + unrelatedField: 'unrelatedValue', + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.filters.unrelatedField).toEqual('unrelatedValue'); }); @@ -240,14 +245,15 @@ describe('SearchFilter.hooks', () => { it('should return resolved values of provided async function', async () => { const expectedValues = ['value1', 'value2']; const asyncFn = () => Promise.resolve(expectedValues); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useAsyncFilterValues(asyncFn, '', undefined, 1000), ); expect(result.current.loading).toEqual(true); - jest.runAllTimers(); - await waitForNextUpdate(); + await act(async () => { + jest.runAllTimers(); + }); expect(result.current.loading).toEqual(false); expect(result.current.value).toEqual(expectedValues); @@ -261,11 +267,15 @@ describe('SearchFilter.hooks', () => { expect(asyncFn).not.toHaveBeenCalled(); // Advance timers by 600ms - jest.advanceTimersByTime(600); + await act(async () => { + jest.advanceTimersByTime(600); + }); expect(asyncFn).not.toHaveBeenCalled(); // Another 600ms to exceed the 1000ms debounce - jest.advanceTimersByTime(600); + await act(async () => { + jest.advanceTimersByTime(600); + }); expect(asyncFn).toHaveBeenCalled(); }); @@ -273,21 +283,23 @@ describe('SearchFilter.hooks', () => { const asyncFn = jest .fn() .mockImplementation((x: string) => Promise.resolve([x])); - const { rerender, waitForNextUpdate } = renderHook( + const { rerender } = renderHook( (props: { inputValue: string } = { inputValue: '' }) => useAsyncFilterValues(asyncFn, props.inputValue, undefined, 1000), ); expect(asyncFn).not.toHaveBeenCalled(); - jest.runAllTimers(); - await waitForNextUpdate(); + await act(async () => { + jest.runAllTimers(); + }); expect(asyncFn).toHaveBeenCalledTimes(1); expect(asyncFn).toHaveBeenCalledWith(''); // Re-render with different input value. rerender({ inputValue: 'somethingElse' }); - jest.runAllTimers(); - await waitForNextUpdate(); + await act(async () => { + jest.runAllTimers(); + }); expect(asyncFn).toHaveBeenCalledTimes(2); expect(asyncFn).toHaveBeenLastCalledWith('somethingElse'); }); @@ -295,15 +307,16 @@ describe('SearchFilter.hooks', () => { it('should not call provided method more than once when re-rendered with same input', async () => { const expectedValues = ['value1', 'value2']; const asyncFn = jest.fn().mockResolvedValue(expectedValues); - const { rerender, waitForNextUpdate } = renderHook( + const { rerender } = renderHook( (props: { inputValue: string } = { inputValue: '' }) => useAsyncFilterValues(asyncFn, props.inputValue, undefined, 1000), ); expect(asyncFn).not.toHaveBeenCalled(); - jest.runAllTimers(); - await waitForNextUpdate(); + await act(async () => { + jest.runAllTimers(); + }); expect(asyncFn).toHaveBeenCalledTimes(1); // Re-render multiple times with the same input. diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index 64c3cbbded..7ac2d6d11b 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -15,8 +15,13 @@ */ import { configApiRef } from '@backstage/core-plugin-api'; -import { render, screen, waitFor } from '@testing-library/react'; -import { act, renderHook } from '@testing-library/react'; +import { + render, + screen, + waitFor, + act, + renderHook, +} from '@testing-library/react'; import { MockConfigApi, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { @@ -70,10 +75,8 @@ describe('SearchContext', () => { }); it('Throws error when no context is set', () => { - const { result } = renderHook(() => useSearch()); - - expect(result.error).toEqual( - Error('useSearch must be used within a SearchContextProvider'), + expect(() => renderHook(() => useSearch())).toThrow( + 'useSearch must be used within a SearchContextProvider', ); }); @@ -82,28 +85,22 @@ describe('SearchContext', () => { expect(hook.result.current).toEqual(false); - const { result, waitForNextUpdate } = renderHook( - () => useSearchContextCheck(), - { - wrapper, - initialProps: { - initialState, - }, - }, - ); + const { result } = renderHook(() => useSearchContextCheck(), { + wrapper: ({ children }) => wrapper({ children, initialState }), + }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current).toEqual(true); }); describe('Uses initial state values', () => { it('Uses default initial state values', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { + const { result } = renderHook(() => useSearch(), { wrapper, }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current).toEqual( expect.objectContaining({ @@ -117,34 +114,32 @@ describe('SearchContext', () => { }); it('Uses provided initial state values', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current).toEqual(expect.objectContaining(initialState)); }); it('Uses page limit provided via config api', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - config: { - search: { - query: { - pageLimit: 100, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState, + config: { + search: { + query: { + pageLimit: 100, + }, }, }, - }, - }, + }), }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current).toEqual( expect.objectContaining({ ...initialState, pageLimit: 100 }), @@ -154,131 +149,122 @@ describe('SearchContext', () => { describe('Resets cursor', () => { it('When term is cleared', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState: { - ...initialState, - term: 'first term', - pageCursor: 'SOMEPAGE', - }, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState: { + ...initialState, + term: 'first term', + pageCursor: 'SOMEPAGE', + }, + }), }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.term).toEqual('first term'); expect(result.current.pageCursor).toEqual('SOMEPAGE'); - act(() => { + await act(async () => { result.current.setTerm(''); }); - await waitForNextUpdate(); - expect(result.current.pageCursor).toBeUndefined(); }); it('When term is set (and different from previous)', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState: { - ...initialState, - term: 'first term', - pageCursor: 'SOMEPAGE', - }, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState: { + ...initialState, + term: 'first term', + pageCursor: 'SOMEPAGE', + }, + }), }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.term).toEqual('first term'); expect(result.current.pageCursor).toEqual('SOMEPAGE'); - act(() => { + await act(async () => { result.current.setTerm('second term'); }); - await waitForNextUpdate(); - expect(result.current.pageCursor).toBeUndefined(); }); it('When filters are cleared', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState: { - ...initialState, - term: 'first term', - filters: { foo: 'bar' }, - pageCursor: 'SOMEPAGE', - }, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState: { + ...initialState, + term: 'first term', + filters: { foo: 'bar' }, + pageCursor: 'SOMEPAGE', + }, + }), }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.filters).toEqual({ foo: 'bar' }); expect(result.current.pageCursor).toEqual('SOMEPAGE'); - act(() => { + await act(async () => { result.current.setFilters({}); }); - await waitForNextUpdate(); - expect(result.current.pageCursor).toBeUndefined(); }); it('When filters are set (and different from previous)', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState: { - ...initialState, - term: 'first term', - filters: { foo: 'bar' }, - pageCursor: 'SOMEPAGE', - }, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState: { + ...initialState, + term: 'first term', + filters: { foo: 'bar' }, + pageCursor: 'SOMEPAGE', + }, + }), }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.filters).toEqual({ foo: 'bar' }); expect(result.current.pageCursor).toEqual('SOMEPAGE'); - act(() => { + await act(async () => { result.current.setFilters({ foo: 'test' }); }); - await waitForNextUpdate(); - expect(result.current.pageCursor).toBeUndefined(); }); }); describe('Performs search (and sets results)', () => { it('When term is set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await act(async () => {}); const term = 'term'; - act(() => { + await act(async () => { result.current.setTerm(term); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ term, types: ['*'], @@ -287,23 +273,18 @@ describe('SearchContext', () => { }); it('When types is set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await act(async () => {}); const types = ['type']; - act(() => { + await act(async () => { result.current.setTypes(types); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ types, term: '', @@ -312,23 +293,18 @@ describe('SearchContext', () => { }); it('When filters are set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await act(async () => {}); const filters = { filter: 'filter' }; - act(() => { + await act(async () => { result.current.setFilters(filters); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ filters, term: '', @@ -337,23 +313,18 @@ describe('SearchContext', () => { }); it('When page limit is set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await act(async () => {}); const pageLimit = 30; - act(() => { + await act(async () => { result.current.setPageLimit(pageLimit); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ pageLimit, term: '', @@ -363,23 +334,18 @@ describe('SearchContext', () => { }); it('When page cursor is set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await act(async () => {}); const pageCursor = 'SOMEPAGE'; - act(() => { + await act(async () => { result.current.setPageCursor(pageCursor); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ pageCursor, term: '', @@ -394,24 +360,19 @@ describe('SearchContext', () => { nextPageCursor: 'NEXT', }); - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.fetchNextPage).toBeDefined(); expect(result.current.fetchPreviousPage).toBeUndefined(); - act(() => { + await act(async () => { result.current.fetchNextPage!(); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ term: '', types: ['*'], @@ -426,24 +387,19 @@ describe('SearchContext', () => { previousPageCursor: 'PREVIOUS', }); - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.fetchNextPage).toBeUndefined(); expect(result.current.fetchPreviousPage).toBeDefined(); - act(() => { + await act(async () => { result.current.fetchPreviousPage!(); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ term: '', types: ['*'], diff --git a/plugins/techdocs-react/src/context.test.tsx b/plugins/techdocs-react/src/context.test.tsx index 7890e755b4..e66630b04e 100644 --- a/plugins/techdocs-react/src/context.test.tsx +++ b/plugins/techdocs-react/src/context.test.tsx @@ -19,7 +19,11 @@ import { renderHook, act } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; import { lightTheme } from '@backstage/theme'; -import { MockAnalyticsApi, TestApiProvider } from '@backstage/test-utils'; +import { + MockAnalyticsApi, + MockConfigApi, + TestApiProvider, +} from '@backstage/test-utils'; import { Entity, CompoundEntityRef } from '@backstage/catalog-model'; import { analyticsApiRef, @@ -30,6 +34,7 @@ import { import { techdocsApiRef } from './api'; import { useTechDocsReaderPage, TechDocsReaderPageProvider } from './context'; import { TechDocsMetadata } from './types'; +import { JsonObject } from '@backstage/config'; const mockShadowRoot = () => { const div = document.createElement('div'); @@ -60,10 +65,6 @@ const techdocsApiMock = { getTechDocsMetadata: jest.fn().mockResolvedValue(mockTechDocsMetadata), }; -const configApiMock = { - getOptionalBoolean: jest.fn().mockReturnValue(undefined), -}; - const analyticsApiMock = new MockAnalyticsApi(); const wrapper = ({ @@ -72,16 +73,18 @@ const wrapper = ({ name: mockEntityMetadata.metadata.name, namespace: mockEntityMetadata.metadata.namespace!!, }, + config, children, }: { entityRef?: CompoundEntityRef; + config?: JsonObject; children: React.ReactNode; }) => ( @@ -98,47 +101,32 @@ describe('useTechDocsReaderPage', () => { }); it('should set title', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useTechDocsReaderPage(), - { wrapper }, - ); + const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); expect(result.current.title).toBe(''); - act(() => result.current.setTitle('test site title')); - - await waitForNextUpdate(); + await act(async () => result.current.setTitle('test site title')); expect(result.current.title).toBe('test site title'); }); it('should set subtitle', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useTechDocsReaderPage(), - { wrapper }, - ); + const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); expect(result.current.subtitle).toBe(''); - act(() => result.current.setSubtitle('test site subtitle')); - - await waitForNextUpdate(); + await act(async () => result.current.setSubtitle('test site subtitle')); expect(result.current.subtitle).toBe('test site subtitle'); }); it('should set shadow root', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useTechDocsReaderPage(), - { wrapper }, - ); + const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); // mock shadowroot const shadowRoot = mockShadowRoot(); - act(() => result.current.setShadowRoot(shadowRoot)); - - await waitForNextUpdate(); + await act(async () => result.current.setShadowRoot(shadowRoot)); expect(result.current.shadowRoot?.innerHTML).toBe( '

Shadow DOM Mock

', @@ -152,30 +140,35 @@ describe('useTechDocsReaderPage', () => { namespace: mockEntityMetadata.metadata.namespace?.toLocaleLowerCase(), }; const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); + await act(async () => {}); expect(result.current.entityRef).toStrictEqual(lowercaseEntityRef); }); it('entityRef is not modified when legacyUseCaseSensitiveTripletPaths is true', async () => { - configApiMock.getOptionalBoolean.mockReturnValueOnce(true); const caseSensitiveEntityRef = { kind: mockEntityMetadata.kind, name: mockEntityMetadata.metadata.name, namespace: mockEntityMetadata.metadata.namespace!!, }; - const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); + const { result } = renderHook(() => useTechDocsReaderPage(), { + wrapper: ({ children }) => + wrapper({ + children, + config: { techdocs: { legacyUseCaseSensitiveTripletPaths: true } }, + }), + }); + await act(async () => {}); expect(result.current.entityRef).toStrictEqual(caseSensitiveEntityRef); }); it('entityRef provided as analytics context', async () => { - const { waitForNextUpdate } = renderHook( - () => useAnalytics().captureEvent('action', 'subject'), - { wrapper }, - ); - - await waitForNextUpdate(); + renderHook(() => useAnalytics().captureEvent('action', 'subject'), { + wrapper, + }); + await act(async () => {}); expect(analyticsApiMock.getEvents()[0]).toMatchObject({ action: 'action', diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx index e3d5a59587..43dabaa7c7 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { renderHook } from '@testing-library/react'; +import { act, renderHook } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; @@ -95,12 +95,9 @@ describe('context', () => { }); it('should return expected entity values', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useEntityMetadata(), - { wrapper }, - ); + const { result } = renderHook(() => useEntityMetadata(), { wrapper }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.value).toBeDefined(); expect(result.current.error).toBeUndefined(); @@ -116,12 +113,9 @@ describe('context', () => { }); it('should return expected techdocs metadata values', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useTechDocsMetadata(), - { wrapper }, - ); + const { result } = renderHook(() => useTechDocsMetadata(), { wrapper }); - await waitForNextUpdate(); + await act(async () => {}); expect(result.current.value).toBeDefined(); expect(result.current.error).toBeUndefined(); diff --git a/plugins/techdocs/src/reader/components/useReaderState.test.tsx b/plugins/techdocs/src/reader/components/useReaderState.test.tsx index e3b60f6f25..d8851a805d 100644 --- a/plugins/techdocs/src/reader/components/useReaderState.test.tsx +++ b/plugins/techdocs/src/reader/components/useReaderState.test.tsx @@ -16,7 +16,7 @@ import { NotFoundError } from '@backstage/errors'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import React from 'react'; import { techdocsStorageApiRef } from '../../api'; import { @@ -284,47 +284,45 @@ describe('useReaderState', () => { return 'cached'; }); - await act(async () => { - const { result, waitForValueToChange } = await renderHook( - () => useReaderState('Component', 'default', 'backstage', '/example'), - { wrapper: Wrapper }, - ); + const { result } = renderHook( + () => useReaderState('Component', 'default', 'backstage', '/example'), + { wrapper: Wrapper }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - await waitForValueToChange(() => result.current.state); - - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), }); + + await act(async () => {}); + + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); it('should reload initially missing content', async () => { @@ -336,6 +334,7 @@ describe('useReaderState', () => { }); techdocsStorageApi.syncEntityDocs.mockImplementation( async (_, logHandler) => { + await 'a tick'; logHandler?.call(this, 'Line 1'); logHandler?.call(this, 'Line 2'); await new Promise(resolve => setTimeout(resolve, 1100)); @@ -343,75 +342,73 @@ describe('useReaderState', () => { }, ); - await act(async () => { - const { result, waitForValueToChange } = await renderHook( - () => useReaderState('Component', 'default', 'backstage', '/example'), - { wrapper: Wrapper }, - ); + const { result } = renderHook( + () => useReaderState('Component', 'default', 'backstage', '/example'), + { wrapper: Wrapper }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - await waitForValueToChange(() => result.current.state, { - timeout: 2000, - }); - - expect(result.current).toEqual({ - state: 'INITIAL_BUILD', - path: '/example', - content: undefined, - contentErrorMessage: 'NotFoundError: Page Not Found', - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), - }); - - await waitForValueToChange(() => result.current.state); - - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - await waitForValueToChange(() => result.current.state); - - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledTimes(1); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), }); + + await waitFor(() => expect(result.current.state).toBe('INITIAL_BUILD'), { + timeout: 2000, + }); + + expect(result.current).toEqual({ + state: 'INITIAL_BUILD', + path: '/example', + content: undefined, + contentErrorMessage: 'NotFoundError: Page Not Found', + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); + + await waitFor(() => expect(result.current.state).toBe('CHECKING')); + + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH')); + + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledTimes(1); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); it('should handle stale content', async () => { @@ -423,6 +420,7 @@ describe('useReaderState', () => { }); techdocsStorageApi.syncEntityDocs.mockImplementation( async (_, logHandler) => { + await 'a tick'; logHandler?.call(this, 'Line 1'); logHandler?.call(this, 'Line 2'); await new Promise(resolve => setTimeout(resolve, 1100)); @@ -430,101 +428,105 @@ describe('useReaderState', () => { }, ); - await act(async () => { - const { result, waitForValueToChange } = await renderHook( - () => useReaderState('Component', 'default', 'backstage', '/example'), - { wrapper: Wrapper }, - ); + const { result } = renderHook( + () => useReaderState('Component', 'default', 'backstage', '/example'), + { wrapper: Wrapper }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - // the content is returned but the sync is in progress - await waitForValueToChange(() => result.current.state); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), - }); - - // the sync takes longer than 1 seconds so the refreshing state starts - await waitForValueToChange(() => result.current.state); - expect(result.current).toEqual({ - state: 'CONTENT_STALE_REFRESHING', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), - }); - - // the content is updated but not yet displayed - await waitForValueToChange(() => result.current.state); - expect(result.current).toEqual({ - state: 'CONTENT_STALE_READY', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), - }); - - // reload the content - result.current.contentReload(); - - // the new content refresh is triggered - await waitForValueToChange(() => result.current.state); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - // the new content is loaded - await waitForValueToChange(() => result.current.state, { - timeout: 2000, - }); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my new content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), }); + + // the content is returned but the sync is in progress + await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH')); + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); + + // the sync takes longer than 1 seconds so the refreshing state starts + await waitFor(() => + expect(result.current.state).toBe('CONTENT_STALE_REFRESHING'), + ); + expect(result.current).toEqual({ + state: 'CONTENT_STALE_REFRESHING', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); + + // the content is updated but not yet displayed + await waitFor(() => + expect(result.current.state).toBe('CONTENT_STALE_READY'), + ); + expect(result.current).toEqual({ + state: 'CONTENT_STALE_READY', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); + + // reload the content + await act(async () => { + result.current.contentReload(); + }); + + // the new content refresh is triggered + await waitFor(() => expect(result.current.state).toBe('CHECKING')); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + // the new content is loaded + await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH'), { + timeout: 2000, + }); + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my new content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); it('should handle navigation', async () => { @@ -537,93 +539,93 @@ describe('useReaderState', () => { .mockRejectedValueOnce(new NotFoundError('Some error description')); techdocsStorageApi.syncEntityDocs.mockResolvedValue('cached'); - await act(async () => { - const { result, waitForValueToChange, rerender } = await renderHook( - ({ path }: { path: string }) => - useReaderState('Component', 'default', 'backstage', path), - { initialProps: { path: '/example' }, wrapper: Wrapper as any }, - ); + const { result, rerender } = renderHook( + ({ path }: { path: string }) => + useReaderState('Component', 'default', 'backstage', path), + { initialProps: { path: '/example' }, wrapper: Wrapper as any }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - // show the content - await waitForValueToChange(() => result.current.state); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - // navigate - rerender({ path: '/new' }); - - await waitForValueToChange(() => result.current.state); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - await waitForValueToChange(() => result.current.state, { - timeout: 2000, - }); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/new', - content: 'my new content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - // navigate - rerender({ path: '/missing' }); - - await waitForValueToChange(() => result.current.state); - expect(result.current).toEqual({ - state: 'CONTENT_NOT_FOUND', - path: '/missing', - content: undefined, - contentErrorMessage: 'NotFoundError: Some error description', - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/new', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), }); + + // show the content + await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH')); + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + // navigate + rerender({ path: '/new' }); + + await waitFor(() => expect(result.current.state).toBe('CHECKING')); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH'), { + timeout: 2000, + }); + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/new', + content: 'my new content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + // navigate + rerender({ path: '/missing' }); + + await waitFor(() => + expect(result.current.state).toBe('CONTENT_NOT_FOUND'), + ); + expect(result.current).toEqual({ + state: 'CONTENT_NOT_FOUND', + path: '/missing', + content: undefined, + contentErrorMessage: 'NotFoundError: Some error description', + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/new', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); it('should handle content error', async () => { @@ -632,47 +634,47 @@ describe('useReaderState', () => { ); techdocsStorageApi.syncEntityDocs.mockResolvedValue('cached'); - await act(async () => { - const { result, waitForValueToChange } = await renderHook( - () => useReaderState('Component', 'default', 'backstage', '/example'), - { wrapper: Wrapper }, - ); + const { result } = renderHook( + () => useReaderState('Component', 'default', 'backstage', '/example'), + { wrapper: Wrapper }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - // the content loading threw an error - await waitForValueToChange(() => result.current.state); - expect(result.current).toEqual({ - state: 'CONTENT_NOT_FOUND', - path: '/example', - content: undefined, - contentErrorMessage: 'NotFoundError: Some error description', - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), }); + + // the content loading threw an error + await waitFor(() => + expect(result.current.state).toBe('CONTENT_NOT_FOUND'), + ); + expect(result.current).toEqual({ + state: 'CONTENT_NOT_FOUND', + path: '/example', + content: undefined, + contentErrorMessage: 'NotFoundError: Some error description', + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); }); }); From 80a79cc1e77c659c9e461e7ad36223d6cb63e256 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 13:11:15 +0200 Subject: [PATCH 104/348] plugins: rtl 13 fixes for tests Signed-off-by: Patrik Oldsberg --- .../BitriseBuildDetailsDialog.test.tsx | 5 +- .../StepPrepareCreatePullRequest.test.tsx | 203 +++++++++--------- .../src/components/useImportState.test.tsx | 7 - .../EntityAutocompletePicker.test.tsx | 4 +- .../EntityLifecyclePicker.test.tsx | 28 +-- .../EntityNamespacePicker.test.tsx | 4 +- .../EntityPeekAheadPopover.test.tsx | 2 +- .../EntityTagPicker/EntityTagPicker.test.tsx | 27 ++- .../EntitySwitch/EntitySwitch.test.tsx | 6 +- .../src/features/Features.test.tsx | 6 +- .../src/hooks/useResponseSteps.test.ts | 4 +- .../Cards/RecentWorkflowRunsCard.test.tsx | 2 +- .../CreatePlaylistButton.test.tsx | 4 + .../PlaylistEditDialog.test.tsx | 10 + .../PlaylistPage/PlaylistHeader.test.tsx | 6 + .../PlaylistPage/PlaylistPage.test.tsx | 4 +- .../next/components/Stepper/Stepper.test.tsx | 10 +- .../TemplateCategoryPicker.test.tsx | 3 +- .../ActionsPage/ActionsPage.test.tsx | 12 +- .../DryRunResults/DryRunResultsView.test.tsx | 6 +- .../SearchFilter.Autocomplete.test.tsx | 4 +- .../components/Incident/Incidents.test.tsx | 66 +++--- .../src/test-utils.tsx | 8 +- .../components/TechDocsBuildLogs.test.tsx | 4 +- .../TechDocsReaderPage.test.tsx | 131 ++++++----- .../TechDocsReaderPageContent.test.tsx | 74 +++---- .../TechDocsReaderPageHeader.test.tsx | 134 +++++------- 27 files changed, 371 insertions(+), 403 deletions(-) diff --git a/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx b/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx index 7992e08f37..e283448b36 100644 --- a/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx +++ b/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx @@ -15,9 +15,10 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; +import { act, render } from '@testing-library/react'; import { BitriseBuildDetailsDialog } from './BitriseBuildDetailsDialog'; import { BitriseBuildResult } from '../../api/bitriseApi.model'; +import userEvent from '@testing-library/user-event'; jest.mock('../BitriseArtifactsComponent', () => ({ BitriseArtifactsComponent: (_props: { build: string }) => <>VISIBLE, @@ -48,7 +49,7 @@ describe('BitriseArtifactsComponent', () => { expect(rendered.queryByText('VISIBLE')).not.toBeInTheDocument(); - btn.click(); + await act(() => userEvent.click(btn)); expect(rendered.getByText('VISIBLE')).toBeInTheDocument(); }); diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index 36f1217c37..45566528bc 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -18,7 +18,7 @@ import { configApiRef, errorApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { TestApiProvider, MockConfigApi } from '@backstage/test-utils'; import { TextField } from '@material-ui/core'; -import { act, render, screen } from '@testing-library/react'; +import { act, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { AnalyzeResult, catalogImportApiRef } from '../../api'; @@ -101,36 +101,36 @@ describe('', () => { it('renders without exploding', async () => { catalogApi.getEntities.mockReturnValue(Promise.resolve({ items: [] })); - await act(async () => { - render( - { - return ( - <> - - - - - - ); - }} - />, - { - wrapper: Wrapper, - }, - ); + render( + { + return ( + <> + + + + + + ); + }} + />, + { + wrapper: Wrapper, + }, + ); - const title = await screen.findByText('My title'); - const description = await screen.findByText('body', { - selector: 'strong', - }); - expect(title).toBeInTheDocument(); - expect(title).toBeVisible(); - expect(description).toBeInTheDocument(); - expect(description).toBeVisible(); + await act(async () => {}); + + const title = await screen.findByText('My title'); + const description = await screen.findByText('body', { + selector: 'strong', }); + expect(title).toBeInTheDocument(); + expect(title).toBeVisible(); + expect(description).toBeInTheDocument(); + expect(description).toBeVisible(); }); it('should submit created PR', async () => { @@ -142,39 +142,38 @@ describe('', () => { }), ); - await act(async () => { - render( - { - return ( - <> - - - - - - ); - }} - />, - { - wrapper: Wrapper, - }, - ); + render( + { + return ( + <> + + + + + + ); + }} + />, + { + wrapper: Wrapper, + }, + ); + await act(async () => {}); - await userEvent.type(await screen.findByLabelText('name'), '-changed'); - await userEvent.type(await screen.findByLabelText('owner'), '-changed'); - await userEvent.click(screen.getByRole('button', { name: /Create PR/i })); - }); + await userEvent.type(await screen.findByLabelText('name'), '-changed'); + await userEvent.type(await screen.findByLabelText('owner'), '-changed'); + await userEvent.click(screen.getByRole('button', { name: /Create PR/i })); expect(catalogImportApi.submitPullRequest).toHaveBeenCalledTimes(1); expect(catalogImportApi.submitPullRequest.mock.calls[0]).toMatchObject([ @@ -226,31 +225,30 @@ spec: new Error('some error'), ); - await act(async () => { - render( - { - return ( - <> - - - - - - ); - }} - />, - { - wrapper: Wrapper, - }, - ); + render( + { + return ( + <> + + + + + + ); + }} + />, + { + wrapper: Wrapper, + }, + ); + await act(async () => {}); - await userEvent.click( - await screen.findByRole('button', { name: /Create PR/i }), - ); - }); + await userEvent.click( + await screen.findByRole('button', { name: /Create PR/i }), + ); expect(screen.getByText('some error')).toBeInTheDocument(); expect(catalogImportApi.submitPullRequest).toHaveBeenCalledTimes(1); @@ -273,30 +271,27 @@ spec: }), ); - await act(async () => { - render( - , - { - wrapper: Wrapper, - }, - ); + render( + , + { + wrapper: Wrapper, + }, + ); + await act(async () => {}); + + await waitFor(() => { + expect(catalogApi.getEntities).toHaveBeenCalledTimes(1); }); - expect(catalogApi.getEntities).toHaveBeenCalledTimes(1); expect(renderFormFieldsFn).toHaveBeenCalled(); expect(renderFormFieldsFn.mock.calls[0][0]).toMatchObject({ - groups: [], - groupsLoading: true, + groups: ['my-group'], + groupsLoading: false, }); - expect( - renderFormFieldsFn.mock.calls[ - renderFormFieldsFn.mock.calls.length - 1 - ][0], - ).toMatchObject({ groups: ['my-group'], groupsLoading: false }); }); describe('generateEntities', () => { diff --git a/plugins/catalog-import/src/components/useImportState.test.tsx b/plugins/catalog-import/src/components/useImportState.test.tsx index 2345b2d696..dc2cb30f6f 100644 --- a/plugins/catalog-import/src/components/useImportState.test.tsx +++ b/plugins/catalog-import/src/components/useImportState.test.tsx @@ -73,7 +73,6 @@ describe('useImportState', () => { describe('onAnalysis & onPrepare & onReview & onReset', () => { it('should work', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current).toMatchObject({ activeFlow: 'unknown', @@ -148,7 +147,6 @@ describe('useImportState', () => { it('should work skipped', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current).toMatchObject({ activeFlow: 'unknown', @@ -198,7 +196,6 @@ describe('useImportState', () => { it('should ignore on invalid state', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); // state 'analyze' act(() => { @@ -264,7 +261,6 @@ describe('useImportState', () => { describe('onGoBack', () => { it('should work', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current.activeStepNumber).toBe(0); expect(result.current.onGoBack).toBeUndefined(); @@ -303,7 +299,6 @@ describe('useImportState', () => { it('should work for skipped', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current.activeStepNumber).toBe(0); expect(result.current.onGoBack).toBeUndefined(); @@ -329,7 +324,6 @@ describe('useImportState', () => { describe('should consider prepareNotRepeatable', () => { it('as true', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current.onGoBack).toBeUndefined(); @@ -351,7 +345,6 @@ describe('useImportState', () => { it('as false', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current.onGoBack).toBeUndefined(); diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx index 38edb9b064..32e66dc578 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx @@ -179,9 +179,7 @@ describe('', () => {
, ); await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - options: undefined, - }), + expect(screen.getByTestId('options-picker-expand')).toBeInTheDocument(), ); fireEvent.click(screen.getByTestId('options-picker-expand')); diff --git a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx index 19554f18b7..de40f90c55 100644 --- a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx @@ -74,9 +74,10 @@ describe('', () => {
, ); - await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); - expect(updateFilters).toHaveBeenLastCalledWith({ - lifecycles: new EntityLifecycleFilter(['experimental']), + await waitFor(() => { + expect(updateFilters).toHaveBeenLastCalledWith({ + lifecycles: new EntityLifecycleFilter(['experimental']), + }); }); }); @@ -119,9 +120,10 @@ describe('', () => { , ); - await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); - expect(updateFilters).toHaveBeenLastCalledWith({ - lifecycles: new EntityLifecycleFilter(['production']), + await waitFor(() => { + expect(updateFilters).toHaveBeenLastCalledWith({ + lifecycles: new EntityLifecycleFilter(['production']), + }); }); fireEvent.click(screen.getByTestId('lifecycles-picker-expand')); expect(screen.getByLabelText('production')).toBeChecked(); @@ -147,9 +149,10 @@ describe('', () => { , ); - await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); - expect(updateFilters).toHaveBeenLastCalledWith({ - lifecycles: new EntityLifecycleFilter(['experimental']), + await waitFor(() => { + expect(updateFilters).toHaveBeenLastCalledWith({ + lifecycles: new EntityLifecycleFilter(['experimental']), + }); }); rendered.rerender( @@ -210,9 +213,10 @@ describe('', () => { , ); - await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); - expect(updateFilters).toHaveBeenLastCalledWith({ - lifecycles: new EntityLifecycleFilter(['production']), + await waitFor(() => { + expect(updateFilters).toHaveBeenLastCalledWith({ + lifecycles: new EntityLifecycleFilter(['production']), + }); }); }); }); diff --git a/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx b/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx index 7dd13620c7..c4b5e64c9d 100644 --- a/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx @@ -113,9 +113,7 @@ describe('', () => { , ); await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - namespace: undefined, - }), + expect(screen.getByTestId('namespace-picker-expand')).toBeInTheDocument(), ); fireEvent.click(screen.getByTestId('namespace-picker-expand')); diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx index f665ca6c00..85a477801a 100644 --- a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx +++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx @@ -49,7 +49,7 @@ const apis = TestApiRegistry.from([catalogApiRef, catalogApi]); describe('', () => { it('renders all owners', async () => { - renderInTestApp( + await renderInTestApp( diff --git a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx index bfaa689190..917ece047c 100644 --- a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx @@ -14,7 +14,13 @@ * limitations under the License. */ -import { fireEvent, render, waitFor, screen } from '@testing-library/react'; +import { + fireEvent, + render, + waitFor, + screen, + act, +} from '@testing-library/react'; import React from 'react'; import { MockEntityListContextProvider } from '../../testUtils/providers'; import { EntityTagFilter } from '../../filters'; @@ -127,9 +133,7 @@ describe('', () => { , ); await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - tags: undefined, - }), + expect(screen.getByTestId('tags-picker-expand')).toBeInTheDocument(), ); fireEvent.click(screen.getByTestId('tags-picker-expand')); @@ -218,13 +222,16 @@ describe('', () => { , ); await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - tags: new EntityTagFilter(['tag1']), - }), + expect(screen.getByTestId('tags-picker-expand')).toBeInTheDocument(), ); - fireEvent.click(screen.getByTestId('tags-picker-expand')); - fireEvent.click(screen.getByLabelText('tag2')); - expect(screen.getByLabelText('tag2')).toBeChecked(); + + await act(async () => { + fireEvent.click(screen.getByTestId('tags-picker-expand')); + }); + await act(async () => { + fireEvent.click(screen.getByLabelText('tag2')); + }); + expect(updateFilters).toHaveBeenLastCalledWith({ tags: new EntityTagFilter(['tag1', 'tag2']), }); diff --git a/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx b/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx index d9998b0ca5..aebdd6b9c2 100644 --- a/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx +++ b/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx @@ -19,7 +19,7 @@ import { AsyncEntityProvider, EntityProvider, } from '@backstage/plugin-catalog-react'; -import { render, screen, waitFor } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import React, { useEffect } from 'react'; import { isKind } from './conditions'; import { EntitySwitch } from './EntitySwitch'; @@ -517,9 +517,7 @@ describe('EntitySwitch', () => { , ); - await waitFor(() => expect(shouldRender).toHaveBeenCalled()); - - expect(screen.getByText('C')).toBeInTheDocument(); + await expect(screen.findByText('C')).resolves.toBeInTheDocument(); expect(screen.queryByText('A')).not.toBeInTheDocument(); expect(screen.queryByText('B')).not.toBeInTheDocument(); }); diff --git a/plugins/git-release-manager/src/features/Features.test.tsx b/plugins/git-release-manager/src/features/Features.test.tsx index f3a70c2bda..abde878648 100644 --- a/plugins/git-release-manager/src/features/Features.test.tsx +++ b/plugins/git-release-manager/src/features/Features.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { render, act, waitFor } from '@testing-library/react'; +import { render, waitFor } from '@testing-library/react'; import { Features } from './Features'; import { mockCalverProject } from '../test-helpers/test-helpers'; @@ -49,9 +49,7 @@ describe('Features', () => { />, ); - await act(async () => { - await waitFor(() => getByTestId(TEST_IDS.info.info)); - }); + await waitFor(() => getByTestId(TEST_IDS.info.info)); expect(getByTestId(TEST_IDS.info.info)).toMatchInlineSnapshot(`
{ "icon": "failure", "message": Something went wrong - + { "icon": "failure", "message": Something went wrong - + ', () => { }); const renderSubject = async (props: any = {}) => { - renderInTestApp( + await renderInTestApp( ', () => { act(() => { fireEvent.click(rendered.getByRole('button')); + }); + act(() => { fireEvent.click(rendered.getByTestId('mock-playlist-edit-dialog')); }); @@ -128,6 +130,8 @@ describe('', () => { act(() => { fireEvent.click(rendered.getByRole('button')); + }); + act(() => { fireEvent.click(rendered.getByTestId('mock-playlist-edit-dialog')); }); diff --git a/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx b/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx index b9da819baa..eaf00cbde1 100644 --- a/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx +++ b/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx @@ -78,7 +78,9 @@ describe('', () => { }, }, ); + }); + act(() => { fireEvent.input( getByRole( rendered.getByTestId('edit-dialog-description-input'), @@ -90,17 +92,25 @@ describe('', () => { }, }, ); + }); + act(() => { fireEvent.mouseDown( getByRole(rendered.getByTestId('edit-dialog-owner-select'), 'button'), ); + }); + act(() => { fireEvent.click(rendered.getByText('test-owner')); + }); + act(() => { fireEvent.click( getByRole(rendered.getByTestId('edit-dialog-public-option'), 'radio'), ); + }); + act(() => { fireEvent.click(rendered.getByTestId('edit-dialog-save-button')); }); diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistHeader.test.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistHeader.test.tsx index 60be071baf..480ac038f2 100644 --- a/plugins/playlist/src/components/PlaylistPage/PlaylistHeader.test.tsx +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistHeader.test.tsx @@ -192,6 +192,8 @@ describe('PlaylistHeader', () => { act(() => { fireEvent.click(rendered.getByTestId('header-action-menu')); + }); + act(() => { fireEvent.click( rendered .getAllByTestId('header-action-item') @@ -224,11 +226,15 @@ describe('PlaylistHeader', () => { act(() => { fireEvent.click(rendered.getByTestId('header-action-menu')); + }); + act(() => { fireEvent.click( rendered .getAllByTestId('header-action-item') .find(e => e.innerHTML.includes('Delete Playlist'))!, ); + }); + act(() => { fireEvent.click(rendered.getByTestId('delete-playlist-dialog-button')); }); diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx index 73bd6980e9..ef9b6d060b 100644 --- a/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx @@ -109,8 +109,8 @@ describe('PlaylistPage', () => { act(() => { fireEvent.click(rendered.getByTestId('playlist-page-follow-button')); - testPlaylist.isFollowing = true; }); + testPlaylist.isFollowing = true; await waitFor(() => { expect(playlistApi.followPlaylist).toHaveBeenCalledWith('id1'); @@ -124,8 +124,8 @@ describe('PlaylistPage', () => { act(() => { fireEvent.click(rendered.getByTestId('playlist-page-follow-button')); - testPlaylist.isFollowing = false; }); + testPlaylist.isFollowing = false; await waitFor(() => { expect(playlistApi.unfollowPlaylist).toHaveBeenCalledWith('id1'); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx index 24126152ed..34243e232d 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx @@ -273,12 +273,12 @@ describe('Stepper', () => { />, ); - await act(async () => { - await fireEvent.click(getByRole('button', { name: 'Review' })); - - expect(getByRole('progressbar')).toBeInTheDocument(); - expect(getByRole('button', { name: 'Review' })).toBeDisabled(); + act(() => { + fireEvent.click(getByRole('button', { name: 'Review' })); }); + + expect(getByRole('progressbar')).toBeInTheDocument(); + expect(getByRole('button', { name: 'Review' })).toBeDisabled(); }); it('should transform default error message', async () => { diff --git a/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.test.tsx index ce6e342809..f3a6a99c42 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.test.tsx @@ -20,6 +20,7 @@ import { TemplateCategoryPicker } from './TemplateCategoryPicker'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { alertApiRef } from '@backstage/core-plugin-api'; import { fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; jest.mock('@backstage/plugin-catalog-react', () => ({ useEntityTypeFilter: jest.fn(), @@ -91,7 +92,7 @@ describe('TemplateCategoryPicker', () => { ); const openButton = getByRole('button', { name: 'Open' }); - openButton.click(); + await userEvent.click(openButton); expect(getByRole('checkbox', { name: 'Foo' })).toBeInTheDocument(); expect(getByRole('checkbox', { name: 'Bar' })).toBeInTheDocument(); diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx index a402e078a8..af2e4dc886 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx @@ -22,6 +22,8 @@ import { import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { ApiProvider } from '@backstage/core-app-api'; import { rootRouteRef } from '../../routes'; +import { userEvent } from '@testing-library/user-event'; +import { act } from 'react-dom/test-utils'; const scaffolderApiMock: jest.Mocked = { scaffold: jest.fn(), @@ -261,7 +263,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('nested prop b')).not.toBeInTheDocument(); expect(rendered.queryByText('number')).not.toBeInTheDocument(); - objectChip.click(); + await act(() => userEvent.click(objectChip)); expect(rendered.queryByText('nested prop a')).toBeInTheDocument(); expect(rendered.queryByText('string')).toBeInTheDocument(); @@ -323,7 +325,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('nested prop b')).not.toBeInTheDocument(); expect(rendered.queryByText('nested object c')).not.toBeInTheDocument(); - objectChip.click(); + await act(() => userEvent.click(objectChip)); expect(rendered.queryByText('nested object a')).toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).toBeInTheDocument(); @@ -331,7 +333,7 @@ describe('TemplatePage', () => { const allObjectChips = rendered.getAllByText('object'); expect(allObjectChips.length).toBe(2); - allObjectChips[1].click(); + await act(() => userEvent.click(allObjectChips[1])); expect(rendered.queryByText('nested object a')).toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).toBeInTheDocument(); @@ -374,7 +376,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('No schema defined')).not.toBeInTheDocument(); - objectChip.click(); + await act(() => userEvent.click(objectChip)); expect(rendered.queryByText('No schema defined')).toBeInTheDocument(); }); @@ -471,7 +473,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('nested object a')).not.toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).not.toBeInTheDocument(); - objectChip.click(); + await act(() => userEvent.click(objectChip)); expect(rendered.queryByText('nested object a')).toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).toBeInTheDocument(); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx index c2d8d3a2a4..36cdbec088 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx @@ -16,7 +16,7 @@ import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; +import { act, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React, { ReactNode, useEffect } from 'react'; import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; @@ -90,10 +90,10 @@ describe('DryRunResultsView', () => { expect(screen.queryByText('Foo Message')).not.toBeInTheDocument(); expect(screen.queryByText('Foo Link')).not.toBeInTheDocument(); - await userEvent.click(screen.getByText('Log')); + await act(() => userEvent.click(screen.getByText('Log'))); expect(screen.getByText('Foo Message')).toBeInTheDocument(); - await userEvent.click(screen.getByText('Output')); + await act(() => userEvent.click(screen.getByText('Output'))); expect(screen.getByText('Foo Link')).toBeInTheDocument(); }); }); diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx index e95f7fa856..3bb1140852 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx @@ -15,7 +15,7 @@ */ import { MockConfigApi, TestApiProvider } from '@backstage/test-utils'; -import { screen, render, waitFor, within } from '@testing-library/react'; +import { screen, render, waitFor, within, act } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; @@ -364,7 +364,7 @@ describe('SearchFilter.Autocomplete', () => { }); // Blur the field and only one tag should be shown with a +1. - input.blur(); + await act(() => userEvent.tab()); expect( screen.queryByRole('button', { name: values[0] }), ).not.toBeInTheDocument(); 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 665dd3281c..9b8d5feb97 100644 --- a/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx +++ b/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx @@ -34,8 +34,12 @@ const apis = TestApiRegistry.from( ); describe('Incidents', () => { + beforeEach(() => { + jest.useFakeTimers(); + }); afterEach(() => { jest.resetAllMocks(); + jest.useRealTimers(); }); it('Renders an empty state when there are no incidents', async () => { @@ -47,13 +51,10 @@ describe('Incidents', () => { , ); - await waitFor(() => !screen.queryByTestId('progress')); - await waitFor( - () => - expect( - screen.getByText('Nice! No incidents found!'), - ).toBeInTheDocument(), - { timeout: 2000 }, + jest.advanceTimersByTime(2000); + await waitFor(() => expect(screen.queryByTestId('progress')).toBe(null)); + await waitFor(() => + expect(screen.getByText('Nice! No incidents found!')).toBeInTheDocument(), ); }); @@ -66,15 +67,14 @@ describe('Incidents', () => { , ); - await waitFor(() => !screen.queryByTestId('progress')); - await waitFor( - () => - expect( - screen.getByText('user', { - exact: false, - }), - ).toBeInTheDocument(), - { timeout: 2000 }, + jest.advanceTimersByTime(2000); + await waitFor(() => expect(screen.queryByTestId('progress')).toBe(null)); + await waitFor(() => + expect( + screen.getByText('user', { + exact: false, + }), + ).toBeInTheDocument(), ); expect(screen.getByText('test-incident')).toBeInTheDocument(); expect(screen.getByTitle('Acknowledged')).toBeInTheDocument(); @@ -93,15 +93,14 @@ describe('Incidents', () => { , ); - await waitFor(() => !screen.queryByTestId('progress')); - await waitFor( - () => - expect( - screen.getByText('user', { - exact: false, - }), - ).toBeInTheDocument(), - { timeout: 2000 }, + jest.advanceTimersByTime(2000); + await waitFor(() => expect(screen.queryByTestId('progress')).toBe(null)); + await waitFor(() => + expect( + screen.getByText('user', { + exact: false, + }), + ).toBeInTheDocument(), ); expect(screen.getByText('test-incident')).toBeInTheDocument(); expect(screen.getByLabelText('Status warning')).toBeInTheDocument(); @@ -127,15 +126,14 @@ describe('Incidents', () => { , ); - await waitFor(() => !screen.queryByTestId('progress')); - await waitFor( - () => - expect( - screen.getByText( - 'Error encountered while fetching information. Error occurred', - ), - ).toBeInTheDocument(), - { timeout: 2000 }, + jest.advanceTimersByTime(2000); + await waitFor(() => expect(screen.queryByTestId('progress')).toBe(null)); + await waitFor(() => + expect( + screen.getByText( + 'Error encountered while fetching information. Error occurred', + ), + ).toBeInTheDocument(), ); }); }); diff --git a/plugins/techdocs-addons-test-utils/src/test-utils.tsx b/plugins/techdocs-addons-test-utils/src/test-utils.tsx index 1a921437b1..865e8c0d3b 100644 --- a/plugins/techdocs-addons-test-utils/src/test-utils.tsx +++ b/plugins/techdocs-addons-test-utils/src/test-utils.tsx @@ -19,7 +19,6 @@ import React, { ReactElement } from 'react'; // Shadow DOM support for the simple and complete DOM testing utilities // https://github.com/testing-library/dom-testing-library/issues/742#issuecomment-674987855 import { screen } from 'testing-library__dom'; -import { renderToStaticMarkup } from 'react-dom/server'; import { Route } from 'react-router-dom'; import { act, render } from '@testing-library/react'; @@ -39,6 +38,13 @@ import { catalogPlugin } from '@backstage/plugin-catalog'; import { searchApiRef } from '@backstage/plugin-search-react'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; +// Since React 18 react-dom/server eagerly uses TextEncoder, so lazy load and make it available globally first +if (!global.TextEncoder) { + global.TextEncoder = require('util').TextEncoder; +} +const { renderToStaticMarkup } = + require('react-dom/server') as typeof import('react-dom/server'); + const techdocsApi = { getTechDocsMetadata: jest.fn(), getEntityMetadata: jest.fn(), diff --git a/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx b/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx index afdac63a99..85253f54ef 100644 --- a/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx @@ -20,6 +20,8 @@ import { TechDocsBuildLogs, TechDocsBuildLogsDrawerContent, } from './TechDocsBuildLogs'; +import { userEvent } from '@testing-library/user-event'; +import { act } from 'react-dom/test-utils'; // The inside needs mocking to render in jsdom jest.mock('react-virtualized-auto-sizer', () => ({ @@ -38,7 +40,7 @@ describe('', () => { it('should open drawer', async () => { const rendered = await renderInTestApp(); - rendered.getByText(/Show Build Logs/i).click(); + await act(() => userEvent.click(rendered.getByText(/Show Build Logs/i))); expect(rendered.getByText(/Build Details/i)).toBeInTheDocument(); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx index e11b7b6e81..f732afd31d 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ import React from 'react'; -import { act } from '@testing-library/react'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; @@ -150,31 +149,25 @@ describe('', () => { }); it('should render a techdocs reader page with children', async () => { - await act(async () => { - const rendered = await renderInTestApp( - - - techdocs reader page - - , - { - mountedRoutes, - }, - ); - expect( - rendered.container.querySelector('header'), - ).not.toBeInTheDocument(); - expect( - rendered.container.querySelector('article'), - ).not.toBeInTheDocument(); - expect(rendered.getByText('techdocs reader page')).toBeInTheDocument(); - }); + const rendered = await renderInTestApp( + + + techdocs reader page + + , + { + mountedRoutes, + }, + ); + expect(rendered.container.querySelector('header')).not.toBeInTheDocument(); + expect(rendered.container.querySelector('article')).not.toBeInTheDocument(); + expect(rendered.getByText('techdocs reader page')).toBeInTheDocument(); }); it('should render techdocs reader page with addons', async () => { @@ -183,56 +176,52 @@ describe('', () => { const namespace = 'test-namespace'; const kind = 'test'; - await act(async () => { - const rendered = await renderInTestApp( - - - } - > - - - - - - , - { - mountedRoutes, - routeEntries: ['/docs/test-namespace/test/test-name'], - }, - ); + const rendered = await renderInTestApp( + + + } + > + + + + + + , + { + mountedRoutes, + routeEntries: ['/docs/test-namespace/test/test-name'], + }, + ); - expect( - rendered.getByText(`PageMock: ${namespace}#${kind}#${name}`), - ).toBeInTheDocument(); - }); + expect( + rendered.getByText(`PageMock: ${namespace}#${kind}#${name}`), + ).toBeInTheDocument(); }); it('should render techdocs reader page with addons and page', async () => { (Page as jest.Mock).mockImplementation(PageMock); - await act(async () => { - const rendered = await renderInTestApp( - - - } - > -

the page

- - - -
-
-
, - { - mountedRoutes, - routeEntries: ['/docs/test-namespace/test/test-name'], - }, - ); + const rendered = await renderInTestApp( + + + } + > +

the page

+ + + +
+
+
, + { + mountedRoutes, + routeEntries: ['/docs/test-namespace/test/test-name'], + }, + ); - expect(rendered.getByText('the page')).toBeInTheDocument(); - }); + expect(rendered.getByText('the page')).toBeInTheDocument(); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx index 3e5a4c73c3..32fbe21714 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { act, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { @@ -90,18 +90,16 @@ describe('', () => { useTechDocsReaderDom.mockReturnValue(document.createElement('html')); useReaderState.mockReturnValue({ state: 'cached' }); - await act(async () => { - const rendered = await renderInTestApp( - - - , - ); + const rendered = await renderInTestApp( + + + , + ); - await waitFor(() => { - expect( - rendered.getByTestId('techdocs-native-shadowroot'), - ).toBeInTheDocument(); - }); + await waitFor(() => { + expect( + rendered.getByTestId('techdocs-native-shadowroot'), + ).toBeInTheDocument(); }); }); @@ -110,21 +108,19 @@ describe('', () => { useTechDocsReaderDom.mockReturnValue(document.createElement('html')); useReaderState.mockReturnValue({ state: 'cached' }); - await act(async () => { - const rendered = await renderInTestApp( - - - , - ); + const rendered = await renderInTestApp( + + + , + ); - await waitFor(() => { - expect( - rendered.queryByTestId('techdocs-native-shadowroot'), - ).not.toBeInTheDocument(); - expect( - rendered.getByText('ERROR 404: PAGE NOT FOUND'), - ).toBeInTheDocument(); - }); + await waitFor(() => { + expect( + rendered.queryByTestId('techdocs-native-shadowroot'), + ).not.toBeInTheDocument(); + expect( + rendered.getByText('ERROR 404: PAGE NOT FOUND'), + ).toBeInTheDocument(); }); }); @@ -134,21 +130,19 @@ describe('', () => { useTechDocsReaderDom.mockReturnValue(undefined); useReaderState.mockReturnValue({ state: 'CONTENT_NOT_FOUND' }); - await act(async () => { - const rendered = await renderInTestApp( - - - , - ); + const rendered = await renderInTestApp( + + + , + ); - await waitFor(() => { - expect( - rendered.queryByTestId('techdocs-native-shadowroot'), - ).not.toBeInTheDocument(); - expect( - rendered.getByText('ERROR 404: Documentation not found'), - ).toBeInTheDocument(); - }); + await waitFor(() => { + expect( + rendered.queryByTestId('techdocs-native-shadowroot'), + ).not.toBeInTheDocument(); + expect( + rendered.getByText('ERROR 404: Documentation not found'), + ).toBeInTheDocument(); }); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx index a3e03b7cf0..d2956ce919 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ import React from 'react'; -import { act, waitFor } from '@testing-library/react'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; @@ -80,112 +79,77 @@ describe('', () => { getEntityMetadata.mockResolvedValue(mockEntityMetadata); getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); - await act(async () => { - const rendered = await renderInTestApp( - - - , - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, + const rendered = await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + '/docs': rootRouteRef, }, - ); + }, + ); - expect(rendered.container.innerHTML).toContain('header'); + expect(rendered.container.innerHTML).toContain('header'); - await waitFor(() => { - expect(rendered.getAllByText('test-site-name')).toHaveLength(2); - }); + expect(rendered.getAllByText('test-site-name')).toHaveLength(2); + expect(rendered.getByText('test-site-desc')).toBeDefined(); - expect(rendered.getByText('test-site-desc')).toBeDefined(); - }); + expect( + rendered.getByRole('link', { name: 'test:test-namespace/test-name' }), + ).toHaveAttribute('href', '/catalog/test-namespace/test/test-name'); }); it('should render a techdocs page header even if metadata is not loaded', async () => { - await act(async () => { - const rendered = await renderInTestApp( - - - , - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, + const rendered = await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + '/docs': rootRouteRef, }, - ); + }, + ); - expect(rendered.container.innerHTML).toContain('header'); - }); + expect(rendered.container.innerHTML).toContain('header'); }); it('should not render a techdocs page header if entity metadata is missing', async () => { getEntityMetadata.mockResolvedValue(undefined); - await act(async () => { - const rendered = await renderInTestApp( - - - , - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, + const rendered = await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + '/docs': rootRouteRef, }, - ); + }, + ); - await waitFor(() => { - expect(rendered.container.innerHTML).not.toContain('header'); - }); - }); + expect(rendered.container.innerHTML).not.toContain('header'); }); it('should not render a techdocs page header if techdocs metadata is missing', async () => { getTechDocsMetadata.mockResolvedValue(undefined); - await act(async () => { - const rendered = await renderInTestApp( - - - , - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, + const rendered = await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + '/docs': rootRouteRef, }, - ); + }, + ); - await waitFor(() => { - expect(rendered.container.innerHTML).not.toContain('header'); - }); - }); - }); - - it('should render a link back to the component page', async () => { - getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); - - await act(async () => { - const rendered = await renderInTestApp( - - - , - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, - }, - ); - - await waitFor(() => { - expect( - rendered.getByRole('link', { name: 'test:test-namespace/test-name' }), - ).toHaveAttribute('href', '/catalog/test-namespace/test/test-name'); - }); - }); + expect(rendered.container.innerHTML).not.toContain('header'); }); }); From fb7a94f4aaceef7316bd1c226ad43c69b8e960cd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 13:29:26 +0200 Subject: [PATCH 105/348] packages: rtl 13 fixes for tests Signed-off-by: Patrik Oldsberg --- .../src/apis/system/ApiProvider.test.tsx | 16 +++++ .../core-app-api/src/app/AppManager.test.tsx | 60 +++++++++---------- .../src/routing/FlatRoutes.beta.test.tsx | 2 +- .../src/routing/FlatRoutes.compat.test.tsx | 2 +- .../src/routing/FlatRoutes.stable.test.tsx | 2 +- .../TabbedLayout/TabbedLayout.test.tsx | 5 ++ .../ErrorBoundary/ErrorBoundary.test.tsx | 5 +- .../src/layout/HeaderTabs/HeaderTabs.test.tsx | 4 +- .../src/routing/RouteResolver.test.ts | 3 +- .../src/testUtils/appWrappers.test.tsx | 5 ++ 10 files changed, 65 insertions(+), 39 deletions(-) diff --git a/packages/core-app-api/src/apis/system/ApiProvider.test.tsx b/packages/core-app-api/src/apis/system/ApiProvider.test.tsx index a6118f0f68..6460e12900 100644 --- a/packages/core-app-api/src/apis/system/ApiProvider.test.tsx +++ b/packages/core-app-api/src/apis/system/ApiProvider.test.tsx @@ -118,6 +118,10 @@ describe('ApiProvider', () => { }).toThrow(/^API context is not available/); }).error, ).toEqual([ + expect.objectContaining({ + detail: new Error('API context is not available'), + type: 'unhandled exception', + }), expect.objectContaining({ detail: new Error('API context is not available'), type: 'unhandled exception', @@ -134,6 +138,10 @@ describe('ApiProvider', () => { }).toThrow(/^API context is not available/); }).error, ).toEqual([ + expect.objectContaining({ + detail: new Error('API context is not available'), + type: 'unhandled exception', + }), expect.objectContaining({ detail: new Error('API context is not available'), type: 'unhandled exception', @@ -156,6 +164,10 @@ describe('ApiProvider', () => { }).toThrow('No implementation available for apiRef{x}'); }).error, ).toEqual([ + expect.objectContaining({ + detail: new Error('No implementation available for apiRef{x}'), + type: 'unhandled exception', + }), expect.objectContaining({ detail: new Error('No implementation available for apiRef{x}'), type: 'unhandled exception', @@ -176,6 +188,10 @@ describe('ApiProvider', () => { }).toThrow('No implementation available for apiRef{x}'); }).error, ).toEqual([ + expect.objectContaining({ + detail: new Error('No implementation available for apiRef{x}'), + type: 'unhandled exception', + }), expect.objectContaining({ detail: new Error('No implementation available for apiRef{x}'), type: 'unhandled exception', diff --git a/packages/core-app-api/src/app/AppManager.test.tsx b/packages/core-app-api/src/app/AppManager.test.tsx index 3d0c47c4d5..fe8d2fa91a 100644 --- a/packages/core-app-api/src/app/AppManager.test.tsx +++ b/packages/core-app-api/src/app/AppManager.test.tsx @@ -639,26 +639,24 @@ describe('Integration Test', () => { const Provider = app.getProvider(); const Router = app.getRouter(); const { error: errorLogs } = withLogCollector(() => { - expect(() => - render( - - - - }> - } /> - - - - , - ), - ).toThrow( - 'Parameter :thing is duplicated in path test/:thing/some/:thing', + render( + + + + }> + } /> + + + + , ); }); expect(errorLogs).toEqual([ - expect.stringContaining( - 'The above error occurred in the component', - ), + expect.objectContaining({ + message: expect.stringContaining( + 'Parameter :thing is duplicated in path test/:thing/some/:thing', + ), + }), ]); }); @@ -676,24 +674,22 @@ describe('Integration Test', () => { const Provider = app.getProvider(); const Router = app.getRouter(); const { error: errorLogs } = withLogCollector(() => { - expect(() => - render( - - - - } /> - - - , - ), - ).toThrow( - /^External route 'extRouteRef1' of the 'blob' plugin must be bound to a target route/, + render( + + + + } /> + + + , ); }); expect(errorLogs).toEqual([ - expect.stringContaining( - 'The above error occurred in the component', - ), + expect.objectContaining({ + message: expect.stringMatching( + /^External route 'extRouteRef1' of the 'blob' plugin must be bound to a target route/, + ), + }), ]); }); diff --git a/packages/core-app-api/src/routing/FlatRoutes.beta.test.tsx b/packages/core-app-api/src/routing/FlatRoutes.beta.test.tsx index 30be04d2d4..8d4d10c52a 100644 --- a/packages/core-app-api/src/routing/FlatRoutes.beta.test.tsx +++ b/packages/core-app-api/src/routing/FlatRoutes.beta.test.tsx @@ -56,7 +56,7 @@ function makeRouteRenderer(node: ReactNode) { ); if (rendered) { rendered.unmount(); - rendered.rerender(content); + rendered = render(content); } else { rendered = render(content); } diff --git a/packages/core-app-api/src/routing/FlatRoutes.compat.test.tsx b/packages/core-app-api/src/routing/FlatRoutes.compat.test.tsx index 5d2ca15672..c32b306387 100644 --- a/packages/core-app-api/src/routing/FlatRoutes.compat.test.tsx +++ b/packages/core-app-api/src/routing/FlatRoutes.compat.test.tsx @@ -83,7 +83,7 @@ describe.each(['beta', 'stable'])('FlatRoutes %s', rrVersion => { ); if (rendered) { rendered.unmount(); - rendered.rerender(content); + rendered = render(content); } else { rendered = render(content); } diff --git a/packages/core-app-api/src/routing/FlatRoutes.stable.test.tsx b/packages/core-app-api/src/routing/FlatRoutes.stable.test.tsx index 93297edc4c..ece6c22ff2 100644 --- a/packages/core-app-api/src/routing/FlatRoutes.stable.test.tsx +++ b/packages/core-app-api/src/routing/FlatRoutes.stable.test.tsx @@ -56,7 +56,7 @@ function makeRouteRenderer(node: ReactNode) { ); if (rendered) { rendered.unmount(); - rendered.rerender(content); + rendered = render(content); } else { rendered = render(content); } diff --git a/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx b/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx index f5a059d615..c7109686d5 100644 --- a/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx +++ b/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx @@ -48,6 +48,11 @@ describe('TabbedLayout', () => { }); expect(error).toEqual([ + expect.objectContaining({ + detail: new Error( + 'Child of TabbedLayout must be an TabbedLayout.Route', + ), + }), expect.objectContaining({ detail: new Error( 'Child of TabbedLayout must be an TabbedLayout.Route', diff --git a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx index 6a16224a02..8bfb228f53 100644 --- a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx +++ b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx @@ -67,6 +67,9 @@ describe('', () => { }); expect(error).toEqual([ + expect.objectContaining({ + detail: new Error('Bomb'), + }), expect.objectContaining({ detail: new Error('Bomb'), }), @@ -75,6 +78,6 @@ describe('', () => { ), expect.stringMatching(/^ErrorBoundary/), ]); - expect(error.length).toEqual(3); + expect(error.length).toEqual(4); }); }); diff --git a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx index ce5c572eef..0d5f3d5586 100644 --- a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx +++ b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx @@ -19,6 +19,8 @@ import Badge from '@material-ui/core/Badge'; import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { HeaderTabs } from './HeaderTabs'; +import { act } from 'react-dom/test-utils'; +import userEvent from '@testing-library/user-event'; const mockTabs = [ { id: 'overview', label: 'Overview' }, @@ -41,7 +43,7 @@ describe('', () => { 'false', ); - rendered.getByText('Docs').click(); + await act(() => userEvent.click(rendered.getByText('Docs'))); expect(rendered.getByText('Docs').parentElement).toHaveAttribute( 'aria-selected', diff --git a/packages/frontend-app-api/src/routing/RouteResolver.test.ts b/packages/frontend-app-api/src/routing/RouteResolver.test.ts index ef7a438734..e37ee14929 100644 --- a/packages/frontend-app-api/src/routing/RouteResolver.test.ts +++ b/packages/frontend-app-api/src/routing/RouteResolver.test.ts @@ -26,9 +26,8 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { RouteResolver } from './RouteResolver'; import { MATCH_ALL_ROUTE } from './extractRouteInfoFromInstanceTree'; -const element = () => null; const rest = { - element, + element: null, caseSensitive: false, children: [MATCH_ALL_ROUTE], plugins: new Set(), diff --git a/packages/test-utils/src/testUtils/appWrappers.test.tsx b/packages/test-utils/src/testUtils/appWrappers.test.tsx index 19bdc15a48..79327afc0b 100644 --- a/packages/test-utils/src/testUtils/appWrappers.test.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.test.tsx @@ -92,6 +92,11 @@ describe('wrapInTestApp', () => { }); expect(error).toEqual([ + expect.objectContaining({ + detail: new Error( + 'MockErrorApi received unexpected error, Error: NOPE', + ), + }), expect.objectContaining({ detail: new Error( 'MockErrorApi received unexpected error, Error: NOPE', From 070f8e2c95b6a879e5fad0d3d764badfb95936bb Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 14:06:21 +0200 Subject: [PATCH 106/348] root: patch @material-ui/pickers to replace references to React.SFC with React.FC Signed-off-by: Patrik Oldsberg --- ...ial-ui-pickers-npm-3.3.11-1c8f68ea20.patch | 112 ++++++++++++++++++ package.json | 4 +- yarn.lock | 22 +++- 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 .yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch diff --git a/.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch b/.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch new file mode 100644 index 0000000000..1e3c82e9dd --- /dev/null +++ b/.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch @@ -0,0 +1,112 @@ +diff --git a/DateTimePicker/DateTimePickerTabs.d.ts b/DateTimePicker/DateTimePickerTabs.d.ts +index 52396cccbb66861dd6519459141e7744aa25aaf8..75c5a9053a88abf2454b7783c0101a1a8c9375f1 100644 +--- a/DateTimePicker/DateTimePickerTabs.d.ts ++++ b/DateTimePicker/DateTimePickerTabs.d.ts +@@ -7,5 +7,5 @@ export interface DateTimePickerTabsProps { + timeIcon?: React.ReactNode; + } + export declare const useStyles: (props?: any) => Record<"tabs", string>; +-export declare const DateTimePickerTabs: React.SFC; ++export declare const DateTimePickerTabs: React.FC; + export default DateTimePickerTabs; +diff --git a/_shared/ModalDialog.d.ts b/_shared/ModalDialog.d.ts +index 067070067ccf6e7699d17f422934daf14370d225..c45a583adef09a2091865db91b2687e66af81b47 100644 +--- a/_shared/ModalDialog.d.ts ++++ b/_shared/ModalDialog.d.ts +@@ -15,7 +15,7 @@ export interface ModalDialogProps extends DialogProps { + showTabs?: boolean; + wider?: boolean; + } +-export declare const ModalDialog: React.SFC>; ++export declare const ModalDialog: React.FC>; + export declare const styles: Record<"dialog" | "dialogRoot" | "dialogRootWider" | "withAdditionalAction", import("@material-ui/core/styles/withStyles").CSSProperties | import("@material-ui/core/styles/withStyles").CreateCSSProperties<{}> | ((props: {}) => import("@material-ui/core/styles/withStyles").CreateCSSProperties<{}>)>; + declare const _default: React.ComponentType; +diff --git a/_shared/PickerToolbar.d.ts b/_shared/PickerToolbar.d.ts +index f1ccd368bf9ab853cf0356d03fce0390becad8cd..e75ef734788cb26cc07dc079c714f759f525c447 100644 +--- a/_shared/PickerToolbar.d.ts ++++ b/_shared/PickerToolbar.d.ts +@@ -5,5 +5,5 @@ export declare const useStyles: (props?: any) => Record<"toolbar" | "toolbarLand + interface PickerToolbarProps extends ExtendMui { + isLandscape: boolean; + } +-declare const PickerToolbar: React.SFC; ++declare const PickerToolbar: React.FC; + export default PickerToolbar; +diff --git a/_shared/WithUtils.d.ts b/_shared/WithUtils.d.ts +index 22fe0425817be182a6c9a1a21a0f9eefb61696e7..b5b2a966ec0ea8427c4355227d8425b9c1af3790 100644 +--- a/_shared/WithUtils.d.ts ++++ b/_shared/WithUtils.d.ts +@@ -4,4 +4,4 @@ import { MaterialUiPickersDate } from '../typings/date'; + export interface WithUtilsProps { + utils: IUtils; + } +-export declare const withUtils: () =>

(Component: React.ComponentType

) => React.SFC>>; ++export declare const withUtils: () =>

(Component: React.ComponentType

) => React.FC>>; +diff --git a/_shared/icons/ArrowLeftIcon.d.ts b/_shared/icons/ArrowLeftIcon.d.ts +index ce0f208a2aa6dae03a77dfe830a10a95c2085030..95a516da22e02b9a4167ee4a52bf2cd0a1b4aec6 100644 +--- a/_shared/icons/ArrowLeftIcon.d.ts ++++ b/_shared/icons/ArrowLeftIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const ArrowLeftIcon: React.SFC; ++export declare const ArrowLeftIcon: React.FC; +diff --git a/_shared/icons/ArrowRightIcon.d.ts b/_shared/icons/ArrowRightIcon.d.ts +index 71443a34f7bbd2cef8c2af487c817b7ea788dd7a..a96314aa8750180773f1d006ed766e5a7e8e071d 100644 +--- a/_shared/icons/ArrowRightIcon.d.ts ++++ b/_shared/icons/ArrowRightIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const ArrowRightIcon: React.SFC; ++export declare const ArrowRightIcon: React.FC; +diff --git a/_shared/icons/DateRangeIcon.d.ts b/_shared/icons/DateRangeIcon.d.ts +index 722f8736d86f248d464c5af855795663d9e220d3..6018043d41861d96335f060ea1dc78336892ce66 100644 +--- a/_shared/icons/DateRangeIcon.d.ts ++++ b/_shared/icons/DateRangeIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const DateRangeIcon: React.SFC; ++export declare const DateRangeIcon: React.FC; +diff --git a/_shared/icons/KeyboardIcon.d.ts b/_shared/icons/KeyboardIcon.d.ts +index c1a0a111d831acc58cf19aa6d54f8324e68de9d8..8d7d1dac47815cef02215c4f11f36e73509b4219 100644 +--- a/_shared/icons/KeyboardIcon.d.ts ++++ b/_shared/icons/KeyboardIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const KeyboardIcon: React.SFC; ++export declare const KeyboardIcon: React.FC; +diff --git a/_shared/icons/TimeIcon.d.ts b/_shared/icons/TimeIcon.d.ts +index 49e0b627132f7d31d1b0a205548229a9f7a2c0a6..15ebc6e630992edb3b01790c0dd651651adf51de 100644 +--- a/_shared/icons/TimeIcon.d.ts ++++ b/_shared/icons/TimeIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const TimeIcon: React.SFC; ++export declare const TimeIcon: React.FC; +diff --git a/views/Calendar/CalendarHeader.d.ts b/views/Calendar/CalendarHeader.d.ts +index 842cbd8e021eb6d8e6553ba68033f13140485b61..7f60b4bffce1a96ade02e2671fd705c8fe87dfa2 100644 +--- a/views/Calendar/CalendarHeader.d.ts ++++ b/views/Calendar/CalendarHeader.d.ts +@@ -15,5 +15,5 @@ export interface CalendarHeaderProps { + onMonthChange: (date: MaterialUiPickersDate, direction: SlideDirection) => void | Promise; + } + export declare const useStyles: (props?: any) => Record<"transitionContainer" | "switchHeader" | "iconButton" | "daysHeader" | "dayLabel", string>; +-export declare const CalendarHeader: React.SFC; ++export declare const CalendarHeader: React.FC; + export default CalendarHeader; +diff --git a/views/Calendar/SlideTransition.d.ts b/views/Calendar/SlideTransition.d.ts +index f00e98a72bd0e6cfd80ab45b33b905e802b60e9b..699119009fa5ea886e7f782425aee39b7608b8c2 100644 +--- a/views/Calendar/SlideTransition.d.ts ++++ b/views/Calendar/SlideTransition.d.ts +@@ -7,5 +7,5 @@ interface SlideTransitionProps { + children: React.ReactChild; + } + export declare const useStyles: (props?: any) => Record<"transitionContainer" | "slideEnter-left" | "slideEnter-right" | "slideEnterActive" | "slideExit" | "slideExitActiveLeft-left" | "slideExitActiveLeft-right", string>; +-declare const SlideTransition: React.SFC; ++declare const SlideTransition: React.FC; + export default SlideTransition; diff --git a/package.json b/package.json index 5ff39c8770..6a21034cae 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,9 @@ "@types/react": "^18", "@types/react-dom": "^18", "jest-haste-map@^29.4.3": "patch:jest-haste-map@npm%3A29.4.3#./.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch", - "mock-fs@^5.2.0": "patch:mock-fs@npm%3A5.2.0#./.yarn/patches/mock-fs-npm-5.2.0-5103a7b507.patch" + "mock-fs@^5.2.0": "patch:mock-fs@npm%3A5.2.0#./.yarn/patches/mock-fs-npm-5.2.0-5103a7b507.patch", + "@material-ui/pickers@^3.3.10": "patch:@material-ui/pickers@npm%3A3.3.11#./.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch", + "@material-ui/pickers@^3.2.10": "patch:@material-ui/pickers@npm%3A3.3.11#./.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch" }, "version": "1.19.0", "dependencies": { diff --git a/yarn.lock b/yarn.lock index 611ade7792..633590050e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13098,7 +13098,7 @@ __metadata: languageName: node linkType: hard -"@material-ui/pickers@npm:^3.2.10, @material-ui/pickers@npm:^3.3.10": +"@material-ui/pickers@npm:3.3.11": version: 3.3.11 resolution: "@material-ui/pickers@npm:3.3.11" dependencies: @@ -13118,6 +13118,26 @@ __metadata: languageName: node linkType: hard +"@material-ui/pickers@patch:@material-ui/pickers@npm%3A3.3.11#./.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch::locator=root%40workspace%3A.": + version: 3.3.11 + resolution: "@material-ui/pickers@patch:@material-ui/pickers@npm%3A3.3.11#./.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch::version=3.3.11&hash=c18f79&locator=root%40workspace%3A." + dependencies: + "@babel/runtime": ^7.6.0 + "@date-io/core": 1.x + "@types/styled-jsx": ^2.2.8 + clsx: ^1.0.2 + react-transition-group: ^4.0.0 + rifm: ^0.7.0 + peerDependencies: + "@date-io/core": ^1.3.6 + "@material-ui/core": ^4.0.0 + prop-types: ^15.6.0 + react: ^16.8.0 || ^17.0.0 + react-dom: ^16.8.0 || ^17.0.0 + checksum: e736e4d53f1b660f4a338e8ca3537dc86638ed41ed988f42baebb18d35d5eab19e4b35952217a46032128639a9af59b354f78dbccc02d90971b844bc5a8cdcf0 + languageName: node + linkType: hard + "@material-ui/styles@npm:^4.10.0, @material-ui/styles@npm:^4.11.0, @material-ui/styles@npm:^4.11.4, @material-ui/styles@npm:^4.11.5, @material-ui/styles@npm:^4.9.6": version: 4.11.5 resolution: "@material-ui/styles@npm:4.11.5" From 38cda5274693ed2809060f66672c1f0e2642cf80 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 15:31:05 +0200 Subject: [PATCH 107/348] dev-utils,techdocs: add conditional support for React 18 Signed-off-by: Patrik Oldsberg --- .changeset/eleven-hounds-invent.md | 5 +++++ .changeset/shaggy-beers-collect.md | 6 ++++++ packages/dev-utils/src/devApp/render.tsx | 5 +---- .../techdocs/src/reader/transformers/renderReactElement.ts | 5 +---- 4 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 .changeset/eleven-hounds-invent.md create mode 100644 .changeset/shaggy-beers-collect.md diff --git a/.changeset/eleven-hounds-invent.md b/.changeset/eleven-hounds-invent.md new file mode 100644 index 0000000000..ba863ebc28 --- /dev/null +++ b/.changeset/eleven-hounds-invent.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +In frontend builds and tests `process.env.HAS_REACT_DOM_CLIENT` will now be defined if `react-dom/client` is present, i.e. if using React 18. This allows for conditional imports of `react-dom/client`. diff --git a/.changeset/shaggy-beers-collect.md b/.changeset/shaggy-beers-collect.md new file mode 100644 index 0000000000..471368d6f2 --- /dev/null +++ b/.changeset/shaggy-beers-collect.md @@ -0,0 +1,6 @@ +--- +'@backstage/dev-utils': patch +'@backstage/plugin-techdocs': patch +--- + +Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. diff --git a/packages/dev-utils/src/devApp/render.tsx b/packages/dev-utils/src/devApp/render.tsx index 335308ff5e..e45ba649f9 100644 --- a/packages/dev-utils/src/devApp/render.tsx +++ b/packages/dev-utils/src/devApp/render.tsx @@ -49,10 +49,7 @@ import { createRoutesFromChildren, Route } from 'react-router-dom'; import { SidebarThemeSwitcher } from './SidebarThemeSwitcher'; import 'react-dom'; -let ReactDOM: - | typeof import('react-dom') - // TODO: replace with import('react-dom/client') when repo is migrated to 18 - | { createRoot(el: HTMLElement): { render(el: JSX.Element): void } }; +let ReactDOM: typeof import('react-dom') | typeof import('react-dom/client'); if (process.env.HAS_REACT_DOM_CLIENT) { ReactDOM = require('react-dom/client'); } else { diff --git a/plugins/techdocs/src/reader/transformers/renderReactElement.ts b/plugins/techdocs/src/reader/transformers/renderReactElement.ts index 86d44532c5..f9b45065f1 100644 --- a/plugins/techdocs/src/reader/transformers/renderReactElement.ts +++ b/plugins/techdocs/src/reader/transformers/renderReactElement.ts @@ -14,10 +14,7 @@ * limitations under the License. */ -let ReactDOM: - | typeof import('react-dom') - // TODO: replace with import('react-dom/client') when repo is migrated to 18 - | { createRoot(el: HTMLElement): { render(el: JSX.Element): void } }; +let ReactDOM: typeof import('react-dom') | typeof import('react-dom/client'); if (process.env.HAS_REACT_DOM_CLIENT) { ReactDOM = require('react-dom/client'); } else { From 7221db37026f64a2e1396c73e5770b27f0500971 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 15:31:33 +0200 Subject: [PATCH 108/348] switch app rendering to ReactDOM.createRoot Signed-off-by: Patrik Oldsberg --- packages/app-next/src/index.tsx | 4 ++-- packages/app/src/index.tsx | 4 ++-- packages/techdocs-cli-embedded-app/src/index.tsx | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/app-next/src/index.tsx b/packages/app-next/src/index.tsx index 3c354b06d0..37a2574484 100644 --- a/packages/app-next/src/index.tsx +++ b/packages/app-next/src/index.tsx @@ -15,7 +15,7 @@ */ import '@backstage/cli/asset-types'; -import ReactDOM from 'react-dom'; +import ReactDOM from 'react-dom/client'; import app from './App'; -ReactDOM.render(app, document.getElementById('root')); +ReactDOM.createRoot(document.getElementById('root')!).render(app); diff --git a/packages/app/src/index.tsx b/packages/app/src/index.tsx index b15bc4c102..e5ca03fe64 100644 --- a/packages/app/src/index.tsx +++ b/packages/app/src/index.tsx @@ -16,7 +16,7 @@ import '@backstage/cli/asset-types'; import React from 'react'; -import ReactDOM from 'react-dom'; +import ReactDOM from 'react-dom/client'; import App from './App'; -ReactDOM.render(, document.getElementById('root')); +ReactDOM.createRoot(document.getElementById('root')!).render(); diff --git a/packages/techdocs-cli-embedded-app/src/index.tsx b/packages/techdocs-cli-embedded-app/src/index.tsx index b15bc4c102..e5ca03fe64 100644 --- a/packages/techdocs-cli-embedded-app/src/index.tsx +++ b/packages/techdocs-cli-embedded-app/src/index.tsx @@ -16,7 +16,7 @@ import '@backstage/cli/asset-types'; import React from 'react'; -import ReactDOM from 'react-dom'; +import ReactDOM from 'react-dom/client'; import App from './App'; -ReactDOM.render(, document.getElementById('root')); +ReactDOM.createRoot(document.getElementById('root')!).render(); From aa2ff48a97ee042dbb97aa15922ac36efea6b757 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 15:40:10 +0200 Subject: [PATCH 109/348] switch react version ranges to full format Signed-off-by: Patrik Oldsberg --- packages/app-defaults/package.json | 4 ++-- packages/app-next-example-plugin/package.json | 4 ++-- packages/core-app-api/package.json | 4 ++-- packages/core-components/package.json | 4 ++-- packages/core-plugin-api/package.json | 4 ++-- packages/frontend-app-api/package.json | 2 +- packages/frontend-plugin-api/package.json | 2 +- packages/integration-react/package.json | 4 ++-- packages/test-utils/package.json | 4 ++-- packages/theme/package.json | 4 ++-- packages/version-bridge/package.json | 4 ++-- plugins/adr/package.json | 4 ++-- plugins/airbrake/package.json | 4 ++-- plugins/allure/package.json | 4 ++-- plugins/analytics-module-ga/package.json | 4 ++-- plugins/analytics-module-ga4/package.json | 4 ++-- plugins/analytics-module-newrelic-browser/package.json | 2 +- plugins/apache-airflow/package.json | 4 ++-- plugins/api-docs-module-protoc-gen-doc/package.json | 4 ++-- plugins/api-docs/package.json | 4 ++-- plugins/apollo-explorer/package.json | 4 ++-- plugins/azure-devops/package.json | 4 ++-- plugins/azure-sites/package.json | 4 ++-- plugins/badges/package.json | 4 ++-- plugins/bazaar/package.json | 4 ++-- plugins/bitrise/package.json | 4 ++-- plugins/catalog-graph/package.json | 4 ++-- plugins/catalog-graphql/package.json | 4 ++-- plugins/catalog-import/package.json | 4 ++-- plugins/catalog-react/package.json | 4 ++-- plugins/catalog-unprocessed-entities/package.json | 4 ++-- plugins/catalog/package.json | 4 ++-- plugins/cicd-statistics-module-gitlab/package.json | 4 ++-- plugins/cicd-statistics/package.json | 4 ++-- plugins/circleci/package.json | 4 ++-- plugins/cloudbuild/package.json | 4 ++-- plugins/code-climate/package.json | 4 ++-- plugins/code-coverage/package.json | 4 ++-- plugins/codescene/package.json | 4 ++-- plugins/config-schema/package.json | 4 ++-- plugins/cost-insights/package.json | 4 ++-- plugins/devtools/package.json | 4 ++-- plugins/dynatrace/package.json | 4 ++-- plugins/entity-feedback/package.json | 4 ++-- plugins/entity-validation/package.json | 4 ++-- plugins/example-todo-list/package.json | 4 ++-- plugins/explore-react/package.json | 4 ++-- plugins/explore/package.json | 4 ++-- plugins/firehydrant/package.json | 4 ++-- plugins/fossa/package.json | 4 ++-- plugins/gcalendar/package.json | 4 ++-- plugins/gcp-projects/package.json | 4 ++-- plugins/git-release-manager/package.json | 4 ++-- plugins/github-actions/package.json | 4 ++-- plugins/github-deployments/package.json | 4 ++-- plugins/github-issues/package.json | 4 ++-- plugins/github-pull-requests-board/package.json | 4 ++-- plugins/gitops-profiles/package.json | 4 ++-- plugins/gocd/package.json | 4 ++-- plugins/graphiql/package.json | 4 ++-- plugins/graphql-voyager/package.json | 4 ++-- plugins/home-react/package.json | 4 ++-- plugins/home/package.json | 4 ++-- plugins/ilert/package.json | 4 ++-- plugins/jenkins/package.json | 4 ++-- plugins/kafka/package.json | 4 ++-- plugins/kubernetes-cluster/package.json | 4 ++-- plugins/kubernetes-react/package.json | 2 +- plugins/kubernetes/package.json | 4 ++-- plugins/lighthouse/package.json | 4 ++-- plugins/linguist/package.json | 4 ++-- plugins/microsoft-calendar/package.json | 4 ++-- plugins/newrelic-dashboard/package.json | 4 ++-- plugins/newrelic/package.json | 4 ++-- plugins/nomad/package.json | 4 ++-- plugins/octopus-deploy/package.json | 4 ++-- plugins/opencost/package.json | 2 +- plugins/org-react/package.json | 4 ++-- plugins/org/package.json | 4 ++-- plugins/pagerduty/package.json | 4 ++-- plugins/periskop/package.json | 4 ++-- plugins/permission-react/package.json | 4 ++-- plugins/playlist/package.json | 4 ++-- plugins/puppetdb/package.json | 4 ++-- plugins/rollbar/package.json | 4 ++-- plugins/scaffolder-react/package.json | 4 ++-- plugins/scaffolder/package.json | 4 ++-- plugins/search-react/package.json | 4 ++-- plugins/search/package.json | 4 ++-- plugins/sentry/package.json | 4 ++-- plugins/shortcuts/package.json | 4 ++-- plugins/sonarqube-react/package.json | 4 ++-- plugins/sonarqube/package.json | 4 ++-- plugins/splunk-on-call/package.json | 4 ++-- plugins/stack-overflow/package.json | 4 ++-- plugins/stackstorm/package.json | 4 ++-- plugins/tech-insights/package.json | 4 ++-- plugins/tech-radar/package.json | 4 ++-- plugins/techdocs-addons-test-utils/package.json | 4 ++-- plugins/techdocs-module-addons-contrib/package.json | 4 ++-- plugins/techdocs-react/package.json | 4 ++-- plugins/todo/package.json | 4 ++-- plugins/user-settings/package.json | 4 ++-- plugins/vault/package.json | 4 ++-- plugins/xcmetrics/package.json | 4 ++-- 105 files changed, 205 insertions(+), 205 deletions(-) diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 6d35e1b125..98ebbffb69 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -42,8 +42,8 @@ "@material-ui/icons": "^4.9.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index 1e1b903271..865c6e0800 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -39,8 +39,8 @@ "@material-ui/icons": "^4.9.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index a138b1fcbb..4806d32d2f 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -57,8 +57,8 @@ "zod": "^3.21.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 77df614044..77825a42f8 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -78,8 +78,8 @@ "zod": "^3.21.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 0e6e15f28b..b7bc44e42f 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -54,8 +54,8 @@ "i18next": "^22.4.15" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index 7d48d5b524..238e66b230 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -49,7 +49,7 @@ "lodash": "^4.17.21" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" } } diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 2c81a747e1..da2d637f19 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -35,7 +35,7 @@ "dist" ], "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "dependencies": { diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index d75c2e612c..f5f77aa775 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -38,8 +38,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index dd310800ad..28aa1715e6 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -62,8 +62,8 @@ }, "peerDependencies": { "@testing-library/react": "^12.1.3 || ^13.0.0 || ^14.0.0", - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/theme/package.json b/packages/theme/package.json index 8b6bd081c1..77109aef87 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -40,8 +40,8 @@ "peerDependencies": { "@material-ui/core": "^4.12.2", "@types/react": "^16.13.1 || ^17.0.0", - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18" + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index 80671efe05..5f1bf4a405 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -36,8 +36,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 7300f8e852..4b7f10c139 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -62,8 +62,8 @@ "remark-gfm": "^3.0.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index c11f14761f..40e061dc78 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/allure/package.json b/plugins/allure/package.json index f7cc3a03c0..b4e11ed240 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -42,8 +42,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 347fd39b76..c8343a0324 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -40,8 +40,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index 782c0657e3..2f6294e106 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -37,8 +37,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index 13e8dae3ca..f03ec3122c 100644 --- a/plugins/analytics-module-newrelic-browser/package.json +++ b/plugins/analytics-module-newrelic-browser/package.json @@ -30,7 +30,7 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18" + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 5d1b5507ed..21cfb80522 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -40,8 +40,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/api-docs-module-protoc-gen-doc/package.json b/plugins/api-docs-module-protoc-gen-doc/package.json index a569f5f02e..80fe6645d7 100644 --- a/plugins/api-docs-module-protoc-gen-doc/package.json +++ b/plugins/api-docs-module-protoc-gen-doc/package.json @@ -36,8 +36,8 @@ "grpc-docs": "^1.1.2" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index fb49f16a7d..7d73535ffc 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -52,8 +52,8 @@ "swagger-ui-react": "^5.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 66aa47faf6..ed80f84890 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -40,8 +40,8 @@ "use-deep-compare-effect": "^1.8.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 12c563c187..e2998417f3 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index a6dc40caf9..ed23dd14f9 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/badges/package.json b/plugins/badges/package.json index c63e1a876c..6cb8fa7642 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 4e04507e65..ed3428d7f9 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -51,8 +51,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index dac5a0f497..311b9e8bbf 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -46,8 +46,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index d167dbaf3a..de83b774a2 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 001dd72869..d8869e2578 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -47,8 +47,8 @@ "winston": "^3.2.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 3db78446d3..6b3c1ba6e0 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -56,8 +56,8 @@ "yaml": "^2.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index f0bf4e822b..202df4647c 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -72,8 +72,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index dd3c3674b8..f6b06095e6 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 96e4a02b45..23c5891283 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -71,8 +71,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index 3aa76191f4..6c7f3c150f 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -43,8 +43,8 @@ "p-limit": "^4.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index e5b30dc101..fb8b736035 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -54,8 +54,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "files": [ diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index ad347a5f87..6b3859bef7 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index cbb707c099..fc6f2ba765 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 13a061310d..6cd94c26c8 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 5247f76d0c..129e8c347d 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -47,8 +47,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index bd59b6e15e..8258ca7eb2 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -42,8 +42,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 9c0fc4e89f..4e1a8a6bd0 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -45,8 +45,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index e131e2ef5c..1ecfb72ba6 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -57,8 +57,8 @@ "yup": "^0.32.9" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index 4e09919e43..721fb23cd2 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -44,8 +44,8 @@ }, "peerDependencies": { "@types/react": "^16.13.1 || ^17.0.0", - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index 9cd80c075a..08b0b58d34 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -41,8 +41,8 @@ }, "peerDependencies": { "@backstage/plugin-catalog-react": "workspace:^", - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 1fb982f803..650cfd8ca5 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index 12f835d98b..89c8c21126 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -51,8 +51,8 @@ "yaml": "^2.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index ad49a18d7c..78f2149f01 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -39,8 +39,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 14ec278cab..ce2c03d8a1 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -37,8 +37,8 @@ "@backstage/plugin-explore-common": "workspace:^" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/explore/package.json b/plugins/explore/package.json index c828622466..041f5009e6 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -66,8 +66,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 1fdee999b3..aff7048567 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 80c662fb88..5e74275c4f 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index c85e9b2ba6..98771b9ae3 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index d68e25a3f6..51816d3420 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -44,8 +44,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 5b9db4f4b5..2fd2284f7a 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -45,8 +45,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index efc202f42d..159dea9b90 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -52,8 +52,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 7ebc23aff8..cd50dcf846 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index e4a1c12c4a..f4a14388a6 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -45,8 +45,8 @@ "react-use": "^17.4.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index d771913b44..4bf335329d 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -51,8 +51,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 594f38556c..ac042db973 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index c4651c6444..2534d7dc3a 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 4dabd20c30..7281f5906f 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -60,8 +60,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index 2e10fcfd2c..d2d4c08bea 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index 043f3a99ff..8e1c3d63e5 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -42,8 +42,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/home/package.json b/plugins/home/package.json index c826c3d408..9ebf11e1f3 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -59,8 +59,8 @@ "zod": "^3.21.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 66d33c5532..87919dc88d 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index eabdd05241..ad66a51017 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -49,8 +49,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 6736b75775..f478adaa7a 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -44,8 +44,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index 703056174f..0d723195cc 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -57,8 +57,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index c93d4ceed7..547ba70543 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -48,7 +48,7 @@ "xterm-addon-fit": "^0.8.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18" + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 54c2c47e78..3415ac9649 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -62,8 +62,8 @@ "xterm-addon-fit": "^0.8.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 80966a30dd..5b244fdbfa 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index f54672d2e6..e09aad5cab 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -45,8 +45,8 @@ "slugify": "^1.6.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index b81f03c565..46d3114b4b 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -65,8 +65,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index 7937c9f52b..15f25d6cc7 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 53e42830c1..04b5449b19 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/nomad/package.json b/plugins/nomad/package.json index 49dbb7692d..b3ba40ace2 100644 --- a/plugins/nomad/package.json +++ b/plugins/nomad/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 824c3c2e78..e7018c5059 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/opencost/package.json b/plugins/opencost/package.json index 51055a738f..f3f5a2f087 100644 --- a/plugins/opencost/package.json +++ b/plugins/opencost/package.json @@ -40,7 +40,7 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "*" }, "devDependencies": { diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index fa6e9fcb39..c09d2fa09c 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/org/package.json b/plugins/org/package.json index 68435904d1..bb64d0b053 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -46,8 +46,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 8450056765..4bd3373eb8 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 29091fef1b..094b94d500 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index fa3d77fc36..c94e3b297d 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -41,8 +41,8 @@ "swr": "^2.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index b6e106ea3b..0af08417b5 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -51,8 +51,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index 877cb2fe5f..096da816fa 100644 --- a/plugins/puppetdb/package.json +++ b/plugins/puppetdb/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 07116ec203..b6742f19e3 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index a54e26304d..d533f5d331 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -81,8 +81,8 @@ "zod-to-json-schema": "^3.20.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 1ef6c70340..7a2b4b0d01 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -92,8 +92,8 @@ "zod-to-json-schema": "^3.20.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 52277961d9..4d5b6e1bbc 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -62,8 +62,8 @@ "react-use": "^17.3.2" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/search/package.json b/plugins/search/package.json index c89c86e518..25b782b197 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -66,8 +66,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 55bcd6c779..cf9eea0b3b 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 18e529f9c1..4002848ce2 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -44,8 +44,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index 9884fbb5c4..c643df3702 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -45,8 +45,8 @@ "@backstage/core-plugin-api": "workspace:^" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index a06a9bfafd..6d0524dba8 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -53,8 +53,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index cc800a6db0..624c89de79 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 173a940096..2e38257b0a 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -46,8 +46,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index af5a926045..eb91c21c1b 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 3c881649b6..9d01e394a3 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 792052f090..3a0377d259 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -59,8 +59,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 8d3ae34018..9a13944481 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -52,8 +52,8 @@ "testing-library__dom": "^7.29.4-beta.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 17fa38c85a..efea387931 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -49,8 +49,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 3abafb9ef1..7f89226844 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -49,8 +49,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 546c6d7f65..9236b376e6 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -44,8 +44,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index d8a60850f1..0ea5e83def 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -62,8 +62,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/vault/package.json b/plugins/vault/package.json index bdbd09da95..7c24d4dee0 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 56befd87c2..f210ebf8ea 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -44,8 +44,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17 || ^18", - "react-dom": "^16.13.1 || ^17 || ^18", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { From 6c2b8721531e6cd4776cb26da7da98b46d11615a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 15:49:02 +0200 Subject: [PATCH 110/348] changesets: add changeset for React 18 support Signed-off-by: Patrik Oldsberg --- .changeset/lazy-hotels-wait.md | 110 +++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 .changeset/lazy-hotels-wait.md diff --git a/.changeset/lazy-hotels-wait.md b/.changeset/lazy-hotels-wait.md new file mode 100644 index 0000000000..515e7fb0ed --- /dev/null +++ b/.changeset/lazy-hotels-wait.md @@ -0,0 +1,110 @@ +--- +'@backstage/plugin-analytics-module-newrelic-browser': patch +'@backstage/plugin-api-docs-module-protoc-gen-doc': patch +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-cicd-statistics-module-gitlab': patch +'@backstage/plugin-catalog-unprocessed-entities': patch +'@backstage/plugin-github-pull-requests-board': patch +'@backstage/plugin-techdocs-addons-test-utils': patch +'@backstage/frontend-plugin-api': patch +'@backstage/plugin-analytics-module-ga4': patch +'@backstage/plugin-analytics-module-ga': patch +'@backstage/plugin-git-release-manager': patch +'@backstage/integration-react': patch +'@backstage/plugin-github-deployments': patch +'@backstage/plugin-kubernetes-cluster': patch +'@backstage/plugin-microsoft-calendar': patch +'@backstage/plugin-newrelic-dashboard': patch +'@backstage/frontend-app-api': patch +'@backstage/plugin-entity-validation': patch +'@backstage/core-components': patch +'@backstage/core-plugin-api': patch +'@backstage/plugin-kubernetes-react': patch +'@backstage/plugin-permission-react': patch +'@backstage/plugin-scaffolder-react': patch +'@backstage/version-bridge': patch +'@backstage/plugin-apollo-explorer': patch +'@backstage/plugin-catalog-graphql': patch +'@backstage/plugin-cicd-statistics': patch +'@backstage/plugin-entity-feedback': patch +'@backstage/plugin-gitops-profiles': patch +'@backstage/plugin-graphql-voyager': patch +'@backstage/plugin-sonarqube-react': patch +'@backstage/plugin-apache-airflow': patch +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-github-actions': patch +'@backstage/plugin-octopus-deploy': patch +'@backstage/plugin-splunk-on-call': patch +'@backstage/plugin-stack-overflow': patch +'@backstage/plugin-techdocs-react': patch +'@backstage/app-defaults': patch +'@backstage/core-app-api': patch +'@backstage/plugin-catalog-graph': patch +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-code-coverage': patch +'@backstage/plugin-config-schema': patch +'@backstage/plugin-cost-insights': patch +'@backstage/plugin-explore-react': patch +'@backstage/plugin-github-issues': patch +'@backstage/plugin-tech-insights': patch +'@backstage/plugin-user-settings': patch +'@backstage/plugin-azure-devops': patch +'@backstage/plugin-code-climate': patch +'@backstage/plugin-gcp-projects': patch +'@backstage/plugin-search-react': patch +'@backstage/create-app': patch +'@backstage/test-utils': patch +'@backstage/plugin-azure-sites': patch +'@backstage/plugin-firehydrant': patch +'@backstage/dev-utils': patch +'@backstage/plugin-cloudbuild': patch +'@backstage/plugin-home-react': patch +'@backstage/plugin-kubernetes': patch +'@backstage/plugin-lighthouse': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-stackstorm': patch +'@backstage/plugin-tech-radar': patch +'@backstage/plugin-codescene': patch +'@backstage/plugin-dynatrace': patch +'@backstage/plugin-gcalendar': patch +'@backstage/plugin-org-react': patch +'@backstage/plugin-pagerduty': patch +'@backstage/plugin-shortcuts': patch +'@backstage/plugin-sonarqube': patch +'@backstage/plugin-xcmetrics': patch +'@backstage/plugin-airbrake': patch +'@backstage/plugin-api-docs': patch +'@backstage/plugin-circleci': patch +'@backstage/plugin-devtools': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-linguist': patch +'@backstage/plugin-newrelic': patch +'@backstage/plugin-opencost': patch +'@backstage/plugin-periskop': patch +'@backstage/plugin-playlist': patch +'@backstage/plugin-puppetdb': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-bitrise': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-explore': patch +'@backstage/plugin-jenkins': patch +'@backstage/plugin-rollbar': patch +'@backstage/theme': patch +'@backstage/plugin-allure': patch +'@backstage/plugin-badges': patch +'@backstage/plugin-bazaar': patch +'@backstage/plugin-search': patch +'@backstage/plugin-sentry': patch +'@backstage/plugin-fossa': patch +'@backstage/plugin-ilert': patch +'@backstage/plugin-kafka': patch +'@backstage/plugin-nomad': patch +'@backstage/plugin-vault': patch +'@backstage/plugin-gocd': patch +'@backstage/plugin-home': patch +'@backstage/plugin-todo': patch +'@backstage/plugin-adr': patch +'@backstage/plugin-org': patch +--- + +Add official support for React 18. From 6c038130bcfaa25c23baf8546d89479273bec366 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 16:09:02 +0200 Subject: [PATCH 111/348] storybook: switch to React 18 Signed-off-by: Patrik Oldsberg --- storybook/package.json | 4 ++-- storybook/yarn.lock | 35 ++++++++++++++++------------------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/storybook/package.json b/storybook/package.json index 6a86cd90bd..46cf09dc79 100644 --- a/storybook/package.json +++ b/storybook/package.json @@ -9,8 +9,8 @@ }, "dependencies": { "@swc/core": "^1.3.46", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.2", + "react-dom": "^18.0.2", "react-hot-loader": "^4.13.0", "swc-loader": "^0.2.3" }, diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 9a533c46c0..00ec6908f0 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -9592,16 +9592,15 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^17.0.2": - version: 17.0.2 - resolution: "react-dom@npm:17.0.2" +"react-dom@npm:^18.0.2": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - scheduler: ^0.20.2 + scheduler: ^0.23.0 peerDependencies: - react: 17.0.2 - checksum: 1c1eaa3bca7c7228d24b70932e3d7c99e70d1d04e13bb0843bbf321582bc25d7961d6b8a6978a58a598af2af496d1cedcfb1bf65f6b0960a0a8161cb8dab743c + react: ^18.2.0 + checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc languageName: node linkType: hard @@ -9710,13 +9709,12 @@ __metadata: languageName: node linkType: hard -"react@npm:^17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" +"react@npm:^18.0.2": + version: 18.2.0 + resolution: "react@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b languageName: node linkType: hard @@ -10149,13 +10147,12 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.20.2": - version: 0.20.2 - resolution: "scheduler@npm:0.20.2" +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc + checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a languageName: node linkType: hard @@ -10682,8 +10679,8 @@ __metadata: "@storybook/react": ^6.5.9 "@storybook/testing-library": ^0.2.0 "@swc/core": ^1.3.46 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.2 + react-dom: ^18.0.2 react-hot-loader: ^4.13.0 storybook-dark-mode: ^1.1.0 swc-loader: ^0.2.3 From ec1dde683185619e3b490be22452be7444ae2990 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Oct 2023 13:25:08 +0200 Subject: [PATCH 112/348] switch to @testing-library/react 14 Signed-off-by: Patrik Oldsberg --- packages/app-defaults/package.json | 2 +- packages/app-next/package.json | 2 +- packages/app/package.json | 2 +- packages/core-app-api/package.json | 2 +- packages/core-components/package.json | 2 +- packages/core-plugin-api/package.json | 2 +- packages/dev-utils/package.json | 2 +- packages/frontend-app-api/package.json | 2 +- packages/frontend-plugin-api/package.json | 2 +- packages/techdocs-cli-embedded-app/package.json | 2 +- packages/version-bridge/package.json | 2 +- plugins/adr/package.json | 2 +- plugins/airbrake/package.json | 2 +- plugins/allure/package.json | 2 +- plugins/analytics-module-ga/package.json | 2 +- plugins/analytics-module-ga4/package.json | 2 +- plugins/analytics-module-newrelic-browser/package.json | 2 +- plugins/apache-airflow/package.json | 2 +- plugins/api-docs/package.json | 2 +- plugins/apollo-explorer/package.json | 2 +- plugins/azure-devops/package.json | 2 +- plugins/azure-sites/package.json | 2 +- plugins/bitrise/package.json | 2 +- plugins/catalog-graph/package.json | 2 +- plugins/catalog-import/package.json | 2 +- plugins/catalog-react/package.json | 2 +- plugins/catalog-unprocessed-entities/package.json | 2 +- plugins/catalog/package.json | 2 +- plugins/circleci/package.json | 2 +- plugins/cloudbuild/package.json | 2 +- plugins/code-climate/package.json | 2 +- plugins/code-coverage/package.json | 2 +- plugins/codescene/package.json | 2 +- plugins/config-schema/package.json | 2 +- plugins/cost-insights/package.json | 2 +- plugins/devtools/package.json | 2 +- plugins/dynatrace/package.json | 2 +- plugins/entity-feedback/package.json | 2 +- plugins/entity-validation/package.json | 2 +- plugins/example-todo-list/package.json | 2 +- plugins/explore-react/package.json | 2 +- plugins/explore/package.json | 2 +- plugins/firehydrant/package.json | 2 +- plugins/fossa/package.json | 2 +- plugins/gcalendar/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/github-issues/package.json | 2 +- plugins/github-pull-requests-board/package.json | 2 +- plugins/gitops-profiles/package.json | 2 +- plugins/gocd/package.json | 2 +- plugins/graphiql/package.json | 2 +- plugins/graphql-voyager/package.json | 2 +- plugins/home-react/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-cluster/package.json | 2 +- plugins/kubernetes-react/package.json | 2 +- plugins/kubernetes/package.json | 2 +- plugins/lighthouse/package.json | 2 +- plugins/linguist/package.json | 2 +- plugins/microsoft-calendar/package.json | 2 +- plugins/newrelic/package.json | 2 +- plugins/nomad/package.json | 2 +- plugins/octopus-deploy/package.json | 2 +- plugins/opencost/package.json | 2 +- plugins/org-react/package.json | 2 +- plugins/org/package.json | 2 +- plugins/pagerduty/package.json | 2 +- plugins/periskop/package.json | 2 +- plugins/permission-react/package.json | 2 +- plugins/playlist/package.json | 2 +- plugins/puppetdb/package.json | 2 +- plugins/rollbar/package.json | 2 +- plugins/scaffolder-react/package.json | 2 +- plugins/scaffolder/package.json | 2 +- plugins/search-react/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/stack-overflow/package.json | 2 +- plugins/stackstorm/package.json | 2 +- plugins/tech-insights/package.json | 2 +- plugins/tech-radar/package.json | 2 +- plugins/techdocs-addons-test-utils/package.json | 3 +-- plugins/techdocs-module-addons-contrib/package.json | 2 +- plugins/techdocs-react/package.json | 2 +- plugins/techdocs/package.json | 2 +- plugins/todo/package.json | 2 +- plugins/user-settings/package.json | 2 +- plugins/vault/package.json | 2 +- plugins/xcmetrics/package.json | 2 +- 98 files changed, 98 insertions(+), 99 deletions(-) diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 98ebbffb69..9ab12f7cc5 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -50,7 +50,7 @@ "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0" }, "files": [ diff --git a/packages/app-next/package.json b/packages/app-next/package.json index a52ec7fd17..635a513c0f 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -100,7 +100,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/jquery": "^3.3.34", "@types/react": "*", diff --git a/packages/app/package.json b/packages/app/package.json index 696aca2288..df48491481 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -106,7 +106,7 @@ "@playwright/test": "^1.32.3", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/jquery": "^3.3.34", "@types/react": "*", diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 4806d32d2f..e6792a3402 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -66,7 +66,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/zen-observable": "^0.8.0", diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 77825a42f8..842a52df43 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -88,7 +88,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/ansi-regex": "^5.0.0", "@types/classnames": "^2.2.9", diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index b7bc44e42f..42f3b8b4d4 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -64,7 +64,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0" }, "files": [ diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 1356c16a2c..d860d67070 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "zen-observable": "^0.10.0" }, diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index 238e66b230..d4a595707a 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -26,7 +26,7 @@ "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0" + "@testing-library/react": "^14.0.0" }, "configSchema": "config.d.ts", "files": [ diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index da2d637f19..cf42f04479 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -27,7 +27,7 @@ "@backstage/frontend-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", "history": "^5.3.0" }, diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 046d4f6db0..8cd74ea71a 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -38,7 +38,7 @@ "@backstage/cli": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/react": "*", "@types/react-dom": "*", diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index 5f1bf4a405..caf196f497 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -43,7 +43,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0" + "@testing-library/react": "^14.0.0" }, "files": [ "dist" diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 4b7f10c139..86e07013bf 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -73,7 +73,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/git-url-parse": "^9.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 40e061dc78..4e6476ecea 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -54,7 +54,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/allure/package.json b/plugins/allure/package.json index b4e11ed240..628eea6651 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -53,7 +53,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index c8343a0324..44d922ed7a 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -51,7 +51,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "msw": "^1.0.0" diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index 2f6294e106..705a430424 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -48,7 +48,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/jest": "^28.1.3", "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index f03ec3122c..06b3cf5e02 100644 --- a/plugins/analytics-module-newrelic-browser/package.json +++ b/plugins/analytics-module-newrelic-browser/package.json @@ -38,7 +38,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 21cfb80522..e87179784f 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -51,7 +51,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 7d73535ffc..53832682af 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -63,7 +63,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/swagger-ui-react": "^4.18.0", "cross-fetch": "^3.1.5", diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index ed80f84890..6af85a2784 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -51,7 +51,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index e2998417f3..7b5d8ee97a 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index ed23dd14f9..c00f1f21af 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 311b9e8bbf..023472669b 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -57,7 +57,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/recharts": "^1.8.15", "msw": "^1.0.0" diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index de83b774a2..0afb6d92f7 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0" }, "files": [ diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 6b3c1ba6e0..b970736695 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -67,7 +67,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 202df4647c..bb18160595 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -84,7 +84,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/zen-observable": "^0.8.0", "react-test-renderer": "^16.13.1" diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index f6b06095e6..b4d95ac20a 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -51,7 +51,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 23c5891283..56ae771314 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -83,7 +83,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0" }, "files": [ diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 6b3859bef7..ddec70c2de 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.25.1", "cross-fetch": "^3.1.5", diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index fc6f2ba765..8b64387aa8 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 6cd94c26c8..dc01c52a13 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -53,7 +53,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.27.1", "@types/luxon": "^3.0.0", diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 129e8c347d..15343a8212 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/highlightjs": "^10.1.0", "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 8258ca7eb2..e36c8e5575 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -53,7 +53,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 4e1a8a6bd0..387921650b 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 1ecfb72ba6..5cd7c3458b 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -68,7 +68,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/pluralize": "^0.0.31", "@types/recharts": "^1.8.14", diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index 721fb23cd2..41ea821dea 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -54,7 +54,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index 08b0b58d34..f8b35eafaa 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -52,7 +52,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "express": "^4.18.1", "msw": "^1.0.0" diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 650cfd8ca5..f2a4697454 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -54,7 +54,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index 89c8c21126..1fee0c7892 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -62,7 +62,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 78f2149f01..7bfc3f898c 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -50,7 +50,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "msw": "^1.0.0" diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index ce2c03d8a1..7599da4ba8 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -47,7 +47,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 041f5009e6..435c5df84d 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -78,7 +78,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index aff7048567..ed723f71cf 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -54,7 +54,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 5e74275c4f..6c08f3d4fd 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 98771b9ae3..d84850677b 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/dompurify": "^2.3.3", "@types/sanitize-html": "^2.6.2", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 51816d3420..24bb9a99fa 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 2fd2284f7a..2c0ce60f6a 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/recharts": "^1.8.15", "msw": "^1.0.0" diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 159dea9b90..ec0d9a03db 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -63,7 +63,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index cd50dcf846..4833a4df8a 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index f4a14388a6..f942ca50bc 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 4bf335329d..2c985beda7 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index ac042db973..5511f1f4fa 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 2534d7dc3a..c2f60d7eb6 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/lodash": "^4.14.173", "@types/luxon": "^3.0.0", diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 7281f5906f..52cff1fdb7 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -71,7 +71,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/codemirror": "^5.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index d2d4c08bea..51b7020154 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -52,7 +52,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index 8e1c3d63e5..5c56caf71b 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -53,7 +53,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/react-grid-layout": "^1.3.2", "cross-fetch": "^3.1.5", diff --git a/plugins/home/package.json b/plugins/home/package.json index 9ebf11e1f3..07e895c243 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -69,7 +69,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/react-grid-layout": "^1.3.2", "msw": "^1.0.0" diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 87919dc88d..42d6a33ab1 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index ad66a51017..8be847f002 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -60,7 +60,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/testing-library__jest-dom": "^5.9.1", "cross-fetch": "^3.1.5", diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index f478adaa7a..1580caa124 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "jest-when": "^3.1.0", "msw": "^1.0.0" diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index 0d723195cc..1949941d47 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -68,7 +68,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "msw": "^1.0.0" diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index 547ba70543..03f647cfb2 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -55,7 +55,7 @@ "@backstage/core-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "jest-websocket-mock": "^2.5.0", "msw": "^1.3.1" }, diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 3415ac9649..ed2dfd35ec 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -73,7 +73,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "jest-websocket-mock": "^2.4.1", "msw": "^1.0.0" diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 5b244fdbfa..c039ae6b30 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index e09aad5cab..3d101548a2 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index 46d3114b4b..57c4a75c39 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -76,7 +76,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 04b5449b19..c4da950dee 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -57,7 +57,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/parse-link-header": "^2.0.1", "cross-fetch": "^3.1.5", diff --git a/plugins/nomad/package.json b/plugins/nomad/package.json index b3ba40ace2..617c8e2c5a 100644 --- a/plugins/nomad/package.json +++ b/plugins/nomad/package.json @@ -53,7 +53,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index e7018c5059..3da25dc2c3 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -52,7 +52,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/opencost/package.json b/plugins/opencost/package.json index f3f5a2f087..f751ed3ba5 100644 --- a/plugins/opencost/package.json +++ b/plugins/opencost/package.json @@ -49,7 +49,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index c09d2fa09c..2097c7658a 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/org/package.json b/plugins/org/package.json index bb64d0b053..b9bf7f0c02 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -61,7 +61,7 @@ "@backstage/types": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 4bd3373eb8..0130724cfa 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 094b94d500..9ec13e9ce1 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -54,7 +54,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/luxon": "^3.0.0", "msw": "^1.0.0" diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index c94e3b297d..9a9650e762 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -49,7 +49,7 @@ "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0" + "@testing-library/react": "^14.0.0" }, "files": [ "dist" diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 0af08417b5..de53e9fafe 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -63,7 +63,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0", "swr": "^2.0.0" diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index 096da816fa..89cd83fcde 100644 --- a/plugins/puppetdb/package.json +++ b/plugins/puppetdb/package.json @@ -58,7 +58,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.1" }, diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index b6742f19e3..d82402c03e 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index d533f5d331..5f29f96946 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -93,7 +93,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.18.1", "@types/luxon": "^3.0.0" diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 7a2b4b0d01..d36ce86acc 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -104,7 +104,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.18.1", "@types/json-schema": "^7.0.9", diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 4d5b6e1bbc..c2c181f657 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -72,7 +72,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0" }, "files": [ diff --git a/plugins/search/package.json b/plugins/search/package.json index 25b782b197..23abaefa1d 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -77,7 +77,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "history": "^5.0.0", "msw": "^1.0.0" diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index cf9eea0b3b..3856270628 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/luxon": "^3.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 4002848ce2..c38125d561 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/zen-observable": "^0.8.2", "msw": "^1.0.0" diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 6d0524dba8..00d6c494db 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -64,7 +64,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 624c89de79..e07a08254f 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -59,7 +59,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/luxon": "^3.0.0", "msw": "^1.0.0" diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 2e38257b0a..f60800d1f9 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -56,7 +56,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index eb91c21c1b..76f9958812 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 9d01e394a3..7735fb3719 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -56,7 +56,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 3a0377d259..82fd7ca147 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -70,7 +70,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/color": "^3.0.1", "@types/d3-force": "^3.0.0", diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 9a13944481..b65cc1d2b1 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -46,7 +46,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "react-use": "^17.2.4", "testing-library__dom": "^7.29.4-beta.1" @@ -61,7 +61,6 @@ "@backstage/dev-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index efea387931..cf92b0c969 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -61,7 +61,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "msw": "^1.0.0" diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 7f89226844..79d2b3cc17 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0" + "@testing-library/react": "^14.0.0" }, "files": [ "alpha", diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 104f764d00..3df7399521 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -86,7 +86,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/dompurify": "^2.2.2", "@types/event-source-polyfill": "^1.0.0", diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 9236b376e6..ec27528d72 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 0ea5e83def..264521ee45 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -73,7 +73,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 7c24d4dee0..055d38073a 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -58,7 +58,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index f210ebf8ea..97887eb2ea 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -55,7 +55,7 @@ "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^13.4.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/luxon": "^3.0.0", "msw": "^1.0.0" From b3cc6b318a140123635deb1551ec24bb0bdd9251 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Oct 2023 13:29:57 +0200 Subject: [PATCH 113/348] sync yarn.lock Signed-off-by: Patrik Oldsberg --- yarn.lock | 657 +++++++++++++++++++++++++----------------------------- 1 file changed, 309 insertions(+), 348 deletions(-) diff --git a/yarn.lock b/yarn.lock index 633590050e..8a90f11890 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3368,11 +3368,11 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -3927,7 +3927,7 @@ __metadata: "@backstage/version-bridge": "workspace:^" "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 "@types/prop-types": ^15.7.3 @@ -3946,8 +3946,8 @@ __metadata: zen-observable: ^0.10.0 zod: ^3.21.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -3974,8 +3974,7 @@ __metadata: "@react-hookz/web": ^20.0.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/ansi-regex": ^5.0.0 "@types/classnames": ^2.2.9 @@ -4022,8 +4021,8 @@ __metadata: zen-observable: ^0.10.0 zod: ^3.21.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4090,15 +4089,14 @@ __metadata: "@backstage/version-bridge": "workspace:^" "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 history: ^5.0.0 i18next: ^22.4.15 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4148,7 +4146,7 @@ __metadata: "@material-ui/icons": ^4.9.1 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 react-use: ^17.2.4 @@ -4216,11 +4214,11 @@ __metadata: "@material-ui/core": ^4.12.4 "@material-ui/icons": ^4.11.3 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 lodash: ^4.17.21 peerDependencies: - react: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4236,7 +4234,7 @@ __metadata: "@backstage/types": "workspace:^" "@backstage/version-bridge": "workspace:^" "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/react-hooks": ^8.0.1 "@types/react": ^16.13.1 || ^17.0.0 history: ^5.3.0 @@ -4244,7 +4242,7 @@ __metadata: zod: ^3.21.4 zod-to-json-schema: ^3.21.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4286,8 +4284,8 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4376,7 +4374,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/git-url-parse": ^9.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -4387,8 +4385,8 @@ __metadata: react-use: ^17.2.4 remark-gfm: ^3.0.1 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4432,14 +4430,14 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4462,14 +4460,14 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4488,7 +4486,7 @@ __metadata: "@backstage/theme": "workspace:^" "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/jest": ^28.1.3 "@types/react": ^16.13.1 || ^17.0.0 @@ -4496,8 +4494,8 @@ __metadata: react-ga4: ^2.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4519,15 +4517,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-ga: ^3.3.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4545,12 +4543,12 @@ __metadata: "@backstage/test-utils": "workspace:^" "@newrelic/browser-agent": ^1.236.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 languageName: unknown linkType: soft @@ -4569,7 +4567,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -4577,8 +4575,8 @@ __metadata: qs: ^6.10.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4592,8 +4590,8 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 grpc-docs: ^1.1.2 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4618,7 +4616,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/swagger-ui-react": ^4.18.0 @@ -4631,8 +4629,8 @@ __metadata: react-use: ^17.2.4 swagger-ui-react: ^5.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4653,15 +4651,15 @@ __metadata: "@material-ui/icons": ^4.9.1 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 use-deep-compare-effect: ^1.8.1 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4992,7 +4990,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 humanize-duration: ^3.27.0 @@ -5000,8 +4998,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5055,15 +5053,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 luxon: ^3.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5117,8 +5115,8 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5169,8 +5167,8 @@ __metadata: react-hook-form: ^7.13.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5206,7 +5204,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/recharts": ^1.8.15 @@ -5217,8 +5215,8 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5705,8 +5703,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 classnames: ^2.3.1 @@ -5715,8 +5712,8 @@ __metadata: qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5746,8 +5743,8 @@ __metadata: node-fetch: ^2.6.7 winston: ^3.2.1 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5776,8 +5773,7 @@ __metadata: "@octokit/rest": ^19.0.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 git-url-parse: ^13.0.0 @@ -5788,8 +5784,8 @@ __metadata: react-use: ^17.2.4 yaml: ^2.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5836,8 +5832,7 @@ __metadata: "@react-hookz/web": ^23.0.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/zen-observable": ^0.8.0 @@ -5850,8 +5845,8 @@ __metadata: yaml: ^2.0.0 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5873,14 +5868,14 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.60 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5913,7 +5908,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 history: ^5.0.0 @@ -5922,8 +5917,8 @@ __metadata: react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5942,8 +5937,8 @@ __metadata: luxon: ^3.0.0 p-limit: ^4.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5970,8 +5965,8 @@ __metadata: react-use: ^17.3.1 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5994,7 +5989,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.25.1 "@types/react": ^16.13.1 || ^17.0.0 @@ -6006,8 +6001,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6030,7 +6025,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -6039,8 +6034,8 @@ __metadata: qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6062,7 +6057,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.27.1 "@types/luxon": ^3.0.0 @@ -6072,8 +6067,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6128,7 +6123,7 @@ __metadata: "@material-ui/styles": ^4.11.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/highlightjs": ^10.1.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -6139,8 +6134,8 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6163,15 +6158,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 rc-progress: 3.5.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6195,7 +6190,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 jsonschema: ^1.2.6 @@ -6203,8 +6198,8 @@ __metadata: react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6238,7 +6233,7 @@ __metadata: "@material-ui/styles": ^4.9.6 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/pluralize": ^0.0.31 "@types/react": ^16.13.1 || ^17.0.0 @@ -6258,8 +6253,8 @@ __metadata: regression: ^2.0.1 yup: ^0.32.9 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6331,7 +6326,7 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.57 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 cross-fetch: ^3.1.5 msw: ^1.0.0 @@ -6339,8 +6334,8 @@ __metadata: react-use: ^17.2.4 peerDependencies: "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6362,7 +6357,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 express: ^4.18.1 @@ -6370,8 +6365,8 @@ __metadata: react-use: ^17.2.4 peerDependencies: "@backstage/plugin-catalog-react": "workspace:^" - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6430,15 +6425,14 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.1 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6468,7 +6462,7 @@ __metadata: "@react-hookz/web": ^20.0.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@uiw/react-codemirror": ^4.9.3 @@ -6477,8 +6471,8 @@ __metadata: react-use: ^17.2.4 yaml: ^2.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6657,14 +6651,14 @@ __metadata: "@backstage/test-utils": "workspace:^" "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^1.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6694,7 +6688,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 classnames: ^2.2.6 @@ -6703,8 +6697,8 @@ __metadata: pluralize: ^8.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6727,15 +6721,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 luxon: ^3.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6759,7 +6753,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -6768,8 +6762,8 @@ __metadata: p-limit: ^3.0.2 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6793,7 +6787,7 @@ __metadata: "@tanstack/react-query": ^4.1.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.3.3 "@types/react": ^16.13.1 || ^17.0.0 @@ -6807,8 +6801,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6830,14 +6824,14 @@ __metadata: "@react-hookz/web": ^20.0.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^1.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6860,8 +6854,7 @@ __metadata: "@octokit/rest": ^19.0.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/recharts": ^1.8.15 @@ -6871,8 +6864,8 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6898,7 +6891,7 @@ __metadata: "@octokit/rest": ^19.0.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -6907,8 +6900,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6935,15 +6928,15 @@ __metadata: "@octokit/graphql": ^5.0.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 luxon: ^3.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6968,7 +6961,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 luxon: ^3.0.0 @@ -6976,8 +6969,8 @@ __metadata: octokit: ^2.0.4 react-use: ^17.4.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7001,7 +6994,7 @@ __metadata: "@octokit/rest": ^19.0.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 luxon: ^3.0.0 @@ -7009,8 +7002,8 @@ __metadata: p-limit: ^4.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7032,15 +7025,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7064,7 +7057,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/lodash": ^4.14.173 "@types/luxon": ^3.0.0 @@ -7075,8 +7068,8 @@ __metadata: qs: ^6.10.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7098,7 +7091,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/codemirror": ^5.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -7109,8 +7102,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7156,15 +7149,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 graphql-voyager: ^1.0.0-rc.31 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7184,15 +7177,15 @@ __metadata: "@rjsf/utils": 5.13.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/react-grid-layout": ^1.3.2 cross-fetch: ^3.1.5 msw: ^1.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7222,8 +7215,7 @@ __metadata: "@rjsf/validator-ajv8": 5.13.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.1 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/react-grid-layout": ^1.3.2 @@ -7235,8 +7227,8 @@ __metadata: react-use: ^17.2.4 zod: ^3.21.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7262,7 +7254,7 @@ __metadata: "@material-ui/pickers": ^3.3.10 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 humanize-duration: ^3.26.0 @@ -7270,8 +7262,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7336,7 +7328,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/testing-library__jest-dom": ^5.9.1 @@ -7345,8 +7337,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7393,16 +7385,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 jest-when: ^3.1.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7483,8 +7474,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 @@ -7496,8 +7486,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7553,8 +7543,7 @@ __metadata: "@material-ui/icons": ^4.11.3 "@material-ui/lab": ^4.0.0-alpha.61 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.1 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cronstrue: ^2.32.0 jest-websocket-mock: ^2.5.0 @@ -7568,7 +7557,7 @@ __metadata: xterm-addon-attach: ^0.9.0 xterm-addon-fit: ^0.8.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 languageName: unknown linkType: soft @@ -7598,8 +7587,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cronstrue: ^2.2.0 @@ -7614,8 +7602,8 @@ __metadata: xterm-addon-attach: ^0.9.0 xterm-addon-fit: ^0.8.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7667,15 +7655,14 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7743,7 +7730,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 luxon: ^2.0.2 @@ -7751,8 +7738,8 @@ __metadata: react-use: ^17.2.4 slugify: ^1.6.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7775,7 +7762,7 @@ __metadata: "@tanstack/react-query": ^4.1.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 classnames: ^2.3.1 @@ -7786,8 +7773,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7811,8 +7798,8 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7834,7 +7821,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/parse-link-header": ^2.0.1 "@types/react": ^16.13.1 || ^17.0.0 @@ -7843,8 +7830,8 @@ __metadata: parse-link-header: ^2.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7888,7 +7875,7 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.60 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -7896,8 +7883,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7920,14 +7907,14 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7950,7 +7937,7 @@ __metadata: "@material-ui/pickers": ^3.3.10 "@material-ui/styles": ^4.11.5 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 axios: ^1.4.0 @@ -7961,7 +7948,7 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: "*" languageName: unknown linkType: soft @@ -7985,14 +7972,14 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8019,8 +8006,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.1 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 lodash: ^4.17.21 @@ -8030,8 +8016,8 @@ __metadata: qs: ^6.10.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8056,7 +8042,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 classnames: ^2.2.6 @@ -8064,8 +8050,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8109,7 +8095,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -8117,8 +8103,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8213,14 +8199,14 @@ __metadata: "@backstage/plugin-permission-common": "workspace:^" "@backstage/test-utils": "workspace:^" "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 react-use: ^17.2.4 swr: ^2.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8290,8 +8276,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 lodash: ^4.17.21 @@ -8302,8 +8287,8 @@ __metadata: react-use: ^17.2.4 swr: ^2.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8355,14 +8340,14 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.57 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8410,8 +8395,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -8420,8 +8404,8 @@ __metadata: react-sparklines: ^1.7.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8669,8 +8653,7 @@ __metadata: "@rjsf/validator-ajv8": 5.13.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 @@ -8690,8 +8673,8 @@ __metadata: zod: ^3.21.4 zod-to-json-schema: ^3.20.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8733,8 +8716,7 @@ __metadata: "@rjsf/validator-ajv8": 5.13.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 @@ -8758,8 +8740,8 @@ __metadata: zod: ^3.21.4 zod-to-json-schema: ^3.20.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8955,16 +8937,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 lodash: ^4.17.21 qs: ^6.9.4 react-use: ^17.3.2 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8994,8 +8975,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 history: ^5.0.0 @@ -9003,8 +8983,8 @@ __metadata: qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9029,7 +9009,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -9039,8 +9019,8 @@ __metadata: react-sparklines: ^1.7.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9062,7 +9042,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/zen-observable": ^0.8.2 @@ -9072,8 +9052,8 @@ __metadata: uuid: ^8.3.2 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9109,8 +9089,8 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9135,7 +9115,7 @@ __metadata: "@material-ui/styles": ^4.10.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -9144,8 +9124,8 @@ __metadata: rc-progress: 3.5.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9168,7 +9148,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -9177,8 +9157,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9219,7 +9199,7 @@ __metadata: "@material-ui/icons": ^4.9.1 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -9228,8 +9208,8 @@ __metadata: qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9250,14 +9230,14 @@ __metadata: "@material-ui/icons": ^4.9.1 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9361,15 +9341,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9391,7 +9371,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/color": ^3.0.1 "@types/d3-force": ^3.0.0 @@ -9402,8 +9382,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9429,15 +9409,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 testing-library__dom: ^7.29.4-beta.1 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9498,7 +9478,7 @@ __metadata: "@react-hookz/web": ^20.0.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 git-url-parse: ^13.0.0 @@ -9506,8 +9486,8 @@ __metadata: photoswipe: ^5.3.7 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9571,16 +9551,15 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@material-ui/styles": ^4.11.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 jss: ~10.10.0 lodash: ^4.17.21 react-helmet: 6.1.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9613,8 +9592,7 @@ __metadata: "@material-ui/styles": ^4.10.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.2.2 "@types/event-source-polyfill": ^1.0.0 @@ -9681,14 +9659,14 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9738,7 +9716,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -9746,8 +9724,8 @@ __metadata: react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9798,14 +9776,14 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9827,7 +9805,7 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -9837,8 +9815,8 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9946,8 +9924,8 @@ __metadata: peerDependencies: "@material-ui/core": ^4.12.2 "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 languageName: unknown linkType: soft @@ -9980,12 +9958,11 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -12304,14 +12281,14 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -16707,22 +16684,6 @@ __metadata: languageName: unknown linkType: soft -"@testing-library/dom@npm:^8.0.0": - version: 8.20.1 - resolution: "@testing-library/dom@npm:8.20.1" - dependencies: - "@babel/code-frame": ^7.10.4 - "@babel/runtime": ^7.12.5 - "@types/aria-query": ^5.0.1 - aria-query: 5.1.3 - chalk: ^4.1.0 - dom-accessibility-api: ^0.5.9 - lz-string: ^1.5.0 - pretty-format: ^27.0.2 - checksum: 06fc8dc67849aadb726cbbad0e7546afdf8923bd39acb64c576d706249bd7d0d05f08e08a31913fb621162e3b9c2bd0dce15964437f030f9fa4476326fdd3007 - languageName: node - linkType: hard - "@testing-library/dom@npm:^9.0.0": version: 9.3.3 resolution: "@testing-library/dom@npm:9.3.3" @@ -16791,17 +16752,17 @@ __metadata: languageName: node linkType: hard -"@testing-library/react@npm:^12.1.3": - version: 12.1.5 - resolution: "@testing-library/react@npm:12.1.5" +"@testing-library/react@npm:^14.0.0": + version: 14.0.0 + resolution: "@testing-library/react@npm:14.0.0" dependencies: "@babel/runtime": ^7.12.5 - "@testing-library/dom": ^8.0.0 - "@types/react-dom": <18.0.0 + "@testing-library/dom": ^9.0.0 + "@types/react-dom": ^18.0.0 peerDependencies: - react: <18.0.0 - react-dom: <18.0.0 - checksum: 4abd0490405e709a7df584a0db604e508a4612398bb1326e8fa32dd9393b15badc826dcf6d2f7525437886d507871f719f127b9860ed69ddd204d1fa834f576a + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 4a54c8f56cc4a39b50803205f84f06280bb76521d6d5d4b3b36651d760c7c7752ef142d857d52aaf4fad4848ed7a8be49afc793a5dda105955d2f8bef24901ac languageName: node linkType: hard @@ -19761,8 +19722,8 @@ __metadata: cross-fetch: ^3.1.5 msw: ^1.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -25355,7 +25316,7 @@ __metadata: "@roadiehq/backstage-plugin-travis-ci": ^2.0.5 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/jquery": ^3.3.34 "@types/react": "*" @@ -25468,7 +25429,7 @@ __metadata: "@roadiehq/backstage-plugin-travis-ci": ^2.0.5 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/jquery": ^3.3.34 "@types/react": "*" @@ -40256,7 +40217,7 @@ __metadata: "@material-ui/icons": ^4.9.1 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^12.1.3 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": "*" "@types/react-dom": "*" From bfee94f0c51c3e86e42bbb6045cc9692940f77b9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Oct 2023 13:40:34 +0200 Subject: [PATCH 114/348] search-react: test fix for RTL 14 Signed-off-by: Patrik Oldsberg --- .../search-react/src/components/SearchBar/SearchBar.test.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx index ce3c285852..d9b29584f8 100644 --- a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx +++ b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx @@ -318,7 +318,7 @@ describe('SearchBar', () => { , ); - const textbox = screen.getByLabelText('Search'); + const textbox = screen.getByLabelText('Search'); let value = 'value'; await user.type(textbox, value); @@ -339,6 +339,8 @@ describe('SearchBar', () => { value = 'new value'; await user.clear(textbox); + await waitFor(() => expect(textbox.value).toBe('')); + // make sure new term is captured await user.type(textbox, value); await waitFor(() => { From 0696ef1a34e454d05618f58e49153727f250eb8b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Oct 2023 13:59:51 +0200 Subject: [PATCH 115/348] replace usages of await act(async () => {}) with waitFor Signed-off-by: Patrik Oldsberg --- .../translation/useTranslationRef.test.tsx | 41 +-- .../StepPrepareCreatePullRequest.test.tsx | 7 +- .../src/hooks/useEntityListProvider.test.tsx | 1 - .../src/hooks/useStarredEntities.test.tsx | 18 +- .../src/hooks/useCustomResources.test.ts | 103 +++--- .../src/hooks/useKubernetesObjects.test.ts | 102 +++--- .../src/hooks/useWebsiteForEntity.test.tsx | 21 +- .../OwnershipCard/useGetEntities.test.ts | 24 +- .../src/hooks/PlaylistListProvider.test.tsx | 12 +- .../components/SearchFilter/hooks.test.tsx | 44 +-- .../src/context/SearchContext.test.tsx | 104 +++--- plugins/techdocs-react/src/context.test.tsx | 30 +- .../TechDocsReaderPage/context.test.tsx | 22 +- .../reader/components/useReaderState.test.tsx | 307 +++++++++--------- 14 files changed, 419 insertions(+), 417 deletions(-) diff --git a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx index dad4740d6c..a7493152de 100644 --- a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx +++ b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx @@ -20,7 +20,7 @@ import { TestApiProvider, withLogCollector, } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { createTranslationRef, TranslationRef } from './TranslationRef'; import { useTranslationRef } from './useTranslationRef'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports @@ -95,12 +95,11 @@ describe('useTranslationRef', () => { wrapper: makeWrapper(translationApi), }); - await act(async () => {}); - - const { t } = result.current; - - expect(t('key1')).toBe('en1'); - expect(t('key2')).toBe('en2'); + await waitFor(() => { + const { t } = result.current; + expect(t('key1')).toBe('en1'); + expect(t('key2')).toBe('en2'); + }); }); it('should switch between languages', async () => { @@ -124,19 +123,21 @@ describe('useTranslationRef', () => { wrapper: makeWrapper(translationApi), }); - const { t } = result.current; + await waitFor(() => { + const { t } = result.current; - expect(t('key1')).toBe('default1'); - expect(t('key2')).toBe('default2'); + expect(t('key1')).toBe('default1'); + expect(t('key2')).toBe('default2'); + }); languageApi.setLanguage('de'); - await act(async () => {}); + await waitFor(() => { + const { t: t2 } = result.current; - const { t: t2 } = result.current; - - expect(t2('key1')).toBe('de1'); - expect(t2('key2')).toBe('de2'); + expect(t2('key1')).toBe('de1'); + expect(t2('key2')).toBe('de2'); + }); }); it('should load default resource', async () => { @@ -163,12 +164,12 @@ describe('useTranslationRef', () => { wrapper: makeWrapper(translationApi), }); - await act(async () => {}); + await waitFor(() => { + const { t } = result.current; - const { t } = result.current; - - expect(t('key1')).toBe('de1'); - expect(t('key2')).toBe('de2'); + expect(t('key1')).toBe('de1'); + expect(t('key2')).toBe('de2'); + }); }); it('should log once and then ignore loading errors', async () => { diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index 45566528bc..079b010ec6 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -18,7 +18,7 @@ import { configApiRef, errorApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { TestApiProvider, MockConfigApi } from '@backstage/test-utils'; import { TextField } from '@material-ui/core'; -import { act, render, screen, waitFor } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { AnalyzeResult, catalogImportApiRef } from '../../api'; @@ -121,8 +121,6 @@ describe('', () => { }, ); - await act(async () => {}); - const title = await screen.findByText('My title'); const description = await screen.findByText('body', { selector: 'strong', @@ -169,7 +167,6 @@ describe('', () => { wrapper: Wrapper, }, ); - await act(async () => {}); await userEvent.type(await screen.findByLabelText('name'), '-changed'); await userEvent.type(await screen.findByLabelText('owner'), '-changed'); @@ -244,7 +241,6 @@ spec: wrapper: Wrapper, }, ); - await act(async () => {}); await userEvent.click( await screen.findByRole('button', { name: /Create PR/i }), @@ -281,7 +277,6 @@ spec: wrapper: Wrapper, }, ); - await act(async () => {}); await waitFor(() => { expect(catalogApi.getEntities).toHaveBeenCalledTimes(1); diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index a3366506f8..d77655ebcc 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -171,7 +171,6 @@ describe('', () => { wrapper: ({ children }) => wrapper({ location: `/catalog?${query}`, children }), }); - await act(async () => {}); await waitFor(() => { expect(result.current.queryParameters).toBeTruthy(); diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx index 6c76e8eb24..e3010a0f4a 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx @@ -60,9 +60,9 @@ describe('useStarredEntities', () => { wrapper, }); - await act(async () => {}); - - expect(result.current.starredEntities.size).toBe(0); + await waitFor(() => { + expect(result.current.starredEntities.size).toBe(0); + }); }); it('should return a set with the current items', async () => { @@ -75,11 +75,11 @@ describe('useStarredEntities', () => { wrapper, }); - await act(async () => {}); - - for (const item of expectedIds) { - expect(result.current.starredEntities.has(item)).toBeTruthy(); - } + await waitFor(() => { + for (const item of expectedIds) { + expect(result.current.starredEntities.has(item)).toBeTruthy(); + } + }); }); it('should listen to changes when the storage is set elsewhere', async () => { @@ -87,8 +87,6 @@ describe('useStarredEntities', () => { wrapper, }); - await act(async () => {}); - expect(result.current.starredEntities.size).toBe(0); expect(result.current.isStarredEntity(mockEntity)).toBeFalsy(); diff --git a/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts b/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts index ace954ec2d..40ab619180 100644 --- a/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts +++ b/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts @@ -16,7 +16,7 @@ import { useCustomResources } from './useCustomResources'; import { Entity } from '@backstage/catalog-model'; -import { act, renderHook, waitFor } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { useApi } from '@backstage/core-plugin-api'; import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; import { generateAuth } from './auth'; @@ -103,11 +103,11 @@ describe('useCustomResources', () => { expect(result.current.loading).toEqual(true); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + }); expectMocksCalledCorrectly(); }); @@ -121,16 +121,13 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - expect(result.current.error).toBeUndefined(); - await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + expectMocksCalledCorrectly(2); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); }); it('should return error when getObjectsByEntity throws', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -143,13 +140,13 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers), ); - await act(async () => {}); + await waitFor(() => { + expect(result.current.error).toBe('some error'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); - expect(result.current.error).toBe('some error'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - expectMocksCalledCorrectly(); + expectMocksCalledCorrectly(); + }); }); describe('when retrying', () => { @@ -166,19 +163,17 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); await waitFor(() => { expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); }); it('should reset error after getCustomObjectsByEntity has failed and then succeeded', async () => { @@ -192,19 +187,17 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); await waitFor(() => { expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); }); it('should reset data after generateAuth succeeded then failed', async () => { @@ -220,19 +213,17 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitFor(() => { - expect(result.current.error).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); it('should reset data after getCustomObjectsByEntity succeeded then failed', async () => { @@ -246,19 +237,17 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitFor(() => { - expect(result.current.error).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); }); }); diff --git a/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts index 9fa642e071..e88432f980 100644 --- a/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts +++ b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts @@ -16,7 +16,7 @@ import { useKubernetesObjects } from './useKubernetesObjects'; import { Entity } from '@backstage/catalog-model'; -import { act, renderHook, waitFor } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { useApi } from '@backstage/core-plugin-api'; import { generateAuth } from './auth'; @@ -92,14 +92,12 @@ describe('useKubernetesObjects', () => { expect(result.current.loading).toEqual(true); await waitFor(() => { + expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + + expectMocksCalledCorrectly(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - - expectMocksCalledCorrectly(); }); it('should update on an interval', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -112,14 +110,12 @@ describe('useKubernetesObjects', () => { expect(result.current.error).toBeUndefined(); await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + expectMocksCalledCorrectly(2); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - - expectMocksCalledCorrectly(2); }); it('should return error when getObjectsByEntity throws', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -130,13 +126,13 @@ describe('useKubernetesObjects', () => { }); const { result } = renderHook(() => useKubernetesObjects(entity)); - await act(async () => {}); + await waitFor(() => { + expect(result.current.error).toBe('some error'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); - expect(result.current.error).toBe('some error'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - expectMocksCalledCorrectly(); + expectMocksCalledCorrectly(); + }); }); describe('when retrying', () => { @@ -151,19 +147,17 @@ describe('useKubernetesObjects', () => { const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await act(async () => {}); - - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); await waitFor(() => { expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); }); it('should reset error after getObjectsByEntity has failed and then succeeded', async () => { @@ -175,19 +169,17 @@ describe('useKubernetesObjects', () => { const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await act(async () => {}); - - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); await waitFor(() => { expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); }); it('should reset data after generateAuth succeeded then failed', async () => { @@ -201,19 +193,17 @@ describe('useKubernetesObjects', () => { const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitFor(() => { - expect(result.current.error).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); it('should reset data after getObjectsByEntity succeeded then failed', async () => { @@ -225,19 +215,17 @@ describe('useKubernetesObjects', () => { const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitFor(() => { - expect(result.current.error).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); }); }); diff --git a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx index 440eb6a6fa..69acd34dc3 100644 --- a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx +++ b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { act, renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { WebsiteListResponse } from '@backstage/plugin-lighthouse-common'; import { lighthouseApiRef } from '../api'; @@ -78,8 +78,9 @@ describe('useWebsiteForEntity', () => { it('returns the lighthouse information for the website url in annotations', async () => { const { result } = subject(); - await act(async () => {}); - expect(result.current?.value).toBe(website); + await waitFor(() => { + expect(result.current?.value).toBe(website); + }); }); describe('where there is an error', () => { @@ -93,9 +94,10 @@ describe('useWebsiteForEntity', () => { it('posts the error to the error api and returns the error to the caller', async () => { const { result } = subject(); - await act(async () => {}); - expect(result.current?.error).toBe(error); - expect(mockErrorApi.post).toHaveBeenCalledWith(error); + await waitFor(() => { + expect(result.current?.error).toBe(error); + expect(mockErrorApi.post).toHaveBeenCalledWith(error); + }); }); }); @@ -110,9 +112,10 @@ describe('useWebsiteForEntity', () => { it('does not post the error to the error api and returns the error to the caller', async () => { const { result } = subject(); - await act(async () => {}); - expect(result.current?.error).toBe(error); - expect(mockErrorApi.post).not.toHaveBeenCalledWith(error); + await waitFor(() => { + expect(result.current?.error).toBe(error); + expect(mockErrorApi.post).not.toHaveBeenCalledWith(error); + }); }); }); }); diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts index cb02f94ac5..eac5a171ba 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts @@ -16,7 +16,7 @@ import { CompoundEntityRef, Entity } from '@backstage/catalog-model'; import { useGetEntities } from './useGetEntities'; import { CatalogApi } from '@backstage/catalog-client'; -import { act, renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { getEntityRelations } from '@backstage/plugin-catalog-react'; const givenParentGroup = 'team.squad1'; @@ -66,11 +66,14 @@ describe('useGetEntities', () => { describe('given aggregated relationsType', () => { const whenHookIsCalledWith = async (_entity: Entity) => { - renderHook(({ entity }) => useGetEntities(entity, 'aggregated'), { - initialProps: { entity: _entity }, - }); + const { result } = renderHook( + ({ entity }) => useGetEntities(entity, 'aggregated'), + { + initialProps: { entity: _entity }, + }, + ); - await act(async () => {}); + await waitFor(() => expect(result.current.loading).toBe(false)); }; beforeEach(() => { @@ -204,11 +207,14 @@ describe('useGetEntities', () => { describe('given direct relationsType', () => { const whenHookIsCalledWith = async (_entity: Entity) => { - renderHook(({ entity }) => useGetEntities(entity, 'direct'), { - initialProps: { entity: _entity }, - }); + const { result } = renderHook( + ({ entity }) => useGetEntities(entity, 'direct'), + { + initialProps: { entity: _entity }, + }, + ); - await act(async () => {}); + await waitFor(() => expect(result.current.loading).toBe(false)); }; it('given group entity should return directly owned entities', async () => { diff --git a/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx b/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx index dda09a0e04..ce0d49802b 100644 --- a/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx +++ b/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx @@ -119,8 +119,8 @@ describe('', () => { }); await waitFor(() => { expect(result.current.backendPlaylists.length).toBe(2); + expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalled(); }); - expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalled(); }); it('resolves frontend filters', async () => { @@ -155,14 +155,12 @@ describe('', () => { wrapper: ({ children }) => wrapper({ location: `/playlist?${query}`, children }), }); - await act(async () => {}); await waitFor(() => { - expect(result.current.queryParameters).toBeTruthy(); - }); - expect(result.current.queryParameters).toEqual({ - personal: 'all', - owners: ['user:default/guest'], + expect(result.current.queryParameters).toEqual({ + personal: 'all', + owners: ['user:default/guest'], + }); }); }); diff --git a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx index 3d61c11b79..884512963f 100644 --- a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { ApiProvider } from '@backstage/core-app-api'; import { MockConfigApi, TestApiRegistry } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { searchApiRef } from '../../api'; import { SearchContextProvider, useSearch } from '../../context'; @@ -77,9 +77,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should set non-empty array value', async () => { @@ -95,9 +95,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set undefined value', async () => { @@ -121,9 +121,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set null value', async () => { @@ -147,9 +147,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set empty string value', async () => { @@ -173,9 +173,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set empty array value', async () => { @@ -199,9 +199,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not affect unrelated filters', async () => { @@ -225,9 +225,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters.unrelatedField).toEqual('unrelatedValue'); + await waitFor(() => { + expect(result.current.filters.unrelatedField).toEqual('unrelatedValue'); + }); }); }); diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index 7ac2d6d11b..5aa217553f 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -89,9 +89,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); - - expect(result.current).toEqual(true); + await waitFor(() => { + expect(result.current).toEqual(true); + }); }); describe('Uses initial state values', () => { @@ -100,17 +100,17 @@ describe('SearchContext', () => { wrapper, }); - await act(async () => {}); - - expect(result.current).toEqual( - expect.objectContaining({ - term: '', - types: [], - filters: {}, - pageLimit: undefined, - pageCursor: undefined, - }), - ); + await waitFor(() => { + expect(result.current).toEqual( + expect.objectContaining({ + term: '', + types: [], + filters: {}, + pageLimit: undefined, + pageCursor: undefined, + }), + ); + }); }); it('Uses provided initial state values', async () => { @@ -118,9 +118,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); - - expect(result.current).toEqual(expect.objectContaining(initialState)); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); }); it('Uses page limit provided via config api', async () => { @@ -139,11 +139,11 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current).toEqual( - expect.objectContaining({ ...initialState, pageLimit: 100 }), - ); + await waitFor(() => { + expect(result.current).toEqual( + expect.objectContaining({ ...initialState, pageLimit: 100 }), + ); + }); }); }); @@ -161,10 +161,10 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current.term).toEqual('first term'); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); + await waitFor(() => { + expect(result.current.term).toEqual('first term'); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); await act(async () => { result.current.setTerm(''); @@ -186,10 +186,10 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current.term).toEqual('first term'); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); + await waitFor(() => { + expect(result.current.term).toEqual('first term'); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); await act(async () => { result.current.setTerm('second term'); @@ -212,10 +212,10 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current.filters).toEqual({ foo: 'bar' }); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); + await waitFor(() => { + expect(result.current.filters).toEqual({ foo: 'bar' }); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); await act(async () => { result.current.setFilters({}); @@ -238,10 +238,10 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current.filters).toEqual({ foo: 'bar' }); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); + await waitFor(() => { + expect(result.current.filters).toEqual({ foo: 'bar' }); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); await act(async () => { result.current.setFilters({ foo: 'test' }); @@ -257,7 +257,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const term = 'term'; @@ -277,7 +279,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const types = ['type']; @@ -297,7 +301,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const filters = { filter: 'filter' }; @@ -317,7 +323,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const pageLimit = 30; @@ -338,7 +346,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const pageCursor = 'SOMEPAGE'; @@ -364,7 +374,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); expect(result.current.fetchNextPage).toBeDefined(); expect(result.current.fetchPreviousPage).toBeUndefined(); @@ -391,7 +403,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); expect(result.current.fetchNextPage).toBeUndefined(); expect(result.current.fetchPreviousPage).toBeDefined(); diff --git a/plugins/techdocs-react/src/context.test.tsx b/plugins/techdocs-react/src/context.test.tsx index e66630b04e..bcab445729 100644 --- a/plugins/techdocs-react/src/context.test.tsx +++ b/plugins/techdocs-react/src/context.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderHook, act } from '@testing-library/react'; +import { renderHook, act, waitFor } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; @@ -140,9 +140,9 @@ describe('useTechDocsReaderPage', () => { namespace: mockEntityMetadata.metadata.namespace?.toLocaleLowerCase(), }; const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); - await act(async () => {}); - - expect(result.current.entityRef).toStrictEqual(lowercaseEntityRef); + await waitFor(() => { + expect(result.current.entityRef).toStrictEqual(lowercaseEntityRef); + }); }); it('entityRef is not modified when legacyUseCaseSensitiveTripletPaths is true', async () => { @@ -159,23 +159,23 @@ describe('useTechDocsReaderPage', () => { config: { techdocs: { legacyUseCaseSensitiveTripletPaths: true } }, }), }); - await act(async () => {}); - - expect(result.current.entityRef).toStrictEqual(caseSensitiveEntityRef); + await waitFor(() => { + expect(result.current.entityRef).toStrictEqual(caseSensitiveEntityRef); + }); }); it('entityRef provided as analytics context', async () => { renderHook(() => useAnalytics().captureEvent('action', 'subject'), { wrapper, }); - await act(async () => {}); - - expect(analyticsApiMock.getEvents()[0]).toMatchObject({ - action: 'action', - subject: 'subject', - context: { - entityRef: 'component:default/test', - }, + await waitFor(() => { + expect(analyticsApiMock.getEvents()[0]).toMatchObject({ + action: 'action', + subject: 'subject', + context: { + entityRef: 'component:default/test', + }, + }); }); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx index 43dabaa7c7..670653ce6b 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { act, renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; @@ -97,11 +97,11 @@ describe('context', () => { it('should return expected entity values', async () => { const { result } = renderHook(() => useEntityMetadata(), { wrapper }); - await act(async () => {}); - - expect(result.current.value).toBeDefined(); - expect(result.current.error).toBeUndefined(); - expect(result.current.value).toMatchObject(mockEntityMetadata); + await waitFor(() => { + expect(result.current.value).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.value).toMatchObject(mockEntityMetadata); + }); }); }); @@ -115,11 +115,11 @@ describe('context', () => { it('should return expected techdocs metadata values', async () => { const { result } = renderHook(() => useTechDocsMetadata(), { wrapper }); - await act(async () => {}); - - expect(result.current.value).toBeDefined(); - expect(result.current.error).toBeUndefined(); - expect(result.current.value).toMatchObject(mockTechDocsMetadata); + await waitFor(() => { + expect(result.current.value).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.value).toMatchObject(mockTechDocsMetadata); + }); }); }); }); diff --git a/plugins/techdocs/src/reader/components/useReaderState.test.tsx b/plugins/techdocs/src/reader/components/useReaderState.test.tsx index d8851a805d..60898ab288 100644 --- a/plugins/techdocs/src/reader/components/useReaderState.test.tsx +++ b/plugins/techdocs/src/reader/components/useReaderState.test.tsx @@ -299,16 +299,16 @@ describe('useReaderState', () => { contentReload: expect.any(Function), }); - await act(async () => {}); - - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( @@ -357,42 +357,45 @@ describe('useReaderState', () => { contentReload: expect.any(Function), }); - await waitFor(() => expect(result.current.state).toBe('INITIAL_BUILD'), { - timeout: 2000, + await waitFor( + () => { + expect(result.current).toEqual({ + state: 'INITIAL_BUILD', + path: '/example', + content: undefined, + contentErrorMessage: 'NotFoundError: Page Not Found', + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); + }, + { + timeout: 2000, + }, + ); + + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); - expect(result.current).toEqual({ - state: 'INITIAL_BUILD', - path: '/example', - content: undefined, - contentErrorMessage: 'NotFoundError: Page Not Found', - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), - }); - - await waitFor(() => expect(result.current.state).toBe('CHECKING')); - - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH')); - - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); @@ -444,43 +447,42 @@ describe('useReaderState', () => { }); // the content is returned but the sync is in progress - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH')); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); }); // the sync takes longer than 1 seconds so the refreshing state starts - await waitFor(() => - expect(result.current.state).toBe('CONTENT_STALE_REFRESHING'), - ); - expect(result.current).toEqual({ - state: 'CONTENT_STALE_REFRESHING', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_STALE_REFRESHING', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); }); // the content is updated but not yet displayed - await waitFor(() => - expect(result.current.state).toBe('CONTENT_STALE_READY'), - ); - expect(result.current).toEqual({ - state: 'CONTENT_STALE_READY', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_STALE_READY', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); }); // reload the content @@ -489,30 +491,35 @@ describe('useReaderState', () => { }); // the new content refresh is triggered - await waitFor(() => expect(result.current.state).toBe('CHECKING')); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); // the new content is loaded - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH'), { - timeout: 2000, - }); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my new content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); + await waitFor( + () => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my new content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + }, + { + timeout: 2000, + }, + ); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( @@ -556,58 +563,63 @@ describe('useReaderState', () => { }); // show the content - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH')); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); // navigate rerender({ path: '/new' }); - await waitFor(() => expect(result.current.state).toBe('CHECKING')); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH'), { - timeout: 2000, - }); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/new', - content: 'my new content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); + await waitFor( + () => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/new', + content: 'my new content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + }, + { + timeout: 2000, + }, + ); // navigate rerender({ path: '/missing' }); - await waitFor(() => - expect(result.current.state).toBe('CONTENT_NOT_FOUND'), - ); - expect(result.current).toEqual({ - state: 'CONTENT_NOT_FOUND', - path: '/missing', - content: undefined, - contentErrorMessage: 'NotFoundError: Some error description', - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_NOT_FOUND', + path: '/missing', + content: undefined, + contentErrorMessage: 'NotFoundError: Some error description', + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( @@ -650,17 +662,16 @@ describe('useReaderState', () => { }); // the content loading threw an error - await waitFor(() => - expect(result.current.state).toBe('CONTENT_NOT_FOUND'), - ); - expect(result.current).toEqual({ - state: 'CONTENT_NOT_FOUND', - path: '/example', - content: undefined, - contentErrorMessage: 'NotFoundError: Some error description', - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_NOT_FOUND', + path: '/example', + content: undefined, + contentErrorMessage: 'NotFoundError: Some error description', + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( From 7e045eb0c3fb72c12a1f717bf6bb4387a62d3491 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Oct 2023 14:21:41 +0200 Subject: [PATCH 116/348] remove act wrapping of userEvent Signed-off-by: Patrik Oldsberg --- .../src/layout/HeaderTabs/HeaderTabs.test.tsx | 3 +-- .../BitriseBuildDetailsDialog.test.tsx | 4 ++-- .../components/ActionsPage/ActionsPage.test.tsx | 11 +++++------ .../DryRunResults/DryRunResultsView.test.tsx | 14 +++++++++----- .../SearchFilter.Autocomplete.test.tsx | 4 ++-- .../reader/components/TechDocsBuildLogs.test.tsx | 3 +-- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx index 0d5f3d5586..f656696f8a 100644 --- a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx +++ b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx @@ -19,7 +19,6 @@ import Badge from '@material-ui/core/Badge'; import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { HeaderTabs } from './HeaderTabs'; -import { act } from 'react-dom/test-utils'; import userEvent from '@testing-library/user-event'; const mockTabs = [ @@ -43,7 +42,7 @@ describe('', () => { 'false', ); - await act(() => userEvent.click(rendered.getByText('Docs'))); + await userEvent.click(rendered.getByText('Docs')); expect(rendered.getByText('Docs').parentElement).toHaveAttribute( 'aria-selected', diff --git a/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx b/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx index e283448b36..65efb9b64f 100644 --- a/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx +++ b/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { act, render } from '@testing-library/react'; +import { render } from '@testing-library/react'; import { BitriseBuildDetailsDialog } from './BitriseBuildDetailsDialog'; import { BitriseBuildResult } from '../../api/bitriseApi.model'; import userEvent from '@testing-library/user-event'; @@ -49,7 +49,7 @@ describe('BitriseArtifactsComponent', () => { expect(rendered.queryByText('VISIBLE')).not.toBeInTheDocument(); - await act(() => userEvent.click(btn)); + await userEvent.click(btn); expect(rendered.getByText('VISIBLE')).toBeInTheDocument(); }); diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx index af2e4dc886..614e3fcff0 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx @@ -23,7 +23,6 @@ import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { ApiProvider } from '@backstage/core-app-api'; import { rootRouteRef } from '../../routes'; import { userEvent } from '@testing-library/user-event'; -import { act } from 'react-dom/test-utils'; const scaffolderApiMock: jest.Mocked = { scaffold: jest.fn(), @@ -263,7 +262,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('nested prop b')).not.toBeInTheDocument(); expect(rendered.queryByText('number')).not.toBeInTheDocument(); - await act(() => userEvent.click(objectChip)); + await userEvent.click(objectChip); expect(rendered.queryByText('nested prop a')).toBeInTheDocument(); expect(rendered.queryByText('string')).toBeInTheDocument(); @@ -325,7 +324,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('nested prop b')).not.toBeInTheDocument(); expect(rendered.queryByText('nested object c')).not.toBeInTheDocument(); - await act(() => userEvent.click(objectChip)); + await userEvent.click(objectChip); expect(rendered.queryByText('nested object a')).toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).toBeInTheDocument(); @@ -333,7 +332,7 @@ describe('TemplatePage', () => { const allObjectChips = rendered.getAllByText('object'); expect(allObjectChips.length).toBe(2); - await act(() => userEvent.click(allObjectChips[1])); + await userEvent.click(allObjectChips[1]); expect(rendered.queryByText('nested object a')).toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).toBeInTheDocument(); @@ -376,7 +375,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('No schema defined')).not.toBeInTheDocument(); - await act(() => userEvent.click(objectChip)); + await userEvent.click(objectChip); expect(rendered.queryByText('No schema defined')).toBeInTheDocument(); }); @@ -473,7 +472,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('nested object a')).not.toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).not.toBeInTheDocument(); - await act(() => userEvent.click(objectChip)); + await userEvent.click(objectChip); expect(rendered.queryByText('nested object a')).toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).toBeInTheDocument(); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx index 36cdbec088..c5c391907e 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx @@ -16,7 +16,7 @@ import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { act, screen } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React, { ReactNode, useEffect } from 'react'; import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; @@ -90,10 +90,14 @@ describe('DryRunResultsView', () => { expect(screen.queryByText('Foo Message')).not.toBeInTheDocument(); expect(screen.queryByText('Foo Link')).not.toBeInTheDocument(); - await act(() => userEvent.click(screen.getByText('Log'))); - expect(screen.getByText('Foo Message')).toBeInTheDocument(); + await userEvent.click(screen.getByText('Log')); + await waitFor(() => { + expect(screen.getByText('Foo Message')).toBeInTheDocument(); + }); - await act(() => userEvent.click(screen.getByText('Output'))); - expect(screen.getByText('Foo Link')).toBeInTheDocument(); + await userEvent.click(screen.getByText('Output')); + await waitFor(() => { + expect(screen.getByText('Foo Link')).toBeInTheDocument(); + }); }); }); diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx index 3bb1140852..abf5e828f6 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx @@ -15,7 +15,7 @@ */ import { MockConfigApi, TestApiProvider } from '@backstage/test-utils'; -import { screen, render, waitFor, within, act } from '@testing-library/react'; +import { screen, render, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; @@ -364,7 +364,7 @@ describe('SearchFilter.Autocomplete', () => { }); // Blur the field and only one tag should be shown with a +1. - await act(() => userEvent.tab()); + await userEvent.tab(); expect( screen.queryByRole('button', { name: values[0] }), ).not.toBeInTheDocument(); diff --git a/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx b/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx index 85253f54ef..34aaf76394 100644 --- a/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx @@ -21,7 +21,6 @@ import { TechDocsBuildLogsDrawerContent, } from './TechDocsBuildLogs'; import { userEvent } from '@testing-library/user-event'; -import { act } from 'react-dom/test-utils'; // The inside needs mocking to render in jsdom jest.mock('react-virtualized-auto-sizer', () => ({ @@ -40,7 +39,7 @@ describe('', () => { it('should open drawer', async () => { const rendered = await renderInTestApp(); - await act(() => userEvent.click(rendered.getByText(/Show Build Logs/i))); + await userEvent.click(rendered.getByText(/Show Build Logs/i)); expect(rendered.getByText(/Build Details/i)).toBeInTheDocument(); }); }); From 1bfb47b8d4deef803c4788adcb0efefe30b78829 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Oct 2023 14:29:26 +0200 Subject: [PATCH 117/348] catalog-react: replace unnecessary rerender it tests Signed-off-by: Patrik Oldsberg --- .../useUnregisterEntityDialogState.test.tsx | 55 +++++++++---------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx index 342fe4758d..f0da550d0b 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx @@ -17,7 +17,7 @@ import { CatalogApi, Location } from '@backstage/catalog-client'; import { Entity, ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model'; import { catalogApiRef } from '../../api'; -import { act, renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import React from 'react'; import { useUnregisterEntityDialogState } from './useUnregisterEntityDialogState'; import { TestApiProvider } from '@backstage/test-utils'; @@ -87,16 +87,14 @@ describe('useUnregisterEntityDialogState', () => { resolveLocation({ type: 'url', target: 'https://example.com', id: 'x' }); resolveColocatedEntities([entity]); - await act(async () => { - await rendered.rerender(); - }); - - expect(rendered.result.current).toEqual({ - type: 'unregister', - location: 'url:https://example.com', - colocatedEntities: [{ kind: 'Component', namespace: 'ns', name: 'n' }], - unregisterLocation: expect.any(Function), - deleteEntity: expect.any(Function), + await waitFor(() => { + expect(rendered.result.current).toEqual({ + type: 'unregister', + location: 'url:https://example.com', + colocatedEntities: [{ kind: 'Component', namespace: 'ns', name: 'n' }], + unregisterLocation: expect.any(Function), + deleteEntity: expect.any(Function), + }); }); }); @@ -110,14 +108,13 @@ describe('useUnregisterEntityDialogState', () => { resolveLocation({ type: 'bootstrap', target: 'bootstrap', id: 'x' }); resolveColocatedEntities([]); - await act(async () => { - await rendered.rerender(); - }); - expect(rendered.result.current).toEqual({ - type: 'bootstrap', - location: 'bootstrap:bootstrap', - deleteEntity: expect.any(Function), + await waitFor(() => { + expect(rendered.result.current).toEqual({ + type: 'bootstrap', + location: 'bootstrap:bootstrap', + deleteEntity: expect.any(Function), + }); }); }); @@ -130,13 +127,12 @@ describe('useUnregisterEntityDialogState', () => { resolveLocation(undefined); resolveColocatedEntities([]); - await act(async () => { - await rendered.rerender(); - }); - expect(rendered.result.current).toEqual({ - type: 'only-delete', - deleteEntity: expect.any(Function), + await waitFor(() => { + expect(rendered.result.current).toEqual({ + type: 'only-delete', + deleteEntity: expect.any(Function), + }); }); }); @@ -147,13 +143,12 @@ describe('useUnregisterEntityDialogState', () => { resolveLocation(undefined); resolveColocatedEntities([]); - await act(async () => { - await rendered.rerender(); - }); - expect(rendered.result.current).toEqual({ - type: 'only-delete', - deleteEntity: expect.any(Function), + await waitFor(() => { + expect(rendered.result.current).toEqual({ + type: 'only-delete', + deleteEntity: expect.any(Function), + }); }); }); }); From bb981cc0ce83308d4f921719446998c804561d0d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 13:09:19 +0200 Subject: [PATCH 118/348] changesets: cleanup changeset for react-dom/client support that was already released Signed-off-by: Patrik Oldsberg --- .changeset/eleven-hounds-invent.md | 5 ----- .changeset/lazy-hotels-wait.md | 1 - 2 files changed, 6 deletions(-) delete mode 100644 .changeset/eleven-hounds-invent.md diff --git a/.changeset/eleven-hounds-invent.md b/.changeset/eleven-hounds-invent.md deleted file mode 100644 index ba863ebc28..0000000000 --- a/.changeset/eleven-hounds-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -In frontend builds and tests `process.env.HAS_REACT_DOM_CLIENT` will now be defined if `react-dom/client` is present, i.e. if using React 18. This allows for conditional imports of `react-dom/client`. diff --git a/.changeset/lazy-hotels-wait.md b/.changeset/lazy-hotels-wait.md index 515e7fb0ed..85879880f5 100644 --- a/.changeset/lazy-hotels-wait.md +++ b/.changeset/lazy-hotels-wait.md @@ -56,7 +56,6 @@ '@backstage/test-utils': patch '@backstage/plugin-azure-sites': patch '@backstage/plugin-firehydrant': patch -'@backstage/dev-utils': patch '@backstage/plugin-cloudbuild': patch '@backstage/plugin-home-react': patch '@backstage/plugin-kubernetes': patch From 3e1d63ba3fda7866e97b24e9dd83d8bcec361d4d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 14:27:06 +0200 Subject: [PATCH 119/348] frontend-plugin-api: remove usage of @testing-library/react-hooks Signed-off-by: Patrik Oldsberg --- packages/frontend-plugin-api/package.json | 1 - packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx | 2 +- yarn.lock | 3 +-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index cf42f04479..baf8cb4575 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -28,7 +28,6 @@ "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^14.0.0", - "@testing-library/react-hooks": "^8.0.1", "history": "^5.3.0" }, "files": [ diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx b/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx index c786cd71fa..dcd56f81a6 100644 --- a/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx +++ b/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React from 'react'; import { MemoryRouter, Router } from 'react-router-dom'; import { createVersionedContextForTesting } from '@backstage/version-bridge'; diff --git a/yarn.lock b/yarn.lock index 8a90f11890..adcd02c577 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4235,7 +4235,6 @@ __metadata: "@backstage/version-bridge": "workspace:^" "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 - "@testing-library/react-hooks": ^8.0.1 "@types/react": ^16.13.1 || ^17.0.0 history: ^5.3.0 lodash: ^4.17.21 @@ -16730,7 +16729,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/react-hooks@npm:^8.0.0, @testing-library/react-hooks@npm:^8.0.1": +"@testing-library/react-hooks@npm:^8.0.0": version: 8.0.1 resolution: "@testing-library/react-hooks@npm:8.0.1" dependencies: From 9a6db6bba2f8b3b0c34228cf01c4d911f09b5fc8 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 17 Oct 2023 14:44:45 +0200 Subject: [PATCH 120/348] feat: create core interop api package Signed-off-by: Camila Belo Co-authored-by: Patrik Oldsberg --- packages/core-compat-api/.eslintrc.js | 1 + packages/core-compat-api/README.md | 12 ++++++++ packages/core-compat-api/package.json | 33 ++++++++++++++++++++++ packages/core-compat-api/src/index.ts | 16 +++++++++++ packages/core-compat-api/src/setupTests.ts | 16 +++++++++++ yarn.lock | 28 +++++++++++++++++- 6 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 packages/core-compat-api/.eslintrc.js create mode 100644 packages/core-compat-api/README.md create mode 100644 packages/core-compat-api/package.json create mode 100644 packages/core-compat-api/src/index.ts create mode 100644 packages/core-compat-api/src/setupTests.ts diff --git a/packages/core-compat-api/.eslintrc.js b/packages/core-compat-api/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/core-compat-api/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/core-compat-api/README.md b/packages/core-compat-api/README.md new file mode 100644 index 0000000000..5faa299f03 --- /dev/null +++ b/packages/core-compat-api/README.md @@ -0,0 +1,12 @@ +# @backstage/core-compat-api + +_This package was created through the Backstage CLI_. + +## Installation + +Install the package via Yarn: + +```sh +cd # if within a monorepo +yarn add @backstage/core-compat-api +``` diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json new file mode 100644 index 0000000000..76c3bc6b4e --- /dev/null +++ b/packages/core-compat-api/package.json @@ -0,0 +1,33 @@ +{ + "name": "@backstage/core-compat-api", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": true, + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "web-library" + }, + "sideEffects": false, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@testing-library/jest-dom": "^5.10.1" + }, + "files": [ + "dist" + ] +} diff --git a/packages/core-compat-api/src/index.ts b/packages/core-compat-api/src/index.ts new file mode 100644 index 0000000000..4b9026cde5 --- /dev/null +++ b/packages/core-compat-api/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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/packages/core-compat-api/src/setupTests.ts b/packages/core-compat-api/src/setupTests.ts new file mode 100644 index 0000000000..865308e634 --- /dev/null +++ b/packages/core-compat-api/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import '@testing-library/jest-dom'; diff --git a/yarn.lock b/yarn.lock index 0fe4bb7768..0d17afeec6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,7 +12,7 @@ __metadata: languageName: node linkType: hard -"@adobe/css-tools@npm:^4.3.1": +"@adobe/css-tools@npm:^4.0.1, @adobe/css-tools@npm:^4.3.1": version: 4.3.1 resolution: "@adobe/css-tools@npm:4.3.1" checksum: ad43456379ff391132aff687ece190cb23ea69395e23c9b96690eeabe2468da89a4aaf266e4f8b6eaab53db3d1064107ce0f63c3a974e864f4a04affc768da3f @@ -3952,6 +3952,15 @@ __metadata: languageName: unknown linkType: soft +"@backstage/core-compat-api@workspace:packages/core-compat-api": + version: 0.0.0-use.local + resolution: "@backstage/core-compat-api@workspace:packages/core-compat-api" + dependencies: + "@backstage/cli": "workspace:^" + "@testing-library/jest-dom": ^5.10.1 + languageName: unknown + linkType: soft + "@backstage/core-components@^0.13.5, @backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" @@ -16700,6 +16709,23 @@ __metadata: languageName: node linkType: hard +"@testing-library/jest-dom@npm:^5.10.1": + version: 5.17.0 + resolution: "@testing-library/jest-dom@npm:5.17.0" + dependencies: + "@adobe/css-tools": ^4.0.1 + "@babel/runtime": ^7.9.2 + "@types/testing-library__jest-dom": ^5.9.1 + aria-query: ^5.0.0 + chalk: ^3.0.0 + css.escape: ^1.5.1 + dom-accessibility-api: ^0.5.6 + lodash: ^4.17.15 + redent: ^3.0.0 + checksum: 9f28dbca8b50d7c306aae40c3aa8e06f0e115f740360004bd87d57f95acf7ab4b4f4122a7399a76dbf2bdaaafb15c99cc137fdcb0ae457a92e2de0f3fbf9b03b + languageName: node + linkType: hard + "@testing-library/jest-dom@npm:^6.0.0": version: 6.1.4 resolution: "@testing-library/jest-dom@npm:6.1.4" From 8462548e8f1c39e44fb06f802127241a3fb6052d Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 17 Oct 2023 14:51:04 +0200 Subject: [PATCH 121/348] feat: move legacy collect routes Signed-off-by: Camila Belo Co-authored-by: Patrik Oldsberg --- packages/core-compat-api/package.json | 14 ++- .../src/collectLegacyRoutes.test.tsx | 65 +++++++++++ .../src/collectLegacyRoutes.tsx | 103 ++++++++++++++++++ yarn.lock | 9 ++ 4 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 packages/core-compat-api/src/collectLegacyRoutes.test.tsx create mode 100644 packages/core-compat-api/src/collectLegacyRoutes.tsx diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json index 76c3bc6b4e..19d3104103 100644 --- a/packages/core-compat-api/package.json +++ b/packages/core-compat-api/package.json @@ -25,9 +25,21 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/plugin-puppetdb": "workspace:^", + "@backstage/plugin-stackstorm": "workspace:^", + "@oriflame/backstage-plugin-score-card": "^0.7.0", "@testing-library/jest-dom": "^5.10.1" }, "files": [ "dist" - ] + ], + "peerDependencies": { + "react": "*", + "react-router-dom": "*" + }, + "dependencies": { + "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^" + } } diff --git a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx new file mode 100644 index 0000000000..530013c283 --- /dev/null +++ b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx @@ -0,0 +1,65 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { FlatRoutes } from '@backstage/core-app-api'; +import { createPageExtension } from '@backstage/frontend-plugin-api'; +import { PuppetDbPage } from '@backstage/plugin-puppetdb'; +import { StackstormPage } from '@backstage/plugin-stackstorm'; +import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card'; +import { Route } from 'react-router-dom'; + +import { getComponentData } from '@backstage/core-plugin-api'; +import { collectLegacyRoutes } from './collectLegacyRoutes'; + +jest.mock('@backstage/frontend-plugin-api', () => ({ + ...jest.requireActual('@backstage/frontend-plugin-api'), + createPageExtension: opts => opts, +})); + +describe('collectLegacyRoutes', () => { + it('should collect legacy routes', () => { + const collected = collectLegacyRoutes( + + } /> + } /> + } /> + , + ); + + expect(collected).toEqual([ + createPageExtension({ + id: 'plugin.score-card.page', + defaultPath: 'score-board', + routeRef: getComponentData(, 'core.mountPoint'), + loader: expect.any(Function), + }), + createPageExtension({ + id: 'plugin.stackstorm.page', + defaultPath: 'stackstorm', + routeRef: getComponentData(, 'core.mountPoint'), + loader: expect.any(Function), + }), + createPageExtension({ + id: 'plugin.puppetDb.page', + defaultPath: 'puppetdb', + routeRef: getComponentData(, 'core.mountPoint'), + loader: expect.any(Function), + }), + // ?????????????? + ]); + }); +}); diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx new file mode 100644 index 0000000000..b40ae78439 --- /dev/null +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -0,0 +1,103 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { ReactNode } from 'react'; +import { Extension, createPageExtension } from '@backstage/frontend-plugin-api'; +import { Route, Routes } from 'react-router-dom'; +import { + BackstagePlugin, + RouteRef, + getComponentData, +} from '@backstage/core-plugin-api'; + +export function collectLegacyRoutes( + flatRoutesElement: JSX.Element, +): Extension[] { + // const results = traverseElementTree({ + // root, + // discoverers: [childDiscoverer, routeElementDiscoverer], + // collectors: { + // foo: createCollector( + // () => new Set(), + // (acc, node) => { + // const plugin = getComponentData(node, 'core.plugin'); + // if (plugin) { + // acc.add(plugin); + // } + // }, + // ) + // }, + // }) + const results = new Array>(); + + React.Children.forEach( + flatRoutesElement.props.children, + (route: ReactNode) => { + if (!React.isValidElement(route)) { + return; + } + + // TODO(freben): Handle feature flag and permissions framework wrapper elements + if (route.type !== Route) { + return; + } + + const routeElement = route.props.element; + + // TODO: to support deeper extension component, e.g. hidden within , use https://github.com/backstage/backstage/blob/518a34646b79ec2028cc0ed6bc67d4366c51c4d6/packages/core-app-api/src/routing/collectors.tsx#L69 + const plugin = getComponentData( + routeElement, + 'core.plugin', + ); + if (!plugin) { + return; + } + + const routeRef = getComponentData( + routeElement, + 'core.mountPoint', + ); + + const pluginId = plugin.getId(); + const path: string = route.props.path; + + const detectedExtension = createPageExtension({ + id: `plugin.${pluginId}.page`, + defaultPath: path[0] === '/' ? path.slice(1) : path, + routeRef, + + loader: async () => + route.props.children ? ( + + + + + + ) : ( + routeElement + ), + }); + + plugin.getApis(); // Create DI API extensions from these + + // TODO: Create converted plugin instance instead. We need to move over APIs etc. + results.push(detectedExtension); + }, + ); + + // TODO: For every legacy plugin that we find, make sure any matching plugin is disabled in the new system + return results; +} diff --git a/yarn.lock b/yarn.lock index 0d17afeec6..1c101630dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3957,7 +3957,16 @@ __metadata: resolution: "@backstage/core-compat-api@workspace:packages/core-compat-api" dependencies: "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" + "@backstage/plugin-puppetdb": "workspace:^" + "@backstage/plugin-stackstorm": "workspace:^" + "@oriflame/backstage-plugin-score-card": ^0.7.0 "@testing-library/jest-dom": ^5.10.1 + peerDependencies: + react: "*" + react-router-dom: "*" languageName: unknown linkType: soft From 4830d0df028a64f2134e563fca2e1eae88fbf9d3 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 17 Oct 2023 15:18:44 +0200 Subject: [PATCH 122/348] feat: use collect legacy routes in app-next Co-authored-by: Patrik Oldsberg Signed-off-by: Patrik Oldsberg --- packages/app-next/package.json | 1 + packages/app-next/src/App.tsx | 37 ++++++++++++++++++- .../src/collectLegacyRoutes.tsx | 17 +++++++-- packages/core-compat-api/src/index.ts | 2 +- yarn.lock | 3 +- 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 635a513c0f..71d888ee50 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -12,6 +12,7 @@ "@backstage/cli": "workspace:^", "@backstage/config": "workspace:^", "@backstage/core-app-api": "workspace:^", + "@backstage/core-compat-api": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/frontend-app-api": "workspace:^", diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index d64c4dbb15..5e9205e2c4 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -27,6 +27,7 @@ import homePlugin, { import { coreExtensionData, createExtension, + createApiExtension, createExtensionOverrides, createPageExtension, } from '@backstage/frontend-plugin-api'; @@ -34,6 +35,16 @@ import { entityRouteRef } from '@backstage/plugin-catalog-react'; import techdocsPlugin from '@backstage/plugin-techdocs/alpha'; import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; import { homePage } from './HomePage'; +import { collectLegacyRoutes } from '@backstage/core-compat-api'; +import { FlatRoutes } from '@backstage/core-app-api'; +import { Route } from 'react-router'; +import { CatalogImportPage } from '@backstage/plugin-catalog-import'; +import { createApiFactory, configApiRef } from '@backstage/core-plugin-api'; +import { + ScmAuth, + ScmIntegrationsApi, + scmIntegrationsApiRef, +} from '@backstage/integration-react'; /* @@ -83,6 +94,24 @@ const homePageExtension = createExtension({ }, }); +const scmAuthExtension = createApiExtension({ + factory: ScmAuth.createDefaultApiFactory(), +}); + +const scmIntegrationApi = createApiExtension({ + factory: createApiFactory({ + api: scmIntegrationsApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi), + }), +}); + +const collectedLegacyRoutes = collectLegacyRoutes( + + } /> + , +); + const app = createApp({ features: [ graphiqlPlugin, @@ -92,7 +121,13 @@ const app = createApp({ userSettingsPlugin, homePlugin, createExtensionOverrides({ - extensions: [entityPageExtension, homePageExtension], + extensions: [ + entityPageExtension, + homePageExtension, + scmAuthExtension, + scmIntegrationApi, + ...collectedLegacyRoutes, + ], }), ], /* Handled through config instead */ diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index b40ae78439..ea235d57a6 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -15,13 +15,18 @@ */ import React, { ReactNode } from 'react'; -import { Extension, createPageExtension } from '@backstage/frontend-plugin-api'; +import { + Extension, + createApiExtension, + createPageExtension, +} from '@backstage/frontend-plugin-api'; import { Route, Routes } from 'react-router-dom'; import { BackstagePlugin, RouteRef, getComponentData, } from '@backstage/core-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; export function collectLegacyRoutes( flatRoutesElement: JSX.Element, @@ -77,7 +82,7 @@ export function collectLegacyRoutes( const detectedExtension = createPageExtension({ id: `plugin.${pluginId}.page`, defaultPath: path[0] === '/' ? path.slice(1) : path, - routeRef, + routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined, loader: async () => route.props.children ? ( @@ -91,7 +96,13 @@ export function collectLegacyRoutes( ), }); - plugin.getApis(); // Create DI API extensions from these + results.push( + ...Array.from(plugin.getApis()).map(factory => + createApiExtension({ + factory, + }), + ), + ); // TODO: Create converted plugin instance instead. We need to move over APIs etc. results.push(detectedExtension); diff --git a/packages/core-compat-api/src/index.ts b/packages/core-compat-api/src/index.ts index 4b9026cde5..2181b2fa9a 100644 --- a/packages/core-compat-api/src/index.ts +++ b/packages/core-compat-api/src/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export {}; +export { collectLegacyRoutes } from './collectLegacyRoutes'; diff --git a/yarn.lock b/yarn.lock index 1c101630dc..f06b7b486d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3952,7 +3952,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-compat-api@workspace:packages/core-compat-api": +"@backstage/core-compat-api@workspace:^, @backstage/core-compat-api@workspace:packages/core-compat-api": version: 0.0.0-use.local resolution: "@backstage/core-compat-api@workspace:packages/core-compat-api" dependencies: @@ -25274,6 +25274,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/core-app-api": "workspace:^" + "@backstage/core-compat-api": "workspace:^" "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/frontend-app-api": "workspace:^" From c5e8be56c3bad51214fdbe8267b2232da29d928a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 15:44:31 +0200 Subject: [PATCH 123/348] core-compat-api: collect into legacy plugin instead of extension + test refactor Co-authored-by: Camila Belo Signed-off-by: Patrik Oldsberg --- packages/app-next/src/App.tsx | 4 +- .../src/collectLegacyRoutes.test.tsx | 88 +++++++++++++------ .../src/collectLegacyRoutes.tsx | 69 +++++++-------- 3 files changed, 94 insertions(+), 67 deletions(-) diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 5e9205e2c4..194c26f193 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -106,7 +106,7 @@ const scmIntegrationApi = createApiExtension({ }), }); -const collectedLegacyRoutes = collectLegacyRoutes( +const collectedLegacyPlugin = collectLegacyRoutes( } /> , @@ -120,13 +120,13 @@ const app = createApp({ techdocsPlugin, userSettingsPlugin, homePlugin, + ...collectedLegacyPlugin, createExtensionOverrides({ extensions: [ entityPageExtension, homePageExtension, scmAuthExtension, scmIntegrationApi, - ...collectedLegacyRoutes, ], }), ], diff --git a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx index 530013c283..486c373991 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx @@ -14,22 +14,15 @@ * limitations under the License. */ -import React from 'react'; import { FlatRoutes } from '@backstage/core-app-api'; -import { createPageExtension } from '@backstage/frontend-plugin-api'; import { PuppetDbPage } from '@backstage/plugin-puppetdb'; import { StackstormPage } from '@backstage/plugin-stackstorm'; import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card'; +import React from 'react'; import { Route } from 'react-router-dom'; -import { getComponentData } from '@backstage/core-plugin-api'; import { collectLegacyRoutes } from './collectLegacyRoutes'; -jest.mock('@backstage/frontend-plugin-api', () => ({ - ...jest.requireActual('@backstage/frontend-plugin-api'), - createPageExtension: opts => opts, -})); - describe('collectLegacyRoutes', () => { it('should collect legacy routes', () => { const collected = collectLegacyRoutes( @@ -40,26 +33,65 @@ describe('collectLegacyRoutes', () => { , ); - expect(collected).toEqual([ - createPageExtension({ - id: 'plugin.score-card.page', - defaultPath: 'score-board', - routeRef: getComponentData(, 'core.mountPoint'), - loader: expect.any(Function), - }), - createPageExtension({ - id: 'plugin.stackstorm.page', - defaultPath: 'stackstorm', - routeRef: getComponentData(, 'core.mountPoint'), - loader: expect.any(Function), - }), - createPageExtension({ - id: 'plugin.puppetDb.page', - defaultPath: 'puppetdb', - routeRef: getComponentData(, 'core.mountPoint'), - loader: expect.any(Function), - }), - // ?????????????? + expect( + collected.map(p => ({ + id: p.id, + extensions: p.extensions.map(e => ({ + id: e.id, + attachTo: e.attachTo, + disabled: e.disabled, + defaultConfig: e.configSchema?.parse({}), + })), + })), + ).toEqual([ + { + id: 'score-card', + extensions: [ + { + id: 'plugin.score-card.page', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'score-board' }, + }, + { + id: 'apis.plugin.scoringdata.service', + attachTo: { id: 'core', input: 'apis' }, + disabled: false, + }, + ], + }, + { + id: 'stackstorm', + extensions: [ + { + id: 'plugin.stackstorm.page', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'stackstorm' }, + }, + { + id: 'apis.plugin.stackstorm.service', + attachTo: { id: 'core', input: 'apis' }, + disabled: false, + }, + ], + }, + { + id: 'puppetDb', + extensions: [ + { + id: 'plugin.puppetDb.page', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'puppetdb' }, + }, + { + id: 'apis.plugin.puppetdb.service', + attachTo: { id: 'core', input: 'apis' }, + disabled: false, + }, + ], + }, ]); }); }); diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index ea235d57a6..e030fecb5a 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -19,10 +19,12 @@ import { Extension, createApiExtension, createPageExtension, + createPlugin, + BackstagePlugin, } from '@backstage/frontend-plugin-api'; import { Route, Routes } from 'react-router-dom'; import { - BackstagePlugin, + BackstagePlugin as LegacyBackstagePlugin, RouteRef, getComponentData, } from '@backstage/core-plugin-api'; @@ -30,23 +32,8 @@ import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; export function collectLegacyRoutes( flatRoutesElement: JSX.Element, -): Extension[] { - // const results = traverseElementTree({ - // root, - // discoverers: [childDiscoverer, routeElementDiscoverer], - // collectors: { - // foo: createCollector( - // () => new Set(), - // (acc, node) => { - // const plugin = getComponentData(node, 'core.plugin'); - // if (plugin) { - // acc.add(plugin); - // } - // }, - // ) - // }, - // }) - const results = new Array>(); +): BackstagePlugin[] { + const results = new Array(); React.Children.forEach( flatRoutesElement.props.children, @@ -63,7 +50,7 @@ export function collectLegacyRoutes( const routeElement = route.props.element; // TODO: to support deeper extension component, e.g. hidden within , use https://github.com/backstage/backstage/blob/518a34646b79ec2028cc0ed6bc67d4366c51c4d6/packages/core-app-api/src/routing/collectors.tsx#L69 - const plugin = getComponentData( + const plugin = getComponentData( routeElement, 'core.plugin', ); @@ -79,24 +66,28 @@ export function collectLegacyRoutes( const pluginId = plugin.getId(); const path: string = route.props.path; - const detectedExtension = createPageExtension({ - id: `plugin.${pluginId}.page`, - defaultPath: path[0] === '/' ? path.slice(1) : path, - routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined, + const detectedExtensions = new Array>(); - loader: async () => - route.props.children ? ( - - - - - - ) : ( - routeElement - ), - }); + detectedExtensions.push( + createPageExtension({ + id: `plugin.${pluginId}.page`, + defaultPath: path[0] === '/' ? path.slice(1) : path, + routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined, - results.push( + loader: async () => + route.props.children ? ( + + + + + + ) : ( + routeElement + ), + }), + ); + + detectedExtensions.push( ...Array.from(plugin.getApis()).map(factory => createApiExtension({ factory, @@ -104,8 +95,12 @@ export function collectLegacyRoutes( ), ); - // TODO: Create converted plugin instance instead. We need to move over APIs etc. - results.push(detectedExtension); + results.push( + createPlugin({ + id: plugin.getId(), + extensions: detectedExtensions, + }), + ); }, ); From 685a4c8901bd2fc7867d06232b41b4732419f1ca Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 16:44:39 +0200 Subject: [PATCH 124/348] frontend-app-api: remove plugin duplicates Co-authored-by: Camila Belo Signed-off-by: Patrik Oldsberg --- .changeset/rude-tomatoes-itch.md | 5 +++ .../src/collectLegacyRoutes.tsx | 1 - .../frontend-app-api/src/wiring/createApp.tsx | 35 +++++++++++++++---- 3 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 .changeset/rude-tomatoes-itch.md diff --git a/.changeset/rude-tomatoes-itch.md b/.changeset/rude-tomatoes-itch.md new file mode 100644 index 0000000000..1071f65756 --- /dev/null +++ b/.changeset/rude-tomatoes-itch.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Installed features are now deduplicated both by reference and ID when available. Features passed to `createApp` now override both discovered and loaded features. diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index e030fecb5a..785e562624 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -104,6 +104,5 @@ export function collectLegacyRoutes( }, ); - // TODO: For every legacy plugin that we find, make sure any matching plugin is disabled in the new system return results; } diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index 87b2042d34..8b411ac38b 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -267,6 +267,29 @@ export function createInstances(options: { return { coreInstance, instances }; } +function deduplicateFeatures( + allFeatures: (BackstagePlugin | ExtensionOverrides)[], +): (BackstagePlugin | ExtensionOverrides)[] { + // Start by removing duplicates by reference + const features = Array.from(new Set(allFeatures)); + + // Plugins are deduplicated by ID, last one wins + const seenIds = new Set(); + return features + .reverse() + .filter(feature => { + if (feature.$$type !== '@backstage/BackstagePlugin') { + return true; + } + if (seenIds.has(feature.id)) { + return false; + } + seenIds.add(feature.id); + return true; + }) + .reverse(); +} + /** @public */ export function createApp(options: { features?: (BackstagePlugin | ExtensionOverrides)[]; @@ -287,13 +310,11 @@ export function createApp(options: { const discoveredFeatures = getAvailableFeatures(config); const loadedFeatures = (await options.featureLoader?.({ config })) ?? []; - const allFeatures = Array.from( - new Set([ - ...discoveredFeatures, - ...(options.features ?? []), - ...loadedFeatures, - ]), - ); + const allFeatures = deduplicateFeatures([ + ...discoveredFeatures, + ...loadedFeatures, + ...(options.features ?? []), + ]); const { coreInstance } = createInstances({ features: allFeatures, From dca88645f6dd9a914a1659ca31a362d970859afb Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 17:06:42 +0200 Subject: [PATCH 125/348] core-compat-api: add notes on way forward with legacy compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Camila Belo Signed-off-by: Patrik Oldsberg --- .../src/collectLegacyRoutes.tsx | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index 785e562624..6de59fa214 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -30,6 +30,34 @@ import { } from '@backstage/core-plugin-api'; import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +/* + +# Legacy interoperability + +Use-cases (prioritized): + 1. Slowly migrate over an existing app to DI, piece by piece + 2. Use a legacy plugin in a new DI app + 3. Use DI in an existing legacy app + +Starting point: use-case #1 + +Potential solutions: + 1. Codemods (we're not considering this for now) + 2. Legacy apps are migrated bottom-up, i.e. keep legacy root, replace pages with DI + 3. Legacy apps are migrated top-down i.e. switch out base to DI, legacy adapter allows for usage of existing app structure + +Chosen path: #3 + +Existing tasks: + - Adopters can migrate their existing app gradually (~4) + - Example-app uses legacy base with DI adapters + - Create an API that lets you inject DI into existing apps - working assumption is that this is enough + - Adopters can use legacy plugins in DI through adapters (~8) + - App-next uses DI base with legacy adapters + - Create a legacy adapter that is able to take an existing extension tree + +*/ + export function collectLegacyRoutes( flatRoutesElement: JSX.Element, ): BackstagePlugin[] { From ba0a665840f0257a0b6090ca72dcbbfb55f842aa Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 17:53:48 +0200 Subject: [PATCH 126/348] core-compat-api: add API report + fix Signed-off-by: Patrik Oldsberg --- packages/core-compat-api/api-report.md | 16 ++++++++++++++++ .../core-compat-api/src/collectLegacyRoutes.tsx | 1 + 2 files changed, 17 insertions(+) create mode 100644 packages/core-compat-api/api-report.md diff --git a/packages/core-compat-api/api-report.md b/packages/core-compat-api/api-report.md new file mode 100644 index 0000000000..5175c76ac8 --- /dev/null +++ b/packages/core-compat-api/api-report.md @@ -0,0 +1,16 @@ +## API Report File for "@backstage/core-compat-api" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; + +// @public (undocumented) +export function collectLegacyRoutes( + flatRoutesElement: JSX.Element, +): BackstagePlugin[]; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index 6de59fa214..2b149e6285 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -58,6 +58,7 @@ Existing tasks: */ +/** @public */ export function collectLegacyRoutes( flatRoutesElement: JSX.Element, ): BackstagePlugin[] { From f2cb14651e09abd574c05832e033731fca9e9963 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 18 Oct 2023 09:26:15 +0200 Subject: [PATCH 127/348] test(frontend-app-api): cover features deduplication Signed-off-by: Camila Belo --- .../src/wiring/createApp.test.tsx | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/frontend-app-api/src/wiring/createApp.test.tsx b/packages/frontend-app-api/src/wiring/createApp.test.tsx index 0f2a6d38ce..de574bc6a9 100644 --- a/packages/frontend-app-api/src/wiring/createApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.test.tsx @@ -23,7 +23,7 @@ import { createThemeExtension, } from '@backstage/frontend-plugin-api'; import { createApp, createInstances } from './createApp'; -import { screen } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { MockConfigApi, renderWithEffects } from '@backstage/test-utils'; import React from 'react'; @@ -244,4 +244,42 @@ describe('createApp', () => { } `); }); + + it('should deduplicate features keeping the last received one', async () => { + const duplicatedFeatureId = 'test'; + const app = createApp({ + configLoader: async () => new MockConfigApi({}), + features: [ + createPlugin({ + id: duplicatedFeatureId, + extensions: [ + createPageExtension({ + id: 'test.page.first', + defaultPath: '/', + loader: async () =>

First Page
, + }), + ], + }), + createPlugin({ + id: duplicatedFeatureId, + extensions: [ + createPageExtension({ + id: 'test.page.last', + defaultPath: '/', + loader: async () =>
Last Page
, + }), + ], + }), + ], + }); + + await renderWithEffects(app.createRoot()); + + await waitFor(() => + expect(screen.queryByText('First Page')).not.toBeInTheDocument(), + ); + await waitFor(() => + expect(screen.getByText('Last Page')).toBeInTheDocument(), + ); + }); }); From 0ea8e5d0351620a6b423c207d3e8d7a2841a73b2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 10:04:41 +0200 Subject: [PATCH 128/348] core-compat-api: add missing catalog info Signed-off-by: Patrik Oldsberg --- packages/core-compat-api/catalog-info.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 packages/core-compat-api/catalog-info.yaml diff --git a/packages/core-compat-api/catalog-info.yaml b/packages/core-compat-api/catalog-info.yaml new file mode 100644 index 0000000000..f20f0543a0 --- /dev/null +++ b/packages/core-compat-api/catalog-info.yaml @@ -0,0 +1,9 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-core-compat-api + title: '@backstage/core-compat-api' +spec: + lifecycle: experimental + type: backstage-web-library + owner: maintainers From 514310a76ca9b17ece365febff0c34fd1773b81b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 12:18:31 +0200 Subject: [PATCH 129/348] app-next: naming tweak Signed-off-by: Patrik Oldsberg --- packages/app-next/src/App.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 194c26f193..4e42d9b268 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -106,7 +106,7 @@ const scmIntegrationApi = createApiExtension({ }), }); -const collectedLegacyPlugin = collectLegacyRoutes( +const collectedLegacyPlugins = collectLegacyRoutes( } /> , @@ -120,7 +120,7 @@ const app = createApp({ techdocsPlugin, userSettingsPlugin, homePlugin, - ...collectedLegacyPlugin, + ...collectedLegacyPlugins, createExtensionOverrides({ extensions: [ entityPageExtension, From 4e696ee7eb972f5821b105ea31aeadaa2e3034f6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 12:20:44 +0200 Subject: [PATCH 130/348] core-compat-api: fix dependencies Signed-off-by: Patrik Oldsberg --- packages/core-compat-api/package.json | 6 +++--- yarn.lock | 25 ++++--------------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json index 19d3104103..d27049c2a4 100644 --- a/packages/core-compat-api/package.json +++ b/packages/core-compat-api/package.json @@ -29,14 +29,14 @@ "@backstage/plugin-puppetdb": "workspace:^", "@backstage/plugin-stackstorm": "workspace:^", "@oriflame/backstage-plugin-score-card": "^0.7.0", - "@testing-library/jest-dom": "^5.10.1" + "@testing-library/jest-dom": "^6.0.0" }, "files": [ "dist" ], "peerDependencies": { - "react": "*", - "react-router-dom": "*" + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "dependencies": { "@backstage/core-plugin-api": "workspace:^", diff --git a/yarn.lock b/yarn.lock index f06b7b486d..636d159dd3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,7 +12,7 @@ __metadata: languageName: node linkType: hard -"@adobe/css-tools@npm:^4.0.1, @adobe/css-tools@npm:^4.3.1": +"@adobe/css-tools@npm:^4.3.1": version: 4.3.1 resolution: "@adobe/css-tools@npm:4.3.1" checksum: ad43456379ff391132aff687ece190cb23ea69395e23c9b96690eeabe2468da89a4aaf266e4f8b6eaab53db3d1064107ce0f63c3a974e864f4a04affc768da3f @@ -3963,10 +3963,10 @@ __metadata: "@backstage/plugin-puppetdb": "workspace:^" "@backstage/plugin-stackstorm": "workspace:^" "@oriflame/backstage-plugin-score-card": ^0.7.0 - "@testing-library/jest-dom": ^5.10.1 + "@testing-library/jest-dom": ^6.0.0 peerDependencies: - react: "*" - react-router-dom: "*" + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -16718,23 +16718,6 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:^5.10.1": - version: 5.17.0 - resolution: "@testing-library/jest-dom@npm:5.17.0" - dependencies: - "@adobe/css-tools": ^4.0.1 - "@babel/runtime": ^7.9.2 - "@types/testing-library__jest-dom": ^5.9.1 - aria-query: ^5.0.0 - chalk: ^3.0.0 - css.escape: ^1.5.1 - dom-accessibility-api: ^0.5.6 - lodash: ^4.17.15 - redent: ^3.0.0 - checksum: 9f28dbca8b50d7c306aae40c3aa8e06f0e115f740360004bd87d57f95acf7ab4b4f4122a7399a76dbf2bdaaafb15c99cc137fdcb0ae457a92e2de0f3fbf9b03b - languageName: node - linkType: hard - "@testing-library/jest-dom@npm:^6.0.0": version: 6.1.4 resolution: "@testing-library/jest-dom@npm:6.1.4" From 1776e7be25f624a366c390bd939f54cc4fec7d4d Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 5 Oct 2023 15:34:12 +0200 Subject: [PATCH 131/348] feat(frontend-app-api): add default translation api impl Signed-off-by: Camila Belo --- .../frontend-app-api/src/wiring/createApp.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index 8b411ac38b..e770a6b4c1 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -492,6 +492,21 @@ function createApiHolder( factory: () => AppThemeSelector.createWithStorage(themeExtensions), }); + factoryRegistry.register('static', { + api: appLanguageApiRef, + deps: {}, + factory: () => AppLanguageSelector.createWithStorage(), + }); + + factoryRegistry.register('default', { + api: translationApiRef, + deps: { languageApi: appLanguageApiRef }, + factory: ({ languageApi }) => + I18nextTranslationApi.create({ + languageApi, + }), + }); + factoryRegistry.register('static', { api: configApiRef, deps: {}, From e6c9103935b092de3afe9046d8d92406e63594b4 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 4 Oct 2023 10:11:29 +0200 Subject: [PATCH 132/348] feat(catalog): create index page and sidebar item Signed-off-by: Camila Belo --- plugins/catalog/src/alpha.tsx | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index 5e78a52f9b..e34830f21d 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -14,6 +14,8 @@ * limitations under the License. */ +import React from 'react'; +import HomeIcon from '@material-ui/icons/Home'; import { createApiFactory, discoveryApiRef, @@ -22,8 +24,11 @@ import { } from '@backstage/core-plugin-api'; import { CatalogClient } from '@backstage/catalog-client'; import { + createSchemaFromZod, createApiExtension, + createPageExtension, createPlugin, + createNavItemExtension, } from '@backstage/frontend-plugin-api'; import { catalogApiRef, @@ -31,6 +36,7 @@ import { } from '@backstage/plugin-catalog-react'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; import { DefaultStarredEntitiesApi } from './apis'; +import { rootRouteRef } from './routes'; /** @alpha */ export const CatalogApi = createApiExtension({ @@ -65,6 +71,41 @@ export const CatalogSearchResultListItemExtension = ), }); +/** @alpha */ +export const CatalogIndexPage = createPageExtension({ + id: 'catalog', + routeRef: rootRouteRef, + configSchema: createSchemaFromZod(z => + z.object({ + path: z.string().default('/catalog'), + initialKind: z.string().default('component'), + initiallySelectedFilter: z + .enum(['owned', 'starred', 'all']) + .default('owned'), + ownerPickerMode: z.enum(['owners-only', 'all']).optional(), + }), + ), + loader: async ({ config }) => { + const { CatalogPage } = await import('./components/CatalogPage'); + const { ownerPickerMode, initialKind, initiallySelectedFilter } = config; + + return ( + + ); + }, +}); + +const CatalogNavItem = createNavItemExtension({ + id: 'catalog.nav.index', + routeRef: rootRouteRef, + title: 'Catalog', + icon: HomeIcon, +}); + /** @alpha */ export default createPlugin({ id: 'catalog', @@ -72,5 +113,7 @@ export default createPlugin({ CatalogApi, StarredEntitiesApi, CatalogSearchResultListItemExtension, + CatalogNavItem, + CatalogIndexPage, ], }); From 5dc00a5d8890d6504600e8556d1c6dd602fabaa3 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 5 Oct 2023 15:08:24 +0200 Subject: [PATCH 133/348] feat(catalog): create index page filters Signed-off-by: Camila Belo --- plugins/catalog/src/alpha.tsx | 202 ++++++++++++++++-- .../CatalogPage/DefaultCatalogPage.tsx | 22 +- 2 files changed, 197 insertions(+), 27 deletions(-) diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index e34830f21d..86ff0a1846 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -29,14 +29,24 @@ import { createPageExtension, createPlugin, createNavItemExtension, + createExtension, + coreExtensionData, + AnyExtensionInputMap, + PortableSchema, + ExtensionBoundary, + createExtensionInput, } from '@backstage/frontend-plugin-api'; import { + AsyncEntityProvider, catalogApiRef, + entityRouteRef, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; import { DefaultStarredEntitiesApi } from './apis'; import { rootRouteRef } from './routes'; +import { Progress } from '@backstage/core-components'; +import { useEntityFromUrl } from './components/CatalogEntityPage/useEntityFromUrl'; /** @alpha */ export const CatalogApi = createApiExtension({ @@ -72,30 +82,175 @@ export const CatalogSearchResultListItemExtension = }); /** @alpha */ -export const CatalogIndexPage = createPageExtension({ - id: 'catalog', - routeRef: rootRouteRef, +export function createCatalogFilterExtension< + TInputs extends AnyExtensionInputMap, + TConfig = never, +>(options: { + id: string; + inputs?: TInputs; + configSchema?: PortableSchema; + loader: (options: { config: TConfig }) => Promise; +}) { + return createExtension({ + id: `catalog.filter.${options.id}`, + attachTo: { id: 'catalog', input: 'filters' }, + inputs: options.inputs ?? {}, + configSchema: options.configSchema, + output: { + element: coreExtensionData.reactElement, + }, + factory({ bind, config, source }) { + const LazyComponent = React.lazy(() => + options + .loader({ config }) + .then(element => ({ default: () => element })), + ); + + bind({ + element: ( + + }> + + + + ), + }); + }, + }); +} + +/** @alpha */ +export const CatalogEntityTagFilter = createCatalogFilterExtension({ + id: 'entity.tag', + loader: async () => { + const { EntityTagPicker } = await import('@backstage/plugin-catalog-react'); + return ; + }, +}); + +/** @alpha */ +export const CatalogEntityKindFilter = createCatalogFilterExtension({ + id: 'entity.kind', configSchema: createSchemaFromZod(z => z.object({ - path: z.string().default('/catalog'), - initialKind: z.string().default('component'), - initiallySelectedFilter: z - .enum(['owned', 'starred', 'all']) - .default('owned'), - ownerPickerMode: z.enum(['owners-only', 'all']).optional(), + initialFilter: z.string().default('component'), }), ), loader: async ({ config }) => { - const { CatalogPage } = await import('./components/CatalogPage'); - const { ownerPickerMode, initialKind, initiallySelectedFilter } = config; - - return ( - + const { EntityKindPicker } = await import( + '@backstage/plugin-catalog-react' ); + return ; + }, +}); + +/** @alpha */ +export const CatalogEntityTypeFilter = createCatalogFilterExtension({ + id: 'entity.type', + loader: async () => { + const { EntityTypePicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +/** @alpha */ +export const CatalogEntityOwnerFilter = createCatalogFilterExtension({ + id: 'entity.mode', + configSchema: createSchemaFromZod(z => + z.object({ + mode: z.enum(['owners-only', 'all']).optional(), + }), + ), + loader: async ({ config }) => { + const { EntityOwnerPicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +/** @alpha */ +export const CatalogEntityNamespaceFilter = createCatalogFilterExtension({ + id: 'entity.namespace', + loader: async () => { + const { EntityNamespacePicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +/** @alpha */ +export const CatalogEntityLifecycleFilter = createCatalogFilterExtension({ + id: 'entity.lifecycle', + loader: async () => { + const { EntityLifecyclePicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +/** @alpha */ +export const CatalogEntityProcessingStatusFilter = createCatalogFilterExtension( + { + id: 'entity.processing.status', + loader: async () => { + const { EntityProcessingStatusPicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, + }, +); + +/** @alpha */ +export const CatalogUserListFilter = createCatalogFilterExtension({ + id: 'user.list', + configSchema: createSchemaFromZod(z => + z.object({ + initialFilter: z.enum(['owned', 'starred', 'all']).default('owned'), + }), + ), + loader: async ({ config }) => { + const { UserListPicker } = await import('@backstage/plugin-catalog-react'); + return ; + }, +}); + +/** @alpha */ +export const CatalogIndexPage = createPageExtension({ + id: 'catalog', + defaultPath: '/catalog', + routeRef: rootRouteRef, + inputs: { + filters: createExtensionInput({ + element: coreExtensionData.reactElement, + }), + }, + loader: async ({ inputs }) => { + const { DefaultCatalogPage } = await import('./components/CatalogPage'); + const filters = inputs.filters.map(filter => filter.element); + return ; + }, +}); + +/** @alpha */ +export const CatalogEntityPage = createPageExtension({ + id: 'catalog:entity', + defaultPath: '/catalog/:namespace/:kind/:name', + routeRef: entityRouteRef, + loader: async () => { + const Component = () => { + return ( + +
🚧 Work In Progress
+
+ ); + }; + return ; }, }); @@ -113,7 +268,16 @@ export default createPlugin({ CatalogApi, StarredEntitiesApi, CatalogSearchResultListItemExtension, - CatalogNavItem, + CatalogEntityKindFilter, + CatalogEntityTypeFilter, + CatalogUserListFilter, + CatalogEntityOwnerFilter, + CatalogEntityLifecycleFilter, + CatalogEntityTagFilter, + CatalogEntityProcessingStatusFilter, + CatalogEntityNamespaceFilter, CatalogIndexPage, + CatalogEntityPage, + CatalogNavItem, ], }); diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx index fb9b282d57..7d75ce4b1d 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx @@ -57,6 +57,7 @@ export interface DefaultCatalogPageProps { tableOptions?: TableProps['options']; emptyContent?: ReactNode; ownerPickerMode?: EntityOwnerPickerProps['mode']; + filters?: ReactNode; } export function DefaultCatalogPage(props: DefaultCatalogPageProps) { @@ -68,6 +69,7 @@ export function DefaultCatalogPage(props: DefaultCatalogPageProps) { tableOptions = {}, emptyContent, ownerPickerMode, + filters, } = props; const orgName = useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; @@ -87,14 +89,18 @@ export function DefaultCatalogPage(props: DefaultCatalogPageProps) { - - - - - - - - + {filters ?? ( + <> + + + + + + + + + + )} Date: Thu, 5 Oct 2023 16:08:04 +0200 Subject: [PATCH 134/348] chore: add changeset files Signed-off-by: Camila Belo --- .changeset/new-beers-drive.md | 7 +++++++ .changeset/sharp-falcons-clean.md | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 .changeset/new-beers-drive.md create mode 100644 .changeset/sharp-falcons-clean.md diff --git a/.changeset/new-beers-drive.md b/.changeset/new-beers-drive.md new file mode 100644 index 0000000000..370734b7c5 --- /dev/null +++ b/.changeset/new-beers-drive.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Create declarative extensions for the `Catalog` plugin; this initial plugin preset contains sidebar item, index page and filter extensions, all distributed via `/alpha` subpath. + +The `EntityPage` will be migrated in a follow-up patch. diff --git a/.changeset/sharp-falcons-clean.md b/.changeset/sharp-falcons-clean.md new file mode 100644 index 0000000000..bc247be451 --- /dev/null +++ b/.changeset/sharp-falcons-clean.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Register default implementation for the `Translation API` on the new `createApp`. From a4444632f0919c18e4e33bca26259e6f77d5c313 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 18 Oct 2023 12:06:24 +0200 Subject: [PATCH 135/348] refactor(catalog): create base catalog page component Signed-off-by: Camila Belo --- plugins/catalog/src/alpha.tsx | 4 +- .../CatalogPage/DefaultCatalogPage.tsx | 108 ++++++++++-------- .../src/components/CatalogPage/index.ts | 7 +- 3 files changed, 68 insertions(+), 51 deletions(-) diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index 86ff0a1846..3cc34b5c96 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -231,9 +231,9 @@ export const CatalogIndexPage = createPageExtension({ }), }, loader: async ({ inputs }) => { - const { DefaultCatalogPage } = await import('./components/CatalogPage'); + const { BaseCatalogPage } = await import('./components/CatalogPage'); const filters = inputs.filters.map(filter => filter.element); - return ; + return {filters}} />; }, }); diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx index 7d75ce4b1d..e50c69b8ec 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx @@ -44,33 +44,15 @@ import { CatalogTable, CatalogTableRow } from '../CatalogTable'; import { catalogTranslationRef } from '../../translation'; import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; -/** - * Props for root catalog pages. - * - * @public - */ -export interface DefaultCatalogPageProps { - initiallySelectedFilter?: UserListFilterKind; - columns?: TableColumn[]; - actions?: TableProps['actions']; - initialKind?: string; - tableOptions?: TableProps['options']; - emptyContent?: ReactNode; - ownerPickerMode?: EntityOwnerPickerProps['mode']; - filters?: ReactNode; +/** @internal */ +export interface BaseCatalogPageProps { + filters: ReactNode; + content?: ReactNode; } -export function DefaultCatalogPage(props: DefaultCatalogPageProps) { - const { - columns, - actions, - initiallySelectedFilter = 'owned', - initialKind = 'component', - tableOptions = {}, - emptyContent, - ownerPickerMode, - filters, - } = props; +/** @internal */ +export function BaseCatalogPage(props: BaseCatalogPageProps) { + const { filters, content = } = props; const orgName = useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; const createComponentLink = useRouteRef(createComponentRouteRef); @@ -88,31 +70,63 @@ export function DefaultCatalogPage(props: DefaultCatalogPageProps) { - - {filters ?? ( - <> - - - - - - - - - - )} - - - - + {filters} + {content} ); } + +/** + * Props for root catalog pages. + * + * @public + */ +export interface DefaultCatalogPageProps { + initiallySelectedFilter?: UserListFilterKind; + columns?: TableColumn[]; + actions?: TableProps['actions']; + initialKind?: string; + tableOptions?: TableProps['options']; + emptyContent?: ReactNode; + ownerPickerMode?: EntityOwnerPickerProps['mode']; +} + +export function DefaultCatalogPage(props: DefaultCatalogPageProps) { + const { + columns, + actions, + initiallySelectedFilter = 'owned', + initialKind = 'component', + tableOptions = {}, + emptyContent, + ownerPickerMode, + } = props; + + return ( + + + + + + + + + + + } + content={ + + } + /> + ); +} diff --git a/plugins/catalog/src/components/CatalogPage/index.ts b/plugins/catalog/src/components/CatalogPage/index.ts index 9a3d083f41..258fedf15c 100644 --- a/plugins/catalog/src/components/CatalogPage/index.ts +++ b/plugins/catalog/src/components/CatalogPage/index.ts @@ -15,5 +15,8 @@ */ export { CatalogPage } from './CatalogPage'; -export { DefaultCatalogPage } from './DefaultCatalogPage'; -export type { DefaultCatalogPageProps } from './DefaultCatalogPage'; +export { BaseCatalogPage, DefaultCatalogPage } from './DefaultCatalogPage'; +export type { + BaseCatalogPageProps, + DefaultCatalogPageProps, +} from './DefaultCatalogPage'; From 0194963f0f0d96188a69ff81d74e9a9aef2f863e Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 18 Oct 2023 12:07:15 +0200 Subject: [PATCH 136/348] refactor(catalog): remove extensions exports Signed-off-by: Camila Belo --- plugins/catalog/src/alpha.tsx | 46 +++++++++++++---------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index 3cc34b5c96..0a6a093b7a 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -119,8 +119,7 @@ export function createCatalogFilterExtension< }); } -/** @alpha */ -export const CatalogEntityTagFilter = createCatalogFilterExtension({ +const CatalogEntityTagFilter = createCatalogFilterExtension({ id: 'entity.tag', loader: async () => { const { EntityTagPicker } = await import('@backstage/plugin-catalog-react'); @@ -128,8 +127,7 @@ export const CatalogEntityTagFilter = createCatalogFilterExtension({ }, }); -/** @alpha */ -export const CatalogEntityKindFilter = createCatalogFilterExtension({ +const CatalogEntityKindFilter = createCatalogFilterExtension({ id: 'entity.kind', configSchema: createSchemaFromZod(z => z.object({ @@ -144,8 +142,7 @@ export const CatalogEntityKindFilter = createCatalogFilterExtension({ }, }); -/** @alpha */ -export const CatalogEntityTypeFilter = createCatalogFilterExtension({ +const CatalogEntityTypeFilter = createCatalogFilterExtension({ id: 'entity.type', loader: async () => { const { EntityTypePicker } = await import( @@ -155,8 +152,7 @@ export const CatalogEntityTypeFilter = createCatalogFilterExtension({ }, }); -/** @alpha */ -export const CatalogEntityOwnerFilter = createCatalogFilterExtension({ +const CatalogEntityOwnerFilter = createCatalogFilterExtension({ id: 'entity.mode', configSchema: createSchemaFromZod(z => z.object({ @@ -171,8 +167,7 @@ export const CatalogEntityOwnerFilter = createCatalogFilterExtension({ }, }); -/** @alpha */ -export const CatalogEntityNamespaceFilter = createCatalogFilterExtension({ +const CatalogEntityNamespaceFilter = createCatalogFilterExtension({ id: 'entity.namespace', loader: async () => { const { EntityNamespacePicker } = await import( @@ -182,8 +177,7 @@ export const CatalogEntityNamespaceFilter = createCatalogFilterExtension({ }, }); -/** @alpha */ -export const CatalogEntityLifecycleFilter = createCatalogFilterExtension({ +const CatalogEntityLifecycleFilter = createCatalogFilterExtension({ id: 'entity.lifecycle', loader: async () => { const { EntityLifecyclePicker } = await import( @@ -193,21 +187,17 @@ export const CatalogEntityLifecycleFilter = createCatalogFilterExtension({ }, }); -/** @alpha */ -export const CatalogEntityProcessingStatusFilter = createCatalogFilterExtension( - { - id: 'entity.processing.status', - loader: async () => { - const { EntityProcessingStatusPicker } = await import( - '@backstage/plugin-catalog-react' - ); - return ; - }, +const CatalogEntityProcessingStatusFilter = createCatalogFilterExtension({ + id: 'entity.processing.status', + loader: async () => { + const { EntityProcessingStatusPicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; }, -); +}); -/** @alpha */ -export const CatalogUserListFilter = createCatalogFilterExtension({ +const CatalogUserListFilter = createCatalogFilterExtension({ id: 'user.list', configSchema: createSchemaFromZod(z => z.object({ @@ -220,8 +210,7 @@ export const CatalogUserListFilter = createCatalogFilterExtension({ }, }); -/** @alpha */ -export const CatalogIndexPage = createPageExtension({ +const CatalogIndexPage = createPageExtension({ id: 'catalog', defaultPath: '/catalog', routeRef: rootRouteRef, @@ -237,8 +226,7 @@ export const CatalogIndexPage = createPageExtension({ }, }); -/** @alpha */ -export const CatalogEntityPage = createPageExtension({ +const CatalogEntityPage = createPageExtension({ id: 'catalog:entity', defaultPath: '/catalog/:namespace/:kind/:name', routeRef: entityRouteRef, From 14e135c0f10e30f7abec2b83dfe48728aad034c6 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sun, 15 Oct 2023 10:06:27 +0200 Subject: [PATCH 137/348] feat(catalog): provide external routes Signed-off-by: Camila Belo --- packages/app-next/app-config.yaml | 2 ++ plugins/catalog/src/alpha.tsx | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index eaaa2b0560..6f6081fece 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -4,6 +4,8 @@ app: routes: bindings: plugin.pages.externalRoutes.pageX: plugin.pages.routes.pageX + # waiting for https://github.com/backstage/backstage/pull/20605 + # catalog.externalRoutes.viewTechDoc: techdocs.routes.docRoot extensions: - apis.plugin.graphiql.browse.gitlab: true diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index 0a6a093b7a..bc568cafd2 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -22,6 +22,7 @@ import { fetchApiRef, storageApiRef, } from '@backstage/core-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; import { CatalogClient } from '@backstage/catalog-client'; import { createSchemaFromZod, @@ -44,7 +45,12 @@ import { } from '@backstage/plugin-catalog-react'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; import { DefaultStarredEntitiesApi } from './apis'; -import { rootRouteRef } from './routes'; +import { + createComponentRouteRef, + createFromTemplateRouteRef, + rootRouteRef, + viewTechDocRouteRef, +} from './routes'; import { Progress } from '@backstage/core-components'; import { useEntityFromUrl } from './components/CatalogEntityPage/useEntityFromUrl'; @@ -213,7 +219,7 @@ const CatalogUserListFilter = createCatalogFilterExtension({ const CatalogIndexPage = createPageExtension({ id: 'catalog', defaultPath: '/catalog', - routeRef: rootRouteRef, + routeRef: convertLegacyRouteRef(rootRouteRef), inputs: { filters: createExtensionInput({ element: coreExtensionData.reactElement, @@ -229,7 +235,7 @@ const CatalogIndexPage = createPageExtension({ const CatalogEntityPage = createPageExtension({ id: 'catalog:entity', defaultPath: '/catalog/:namespace/:kind/:name', - routeRef: entityRouteRef, + routeRef: convertLegacyRouteRef(entityRouteRef), loader: async () => { const Component = () => { return ( @@ -244,7 +250,7 @@ const CatalogEntityPage = createPageExtension({ const CatalogNavItem = createNavItemExtension({ id: 'catalog.nav.index', - routeRef: rootRouteRef, + routeRef: convertLegacyRouteRef(rootRouteRef), title: 'Catalog', icon: HomeIcon, }); @@ -252,6 +258,15 @@ const CatalogNavItem = createNavItemExtension({ /** @alpha */ export default createPlugin({ id: 'catalog', + routes: { + catalogIndex: convertLegacyRouteRef(rootRouteRef), + catalogEntity: convertLegacyRouteRef(entityRouteRef), + }, + externalRoutes: { + viewTechDoc: convertLegacyRouteRef(viewTechDocRouteRef), + createComponent: convertLegacyRouteRef(createComponentRouteRef), + createFromTemplate: convertLegacyRouteRef(createFromTemplateRouteRef), + }, extensions: [ CatalogApi, StarredEntitiesApi, From fbd1f5e972c754b149bc7e0e2791d95a9c4f2fe6 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 18 Oct 2023 12:41:15 +0200 Subject: [PATCH 138/348] chore(catalog): update api reports Signed-off-by: Camila Belo --- plugins/catalog/alpha-api-report.md | 46 ++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/alpha-api-report.md index db76a2e0f3..aba33fc092 100644 --- a/plugins/catalog/alpha-api-report.md +++ b/plugins/catalog/alpha-api-report.md @@ -3,8 +3,14 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +/// + +import { AnyExtensionInputMap } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; +import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; +import { PortableSchema } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) export const CatalogApi: Extension<{}>; @@ -15,7 +21,45 @@ export const CatalogSearchResultListItemExtension: Extension<{ }>; // @alpha (undocumented) -const _default: BackstagePlugin<{}, {}>; +export function createCatalogFilterExtension< + TInputs extends AnyExtensionInputMap, + TConfig = never, +>(options: { + id: string; + inputs?: TInputs; + configSchema?: PortableSchema; + loader: (options: { config: TConfig }) => Promise; +}): Extension; + +// @alpha (undocumented) +const _default: BackstagePlugin< + { + catalogIndex: RouteRef; + catalogEntity: RouteRef<{ + name: string; + kind: string; + namespace: string; + }>; + }, + { + viewTechDoc: ExternalRouteRef< + { + name: string; + kind: string; + namespace: string; + }, + true + >; + createComponent: ExternalRouteRef; + createFromTemplate: ExternalRouteRef< + { + namespace: string; + templateName: string; + }, + true + >; + } +>; export default _default; // @alpha (undocumented) From 95f0d3f5a054ecf3b31afb515432036df99fc82a Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 18 Oct 2023 13:44:26 +0200 Subject: [PATCH 139/348] refactor(catalog): use better pege extension ids Signed-off-by: Camila Belo --- plugins/catalog/src/alpha.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index bc568cafd2..6eda8c3d26 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -99,7 +99,7 @@ export function createCatalogFilterExtension< }) { return createExtension({ id: `catalog.filter.${options.id}`, - attachTo: { id: 'catalog', input: 'filters' }, + attachTo: { id: 'plugin.catalog.page.index', input: 'filters' }, inputs: options.inputs ?? {}, configSchema: options.configSchema, output: { @@ -217,7 +217,7 @@ const CatalogUserListFilter = createCatalogFilterExtension({ }); const CatalogIndexPage = createPageExtension({ - id: 'catalog', + id: 'plugin.catalog.page.index', defaultPath: '/catalog', routeRef: convertLegacyRouteRef(rootRouteRef), inputs: { @@ -233,7 +233,7 @@ const CatalogIndexPage = createPageExtension({ }); const CatalogEntityPage = createPageExtension({ - id: 'catalog:entity', + id: 'plugin.catalog.page.entity', defaultPath: '/catalog/:namespace/:kind/:name', routeRef: convertLegacyRouteRef(entityRouteRef), loader: async () => { From 193ad022bbb135666c11a808b31423ff682233b6 Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Wed, 18 Oct 2023 13:45:26 +0100 Subject: [PATCH 140/348] add `factRetrieverId` to the logger metadata Signed-off-by: Brian Fletcher --- .changeset/plenty-tigers-argue.md | 5 +++++ .../src/service/fact/FactRetrieverEngine.ts | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/plenty-tigers-argue.md diff --git a/.changeset/plenty-tigers-argue.md b/.changeset/plenty-tigers-argue.md new file mode 100644 index 0000000000..ef9e58d63b --- /dev/null +++ b/.changeset/plenty-tigers-argue.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-insights-backend': patch +--- + +Add `factRetrieverId` to the fact retriever's logger metadata. diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts index 846871db88..b723fcd7f5 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts @@ -175,6 +175,7 @@ export class DefaultFactRetrieverEngine implements FactRetrieverEngine { try { facts = await factRetriever.handler({ ...this.factRetrieverContext, + logger: this.logger.child({ factRetrieverId: factRetriever.id }), entityFilter: factRetriever.entityFilter, }); this.logger.debug( From 69ab567cc485bce750dfdf3619c9b85e07ad62cd Mon Sep 17 00:00:00 2001 From: Djam Date: Tue, 17 Oct 2023 14:25:08 +0200 Subject: [PATCH 141/348] chore: clarify ownership of cicd-statistics plugin Signed-off-by: Djam --- plugins/cicd-statistics/catalog-info.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cicd-statistics/catalog-info.yaml b/plugins/cicd-statistics/catalog-info.yaml index 83021cc033..eab84c1283 100644 --- a/plugins/cicd-statistics/catalog-info.yaml +++ b/plugins/cicd-statistics/catalog-info.yaml @@ -7,4 +7,4 @@ metadata: spec: lifecycle: experimental type: backstage-frontend-plugin - owner: maintainers + owner: sharks From fa1112005057b9bb5b9dba4b8cacd4b3c2a6230e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 15:49:21 +0200 Subject: [PATCH 142/348] search: fix alpha plugin id Co-authored-by: Camila Belo Co-authored-by: Philipp Hugenroth Signed-off-by: Patrik Oldsberg --- .changeset/three-moles-mix.md | 5 +++++ plugins/search/src/alpha.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/three-moles-mix.md diff --git a/.changeset/three-moles-mix.md b/.changeset/three-moles-mix.md new file mode 100644 index 0000000000..d1e48194a1 --- /dev/null +++ b/.changeset/three-moles-mix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Fixed incorrect plugin ID in `/alpha` export. diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index a471cf730d..14e7067dfa 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -243,7 +243,7 @@ export const SearchNavItem = createNavItemExtension({ /** @alpha */ export default createPlugin({ - id: 'plugin.search', + id: 'search', extensions: [SearchApi, SearchPage, SearchNavItem], routes: { root: convertLegacyRouteRef(rootRouteRef), From 9a4c92194f77660cf7065d3c7242f98d75e201e4 Mon Sep 17 00:00:00 2001 From: djamaile Date: Wed, 18 Oct 2023 15:50:44 +0200 Subject: [PATCH 143/348] fix: update CODEOWNERS Signed-off-by: djamaile --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 25073c9556..92f2d57885 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -32,6 +32,7 @@ yarn.lock @backstage/maintainers @backst /plugins/catalog-backend-module-msgraph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann /plugins/catalog-backend-module-puppetdb @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers /plugins/catalog-graph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @backstage/sda-se-reviewers +/plugins/cicd-statistics @backstage/sharks /plugins/circleci @backstage/maintainers @backstage/reviewers @adamdmharvey /plugins/code-coverage @backstage/maintainers @backstage/reviewers @alde /plugins/code-coverage-backend @backstage/maintainers @backstage/reviewers @alde From 9ab0572217d79b1ed6f28b1fc8199c39564c5bd6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 15:51:56 +0200 Subject: [PATCH 144/348] core-app-api: add core.type markers for AppRouter and FlatRoutes Co-authored-by: Camila Belo Co-authored-by: Vincenzo Scamporlino Co-authored-by: Philipp Hugenroth Signed-off-by: Patrik Oldsberg --- .changeset/tidy-camels-boil.md | 5 +++++ packages/core-app-api/src/app/AppRouter.tsx | 3 +++ packages/core-app-api/src/routing/FlatRoutes.tsx | 8 +++++++- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 .changeset/tidy-camels-boil.md diff --git a/.changeset/tidy-camels-boil.md b/.changeset/tidy-camels-boil.md new file mode 100644 index 0000000000..6e59f96f34 --- /dev/null +++ b/.changeset/tidy-camels-boil.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-app-api': patch +--- + +Add component data `core.type` marker for `AppRouter` and `FlatRoutes`. diff --git a/packages/core-app-api/src/app/AppRouter.tsx b/packages/core-app-api/src/app/AppRouter.tsx index 9d07be1ffd..7481f6662a 100644 --- a/packages/core-app-api/src/app/AppRouter.tsx +++ b/packages/core-app-api/src/app/AppRouter.tsx @@ -16,6 +16,7 @@ import React, { useContext, ReactNode, ComponentType, useState } from 'react'; import { + attachComponentData, ConfigApi, configApiRef, IdentityApi, @@ -186,3 +187,5 @@ export function AppRouter(props: AppRouterProps) { ); } + +attachComponentData(AppRouter, 'core.type', 'AppRouter'); diff --git a/packages/core-app-api/src/routing/FlatRoutes.tsx b/packages/core-app-api/src/routing/FlatRoutes.tsx index abb7fe9432..46c2270d0d 100644 --- a/packages/core-app-api/src/routing/FlatRoutes.tsx +++ b/packages/core-app-api/src/routing/FlatRoutes.tsx @@ -16,7 +16,11 @@ import React, { ReactNode, useMemo } from 'react'; import { useRoutes } from 'react-router-dom'; -import { useApp, useElementFilter } from '@backstage/core-plugin-api'; +import { + attachComponentData, + useApp, + useElementFilter, +} from '@backstage/core-plugin-api'; import { isReactRouterBeta } from '../app/isReactRouterBeta'; let warned = false; @@ -115,3 +119,5 @@ export const FlatRoutes = (props: FlatRoutesProps): JSX.Element | null => { return useRoutes(withNotFound); }; + +attachComponentData(FlatRoutes, 'core.type', 'FlatRoutes'); From d267d2d92b6d0d961131ad4cd74596b6092faf8d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 15:53:52 +0200 Subject: [PATCH 145/348] core-compat-api: fix plugin and extension duplication in collected routes Co-authored-by: Camila Belo Co-authored-by: Vincenzo Scamporlino Co-authored-by: Philipp Hugenroth Signed-off-by: Patrik Oldsberg --- .../src/collectLegacyRoutes.test.tsx | 7 ++++ .../src/collectLegacyRoutes.tsx | 37 +++++++++++-------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx index 486c373991..85fed83e8c 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx @@ -30,6 +30,7 @@ describe('collectLegacyRoutes', () => { } /> } /> } /> + } /> , ); @@ -85,6 +86,12 @@ describe('collectLegacyRoutes', () => { disabled: false, defaultConfig: { path: 'puppetdb' }, }, + { + id: 'plugin.puppetDb.page2', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'puppetdb' }, + }, { id: 'apis.plugin.puppetdb.service', attachTo: { id: 'core', input: 'apis' }, diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index 2b149e6285..8178de2876 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -62,7 +62,10 @@ Existing tasks: export function collectLegacyRoutes( flatRoutesElement: JSX.Element, ): BackstagePlugin[] { - const results = new Array(); + const createdPluginIds = new Map< + LegacyBackstagePlugin, + Extension[] + >(); React.Children.forEach( flatRoutesElement.props.children, @@ -93,13 +96,18 @@ export function collectLegacyRoutes( ); const pluginId = plugin.getId(); - const path: string = route.props.path; - const detectedExtensions = new Array>(); + const detectedExtensions = + createdPluginIds.get(plugin) ?? new Array>(); + createdPluginIds.set(plugin, detectedExtensions); + + const path: string = route.props.path; detectedExtensions.push( createPageExtension({ - id: `plugin.${pluginId}.page`, + id: `plugin.${pluginId}.page${ + detectedExtensions.length ? detectedExtensions.length + 1 : '' + }`, defaultPath: path[0] === '/' ? path.slice(1) : path, routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined, @@ -115,23 +123,20 @@ export function collectLegacyRoutes( ), }), ); + }, + ); - detectedExtensions.push( + return Array.from(createdPluginIds).map(([plugin, extensions]) => + createPlugin({ + id: plugin.getId(), + extensions: [ + ...extensions, ...Array.from(plugin.getApis()).map(factory => createApiExtension({ factory, }), ), - ); - - results.push( - createPlugin({ - id: plugin.getId(), - extensions: detectedExtensions, - }), - ); - }, + ], + }), ); - - return results; } From 5409341b53f163cec75dec2645ebd6b9de8f170a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 15:54:38 +0200 Subject: [PATCH 146/348] core-compat-api: add convertLegacyApp Co-authored-by: Camila Belo Co-authored-by: Vincenzo Scamporlino Co-authored-by: Philipp Hugenroth Signed-off-by: Patrik Oldsberg --- .../core-compat-api/src/convertLegacyApp.ts | 138 ++++++++++++++++++ packages/core-compat-api/src/index.ts | 1 + 2 files changed, 139 insertions(+) create mode 100644 packages/core-compat-api/src/convertLegacyApp.ts diff --git a/packages/core-compat-api/src/convertLegacyApp.ts b/packages/core-compat-api/src/convertLegacyApp.ts new file mode 100644 index 0000000000..9343744075 --- /dev/null +++ b/packages/core-compat-api/src/convertLegacyApp.ts @@ -0,0 +1,138 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { + Children, + Fragment, + ReactElement, + ReactNode, + isValidElement, +} from 'react'; +import { + BackstagePlugin, + ExtensionOverrides, + coreExtensionData, + createExtension, + createExtensionInput, + createExtensionOverrides, +} from '@backstage/frontend-plugin-api'; +import { getComponentData } from '@backstage/core-plugin-api'; +import { collectLegacyRoutes } from './collectLegacyRoutes'; + +function selectChildren( + rootNode: ReactNode, + selector?: (element: ReactElement<{ children?: ReactNode }>) => boolean, + strictError?: string, +): Array> { + return Children.toArray(rootNode).flatMap(node => { + if (!isValidElement<{ children?: ReactNode }>(node)) { + return []; + } + + if (node.type === Fragment) { + return selectChildren(node.props.children, selector, strictError); + } + + if (selector === undefined || selector(node)) { + return [node]; + } + + if (strictError) { + throw new Error(strictError); + } + + return selectChildren(node.props.children, selector, strictError); + }); +} + +export function convertLegacyApp( + rootElement: React.JSX.Element, +): (ExtensionOverrides | BackstagePlugin)[] { + const appRouterEls = selectChildren( + rootElement, + el => getComponentData(el, 'core.type') === 'AppRouter', + ); + if (appRouterEls.length !== 1) { + throw new Error( + "Failed to convert legacy app, AppRouter element could not been found. Make sure it's at the top level of the App element tree", + ); + } + + const rootEls = selectChildren( + appRouterEls[0].props.children, + el => + Boolean(el.props.children) && + selectChildren( + el.props.children, + innerEl => getComponentData(innerEl, 'core.type') === 'FlatRoutes', + ).length === 1, + ); + if (rootEls.length !== 1) { + throw new Error( + "Failed to convert legacy app, Root element containing FlatRoutes could not been found. Make sure it's within the AppRouter element of the App element tree", + ); + } + const [rootEl] = rootEls; + + const routesEls = selectChildren( + rootEls[0].props.children, + el => getComponentData(el, 'core.type') === 'FlatRoutes', + ); + if (routesEls.length !== 1) { + throw new Error( + 'Unexpectedly failed to find FlatRoutes in app element tree', + ); + } + const [routesEl] = routesEls; + + const CoreLayoutOverride = createExtension({ + id: 'core.layout', + attachTo: { id: 'core', input: 'root' }, + inputs: { + content: createExtensionInput( + { + element: coreExtensionData.reactElement, + }, + { singleton: true }, + ), + }, + output: { + element: coreExtensionData.reactElement, + }, + factory({ bind, inputs }) { + // Clone the root element, this replaces the FlatRoutes declared in the app with out content input + bind({ + element: React.cloneElement(rootEl, undefined, inputs.content.element), + }); + }, + }); + const CoreNavOverride = createExtension({ + id: 'core.nav', + attachTo: { id: 'core.layout', input: 'nav' }, + output: {}, + factory() {}, + disabled: true, + }); + + const collectedRoutes = collectLegacyRoutes(routesEl); + + return [ + ...collectedRoutes, + createExtensionOverrides({ + extensions: [CoreLayoutOverride, CoreNavOverride], + }), + ]; +} diff --git a/packages/core-compat-api/src/index.ts b/packages/core-compat-api/src/index.ts index 2181b2fa9a..e5f61119a3 100644 --- a/packages/core-compat-api/src/index.ts +++ b/packages/core-compat-api/src/index.ts @@ -14,3 +14,4 @@ * limitations under the License. */ export { collectLegacyRoutes } from './collectLegacyRoutes'; +export { convertLegacyApp } from './convertLegacyApp'; From a4e72d309f11b2a0ac36f410c7dfc8ff167c75c2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 16:01:13 +0200 Subject: [PATCH 147/348] core-compat-api: add test for convertLegacyApp Signed-off-by: Patrik Oldsberg --- .../src/convertLegacyApp.test.tsx | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 packages/core-compat-api/src/convertLegacyApp.test.tsx diff --git a/packages/core-compat-api/src/convertLegacyApp.test.tsx b/packages/core-compat-api/src/convertLegacyApp.test.tsx new file mode 100644 index 0000000000..0f1f6145c9 --- /dev/null +++ b/packages/core-compat-api/src/convertLegacyApp.test.tsx @@ -0,0 +1,129 @@ +/* + * Copyright 2023 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 { AppRouter, FlatRoutes } from '@backstage/core-app-api'; +import { PuppetDbPage } from '@backstage/plugin-puppetdb'; +import { StackstormPage } from '@backstage/plugin-stackstorm'; +import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card'; +import React, { ReactNode } from 'react'; +import { Route } from 'react-router-dom'; +import { convertLegacyApp } from './convertLegacyApp'; + +const Root = ({ children }: { children: ReactNode }) => <>{children}; + +describe('convertLegacyApp', () => { + it('should find and extract root and routes', () => { + const collected = convertLegacyApp( + <> +
+ + +
+ + + } /> + } /> + } /> + } /> + + + + , + ); + + expect( + collected.map((p: any /* TODO */) => ({ + id: p.id, + extensions: p.extensions.map((e: any) => ({ + id: e.id, + attachTo: e.attachTo, + disabled: e.disabled, + defaultConfig: e.configSchema?.parse({}), + })), + })), + ).toEqual([ + { + id: 'score-card', + extensions: [ + { + id: 'plugin.score-card.page', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'score-board' }, + }, + { + id: 'apis.plugin.scoringdata.service', + attachTo: { id: 'core', input: 'apis' }, + disabled: false, + }, + ], + }, + { + id: 'stackstorm', + extensions: [ + { + id: 'plugin.stackstorm.page', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'stackstorm' }, + }, + { + id: 'apis.plugin.stackstorm.service', + attachTo: { id: 'core', input: 'apis' }, + disabled: false, + }, + ], + }, + { + id: 'puppetDb', + extensions: [ + { + id: 'plugin.puppetDb.page', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'puppetdb' }, + }, + { + id: 'plugin.puppetDb.page2', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'puppetdb' }, + }, + { + id: 'apis.plugin.puppetdb.service', + attachTo: { id: 'core', input: 'apis' }, + disabled: false, + }, + ], + }, + { + id: undefined, + extensions: [ + { + id: 'core.layout', + attachTo: { id: 'core', input: 'root' }, + disabled: false, + }, + { + id: 'core.nav', + attachTo: { id: 'core.layout', input: 'nav' }, + disabled: true, + }, + ], + }, + ]); + }); +}); From 43fcf6818c37bb3eb961c4a7e8f1d56c0a05d909 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 16:01:35 +0200 Subject: [PATCH 148/348] frontend-app-api: note in createExtensionInstance Signed-off-by: Patrik Oldsberg --- packages/frontend-app-api/src/wiring/createExtensionInstance.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/frontend-app-api/src/wiring/createExtensionInstance.ts b/packages/frontend-app-api/src/wiring/createExtensionInstance.ts index 5a325dc0a0..767329da7f 100644 --- a/packages/frontend-app-api/src/wiring/createExtensionInstance.ts +++ b/packages/frontend-app-api/src/wiring/createExtensionInstance.ts @@ -63,6 +63,7 @@ function resolveInputs( const undeclaredAttachments = Array.from(attachments.entries()).filter( ([inputName]) => inputMap[inputName] === undefined, ); + // TODO: Make this a warning rather than an error if (undeclaredAttachments.length > 0) { throw new Error( `received undeclared input${ From 2cd0b072b89b02d85c9441dfd6d84348cae9c823 Mon Sep 17 00:00:00 2001 From: Chris Gemmell Date: Thu, 19 Oct 2023 00:37:12 +1100 Subject: [PATCH 149/348] removing consent prompt Signed-off-by: Chris Gemmell --- .../auth-backend-module-microsoft-provider/src/authenticator.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/auth-backend-module-microsoft-provider/src/authenticator.ts b/plugins/auth-backend-module-microsoft-provider/src/authenticator.ts index bf2d7fcaba..ba1d75adf8 100644 --- a/plugins/auth-backend-module-microsoft-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-microsoft-provider/src/authenticator.ts @@ -60,7 +60,6 @@ export const microsoftAuthenticator = createOAuthAuthenticator({ async start(input, helper) { return helper.start(input, { accessType: 'offline', - prompt: 'consent', }); }, From 2817115d09d508f35dac0588a7f314ec528b9de2 Mon Sep 17 00:00:00 2001 From: Chris Gemmell Date: Thu, 19 Oct 2023 00:42:28 +1100 Subject: [PATCH 150/348] added changeset Signed-off-by: Chris Gemmell --- .changeset/shiny-geese-watch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/shiny-geese-watch.md diff --git a/.changeset/shiny-geese-watch.md b/.changeset/shiny-geese-watch.md new file mode 100644 index 0000000000..dfa7175f8c --- /dev/null +++ b/.changeset/shiny-geese-watch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-microsoft-provider': patch +--- + +removed prompt=consent from start method to bugfix #20641 From 19b6c0ed2a40c0b4d622addcc4679f41f6fa47e5 Mon Sep 17 00:00:00 2001 From: Chris Gemmell Date: Thu, 19 Oct 2023 01:04:07 +1100 Subject: [PATCH 151/348] oops, forgot to change the module test Signed-off-by: Chris Gemmell --- .../auth-backend-module-microsoft-provider/src/module.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/auth-backend-module-microsoft-provider/src/module.test.ts b/plugins/auth-backend-module-microsoft-provider/src/module.test.ts index ee7ed8f7f3..2cfedc5d5e 100644 --- a/plugins/auth-backend-module-microsoft-provider/src/module.test.ts +++ b/plugins/auth-backend-module-microsoft-provider/src/module.test.ts @@ -65,7 +65,6 @@ describe('authModuleMicrosoftProvider', () => { expect(startUrl.origin).toBe('https://login.microsoftonline.com'); expect(startUrl.pathname).toBe('/my-tenant-id/oauth2/v2.0/authorize'); expect(Object.fromEntries(startUrl.searchParams)).toEqual({ - prompt: 'consent', response_type: 'code', scope: 'user.read', client_id: 'my-client-id', From 0eab56d6d201e094127d8b885f576bc0dedab2f5 Mon Sep 17 00:00:00 2001 From: Andre Date: Wed, 18 Oct 2023 10:19:51 -0500 Subject: [PATCH 152/348] Cleaned up changeset Signed-off-by: Andre --- .changeset/shiny-geese-watch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/shiny-geese-watch.md b/.changeset/shiny-geese-watch.md index dfa7175f8c..5394a0776d 100644 --- a/.changeset/shiny-geese-watch.md +++ b/.changeset/shiny-geese-watch.md @@ -2,4 +2,4 @@ '@backstage/plugin-auth-backend-module-microsoft-provider': patch --- -removed prompt=consent from start method to bugfix #20641 +Removed `prompt=consent` from start method to fix #20641 From 22b3b859a23e8447620bc8dc80a0b5c92a5d0a2c Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 16 Oct 2023 08:49:18 +0200 Subject: [PATCH 153/348] feat(techdocs): export nav item and routes Signed-off-by: Camila Belo --- plugins/techdocs/src/alpha.tsx | 139 +++++++++++++++++---------------- 1 file changed, 73 insertions(+), 66 deletions(-) diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx index f4d4da6e93..b7ccb0b12c 100644 --- a/plugins/techdocs/src/alpha.tsx +++ b/plugins/techdocs/src/alpha.tsx @@ -15,89 +15,33 @@ */ import React from 'react'; +import LibraryBooks from '@material-ui/icons/LibraryBooks'; import { createPlugin, createSchemaFromZod, createApiExtension, createPageExtension, + createNavItemExtension, } from '@backstage/frontend-plugin-api'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; import { configApiRef, createApiFactory, - createRouteRef, discoveryApiRef, fetchApiRef, identityApiRef, } from '@backstage/core-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; import { techdocsApiRef, techdocsStorageApiRef, } from '@backstage/plugin-techdocs-react'; import { TechDocsClient, TechDocsStorageClient } from './client'; -import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; - -const rootRouteRef = createRouteRef({ - id: 'plugin.techdocs.indexPage', -}); - -const rootDocsRouteRef = createRouteRef({ - id: 'plugin.techdocs.readerPage', - params: ['namespace', 'kind', 'name'], -}); - -/** @alpha */ -export const TechDocsSearchResultListItemExtension = - createSearchResultListItemExtension({ - id: 'techdocs', - configSchema: createSchemaFromZod(z => - z.object({ - // TODO: Define how the icon can be configurable - title: z.string().optional(), - lineClamp: z.number().default(5), - asLink: z.boolean().default(true), - asListItem: z.boolean().default(true), - noTrack: z.boolean().default(false), - }), - ), - predicate: result => result.type === 'techdocs', - component: async ({ config }) => { - const { TechDocsSearchResultListItem } = await import( - './search/components/TechDocsSearchResultListItem' - ); - return props => ; - }, - }); - -/** - * Responsible for rendering the provided router element - * - * @alpha - */ -const TechDocsIndexPage = createPageExtension({ - id: 'plugin.techdocs.indexPage', - defaultPath: '/docs', - routeRef: convertLegacyRouteRef(rootRouteRef), - loader: () => - import('./home/components/TechDocsIndexPage').then(m => ( - - )), -}); - -/** - * Component responsible for composing a TechDocs reader page experience - * - * @alpha - */ -const TechDocsReaderPage = createPageExtension({ - id: 'plugin.techdocs.readerPage', - loader: () => - import('./reader/components/TechDocsReaderPage').then(m => ( - - )), - routeRef: convertLegacyRouteRef(rootDocsRouteRef), - defaultPath: '/docs/:namespace/:kind/:name/*', -}); +import { + rootCatalogDocsRouteRef, + rootDocsRouteRef, + rootRouteRef, +} from './routes'; /** @alpha */ const techDocsStorage = createApiExtension({ @@ -144,18 +88,81 @@ const techDocsClient = createApiExtension({ }, }); +/** @alpha */ +export const TechDocsSearchResultListItemExtension = + createSearchResultListItemExtension({ + id: 'techdocs', + configSchema: createSchemaFromZod(z => + z.object({ + // TODO: Define how the icon can be configurable + title: z.string().optional(), + lineClamp: z.number().default(5), + asLink: z.boolean().default(true), + asListItem: z.boolean().default(true), + noTrack: z.boolean().default(false), + }), + ), + predicate: result => result.type === 'techdocs', + component: async ({ config }) => { + const { TechDocsSearchResultListItem } = await import( + './search/components/TechDocsSearchResultListItem' + ); + return props => ; + }, + }); + +/** + * Responsible for rendering the provided router element + * + * @alpha + */ +const TechDocsIndexPage = createPageExtension({ + id: 'plugin.techdocs.indexPage', + defaultPath: '/docs', + routeRef: convertLegacyRouteRef(rootRouteRef), + loader: () => + import('./home/components/TechDocsIndexPage').then(m => ( + + )), +}); + +/** + * Component responsible for composing a TechDocs reader page experience + * + * @alpha + */ +const TechDocsReaderPage = createPageExtension({ + id: 'plugin.techdocs.readerPage', + defaultPath: '/docs/:namespace/:kind/:name', + routeRef: convertLegacyRouteRef(rootDocsRouteRef), + loader: () => + import('./reader/components/TechDocsReaderPage').then(m => ( + + )), +}); + +/** @alpha */ +const TechDocsNavItem = createNavItemExtension({ + id: 'plugin.techdocs.nav.index', + icon: LibraryBooks, + title: 'Docs', + routeRef: convertLegacyRouteRef(rootRouteRef), +}); + /** @alpha */ export default createPlugin({ id: 'techdocs', extensions: [ - TechDocsIndexPage, - TechDocsReaderPage, techDocsClient, techDocsStorage, + TechDocsNavItem, + TechDocsIndexPage, + TechDocsReaderPage, TechDocsSearchResultListItemExtension, ], routes: { root: convertLegacyRouteRef(rootRouteRef), docRoot: convertLegacyRouteRef(rootDocsRouteRef), + entityContent: convertLegacyRouteRef(rootCatalogDocsRouteRef), }, }); From 8b6a98921d4274e3da6d84099d7570604cf171c6 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 16 Oct 2023 08:49:53 +0200 Subject: [PATCH 154/348] docs(techdocs): update api reports Signed-off-by: Camila Belo --- plugins/techdocs/alpha-api-report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/techdocs/alpha-api-report.md b/plugins/techdocs/alpha-api-report.md index 2b3a934e34..2b63d6e691 100644 --- a/plugins/techdocs/alpha-api-report.md +++ b/plugins/techdocs/alpha-api-report.md @@ -16,6 +16,7 @@ const _default: BackstagePlugin< kind: string; namespace: string; }>; + entityContent: RouteRef; }, {} >; From a3add7a6829110af554635fd93cee3e93ec6e9e6 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 18 Oct 2023 18:37:28 +0200 Subject: [PATCH 155/348] docs: add changeset file Signed-off-by: Camila Belo --- .changeset/giant-cars-walk.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/giant-cars-walk.md diff --git a/.changeset/giant-cars-walk.md b/.changeset/giant-cars-walk.md new file mode 100644 index 0000000000..5e313faa3b --- /dev/null +++ b/.changeset/giant-cars-walk.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Export alpha routes and nav item extension, only available for applications that uses the new Frontend system. From ad2de37115f3202981988efe9156e598059a13cb Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Wed, 18 Oct 2023 13:59:12 -0400 Subject: [PATCH 156/348] refactor Signed-off-by: Sydney Achinger --- .../TechDocsReaderPageContent/TechDocsReaderPageContent.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx index 32fe788716..8508c59142 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx @@ -86,8 +86,10 @@ export const TechDocsReaderPageContent = withTechDocsReaderProvider( const [hashElement] = useShadowRootElements([`[id="${hash.slice(1)}"]`]); useEffect(() => { - if (hashElement && !isStyleLoading) { - hashElement.scrollIntoView(); + if (hash) { + if (hashElement && !isStyleLoading) { + hashElement.scrollIntoView(); + } } else { document?.querySelector('header')?.scrollIntoView(); } From 6db75b900aff3df7bccb650e65930639b73665a3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 17:12:51 +0200 Subject: [PATCH 157/348] catalog-import: add support for new frontend system Signed-off-by: Patrik Oldsberg --- .changeset/chilled-knives-rule.md | 5 ++ plugins/catalog-import/alpha-api-report.md | 19 +++++ plugins/catalog-import/package.json | 20 +++++- plugins/catalog-import/src/alpha.tsx | 84 ++++++++++++++++++++++ yarn.lock | 1 + 5 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 .changeset/chilled-knives-rule.md create mode 100644 plugins/catalog-import/alpha-api-report.md create mode 100644 plugins/catalog-import/src/alpha.tsx diff --git a/.changeset/chilled-knives-rule.md b/.changeset/chilled-knives-rule.md new file mode 100644 index 0000000000..f246beabbd --- /dev/null +++ b/.changeset/chilled-knives-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Create an experimental plugin that is compatible with the declarative integration system, it is exported from the `/alpha` subpath. diff --git a/plugins/catalog-import/alpha-api-report.md b/plugins/catalog-import/alpha-api-report.md new file mode 100644 index 0000000000..63e2cda339 --- /dev/null +++ b/plugins/catalog-import/alpha-api-report.md @@ -0,0 +1,19 @@ +## API Report File for "@backstage/plugin-catalog-import" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +const _default: BackstagePlugin< + { + importPage: RouteRef; + }, + {} +>; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index b970736695..e892338dea 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -6,9 +6,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.tsx", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.tsx" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "frontend-plugin" @@ -39,6 +52,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/integration-react": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", diff --git a/plugins/catalog-import/src/alpha.tsx b/plugins/catalog-import/src/alpha.tsx new file mode 100644 index 0000000000..bde1048f13 --- /dev/null +++ b/plugins/catalog-import/src/alpha.tsx @@ -0,0 +1,84 @@ +/* + * Copyright 2023 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 { + configApiRef, + createApiFactory, + discoveryApiRef, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { + createApiExtension, + createPageExtension, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { + scmAuthApiRef, + scmIntegrationsApiRef, +} from '@backstage/integration-react'; +import React from 'react'; +import { CatalogImportClient, catalogImportApiRef } from './api'; +import { rootRouteRef } from './plugin'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; + +// TODO: It's currently possible to override the import page with a custom one. We need to decide +// whether this type of override is typically done with an input or by overriding the entire extension. +const CatalogImportPageExtension = createPageExtension({ + id: 'plugin.catalog-import.page', + defaultPath: '/catalog-import', + routeRef: convertLegacyRouteRef(rootRouteRef), + loader: () => import('./components/ImportPage').then(m => ), +}); + +const CatalogImportService = createApiExtension({ + factory: createApiFactory({ + api: catalogImportApiRef, + deps: { + discoveryApi: discoveryApiRef, + scmAuthApi: scmAuthApiRef, + identityApi: identityApiRef, + scmIntegrationsApi: scmIntegrationsApiRef, + catalogApi: catalogApiRef, + configApi: configApiRef, + }, + factory: ({ + discoveryApi, + scmAuthApi, + identityApi, + scmIntegrationsApi, + catalogApi, + configApi, + }) => + new CatalogImportClient({ + discoveryApi, + scmAuthApi, + scmIntegrationsApi, + identityApi, + catalogApi, + configApi, + }), + }), +}); + +/** @alpha */ +export default createPlugin({ + id: 'catalog-import', + extensions: [CatalogImportService, CatalogImportPageExtension], + routes: { + importPage: convertLegacyRouteRef(rootRouteRef), + }, +}); diff --git a/yarn.lock b/yarn.lock index 636d159dd3..1e2f6fdb5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5779,6 +5779,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/integration-react": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" From b1ff135ba68150dec215e51c909d3f7f883e2b80 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Wed, 18 Oct 2023 15:48:58 -0500 Subject: [PATCH 158/348] chore: updated Keyloop adopter contact Signed-off-by: Andre Wanlin --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index b5e19106b7..f0d6e4ed0a 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -78,7 +78,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Telstra](https://www.telstra.com.au) | [@kiranpatel11](https://github.com/kiranpatel11), [JasonC](https://github.com/JasonC17) | Primary usage: software catalog and templates
Emerging usage : TechDocs, Explore Ecosystem, TechRadar, etc | | [Mosaico](https://www.mosaico.com.br/) | [Wédney Yuri](https://github.com/wedneyyuri),[@tino.milton](https://github.com/miltonjacomini) | A centralized service catalog of our documentation for our service engineers. | | [Mox Bank](https://www.mox.com/) | [Nick Laqua](https://github.com/nick-laqua-dragon) | "Single pane of glass" developer portal for providing a best-in-class developer experience to our product teams and making Mox the best tech environment in Hongkong 🥰🚀 | -| [Keyloop](https://www.keyloop.com/) | [Andre Wanlin](https://github.com/awanlin) | Future-motive Developer Portal to help our teams create technology to make everything about buying and owning a car better. 🚗 | +| [Keyloop](https://www.keyloop.com/) | [Shawn Bruce](https://github.com/sbruce-keyloop) | Future-motive Developer Portal to help our teams create technology to make everything about buying and owning a car better. 🚗 | | [Simply Business](https://sbtech.simplybusiness.co.uk/) | [@addersuk](https://github.com/addersuk), [@LightningStairs](https://github.com/LightningStairs), [@punitcse](https://github.com/punitcse), [@moltenice](https://github.com/moltenice) | Central developer portal to access everything a developer needs such as docs, internal service catalog, and the ability to quickly create a new service from a template. Internally developed Backstage plugins allow us to customise the experience to how we work. | | [Overwolf](https://www.overwolf.com) | [@tomwolfgang](https://github.com/tomwolfgang) | Dev portal - software catalog, tech-docs, scaffolding | | [Hotmart](https://www.hotmart.com) | [@fabioviana-hotmart](https://github.com/fabioviana-hotmart) | The main Developers Portal to centralize docs, applications and technical metrics. | From 4b5618330acbc7eed8c39f7b037ee1067d46d851 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Wed, 18 Oct 2023 15:54:12 -0500 Subject: [PATCH 159/348] chore: updated Owner Org for awanlin Signed-off-by: Andre Wanlin --- OWNERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OWNERS.md b/OWNERS.md index caf5bc4d14..2ea263f3b4 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -145,7 +145,7 @@ Scope: The Scaffolder frontend and backend plugins, and related tooling. | ------------------------------ | ------------------------- | ----------------------------------------------------- | ------------------------------ | | Adam Harvey | Cisco | [adamdmharvey](https://github.com/adamdmharvey) | `adamharvey_` | | Alex Crome | | [afscrome](https://github.com/afscrome) | `afscrome` | -| Andre Wanlin | Keyloop | [awanlin](https://github.com/awanlin) | `ahhhndre` | +| Andre Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` | | Andrew Thauer | Wealthsimple | [andrewthauer](https://github.com/andrewthauer) | `andrewthauer#3060` | | Aramis Sennyey | Spotify | [sennyeya](https://github.com/sennyeya) | `Aramis#7984` | | Brian Fletcher | Roadie.io | [punkle](https://github.com/punkle) | `Brian Fletcher#7051` | From dd4f4f06f5bbcc1a755d576a3f9a2577f19ff108 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 01:02:27 +0200 Subject: [PATCH 160/348] core-compat-api: update api report + fix Signed-off-by: Patrik Oldsberg --- packages/core-compat-api/api-report.md | 7 +++++++ packages/core-compat-api/src/convertLegacyApp.ts | 1 + 2 files changed, 8 insertions(+) diff --git a/packages/core-compat-api/api-report.md b/packages/core-compat-api/api-report.md index 5175c76ac8..3dd2eb6b22 100644 --- a/packages/core-compat-api/api-report.md +++ b/packages/core-compat-api/api-report.md @@ -6,11 +6,18 @@ /// import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { ExtensionOverrides } from '@backstage/frontend-plugin-api'; +import { default as React_2 } from 'react'; // @public (undocumented) export function collectLegacyRoutes( flatRoutesElement: JSX.Element, ): BackstagePlugin[]; +// @public (undocumented) +export function convertLegacyApp( + rootElement: React_2.JSX.Element, +): (ExtensionOverrides | BackstagePlugin)[]; + // (No @packageDocumentation comment for this package) ``` diff --git a/packages/core-compat-api/src/convertLegacyApp.ts b/packages/core-compat-api/src/convertLegacyApp.ts index 9343744075..59cb136c65 100644 --- a/packages/core-compat-api/src/convertLegacyApp.ts +++ b/packages/core-compat-api/src/convertLegacyApp.ts @@ -58,6 +58,7 @@ function selectChildren( }); } +/** @public */ export function convertLegacyApp( rootElement: React.JSX.Element, ): (ExtensionOverrides | BackstagePlugin)[] { From 47dc8b84b3bb70fbb94a2b748a35e5da2054171f Mon Sep 17 00:00:00 2001 From: Ankit Anand Date: Thu, 19 Oct 2023 04:43:24 +0530 Subject: [PATCH 161/348] removed mock-fs in scaffolder rails Signed-off-by: Ankit Anand --- .../package.json | 5 ++--- .../src/actions/fetch/rails/index.test.ts | 17 +++++++++-------- yarn.lock | 3 +-- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 2bc91478e4..0763690d7c 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -39,13 +39,12 @@ "fs-extra": "^10.0.1" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", - "@types/mock-fs": "^4.13.0", "@types/node": "^18.17.8", - "jest-when": "^3.1.0", - "mock-fs": "^5.2.0" + "jest-when": "^3.1.0" }, "files": [ "dist" diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts index 2a93644f57..10b8466dc2 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts @@ -34,14 +34,14 @@ import { } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; -import mockFs from 'mock-fs'; -import os from 'os'; import { resolve as resolvePath } from 'path'; import { PassThrough } from 'stream'; import { createFetchRailsAction } from './index'; import { fetchContents } from '@backstage/plugin-scaffolder-node'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('fetch:rails', () => { + const mockDir = createMockDirectory(); const integrations = ScmIntegrations.fromConfig( new ConfigReader({ integrations: { @@ -53,7 +53,7 @@ describe('fetch:rails', () => { }), ); - const mockTmpDir = os.tmpdir(); + const mockTmpDir = mockDir.path; const mockContext = { input: { url: 'https://rubyonrails.org/generator', @@ -73,6 +73,9 @@ describe('fetch:rails', () => { createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), }; + mockDir.clear(); + mockDir.addContent({ template: {} }); + const mockReader: UrlReader = { readUrl: jest.fn(), readTree: jest.fn(), @@ -90,14 +93,12 @@ describe('fetch:rails', () => { }); beforeEach(() => { - mockFs({ [`${mockContext.workspacePath}/result`]: {} }); + mockDir.addContent({ + result: '{}', + }); jest.clearAllMocks(); }); - afterEach(() => { - mockFs.restore(); - }); - it('should call fetchContents with the correct values', async () => { await action.handler(mockContext); diff --git a/yarn.lock b/yarn.lock index 636d159dd3..5c88d57903 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8494,6 +8494,7 @@ __metadata: resolution: "@backstage/plugin-scaffolder-backend-module-rails@workspace:plugins/scaffolder-backend-module-rails" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" @@ -8502,12 +8503,10 @@ __metadata: "@backstage/types": "workspace:^" "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 - "@types/mock-fs": ^4.13.0 "@types/node": ^18.17.8 command-exists: ^1.2.9 fs-extra: ^10.0.1 jest-when: ^3.1.0 - mock-fs: ^5.2.0 languageName: unknown linkType: soft From 43a2ff70cbe3b59f62cc4356fc03056bad82d4e8 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Wed, 18 Oct 2023 18:43:08 -0500 Subject: [PATCH 162/348] docs: new backend system updates Signed-off-by: Andre Wanlin --- .../architecture/02-backends.md | 2 +- .../building-backends/01-index.md | 12 ++++++------ .../building-backends/08-migrating.md | 19 +++++++++---------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/docs/backend-system/architecture/02-backends.md b/docs/backend-system/architecture/02-backends.md index 4ba76a5af3..c64024d653 100644 --- a/docs/backend-system/architecture/02-backends.md +++ b/docs/backend-system/architecture/02-backends.md @@ -23,7 +23,7 @@ import scaffolderPlugin from '@backstage/plugin-scaffolder-backend'; const backend = createBackend(); // Install desired features -backend.add(import('@backstage/plugin-catalog-backend')); +backend.add(import('@backstage/plugin-catalog-backend/alpha')); // Features can also be installed using an explicit reference backend.add(scaffolderPlugin()); diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md index 7d331b4ec3..c381999429 100644 --- a/docs/backend-system/building-backends/01-index.md +++ b/docs/backend-system/building-backends/01-index.md @@ -24,9 +24,9 @@ import { createBackend } from '@backstage/backend-defaults'; // Omitted in the e const backend = createBackend(); -backend.add(import('@backstage/plugin-app-backend')); -backend.add(import('@backstage/plugin-catalog-backend')); -backend.add(import('@backstage/plugin-scaffolder-backend')); +backend.add(import('@backstage/plugin-app-backend/alpha')); +backend.add(import('@backstage/plugin-catalog-backend/alpha')); +backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); backend.add( import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), ); @@ -126,8 +126,8 @@ You can now trim down the `src/index.ts` files to only include the plugins and m ```ts const backend = createBackend(); -backend.add(import('@backstage/plugin-app-backend')); -backend.add(import('@backstage/plugin-catalog-backend')); +backend.add(import('@backstage/plugin-app-backend/alpha')); +backend.add(import('@backstage/plugin-catalog-backend/alpha')); backend.add( import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), ); @@ -139,7 +139,7 @@ And `backend-b`, don't forget to clean up dependencies in `package.json` as well ```ts const backend = createBackend(); -backend.add(import('@backstage/plugin-scaffolder-backend')); +backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); backend.start(); ``` diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index 1a380421c1..1e30d0aa9e 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -177,11 +177,10 @@ custom API, so we use a helper function to transform that particular one. To make additions as mentioned above to the environment, you will start to get into the weeds of how the backend system wiring works. You'll need to have a service reference and a service factory that performs the actual creation of -your service. Please see [the services -article](../architecture/03-services.md#defining-a-service) to learn how to -create a service ref and its default factory. You can place that code directly -in the index file for now if you want, or near the actual implementation class -in question. +your service. Please see [the services article](../architecture/03-services.md) +to learn how to create a service ref and its default factory. You can place that +code directly in the index file for now if you want, or near the actual implementation +class in question. In this example, we'll assume that your added environment field is named `example`, and the created ref is named `exampleServiceRef`. @@ -233,7 +232,7 @@ be used in its new form. ```ts title="packages/backend/src/index.ts" const backend = createBackend(); /* highlight-add-next-line */ -backend.add(import('@backstage/plugin-app-backend')); +backend.add(import('@backstage/plugin-app-backend/alpha')); ``` If you need to override the app package name, which otherwise defaults to `"app"`, @@ -248,7 +247,7 @@ A basic installation of the catalog plugin looks as follows. ```ts title="packages/backend/src/index.ts" const backend = createBackend(); /* highlight-add-start */ -backend.add(import('@backstage/plugin-catalog-backend')); +backend.add(import('@backstage/plugin-catalog-backend/alpha')); backend.add( import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), ); @@ -296,7 +295,7 @@ const catalogModuleCustomExtensions = createBackendModule({ /* highlight-add-end */ const backend = createBackend(); -backend.add(import('@backstage/plugin-catalog-backend')); +backend.add(import('@backstage/plugin-catalog-backend/alpha')); backend.add( import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), ); @@ -390,7 +389,7 @@ A basic installation of the scaffolder plugin looks as follows. ```ts title="packages/backend/src/index.ts" const backend = createBackend(); /* highlight-add-next-line */ -backend.add(import('@backstage/plugin-scaffolder-backend')); +backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); ``` If you have other customizations made to `plugins/scaffolder.ts`, such as adding @@ -429,7 +428,7 @@ const scaffolderModuleCustomExtensions = createBackendModule({ /* highlight-add-end */ const backend = createBackend(); -backend.add(import('@backstage/plugin-scaffolder-backend')); +backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); /* highlight-add-next-line */ backend.add(scaffolderModuleCustomExtensions()); ``` From 3bcaa1e292079e146b3b354661b50ec24b893cb1 Mon Sep 17 00:00:00 2001 From: Mayur Deshmukh Date: Thu, 19 Oct 2023 12:28:29 +0530 Subject: [PATCH 163/348] chore: add matomo analytics plugin to microsite Signed-off-by: Mayur Deshmukh --- .../data/plugins/analytics-module-matomo.yaml | 10 ++++++++++ microsite/static/img/matomo.png | Bin 0 -> 52564 bytes 2 files changed, 10 insertions(+) create mode 100644 microsite/data/plugins/analytics-module-matomo.yaml create mode 100644 microsite/static/img/matomo.png diff --git a/microsite/data/plugins/analytics-module-matomo.yaml b/microsite/data/plugins/analytics-module-matomo.yaml new file mode 100644 index 0000000000..e71e7c41d7 --- /dev/null +++ b/microsite/data/plugins/analytics-module-matomo.yaml @@ -0,0 +1,10 @@ +--- +title: 'Analytics Module: Matomo Analytics' +author: Red Hat +authorUrl: https://redhat.com +category: Monitoring +description: Track usage of your Backstage instance using Matomo Analytics. +documentation: https://github.com/janus-idp/backstage-plugins/blob/main/plugins/analytics-module-matomo/README.md +iconUrl: img/matomo.png +npmPackageName: '@janus-idp/backstage-plugin-analytics-module-matomo' +addedDate: '2023-10-17' diff --git a/microsite/static/img/matomo.png b/microsite/static/img/matomo.png new file mode 100644 index 0000000000000000000000000000000000000000..025786b9487cb7058f172d71ff57c9a5bd6a5541 GIT binary patch literal 52564 zcmeEu^;=b2+wP=AK@e0LiA6|DH%Ko)x*L%O0RfQ)K|%px(I6?UlyrlXv@E)nbdgFo zXR!DCexK(rIKP~IU3-h}Ip!GSiTl2vXN+mMnu*q3uWZ+GhGemf!;u)>$1w9&c>?bP9O4o|h457Umxpf0-eUjSB zMHzZUur8HsgccBt*6J1`sB|OXE+pv{C6xzB%Ap0MB{6D3nV67SpT*N9NR1sbWAa}e zfdbNwlfBU(!#LV|Xqhn(4Y6gI3}hn$eIC+zD+}pyL3gc`I)tD}c8CkEYo!2{)j+L- zgtxvxH}D`X^{_V&Axv+`>>EA(D=0V_x+}M*SI=ZJ?m%9GAA9`}lo@jm>~`f5I5>n+$< zbWfiyU9Jp$a+ZXkpKgA`mu#FB%=Tswf9q^}hdMtOB)QMc8WKtsbxO3^kr4SE08IV`c78lsgFvJ)5 zpfWpgH18Pp0%Hq|LnS6cJ-61yBM91UaB3T6zJU>76ZCV)<7!9ZLOzoL3b2ABTp-9q z2F9V)TOrYX1A=5S16j%*Q|z~qvbADUwqeb--8whp50-*;e3c@Uy7?@C@`c&M&#$GJ zLk7yISj;#_C8>B@)onszoo{n|)vmoQ=1g#Eej~k&xiJtI^YOPE#OAcqVQ5d^>d{Bt zAW436Oxvb_N%Rgz(-U@AolYr+PvMcqTP+%G1*%=K7wAHvMsoErBHtkH*XJRP@{i&I zzo?6i;#Eo46$p?A%VppC{><%B%KQ77so!5zl8Z&~XRUqzWJ56hUR=7HtMwNt4o`;z z7e`mSRJkA-;e`TVJEl{dttiN;8LHd;YQK+5*8~r%Zdty#P?=a~O0T@xZG&fUS zG&;OIM+-@WltVt(phvM4rt&I~)5rEqKePXWBNWF*!}{&ba@unHGS4!_GVQM6&9tYI zE;+}Vi_99mc8X*xge$x&*p^A$kF`IhXv`I4Y2D#_Zy;5iRjpB~9$G-m>z*Ps5Og1| zlv|t~KSFLpVsm6$`pd2U&RjgTO5%52WFJcYSK=>>eGfeRkb6PhVb;uKsiZih)?^-} zrAf+pWFzm$y0y3j9&IG8B@-k&Y3s36v-sSL>Ae}R7|$3_!NRFkSd>>ZUvx`*PrFa+ zeW8h_Z;6~XkLFS#?r6d%?V>cb4NVG7>q3!&&?4&sCoPE_KmChvZ2flSc2(&d^~`e9 zrN%CrTNY#$uh?kq@jr#Q2l90=mJdw%yku!ex}a)!CstILB_z$G$fH}Ku@`40fwPq4 za{R$f1$T`(KXK3R?fl)Hhl>v>@_3c&9$6aM7bPSn=zUW7r2a{Mqlv#{D?cr-Nwz`% zEb#W@Zbc>|CVA`kgIH;6np2u{`8V_LKM@l?DB&ow&!xy}knw1Fp1+-x-fR+(uI!XQ z@7c6=O6kjap>^SSntvdVr-xmE2g9Dh8zdF&EqVzWq+!Bstaq#%2p<^XG*Fat9{L_pORSDbe6Pl$2P_K*84_Yh~eOe zPTl@QWkBWUTKVFxu#WJ2%HW4>3E$5B1Qe&W-Vou?B+pVcao@uZ+ceG85qWD8>pIt< zy|8!TO0WAk62&=EDZ1vqH7zT;9k>|(^gv2S8-Q#$1j8<|2Se0N&#zQpt?4+2`G>n%J|B2slw^^Q(n?Ia*GK!Jqkj^M7u~8(LRZ-wqCbhwR+k2+49Yo%g*QTYB;Im zaeC}4qCaElv)`!S+w?THH+hz>ZdK;#1g+IMz1IKfhKLe zuiL87>^E*{-&}d)yD>YlWvr^lslQNVej1WSA$~9XZOPpklEi!dlgzWPRwzQ9dRvlb z<0=b3b<{l@vO-#+R_EE%4R0qDC9WpkevUsiU5US-Q@M3;C_BTMIKVv95L7K)_pwE^ zw$U=bXK+A7LMumWU+Ywhe;YYhWj=BIe0ZC}yYY~Bb8N=2@#sRlr+G#jP5a51)tKcO z{H)?gq9nWsb)0bKXk4t~=(5#~fyB7Lp}$={Q8zk9g%s1$ct6g%A%DC3LGxwWjt4tF zKfZS4hpt6>XBp3B)DiB&5jDQ>^vekE&p&ZS9=xQorsA}dO4&`3OVvy{Gkj`Tui7s@ zJib2fbuK^ifZzkKsJ^G-o>q_TH0t$8to80tL|S~BuOG+Btl3Ou&3!m$4(N-3=caQcCKK?CZ9@nyS35 zj!+co0)un=O`d=5UyYBY3yIA&?RhyJbsilo+@JG%!E`a$*D&S5v|Ze&+Gx5jx%GHT zdMVUY&}GcQdje^!_sQ@3LhwU2(gnqZgcc=UT%gYL zrH7skF{YDTW?%M|klg3=J09DZ7#vO-&Pv=(jBRoB$-P)_-5@KS>H6A5-Q4qv=aI?2 z&e>L*$E*j{&c_7;)ny+Vf95Njlkx-2@A+r3WU;YVm>5ZW=N3HdGeB?BSSV;bfgmpi z2nq;-ppz@`D++?#xgcoW41$D{Ac({XVcIDNL0|phGLN-hO>fS5e1N&9UHv(#DPmen z8}Lm0Q26E^7fr!0I%d7M`ji-6Ukg3fX@^A!DrhoG(r*}C_Rr6K@L+k|Y0UK*jZ7A{ zR@=8KTG-&{zu)hs?LL`4m7HF*J>mKQYs6T4q3BXe)oH@IC1YpexS12I5d1?^!Y1|a zPXU7Tfmr|i7@+t6fBOG60MYvYEDn_JphF6b7X9KiE=EpyInUud3{_EVj)-Y_zmf-2 zmByV{>J~HKu0k2M$UPgqm)DFD{E=*_XI|diMr2UIa{}YaY}?k-RDoX;1JvJgR*$>V zSNc*IET(<+*{jc0O!J0GTjq}5U0GU^`I~*OIXrGYoMf!9XSS%G>UD@ek4%neDI6v@ zS#Th5)SDJAYu?%w@u4Hgq--AQmK~eFa(4N2wt7#}{e@Af2@(x)U&-LE{wix?&#=OjrJI_SmAHnR-S1qoVI01 zSMn`4!&I^FlQ#Iem2c^nD7F*?@;vf3&dx>(9lb{mPt8r==kQ!gcd0JepZ{z~;WpeB z`Z?W#=YoY6y;NWVD?|AFQ7}W(cFMsSdxW^1=vI~!1f$A!SY#=*{GqDorG~_y?`uMA zuWxL5hOpj-G6W?lZK9jSbw=gu^lAe1+y!nvV*;88Uh^peO_vrAxFaFn~! zqV{K9TDv;|zU8?{q(oy$Cwb#V2kV5xk0Ok!AWHcIy1@A5ck<}B3Rt2xsF+cnh$wA- zTlcsePrkda2N0JmC=R%P%)UJQNHgIEM11tClQre&*}CcX(pAlf^7Mri#Rrc*`5pDg z^^EqD^su)Npw_TcGUnn{E*R2!X2&xFDNNnQijRJ8Lq)_wQR}kktUV;}G4Ds~MQv0m zdIjbXGo)oYEEc7HTb{~tpxbzl@Z&_)0D~LexCPyPxgh^uBFB{7`c!Ammi_SeTcLvn zYyFU&GxeEJ3Z5anO0g#U$xCD5w95sd0};O$`_}#q@4i7j@=+hXVpSp_!{@xhZn!*qr6W;eVx?X$2SPB_IG}z zVRhX7%Mn~#loP28s4;{IJ&G58Aj80qL_Ck(mq7TP4sKbN-)K(=BkoF!0Cjx_mg zWcpt8*U#xv9Zm7ggx%z7`sSj=`Cmi7bulV^j7;ujEFQcoR!rpElI4*6(}Uqc)zpcg zLIo{}pTN(pbNBJ5gA9Z9^O~0vTU&H=J$y;!?pNu_?>9+#bv-Q8Pp5GwE-k|fp!mN- zMOmo(APTY10e6ZYeIipd$N`s#bMpo3-ND5PP(0oUO&bq6&2zP!@OSoWF9|x4)Ag;! z7qFzB9yy_q5ObbVYW}@vN_;2t#ox<)_=ubIEEU#dh};WP7&vaop@8|mYg<55e$&mV z@3Q~A%2>R@{KqDvy`Zd&U3Z@jT?~om%a_w=Zq^y zS4;0o&O41|Fq6oa1&c^St=o3dffaiIEoqvH9L1);c& z=38k(&2ziMQP@{vj{F#3=$&2JQR#CP8S{?{lvLKewr3m@7uxX2xRP5ez)SD{_ocx? zCAv(gNQ5{G>IU6w-&a~lZAA0%#7sq^GsL_a^G=tN+r~hGuc7>EQ#jT4?|=^2B(^FB@R?aVU`)(ccKU#LwM4*1+JafTW{)?J~`VGJu<+Hnyg~LLEiS1l z7_#dQIL_{&EBUl^30}P*v!ibI_gJg3nlTjr<+Cl&5PpNp<*%(vPRSAJUNNKSpYlK6 zY?+n|sMCjk;v8_CbmbjxeKwQ){M)&s^^re&(SjRwIGdTz-(#{VC+xNO zUEE_7jLg@!65Jwlh7Jx6oj;;!mCJLQxSW^Govzg3d#lipC)okq8}Zml`LjjhCcf8P z-M90LiLSLd<}VKMq@1XLHEAR7A?_33(VEPQIhyweIEP1cJJUyH^-cNFWVL{q4VmY=qxfTy7TQ$(Ry~7CK`vJwC|@ z!zPsbUr>KTzE*3}knX2~9^vzcu3Nq8KTstV3DBEaWN<7VVMTlg)^XdCxWsgO zV+&4vo5qj2=~d@q#N2uD6#hj%AwI10@MqWloQSp0DVFh&&u3t?+B)e0`u_z!DSWU~ zGq`E|K2dgHaJ?qdo0%1J(IUs_clM!|@8>phl{ zm00Q0)I^Q3UpI8;F+14Ze}Pyk(%EQ72EGvI#yl(;@2NO7uP1QlX66^_dK=kTO97*~ zIl*&kC2`XtHSKgVn}xIG`7VLR%_0haDPA@Ezamv_1w?9`8-NM;)Abix6&nn`wWT%I zI9X8Md~9OLtMYie^U}l7AIjN*MNQ#}qcs-Wj;zxY8S^hssJz2(*sV6HMt!vV4>7-C zS*@M_gJ@z_5EXS(oeAR^@Fk-?$}mtFg5TXmD_wyo$I zgYMiu4;Uc%S2VCJ*P19IS3qz+Bfc}5S;{g)@y?$ehjI90;%7a5-HH9BsL@s*Fevs< zg^?@9 z^S#=-FW>?ZD}L1{L5Qz)>v~_H8LoV*`(Q9;-#Vrdy|-KjSxPn05TFKi&iQBY90eq^ z`)@ucW%R^~GxuvBTn#etC_Y;W9Xb~rh6p|Oucg>Wocl!IT*M3k35YB32H>8g=j@$& zc^?wqq*?o;r1L?`bivu;lh`PnH{j34%%imlm9vmUZY5g8-)MxpR6CCcmq6@mWTR~+ ziZC?gmDa4`N}(ydH?H43kHX%|y<35Yezp?RWIQxx|GTzb+(QP65@JIW zew_@L@i$xJT#a_dfK)~3wmwT?N9jgwxGY7bxLv(bSwrJ7d`|C)rChRIFLn@G6gWT)B2DZLrv*D zFu(g{qwipiYTd5&8WAoG_b)7c>hP@Wkd@(rcoSKKnTk6{e#g2W_(hVKjfig0fJ_1RJUWF~~?RDSM%V)CVD&ii=e=Oq@u4 zR6mY=cIM6)OGhrbB3f(RMU2DeBy`QmF9Cd0{k@iNE=?S80Y%{$8)#%v9G(xzi!11E zQ7>^K)z$kn{L}21V{}aAAf_{s>Revu$+nF10k7;p!E3-Ijm2)w0R>`n&W!Bt%_Nmj zMFSA2w87|Oi+}pkkHSl^eZ!aUarxfod%jc2b`~RHa!hpThsMSJ>z}HHfUP5J$qPrZ zUbdh2Mn@+jJpbt6aP~2CwAQs|b)cwh8Q0Gce{Tc*DRZy2{go_+&y;a|VtScwLlbrF zN-s0CNheVDFrWnJJh3`@l;JhPB}YV3fv|PoHTA>swowlS6SP0b_-VtMTFV`$ai3TB z{9B*`X0L07JB)Gb5f`HIbnM#zcfj!!E21c_C%~|9a>i7|3SnZ9*l(8&I_SA!iLlh^R6%7gc(_ z&kB?9`h`+Brke3}qT}Vbf1}N4yl}}5RJ@MOUx8Seue|buWtA$XZOMS4XnIr zi^R`@<+<~hs!HM(w2=05+mS=hqpj`BJurCfh^o~Ol(?BmO0WY$>`bdhDP-aej67t} z1LN|>y5`G-xSkxK!YFP#PWf~gi&$R}#6V>&pwaLR;HVHn{4p#bWzVGh;4+!Zj79W# z_@1%jlY<)msrD_f3U>J#N70Rms~4yDWYAkL&F+5%wSpCG$6aS5r`((w7~dWIOh!vs z+8A)Arc_|hmuvV8?YC>JVviS3wt=c_Cu`hx1_vj^uJ$CZoU#K8WdI6;q-iDXKDZA* zl>j!hyJ%=TqM8tSt7i6va@5$Ly@xfkI#*e)&*0@n*-myMr4;bxz7h)rFb3Pwn(~7Z zZ$Qcf3#vP6`cC98QE`2B_~*ysVZ0*d}bnh{;bR&DU+&|r0G&RZBc%4vj3#i5^V!9!yko;Ph!CpkaS@|OQ6TQ$!H3Si z7jC}NgEf?^sv5tX?VDbAzXQC?xm6fgKbM@hunnZkwi4PV@q@dPTR<;Y;9>-Dr!k{O zg3)qkJ+gT6vp5du=^qWE1$<$%pRQgm6|wdL{%+>NzLqi;X6COcCqz_`JFqcgd}zr{ z4v6;1U^Mk>fZe40GEqI2tI9|Yb%CDOg`@n$C(~CeLqIo{wfqO*_`0qI%mOjk3-OXr zi9jkBjon$m6)i#+Vsz8A^I><`z8bzx1SWFmt)C7ddgiK+39=2`iohH|xQUrde!tFu zqN@2*yclqY0kj^-cjm@?Sz{nIJY2TS5TMu;ktblmeqQlQUOS9<(K#)ClZ8%2rDvQo z#}Bj7%={_G>rajsjE~p9d^h^P2Don zV6&e;d4t30`%{z-jpi-peKnD0=5S67h*9ZXj+1ancLW{Z=CG2^XNO{e2OtO-l|G3j zO()wLD8V2Z(DbkiSn?`G>|4>HnIW1KkY_if9Zx~$;54uPbjNV_L>$*lgKD(#;K%iX zZiQn8&@?+k+Ji1lFX2~@VUTjn5ZF-?*Jyh3z+tzcMtfWgdJ<7ziih9spFWjmajRKU!QhaD;*RIz61ek=GNKf(}P%2LlgY-mD z-Xtn&!&s5jt{s?LAky7^;Y)-Q@Tn%MY(oHsVNbOYhIoqC*?y2g{EK;-Dnw6R?x*t|I(OfwXAoA4Dvk_rD%sd!S>$M6h}J?PQ|)`R!rI zjsz^|)JI!`$sFQ}6yLd~i7c-OyxB|b`f;=*4yGz`^ZJYrf2_glIj*e(v>+wi8pOrO z=f_BZMD}!d$IL-|Rwrnk>H!xDr;YqRe!VAtP)$IDo5>ISTXY>fh$JggNh3-Q6wB9W zpX*+AA;=<6@O(YH{p{!5Avd3&?GtI@u>b`_fkDMeVmdZWp~YoiK-{vVh~m1zbES{* zt2-o6`R~K+7K0(N`h5}^^a3%^NM!j@J5Pon)gzIloC81le2rEnFs;mPC?9MNQ-H$W zMU9#i&zeX1UXcumCV~mxfNrWY=%%uYIEz3X>NPo6Yqiu1LPQ0HgQqp1vBJg!mG9sm7Zg^WsCatATp{6%(=CC2BH5pY2wKb=CP%Vv zJ;67ue(9e9W(fkbn1R)^pqhYR(S49EO-s1aFWh*iAJjx<(18)ZK5sWvt^E9`((o&U zBwd;}U|JIWmICuNgBr`jAef9I^5`En{B!g}UYE^Dk*rGxlW?I$OIglZK&4`n%%kWZX#KTlUgVXZjkAO^6MC-RM0G-v1AbKD3+%`3sZnedgwM;pI3ZY`yyX_wNH4%*~`lIy+$wLOrB4S)N z8X<8QO7JU``F655f#@aSThzpuO;i5hGXp?*Ft4rthW$-VdDgVUh7nsu+(0`S;3ZIy z+)miv0iL~QK!=jJ(Y}8zfM5Eu91MX!({P{I8jrcC4hbRW1z`O#W!dhX`u zAbh}z@m?R7yquWuM%Io!-Ji#%nMeXlOl?@t=jLaKYap1x!U(~_F6Wt0Z-8Ip4YxoK zGuYf~G+*NZ>?VZR&diHkpXOFVRq~2{Kw0TXW!3|je%kNS)QJ!WxH=keAHLvfR2rqG zHU5#LRPZxHyg8RIr2Vr$Dzwsbj~jj+Io!a^uNwT8^KL_SZHjPR!jN9OqKbLdyO7qq zL^tsQ;|&5bZ&5)(H}>3MNq3q+td6)PFENA)fJVFiHz2eXNm-UaPm6af|FbIq9J?40 zH?0m6^I}xHzNX1;R;yeUAaVjR?-NQ#Z4AV_0WGH%6p^zdSTga1InSi2SYSLEPs|rh zE1sv}s^nmZn&SlFWBV#vLn@OTY-bVm2_XzXo1D*dipWm6JVa|3sa8upbUQ!{;S? zMnB!?*<-`RX36b$^aBEWLtGDhmh)`24*)a_ZVH+|&R@CsQZ!c6Lb#v;jr^D5IgUeA zYzs%-30ZAFD}Z|t@4&7&ClpeikV2A(Q5fnB874F%^yHb>RE}y}K_MH5kyY?{}A`5#07=TjgZeaP$DXqsD3`-ZI<5^9Z>FqlZ6p z7rcg3!w92+unu^2{2@m+7!7*63(hN~Ne@kTMBabd&?uY$WTNd~VedorsfnD@uGdiD zyF|z5U`eE3J}w$p6VNW&NN>PvalD38u=`65~cN8_c zj;wFr=4PdhhJnd!K|`q`XCn*@vy2DGf_IkR#_t3o)o%6d<;Dp4?3Y*17^NcFcXQ1_ z2FcI{Vkwuh!l)ETp-hJikm;mfxgK2$q@2ysDKO2}?C(=yId5LxNtkIfFQO5IQ}dVH z;C{s$u$3dS)=JiT4YB#`qed-@@LCQYb(ScPZxRzS*bc9eXTWgqhO2Ddmc zJ^V5Htt9OKK-Xg^DO#GrH;^mB)S~yple^Gp%926GXi4$A3b9hTO9k?cNIuaId2xga z(DU>_luLLH{S6FAdD0u83BEaLMx0~DKZCqji!nkXk+vdgQi2+CzpVRi;^2e=Jb4Om zQq3Gx$i)umx1cir5)UIMT65+hUlL)Z6wTxykR}HE=i^LOzGvsz8@>w}DAp$rX$dWW z4R5|M;$#34RYL{?I-J3SFT6B*zr$l`qnOMSh8|#W(0IsHS@%s)?_)^lh_&(g07+A_ z4cea$67kG0|Kb-EyLuP?fC2ApJo<~y9W1EI?&X|H)z0(8jNxyK@8j;QD&qPsOnm?T zy(-cFtkX4|lu+V&T3~)N_!UquX2^?%C9ffRyv~E>J?4h_Y88N)c2hBhROF-%J*Gc# z{Pr)B+ik5FFc-tXF45>g;i_N<>M<^q2BH}>m?^TDHgFK zp{?sBn;dS%4lz8HYy_#zvgC^}0p2(3rKCai1!t9o#CejbLuwmQww`h`H3JVGl4w1b zlX|G8lH~i`+3c4ch?-Z|QS%5?LLhZwpn!)SB}-m-&4!XxD?w1^eQ&jjv(zr?GkX8K z3RVvVIL7h*JEUoYp^6Y2DhMkTE~$y*THe3j+#o*_5iS%RWiwe67`V$a7#a$adNCOD zKGz${iH#UHaxlYNTiutUpYLXU69$HSD;#SJ2$P0t=CrcfG2_9u%RS0Yv8T=etY|nu zl4^FiG}R$W7>OV?7bbZ92d-y)(_VMfp@7fyDHHbHQ72Q2ZLLYVQ!eGNl}h5c(%_nk zH#&eCG+X~yd1Vn7h=I1}NI1)=o~WO66}(M}=2$2XOJNXvC$x(zAQbsyAsYHdS= zIPVyIixV)Mhgt+HQa1b1=WjyMuCMm6wJhz{$4P>jZkS z5HSxJlV)5TG(P(5RyybRI8`t(YB40u`zUH`j?%+bwM70Q@#_H>{{wU#=`s6P09y5l zImdt5w0np_%r^Q5LeYyeawWpLAtB66Ng|gVY}T6rvq2+(X=k;X% zVkQQGDdQQRbEJLt?sJ73W+FLsGj*ZNILKS%s3Gm=&wW1NxA<$w1Eo1RY_4_Z4g^DL z10U!QaDK1uZ!@xjm|xOw+IN*TEo>b(FNlc(GpZ#o7(&GE;TGBnQ+qMMxq%8;AFybsaTfwSNfJ6{+4 z>XtAiJg9S^bS5h>uo`#g0j040D?#6ZZhr;fvUsqYrRx)jDP-H-VJM*EOdb$pK{d(2 z1c8XFW|!0AF1n=4EsE+-EiD!r)4M!=9$l*bkp<|Qpfup}dywEpX$}Px{RG8vX^M$j zTJDOG4#e#E+_xGhVdo4>2}8a?Z>1Nvo#9QJJ0ecS8mRgQ&ByFA_mjwh2VDSp5Q0_( zNK|brmedaJvEA3}jumlzH=*2t!i8jZ+IPVT{0odwY zu1#k^dBK5%gNg?G;T&AFwy|itITm6>~xdr$-3o-jsT`oMg!&2$zbBX)K>`7 z-iVFb5E}a}rIA3|N(CKejZsIF^*-SE{{Ce#i@J%PO?yO!-$A#(TW@MO7grrHkR@mu zh352M9kP0hAV7evnlJ^x;BhwYiSNKufgrYz+fcgBxy_05}GN(c2UI*&i6;`{7SyX{jqH8Ka#o(+^K9^Z^s0H;QRV^Z10ubE ze|o!rIBB5(U!ljyZi~y6lK4JMFkx8;D?hf58e?o-f`*jY?1BrVa2lM00fbW~9*I!N z(No~yv9_Zp1^&Vl08`mk)qGF@tZk0?>AU zE>I$%Y@oRd1%&UeWSpQf8kd2rV7|IVs#XE&;%GOqmRnGOivcsLUNBuxPSM2^812dU z?@DS3psCdOpHHiAaKyV|nuDXbR(sGiyhm;w=mrb;m=!r%@QAjNocZjN79a2-*y_2M`BSVTy~XcGU-SU?juITbpK$5_U)? z$Nb0g{dYBh*zlzZe3Qb3R5U{h49A=g`?l z|8oaf^XEMmF<&iTH}AY>KWjg_(Dh%n2ABxieNsFMtj1pZ^O&1!YGdTGtgHxWPl4V!mTYdcMr1Se(XS?K?JY+)Wq(5)st? z*S$xezhq$$G_p(qBD8cF?fPt-Yb%vjiU2yRcCA$}B#jE>>zV*4M;`gbqF|E);u;l2pQ2d*7m;Y-u49V;JGnQjpPsZVA>j;3bRX|}DfeVKN zi0l3-^yrAM`yfGi1ucZzD~=01P7yM#Wt!LsH}qYQSSm72KYUq2V}}psh*eb(1`Gu~ zEz$gkIP!m!5)c7th{3NECBDab3juPl9XyxLt1K% zz0&;%N($(#%&*KCAAcs+>(sbwx1~#4hMhL>O$X?nJVqWgW}rd1u63X+%6J<>;=em+ z>>X0P6-)}f^|mXMj>HeYED(*=kQya=eyooFAFzQ%uwUELU0HVNqCJ@j_YrjWXwx~? z!Q0tjh*m3GFzW?KK6McVGuq*6>4fYAQ4y`C1oL%gA*WWfre?w7 z88hW(xVj?P$!!}xA1XNtc>P$cXETf=%4P&u@>HlK5#bh;19TJwn*@hvsry9HZIxG0 z7FGaVMhuyuh$hC^pQjOn=UUEwF6H!q2<^tU zDk$_+I%uT%XkVg#w(Du6uf;>8rvRY;cFexZby^V>1G3N-ur=L{xRkjbBY*hvQ=P5m zHZHOLYvrGvm;$r%g=V#l&UDIuUPzfDMpvxQH)_8WSi#Do1*10f!7;+5BrlLe&vJA8 zGd_1ExJ@1roLNPep-VPjPoL|lsolhAD!i9c#R-B>8w4NXmk*rtI`~-j)j?>bMTAUq zw6rgX6?Ef1gqFR1GK~)o8j7~vPnrR4g6ni_FaUwTo*{rnisEAS9YOuW^s!t_+P13= zJpetOSLZmk=6n7h!J-T0!bqif*!G4~@bH5^iA0WYeO&c4;F(916Fi7!j>0!K;1!eT zmP#u}GwHNfoWaD<*J?Zgd#8)-hhiZQ1>k(c)k@xDeD=%?G6x`RV4e**BiF=-{Q)Q` z@1vTS%AKnaHFU{I3~#H#DobDY76nk36%l|%UaKeuV`&ife9Lygz%v=x1{?kL5v6!p zm;oQojs|t??KuMPv0qUPZN6TzdMjbh=vDT*feZwXJ6PhwOKA-pz-^<^jBp8{7Qa?( zQ}2R#l3J5soi(9zbGj^@(1T6o4ID~BF&YW-(Y8(rxH2{)n`qu<8i%k|;z@w2Mi zk&5Qqq*|YT(tw6JZHV zqz$03wm}EU1{6Vo%QZJK?OP80S_>wCzHHBnsTLOxt@dJA?)Dui$7Fm=m7Ts3kBvQ1 zD0xQzu7_2CH|B+$|1;bKyp(e53vQE&owL&V!|Fs$#jp+#)!;tye?%8#Q=Q`ks)OzN z#E+%x-p)tSQ&Kn3B-dw}Bpn@9Cl-}JT!jOfRt}1ge;aE7pTQ*?!5Au!+d2NK$KbnS znmL*o@}kZ}@pirXKo1B3cy)38U%3TIiEq@-KU$iz9V)wGmBPs!ccio%OJ99b$MiPg zPvLQYfUFfYn;@%s*4)h!ij&xh5YuC`GorKu=jC%B)IR6M>b;#GX#qKOV9B8Oq6Oap zd5-jCUAhA|NUDdzPruf_JT_Vg5(({h4ZbbOel}9_#?Ib1 zuR7?*8C4h3y^$hX23AHWkP+<$fgsAvIT9}MIDGYTa#*4BamW&3VD5$xfwPs?z0 zb$d7`XC6mH7Y+ja{=Xt`2M$5K{LM{7toitGsW~?_DB5yoZF<>3ffP zjHm0H9=YM&l%JeN9yW9qhHsQE(Pw0PF{SN4G6Xiu_2Rfn*gqR@8}9A=r4lo++lAr= z8+xo@W^V8oSer@x+cVo}=66s|b|U70s;uUsa@T*o3YNSJh?EG_S$Q*|3{>)9FO!@& z3I>K0Od>k68d zBhCEN^#T_bQdpTfn<^6&~Io!i8mCCjIW#2rPYcyZU?$7#aa(gnUD~6E*08;e+7yBX2ORAj)AOP+g zcy`45zIQ-P%mw30@-?`x5mnWQ$-Rz57B>gE|+6e?0(O$SeyZcxk}gX4m6@rQO{5{Wf7S% z!QG_CTt<&bQl4-L_nE$Gf34&fZXT12{;o>Qz=U*`x6=O=WBYf!H=ZI`HLT)><~>Di zUqQGzM7Ms8`(Ij6Zg>yWDDnp}xPJfBXa9?7|C%E2vPL_u8%85`B_t6#@!QyLzlmgTz>ChkR7PRDLadq4O zhxPXC?(FvdlVEH~~ca?S=0SH4(@5>i{R9Cs(Z zw$OpI)R&kMu_Ybfq-H|OUB1$P)1Ax0Pd#q4*qap7s9h!|QN!$CQ_gUFdX&i7^x~ji zTdZ+}%NVR3`On?QjejPo?{#USmwP~YSl2A!ILm7H9D+^zJBrB|rx6f`6)ta(gZ*BQ zVeyedqFu-8q+Q%KyOGOhOjdgwy9Q%PYRt7*SMyhjvRe4OepDsAyb&_Cp+hDGZjuGQ zx&C4!99((@m>kyh5f;f%d^;uPbUx~FMS2;eko~|>T*K9BF5VQ|1}mYln|?iBmv4v^}bN8&9=WZA5pUAiv>wOZCr3^;(--{OPl8d-XSfL3J`4Iw2l9w>3NOAJ6vtnt_kf= z6U7F~G-_}dIal(31V4>>Gpcr86mBqXYue!b&4C^UA(k5`s0LEzLO*RT2^bw-n2g)-m9(dw4-mmz;heLNkadg1cr|WxRLZ%dhY}i!-e+`JA ztkTIdsWZ$z;#&h6q|=ghI82sE z`6g5P?%{)};Rx&f0tAN28@V!;#-Cb8t|>OF?=+;ez?rmi2!WDt6ezr+Z8E?o0Q#qe zA|9m+d_L?y!M$bhv4y)~myUG%?bnZd!9qGg{`mn$Qv0Xh3c*ak2TdX+6G#nf@p9|Q zO&APX+!Pt2$|rN({xAWH$xTby{7VaW-H7mekb0*38k00XKG)B`2%nR-5&=e# zUzmUO!D_HBNU}pd6`cL&0n$+hmu{69e6JBvExtsgZs$Qm#*ElGxQ9*iJe|s6VyD=A zY;22>^p6yH{w^+CMCvt3xg!k1z!chrpf$Qf`J%bf_q(W)Ak@)wKoK?Zq0Zym7iB+G zMm#%JWyCW!de*X}MuwKVTzbMba?{L42BcFZt)9U(xSPbHp=O>>pT*E^(77_Kb`AGx zlgriIdUPh?rbEWe&=ChXCH$8-2n0tyV zCkpodP#XQ#5;!Ljh3kS=DrEPyrDd($zt&^KWbO%gzD+m7mDhXR^oC61^~0bvSh^JX zw@S%moJ2HxpH=539(SO(@-{f0p-m$XGTB&()5*B>(wXkD4Y7)iWa18S*c84xYa?oD zbky=$ZF^efopty&5tdMNLcvN!In^alXW4tN6rK}D7z>VCd%-6W8w~&SVhSGimFoMi zQczFnUnxm}i$!>63C&eolJ4%}%n!K+V;?aP%XnHS-cz$NW~SB2!6%;N_}xDVzuPCW zQj<7?Bw)+(T|6$mkxTq6j_4^8G^+IfhsD%l=U?;?mtOTqPLqRnWL`S~zi?6N9us;D z8+cX&JX_byY|D5pqxr=|CQrhze76Ixz)>K}R$Z3PoZxI`LPDfPu2*Nh0G86puD8XC zBHF!&L+=JTl4c4!!pZI}aJ-0;WxWx^>T^##l+KY6GdDPi7gkoLdfm}M4P0Yx%6PTc z1?%lsR!$>wQfQfo<}a6?DSTH1bxd?i()xj&cc~hBWe)q|saGR)b2Th1u@ZhIX}7sl zz82!LP=sYDKOa*dV%3r+H6U}SaJK!3Tm65Cddq;QzAtKcXaNy^gGh;pbhjWaN`oNX zjM8lo(yh`mz|h?=bayBq-7O#j(lvCyXZ%0U`+R^;b7$^7_ndw9UVE)|$Y)!JGy3vN zlLK2t!8B#U$LEMa*F)K*fFJ<*t;FnkG*an3;JXW9Ta6SY--@bXHk%8;rmqKcCL1gP zuX^=SOt6g4&A3#VbVVSYua{c@*X2I_bYGtO&KFP6|u;s2e}0_GP@-0Chy;^l>xtaOL&J) z3UIy!l^RmPn)78bvAFs2NMy?!5Y7t4%3KkX6Fcf4bMb#I4xYvvtbn%?tk%!K3xovO zQEUot&N8dcN&#|V&6~y1i6NRIy~;fXiV2WHDpTNdtbmC2Qh^qbz98u_3o6~!x7KT! zcLCWlp{4#!&Q-n7H*;3U2kqsk1}LLfrv+UYVk?&I#lt!6Tq#k%LrTu0&=_1?5Zc$E zDc6opqtCO}pFJq4;de9lpBa7L3hi{eG%)~uGA2-SO8+Z?u=YT%TE^Wn?leQ6=eRR8 z{@-0l^q(8?%Ie8o9gSr~lXFHk{6zdw%z%cO4x(ejzsloHeXSTj->n|rBF^B=At4a+g1>~%Pd#4p)X;a@>#}8Q? zYg+cVeb{)iOq?2rk={8qoWlIStyJ^=T&GBje_#1Bg<~8o*)YrPIoSD@%v~(XLC0eD z(xzJB0yifRpm@697(k(wDpI6XR8^aZ(`> zqJn&~v1Bxhy=+gJv~S|I>UWe6$}7yI=fH?_2uf&|A2j-hDc6Ct=4JTbdfC%HGDX=$ zF8v#;-l7-C<<&#{9@&C-zQgAe2c=^V5k+fF-n9_j!A>7k(S z>*eaw&KDT2VCXZ8vtwOaKRh@8Y-+DN^7MoG*DjXYl-CP2OQ;`G=WoldVdt5wnl16{ zqIYZlGmOzmjrVvW!vEH48`%c!y^8m`m!YLb`NB~pM+2<#UeIG9mv^T_&-Cc_ICXMK z_bvpD^^N^qDQh7y5C5BAk{X0-x1V9)wQrN+BdI`qRaZy@p$r1!JGR`kFn-tC=yw2U z`-gExghv745eTk&1wFvuM^YrdvPTfqpK<$9`Ik?hGlipjd9xthes_ z&tAx0BCv!E(q(4mw1DL}{ODZ2>37W)!^HZKIs@JP{s*x?dtQ>t$k(e=EW06ByveRk{uj-W1wA+MqTb>T!f{+SLl@nu z@Za|XdP^s%?Kyv86sx&b6n+Q+ITq-8*n|NFb)3@!P)9;yE11W4wwf-DPYt`)Xvh8Z zkGp9?o#*+Pd!}FLH>}6izf@tV*YMmf7#7yb;4RXGfql^+Yc597Kd6sHWr?@e-@b6T z&S<8SC3%)0MXt=p#&1QN#ZO4TLAT?RggLuV)kL70;#V>7t01ZQUrQCxidBhS25#2B zm;RDw@SQzek&2VJ_?giA)2io>2}|rIGs`r&B7W2tY;F7V%|JI&!AZ9+w#AR`v=rp;AD8L>bJNf#Hj|PB*&5*ym!p!l!YbqGs)oYNP zRb2a(tuRMBl* zf7&7rQhK!AKjN@t|PW`NN#mglbYdH>q-R zv@?Q9YUBqFuQ)RIC<5pzob|&adQ~>jxpcC+J-!iWM_ai+V_^FXR)D!Dllm));=6Za zajC)wMAqYGxo&04n=X6am&R+G$3fvhNqy8-`1b#8w!&1(QxnaXep8o2L^aU6>57J@ z+Y0q7vDr9>-q9+?l&esBzqD}Pdd7X>s`;OMCt19HYXsN$D=_7iPo@Shhv?&-_@b~i z{XSBNPCc1R*xovo!~AcyB=ENz#cM%wDONgpm{z^2qW&we)};)0RHl+@7f+e&sU4nB zNOgEwet&;4c(L5|Na(5kWU`(sltLK+BE%aNdOxik0BF1(#RDuw$X9?I;WqCq2-&(e zq{1Nh$BWdFlg>lQ0w>c#EeP&wy_%^g{8J>sNkhm<1r^z5u)wSb>-hJApEo1+nO>FB z&E=TYgh$^p>jgwEx82zzc|MG;8sW~L}R_4&|HIv#0ij|~a@LJX2lMr6g zU)&ZfjL0_(!i8hz@O#X6LE5EI1OI^uU1Ls)99~Nk7CbV1vFtLCbSUQ^P=JmjNCk$n zLJ&u~6&nC)9^%VDrSf*?Nifcj1s_K-5pK6tYU_9*bG}|fg_FCKDD;!%;;_;=pX#W_|f;u8ZrKSm9zT(vX)X2fE|5RAy zMytltF~)w)y9R03voO8ZVN!S|-8U4uP=7Q|sS|23@8%G3+b0J*P|v@{p-tKkf8%xz(=wHP%{I56OMj#n{rX3 z(%OYfZSjRg86MyGvySMzb%QOPzv6p+Rx_hXW_sVT@ngZ9BBJxt!a=(Scp0fV34uxQ8|+WT1SzJ-wnG7u0_Si8&Q;39UYZd3H$v4Zk5=$7MJWI zm$2X&g3tjGiugBbBb0XoD)04T56*H5$7nan8OofpUSez8D4!5MpG4SEfb!fV`%3edwpP5XEUSM9k6KWp>q zLhYtw<6kmEFkTz*Br}5mY{Ib(4S<}8eC5#uIy3ygb*WKKDHZcf=r35%N%QtAaYt!l zVraGjw554>Z*O=Ei$1QsdS3z;#q?!3Euul)Nc5u?ZZg1crwna!&y~=!9H^Q`xj)PRdoZWo?KDt(l(!oCZ|(Iu~KHa|U-g_WbEZYC-kd+8?Nr`1G6W<`!7ZSmK=Mu25TTuH$c)2L#yo>LG)6iU%eO)jNVt%m~F1Iy*+M0n}iDjs+k|<69Y?t38 zt}#$;IxY);z)Sd?jn>^jd^^x!knP^?h+{1`J%toL<>ER$ajQPSWGeW~U-_&VP;wf$ ze_Y~2S5*WhG@~j>BZd4V}N&>Fa9DC#5gdF)ITT2e+ z8`XPGoBnvlq9qFOh(V}srog-HHThtZ{Ffv5B89YU z9&`+s+u=;gC=#heonYaoHtF3_ITP!uIb_69B7Sk&8j|dn zm~YUI4H;tON}c+@@#}S2{`>vtqP5kC`ink3F3+Dv>WHzqU9Y}6CHtgAA)Ax_RuU-& zA}|F4L*pU;uy3F|1oeglNVLFpX+>adGqg*o%taSWdF=W$x197Vn8)3XK!ul@D>?KZ zGq6?3`^_9GFI<$v>zmfT=eV$yuf(2!eh8Oozc@ni)fTz?_8Q`CRw4VXAhi$R+WIZL z&RWxVNlPi%_R^XIyCpP+qzhDY!0(F*ZHoZHV4I)A^!50@ucPMxNC z){mp9PFq^C&kub{-9CD!>AWK6xFtlaP)3{l(Xl&`6pi(O$yktwAxI)3D9Dnn)k6Bs zC|J!ov~A**-mN;uaS{n+6-n!5{B|+zX()e6b}>VIWv8gZt!p=7#$0T3iSPp4Ggi7} zkc5S_s{UKSZQhrcyY=o9iwnhbH8fH@YNWs}i`MOIqG3B~j5($Wp8dJYK2h{C5}Q;( z4y@zfe>#EQoH?W<0z5~w1&`?#3dD0sNvE0%=1(t(8QL3Yl$`$>?M>3Ua-_baZizy0 zo+pI$kf>>5DdLkxKs(}rE8O$Z6p(0ux)u^$x}dm4A3A9>5$1u9TiCUrtQaTuA@`=~ z#ybvEwcw5RtYd;YV9b#ADVSnrB>Fk>=<5M z8;aBn9^DLbi99Q}H~DsaB1yk>?VgbNWK>Aew}J}_^sqt~O*NhhADH~N1HdN6z_HLr zx(Ch)z=i-6842xS#j4^r>M5?b)Lr8A)Fg6}^PYjm$F+w{jBc@oi#g|qlmBUIQiJCR z3w;1oN;K>nPyWrNNSG~(9yMvxBhqF%g?kQ z`sKTNK4b8pTE&pTU*rkb++=#>$w53K0kEiw7By<^Pc_o)-$E<>b3V7DI+`f4Lx(=; z+KDRgxzs7Yv%_u2Tn(znJ74w9_!K6#gigx48k#QmDjdhp#aZ7<=LE)(yaH|wokMaj zQNSS{rf)~>Fp5X(8P4@-zdDBO$)v+C&-hoZTjCAYhZ)g{O%t&_8i5?k_n6fr;6%LDJ*>%~N9gvAf zdhxrJ(|x@EF$T&+Le4G=a&67gRy1JbyK!7=bm(+4zc;>?`YHIcXOi#Zr@Qm~a*j=F zhF*Vz<6d1TC$@wkI9v1(f-low6S6QWQz+gs?RYP)G-^-Z`VtJ~*I-;*-Mz$9yyo{V zwC!zGGs4rEK3;aQfHdOR8!^JWjKOJgRe7Z@%I-Qu-n3Im&yN*h&#aLi$WvxikZ@Pd zl1|f`^6h?dMAUJ!yTiS8go5I4zBCBN9$WxWP;hS%tGA*j@#t@(($r?9!$)q&VA>`E0ws`nqOnm(k3ge$+>JFD zt2f>B*jS`BV62MLL}Y3mp5?y{W>?@lDT@%>PAV*26i2;eI5$gZvkR25j$M7B6Haaht%3sE`p&Tr1n3mzFq?6cxixdTf&aWdL3k<)pK?Kus0YTP;a10 zC+c)y$tQY>@|d>nId|HR04+Kdt%U}K;sxK^k4G_rlvt}N_ zMYp(`O?PRvEJv}iam4Ff5hdQ6ofnrS^@$}CGy}z|Ti>vJ?xz}kd!!5MV|y%kMDy?L zq&@a3_#@r1Q0z$ofT#juKf1{YDU7z~1A~-x(bi#Nt3A(!iK#F;U~q3jXi`#j3vV{> z^d+)ie&hGxzOX7IR2RYOdc~$8hHnuRt(d_OZ{*ojye+I>|J469&CL`RF3u9u)>~cr z*3>-Qp2YJBd4Tj#lC)mo+hyZew>`rXny0mYqIZbl#_!q{gx0PJvC%IMe@WmSI+e0{ z!h28F!z{^OF=0M;VN)kSFddgY3%5_ZnQ_d@d>oczMy-Uf)=W|8<2z5|!lE>2;p;ua zqWWnj@QwEd##HPVCh)CXAfER|D))7OchRVK5}!A-584el7+4iL%(?iY{}6)qBcf|J z&$)L!J>E}E2+?Q_@A?}qa`kOb7Oq{Ns?ce1+?NF6d_qu}*||wc^IQHqh~yp~ z^T`*^?-#j8*lOmK#D+I2zo+! z)#nalE`oDI@s!7n15LPd{nqhs8n*rxacae_PYK3HwVGRn-u`OC_4)pr%bp5(SW7%G z`b{#e6$lxmctfdcH;yZBGJ)*YxNKP%zA@wH;&nYkdOWw&_jY8Ctyie!p5&2%jm<2A zy@!w~kbp5wRtL0)Nhz`V_;R=TepvAp>2jB-b#Rsn>D67Adtt5y0?bCcDo=YK(G{}r zCqAkUA@8)hC>G~-DKHWn&)}95$WWI1EJq5n=mY3!#5qM~<7nN!<*XcW%1z}xr1~=O zr|TYn>-*ruorc7Q-!EFO!m+5Y^Dd_@RZod8sPRN6()8GR{?>vJ9Hy8M7UAHf?U;IP zDPDSwj|rD*8=rS_neKxAAjexN%BvMK1ghH28 z*+0RG7_^p_x@Btk&&7+B{rFyzsz}ImedlBBYDR@JHYoQbt^FzLZNXSOEs^GG0;{%L z5&wTtmkiJwo#BH;9dS>ynJ!=Rx4y}9mikzvH(jO7=_0Pv($rLFEriGMBP}lJY!$}1KC1OStW19&rEYi|jH{bQ+)M@f4KGk@faO&b02BHI_xvPb> zb-y)^SO3(v?*OaJ)SqHadB%;OiAgGhFd=G(cF`lFUB&JSQ&=J%f9Gu~@$M)FT{)k6 z9y^HXyY3q1?|cvMx$mmrQ*@kMvS^mp)(SOymZQTBZ*I!2;8AE@qHc-}6FN1ENVe2i=Lh9!8u2k@2e ztj4uSrg^ir^L!q;t3?0f{b;LeSdw?s221f=xu)ugtIc#R^fpnQNYr^HV=>0wvMZI| z4@6{&NDPJURG&X8r~id)yuh>#0R{`1*^7#b9gChXaw~TwK58Z*Ul^Bc-GqTPrbaIFMWfRg;`>ov zO6bu`pSTPDiHY<1xDh%$9}~`jp$94tquQXLbxZH4EsZT<%Qh?;jy-w*|0d*-2iEtJ zPBei(vDw^GVJ%0A;ggo&pFV}R_5CSxU~TOhDGqUftY+MT*h*np8_dh9S392az`1P2 zTW4kl)2GrtVG=O>E>HU>KeyKuuD{VzJViEEnJtx~x@$t1-2HdgaM!hGLqv}l z3jDy3`R+HDmPTl{J`k{*dc#Rwm3hocGj$S^h|Jh*ih>`#yuEwy$&75eJ(H;3#feoZ$8SOKi8WpFSF$-_7rVzb@Zk?foPx0s+`pjg0fU7dF!2=b%{ zf_7ui2a=qe4*5mO+@d#?uZqlo$<~%*UOUd^%NNAt5zM zY&Ue}Jx6+@;X(YZ)Zz)a4-orWsEXfI&t7jTAKO~YI}GH{W$8IL3Y2<(`8&Bc{_BEf zQ~p?0U$vyl(ONb4)zG~fTcER;B(AYuh83k!+e{#qEbJ+5CL@+)cY4Ncc}zb>DXu5K zFGXQY}mQW5z2zrPU z)@x)cG&PJQeij=fzgDDZzGd)>RR%^p3>#x(?oipr0eJ2ulDuDdxIcgEcj0(hdl;YV z?k65Fw#8Jv{q&DPwPVxbeNhp{t<+){owUPc&R2m|$#CzyhL4`ui!#SciIURXbC;QE zM?V|aY5a{)eu+cb*|bK+j}ZxXOB{DtkcUky1y)hN-|tYS24%k=npVGxeu)lMeBb*4 z8|C_xmMHW{JL-MueFfw5PN-Jy%Lr>eT>CYhCxa}EVUPV{rNAU$+u%+tdH+@2qS@K$ z^5bN01ihx?!I1hL&rJCndXJ}O-nGt2t@i6A=t-a!ZgL)m;J%b}b`jHb-* zhdET>tuio+l6L~%tQj0J_yzPAN&JA{C_Y?*Ay~abaej0Z%N7NAkQfS6+DGa31s>ZP zjdNg7gPKx!9Ynu;8LM@48}>09;!_C621(B2b|F`gs7w68%~AL0-W>@cLZ%9Ra*s;Y zT3XNm{~5b_D?*5{9iMb7%HUZF;S320;3DuN{men{MoOo6|M&LD^IuwJ*V~)h`mJqe zx;WnbIQhw2nkP7`;wgZM5CLkm=MSe0m^K{Y`fR8;4V`(D;y9-v!9(h`{RF@38ljX| zx9(flH&~5`9vxB)kO9a~4`hWQIO-KD8}_v{O?Y(nxF{) z8{c3Gmk61Rio->6S0KlerYF|?<_IC~RelVzTasA`vE=jfF1f2?EIi;<1@WcuHi;g| zl&J-$DhusE^Q^Fc;^tV*$FprS%ON(D*G3#a|E`le=ol#C=TuC(yeIX zsWVzX2UhdLB9t25GwC6MP(7_l6~Vo=z@iOxX$v~#&!tvua2>>qRmymM&j*ov%K>-C zI-RoBPo5p#JDDQh?*CQsKDyQP6Xk30(!NIiMI6tpkoj(OApLD!?X=Zy)gTl+6sa&mL+O^0MWgm64K zWBI>&R9$iF6HsuysFL1d;`{1htjb9?GZ=EW&0%%(*55wtk&m6|P9q*7*e=dQNY_)V zy^FAzYb!VL)QK#AMqL_U48Sob0lph6@Ntx@tN)@^&$8dxVpgO0YJtAyvzNJd?eS8- zi7Q9UxRez7HkK@2k6xX(PBhi~5X8;LvTd>Rjir}=z^BWCRubxW_L1~G!eSSxiKThP zgEK@ASk;`&no-WO^&ezRGTxW^KP#)~ZssFZ)t5<3$PWJo5!6%s$q{(qQq08ere*o4 zb}0Ee@H+QgE~-g-J0}boZTaxqrk+*OGa_OV67VK_ZLNM4KC8TW`Plai2ylY}-=IdY zY%u}QqA{wt~Gzl6*+`>Cq7If;uDKS%|smWU`)4Q$Pli?RKxFOoRQrXTi<k{Xaz-1BLm!e@_vGhoa(f&|8k*XFG4|It5Q-)~UC}UaWP!06#ssB?lGl3 z>8a2xIH>XOrgBq{Iw%u>$E%lkX)uh$#>Mjmb=Oe!DB}nXTtBo^mGvHBnE27v{KPuw ziA^RNBmZ3#;kyQ7u?mgfKivNGj8?FsK8h|YUVamysT??74TH2J=kV7isVc4 zGx;eK|K#|&HCKk%=Uwr&8&WS(BVp7*P~D&@;Ce}>b&Q5FyMS_^2!6ppqkZzK#%)r< zHlp9Z%k3%^ll~+-_9pE(^4#Dv0t!0Zz9`_(mu0TxEpakUa3sK&1J}%f%DI%}MN_I~ zvI`8xl1XSkGlc;#v+O?QT5s>_HflEhXPu6BFoRZ)fdOC<*A;RxW(V>-;+hhM>sVM^ z8x^>6Cjtl6uU0kYt>*3Ow&vZ@aDesz-e1^dDDc?g)}=0iS7P>ohbd1xR6P4&?lx0i z(mxH`&ajuZ4^lf#$<|6@3_7e%f{1w|G#7su5NB8VMeof;OneD^#hTZY^iPU9~ zg_vgc7oEp`_i46z0~=vvJAPy;uvN*ZR->cfE9ZW(uL>H~Ie|xQiLwz}ISljZA3%(E z8+2K70QR{t=dLIIU6bQ;o=f%8|kjFu<2Z+9{Bc39!7S` z4cFfOSTs4_T;R&Joo+@#k!Po{^mc21vKt?LVSM?QDyIW(tQ_~H3elq9nfs=qbEdu1 zGpVoIoku=&l&{Iv(&)*8q#|qU$TO^xc=Y&5%PgnG6UA0OUZ z2c{QfDXhGuiahG>x=8=BbwTxn%h+Z*8$hKcy*31IHEr4bi{eFS_Gfsho8F<(3A-f? zXQ(P2%*SkZzMA#pR_@dD9G^8Xg>C$}vvR9|;6{j@4Y1YH{Ip{ceARaK$A~YNA z`G|_&3=UR6Gr29j)1wiL>Ee#L)#Az+_Nl|~J4yt^`&`ktS3ifme_Lu4J}uLnfwg0i z&wJ4d^)=;1&LEf*C{Zm^RzePK_!_&|o8Rlm0B^qq9mb-I6W71b6>-ZQL8f*(1zH>rfk0c~A}Jf; zPd%Q%ydyNQCqUzD-{kDe3O|XxIrz+cWqCnP3f7~Vk|$`oUMUT1-WYgO8fULK3h=&- zo#j$Tw^D@~2I0sjm1MYnU{4Wb?9x-n!j?PS9~MrT&tHUAQql3O{Cc zMmu;0M`HxlI)eM1(Z`LSNWVT%bwT;F-$#NtI?&n3Qpl3mGkwSOeWbhnV}J3Tek!Yu zxdizElYASViWEmwZLmaCs{^zbm${1WaRC8(HX@Tt^QBO|B858+z@7bw53jbr4D9pdjAge2PAW{7A6&N}$Mf^UsLwpY4`TKYS`E!gC43tN)MnmKZC#JGwWq!eg_q>=v z%?vu-kPdtv$eXztk=CHobkT*6KO=9T--B;^W`aI7wP_Ef}<81ns-W8=KTFRtvutN$)^RX$b*= zBtKCF29TZHY$3c%qhTlqPYyqagAQpy*qaV>2we>H zK_fY`6aC=-5-UlR=2JK4cYV+WsFZZekv(m1cI$1w3(+|^fdG^t1O0kFBY%QyLkFQ0 zY`4+)17~rZThs{$Lj-XvGb5DP0hMGAScw2L3aG*xfkd4w@i`A)^c$;2`2<+mO1XSO zdO7CYIo#hq&_RNp%qRD!%WOBGMm;-x%orGN7|ag#w|AR{IWW}bYULx~y3ar;j=p8} znd8Q4*n(q)LL}@1^FH&La8em>hPhMgNZ{~#=1;!K%pL=>3%Vm_cjU;PiF$s}@Aog( zVwzJ1I7bc%y$V8qw9zUU%fOW~rgTrpyVSRS3e!!pFmj~-g@R+NfCcJ2Ju&~JlBL9} znaAIhO%;$aGw42(6!eTwzvfIs zi1oN$SuVvqjlWb2@xS@?Yhb;_0O(&WJ%m_Cx7emXvW@q#p|11fBXg~W3apZH+%3uG zUoDxE?d;^d8!Fka$DX`kbl0E^(teppyER6Zn*7ejLp{N(SRm7rL}SAg%}zq_m`&&t zBUKgjnG`02Q%-f|YH7O+Ao3FYl@jKyE)LBcm0ti$!gqSXGv}iE(~^BXc7(ZXR~i+~ z3$`-d8M<_2+ww1$r4_Xrn&{S)Senq@3RE9vIB(R6<|kHn!|1eZwr`%)N{Zp$j)W6j zvJuq1T{5lvLD9xb>V5K$ST%bo?6R6fUZT{$M#TWXL+8NE&;JIHW#bxdMl<75TU~J| z&n2lQ-v8?}?&U;f&bIFtuw#|~0X(Ze24-`fS{OWB-SQ1FJmd11z+(hgVey+;0;7sg z^{X9l)PyD-SfexEoyg|i6D~YZl7*xB$0Ij)0I~kRICVu`QSmaaIH&joJ)gMi!e`z4 z3wVWb&+2l%ixk-MN1=b{-1{xDbx)>AZy4e*oYM~_+4r*oOKJc7=Ua}Tno7)_2eU57 zm|<;);NsbKnH)WNVFP0FOuwi`K5&wZH0~qZa~A&D;3f_kStH6p$0SfjFqP zGy1BSZ0Z<3Y7NKKR?Vj~?CBN~zl=pbrs@r!-ACW{SV8eM@4&jduM{NyuAq^k?v8lb zjf^bbtYiFQK2u}rsfe1vw$6}Ve$BW$y2+cn=D=Q@6Y8BRL}%i_yEJq2gdd{s#`uLv zY#G*`02q3AWqZl8_(^ahqHU*E2FxfHnAK6_!f8$FEhG51VLbz&@Vg|uBhjBk#Jk_k zU1l;;*urP|2pgK2tAta*L&=o`0K@v@b#MGncjN2LWVes8d~ z?tqoN_PXA^x~ueitvv9Xvhj!f;ks9*jkt4a4!7&&ABeN;Wg~Lh>Vr=BmabG+nkqi7 z1+ESC^pTxMP5oIzG#%2+Fp1DdI({H5U>UDV4^<3x5zFp5F~k`y(V5M(wLF=hH5uX=jE#TZqN07tPld321*% zNIv#rFPaYd!Q6!)Zg|yQvS3BoqaNCH)rsvcN5(eCUgdZsMsVyIf_U~|ZzRWR*)LU} zsWp5!l-+nTZZXZ)#NhEF_dO;6f5{ep^F%qR(IMi0LP|jTm53!_;k4rpQ@2wwhCX( zK+WQNrd249yf0BsKN@~n0b43ZK3N>O&lSq?bXUvxUV)}`K^VvwSMD7OVgD%r?wCbv z;MJtQj`p(OJU&G5FF*EeB5p!MQAW;aBQ^++7FE(y+d-rRCPq5crZA?g!5ts6(%!PyjvvEuWGa%T6}xnjZ&HVEg+PZ!VhTUPR@EdP55QPxz6g=(vyr|bD-2IpFW z`GC?VVl0-z8N~JGGmvonyW)Wfdec+W7@K@YnW~k4<#=QXl1u41Go=fp{}#ax>B8hR z+&pRfEtv$l?TQ!yjce7*_jW0-M-K1Av3@RkQ$ZG##s4VL-_)H|{aD8;xdav<(|4;F za}OaNLuP7Br)QHJQ)UCz{rej+WWXK&{^6bx zn9H<1_rDw#o6d4+RL=kKcpx*dT-2G|Kd32vraOrSJEWdG@Z1eAq?MVxIhx}1`#t}%+PsJiL6=Z|;JvM+z%=)(# zwRi9a0U?42!F%{vZMCo^hUWmEV=KRgJN`TzZ{HY)$APnEd(2V~8;w?I{*Uyl68t{p z2|gXGKnooIs%Oq|`^}0fPgJ(ljV#+YSg(CrTs(nAp#QR(OqVYkv*dm8yr%cr{$JQe z7l1;VnHWb|Q!5V2bkVhQR(ic{Z(%(~{V5VNo~065-}!JFC4i1L%d3DT3|OxTZ~QSH z-zx;cxEvq3>~qyO13tcH7M+S$=Cd8=%&itsoq!(hgY{Im+FAXy!4nC1$Er`3cv?2J zxk9swVd(zGNbHm~oBkyE_6TF_x}JFlV`RHMrgC;)JZ}*B`I1*yngJ7^_WRB~RJ zM3#*be)Jp``;JMTyDitA3gohQ5bo8r?V=FY1UNvwjZuonwj&*L9m_AmzeWfFiD1+F zf{+M+)Giy!0CS5lH?nC7F=Opu-ZGA$Xaku+@v}Pl@ISiOZ-oyYl#t&2`}wL3s$6#- z#rDG=zwx~>GfF-GwU(Y@{7>x3gTEc)Yh*pu%~&NrTn8J$`y;$bLX;Qa};?AOSu{x|#7MH(Ne$<3K!V@f4!8L__k z1J%u)xT%;`=Xc}AjCZPu^19f*hY6x|$U-ELv{dYCQvz*+rJgJz#h|PA6gkq(bR=A* z8$@o3H_KAC2smO^X+NRfTusI19hc$P4-<;j+CRvcn(0v)NWaIAJx{nowMx0YDQg%e z<{053VC=i?O`s}Y3A%qAl#ipOr5K+NZg=Wxv9Z7ZLg(-iHjlZ9BKgxves($tgyl!v z$Y^J)8ry^_4}{^lRxFf>$zYBV2@t>We)zVqR z0uKj&NWT#d93i36ZG41O+)qOj{~j)2@vKsD%#f?6+94pM-BIpAzTOw}2mKwP#K66GO-6pw_hOvhjGDYucZYc?sEhACgOFYOiWO|h z*wi=z)hJ}V1~Hi@__1pdAKRCq(G0D!gL?TqI3+a%_h-w{?0-t-YYkI(OkHH$0J3R_ zls&3A48hgHdf5p(k_>Vekm>u=IB55yvc z*{PntJYZgGqkIddklf>d4>H}NnwI|)jvFKb?&~13mE;a&Vx;8h{b9 zQ;0iQz$C#s)L7$0F;aS2q^cPoyNuB4&Pd+LGe=J=}TiR70zk}+`oX=U6_Z}pEDziE_$#`DX_5JIG zbb1-PcB#PxqAEJV9Mg6+u^La_op_HG!aHh~BDO51u=XE_P=y9)O-jnO9N1s=2M|Xi z*(pwj9xx-if{4@mzVU9Z;P9barVSDF`*%i#S9xv>ncY3C1rDjSXoHj{hLm^PP+j&Z zq%%Wv@F~=nqJr_dG1~{>#JvO{yNmu*=P!v#Y1Hfiglx|)Vfl7kVwWbLa@*xuVeeY4 zf=$XPiL<&15W6xpH0%fbx$E9p{0|}~W^kU~jl-0kWEG2E0;tH00)Bwc6D`l2-iuxi z>TEueX~%FyU2dfCN!x|af*j=S_Hn@}x48T$H6sxTT2e3fzkSEcDva5bU`-PR%X51;06$=LyS2QfMBXKUybH~ zkJlZyHTa(r`(g{*GA!MgD@Zav1f{0QX@BGREXv7vFW)LMOD!^Yn8TB498^-&Me8+g z&E+9Sqv|)vFQ!T-z@!a?(F{GzLw9E!4+L3!{m@xfbLo@jABvin;e$XFwkiJfxrGUP z0Vj6XvJtwH;=yO8O2VG(6|~in7YR7M=NnjuEUoR1JG!SZ1O>wa?<<@u>Lhd=iV!Db z*@})4@}5|qR!8LQ>uUSG&*LC{xLnuSYGIsV+c_qh})l{j0<-fEEUXi#^w?&Bjw<)AyZ|yC2iI5Mc^8Dk2VK_;rvD3v8F1r14_qmKitzqfaQf=U zqU<3k2vP97$}Ml_D)Cp3A>$Py3bYZI3SBvPlR=q6EWRslhu~4=EO*Z0vnBt1`1`-T zDJ}!r4AVw&!>qph@z-V3bvihoCkT)N(L7#sz6$Tq(5gk(Id-17U-gH9*?RawuLq74<^(v^ zlL4F|cUQr^GCL&@2jY8nXkKM@z*(__;g11P56wR9KF3}j#@eElbHK!S96Sg@hJ6zH z5;2YquRv^Yf$iR>mqs+i&^wTy&wN1i4Sz3QZ><6=Hms~s7?s?Agz;@$wt69|3@=IxW~W zz0Xa4Cx;B|$K5t`j1fjW(uvXdnG4%zRneuUo+?u9#bx z3)GOpHg$!(NQrfDGA=7Pf%h{$Kv54yM=z=xEU!|e0LCp>YFxWHE}S}D#aN~dtPwF4 zKzR&NV;m$#UsV5MGzUHK!t>W=Rdxp|K^|;D4W_J925hqdY{Q4FSDx7+oDJ7MX<5ZS znv??|aj4Kr#n`HK_*K+`t~$VVvbMUsPhwqPWnI1$wZ*ZdL4Nwe(TnR>aKF!3cWef0 z%X5JgQuuQN#5SWxZo7wYZv}uu#CxMv84fxxz7JmgfRj zI;95HJPyo)ocKsE-Y!b+G<)F0h#&GI+-EOM93#0m3>B#Hi9uCeRN$6nF?2=f2MmG1 z3A*$V%z`uvYz3*O*uHFsC*ay#e^vAev((+hJ^+IacJ$;lK=ET@Kvq4bz)VI8rwlu# z^f!LuhU7~h-lypI(ga6k4KWxgeFFQDn91lBU{#J+*&_po_+-1Z9q?nW%*n$!m>ltA z@n@N8@6VLLs7<>$n0LunS`BC6rUbQ@L>pUy_Prqc*#c zejJRDch^gPmH+48gFWKjU|Ar96po9Airv0e@L?1KaIf}@W$l54V`gxZ%dW=BuPj8| zVJUqc5GgXzk7miO-#`q(P;iW?`a*&MQKS4nb&nY+*~1p~K-f$CFD|;k3e(oiE?x-r z2%^@h4mUQjk^zt91-}Uf*YF&BDtxq9%s~7N_fv29U_pMj|FIRylH_jeod>f%RY%+c zqHp{t?WE@lJp$6#b&2f*JFtvE;LnK97%) zRdQYhRC?qf!+%*8Cx&X$x+#sQ1kvq#ljIS~fT z5!^=5@wId5B^%;jY88;J^L__o{Oc4M`qnD7W_)^JQeaQWZR=0)(Na3BliW2){wQn!?clOa8HhmjmdlqW!KW*~v z8V_G(!^O*txe8)!iPL49YQ}rPOIuXD5PpLRfqj^9_NcaMFC~n8uVr_aqi9-JyR$2o zZCtjTw~QdX*1Tix<=j(n5Ovf^)zCqCNLUe>d<7*vC2)`EZe|lSi*>9BWqqe38g-?v zhh8mzR*2pU2P-m_84n5Ksl9lm3x?s3m))U)LMxpns5$TbQ;0D1Q9Yr6@VIFsjcaXY zoYG#({7X`b0UV~4ZKRYQ6ywLCX6idDl=FWKRS48jus3=;@%k~IHJK+F zCXG1b)KuHi_f?>Jq2EDn!~THXEsTpzj7!I?tW<3dZkAA0RVW-%{NYj9oE+j;nc_dEWn9lbB9 ztl?|2`8hwBqLL!2U`#RoTXV~>VJwXcX*+Xvl0g1{?Y(tZ)Zh0$JVB=t(x5VcbU1{h ziULE*&?$DYw^c0abm}{ zuf5NCoimsaO+^OL<@=88U^7pF{$o}D}8}R>KMEp+=^U~1@`Ua=Vtp8(8np7NM zBlmBx>;FrI_SpJ>!OSgY%^k%3Ze%5W;EcNSZpEAJznld=bT>6m5i0 zH{9sykbtLH=az&9me0JVOw-5=a%WTrpr->k&|35bKKR-M`*r$k;nhj6N1c|#22@-S zaB~0DA6$#m9SkFcb@iV6Wx@XCO`nsWiV@CqE+#LEoNAXpo)?>tp$; zZ}Q_d+a2fb>z$w9Zb#%Or_jStSKUnfjb`C%PqA4|9gv4JI)qv;08WA^5AiKo7Ldd_S;~%X_6a^A5Hiq#<)xn|jcCre#an6PFbIFjft zx$XXov2lq4A8Tr2xBJ+7Sf3ZhX(xs(XTv_05j)7uGP*6KAY+fF-ux<3#Q4!nT!8Ez zgXl1x=oAgC`7Y|O*h@I%;$5G9ih;Z!HV{qvLP$(Uv1kzwlm_mxsYDI$2v*PcB2F+{ zP)O3ERR^dy#axHrcdHS(NE^yLCjP~{xgYAuAt>e_FQ&lNzKB(EtUr?~1X5GKx3hAp zuNQCCD>6}jNBHiBQ@@P8ga7!X{neWG7Y-{I?6bFmt-cD>%>QU0$OWxE76=dOrODB( zp85Pdh2>cStMk>)94Tc_;}W_rGWI$pm!;8p>>U4zcJ4~u!Lp+rzg|?gf||Hl5)||M zc+H2BNAZ4O7{jrGHAX$$Sa$3d%RIZL53$SQA@O~JHeU+3T*Fu+8mGQ*f3_o_qRS42)PG1v z25j(+&44R`K1FtMz~HriIE+FCJFg2^2NJr#1DP+vwx)6se!@cZAp30@p z!-N!eO_9-#e7)=O66jrSZy|1;?+<_(x^mV;y}|pcfx> zo~FJ61d{=kPU=qlw*ZMTa3l+|1E#ev$1H84Qf=xf4!tPJaKI{#*ohP!iK{3m%gR}AZNBqqW{Iv+?^o5Wn| z3Qd*0XSZ7-U^+ZRgU8KH$I*g|WlM4jfkS3b2)tWVURbuHjSFJD<_I6 z7oVq{J?%|Lzj*r=wrFJ`BGq6Lm?I`CV`}25)X&Mm)t_Q%O!SgC&nlusS4qpQ^TO}a z%Ud=tr5m^RugYx46VhI--)2>zhRAN26qCv0HN$7ldY0k&^jT8w|lFf_HB5lR+)n~V_M+5s7! z|JADv5&o?+lV$`hP)&1sv`i?jfz`q}pH5Nb^*T3yGe7btDr@vM(fmq3x>jRTqH`m# z^=&hZHU%!ip4hFo)L_!^sCv@>u*W0SOv2pX@X}cH^?Jn`EM@j{UUN-PdZ^t`wIu*= z6o_`zFmE>vq~roAl62e#XXZ#jF3vGjEp-)L#`qy7&OtgxJ~n-zb}W z_4(1`ZyaRsTH5aew$9yGnGyy~&7J+bZmv8aFM=9B_`GmYH^P}!z}XlsR-oMQSexgO2$MObH$AjqAwPNZ z#V*-PatI<-vhaPZhshgvk1t+1h-HB=@a%OyqhM?|3a7;dQvX*&n#l$<^lGVA&)3t> zq`Wtp>pPGQSN?MHODayzO{$VVv9*1T)kaiATB6_Dg1x|yf^ESQpBfM$vvKk|+RV0K z-L$@5rE;V42t-swe^;vFXWYLa;tHPagZ%1G3DpMzIW`^cBza+Yc>kBTpUXm^L757L;I?3=m2exAnm%%J+9r_G1%Bom^( zFAQ0%DMwRk>v@OJBF219z**7oqUv=6?chut+j+V_%#dC7{Ysy^3@I_IVzVIsX zUi0QC{Nh#SJnyXLnS?%#}&GP<}b$Jx0h zGS8xH{8G^PfDCG9oo4#;da}*UrVLj~$Wh&cH=G-5>nNSzSX{*u4oDK&fcVfu(|sFI z*~hxLyk-oc6sV5j9e_Z;K zPr%jf?br^D5^!6>vW}(HStB?XTB5%X)Wt1|i1)?#`-dm*U)FK9QfghQx98%p`uh4h zxNuORYlXj8rmOdxTa>*;dLU znSEB*LEqNAl!F2KPLGuKOo@111lOovU#_nLyo!l$`%G+=x0@dF-@lC(SJ#F}bMgom zV2}ZG`f4o?xzgWOs(Kv+6I+xA7J0o140wU-F6qf*aC9mZ^3m*t_2&md)!)5lAq8T! zB3`5_X$W)?&DIy3ijy+igm>JMXhbXlQhNnPhVFyqp^5u&Ms_Vr2RArN^Yu zJYpYCp18+~QoFPSb{cC9W$te^t_&Tj`^O296Fi8wrGndpcAAZK%CsxnT96`(+oxW0+6yQ+ zgl~I!ZEgLxK)ccK)h9d}_KfEe7+yW{V8^GyHZHr(_t!Hnx7Yj$6RWKf zKK!$HthHH23`)tOt2VBB^CizdJjUH@_XF(CrIg9j zN+9xZ)ZbsN5huP@PK%oA_Ug;=7A6XZ#-4QLcsYA}3l3(^bdjoo&u>AjD8uRm&XoPg zFtv3BlwD;+tQ+2CTKcqqN@BEAxE+%K zNTpHj%hX)ps`J-;2jOb6KBzdqy$&HwZ2HN#McPMIr$l!pbc2(qN9z~w&NjJU_;8Gz zm=gM-Gb^vCXw^Gu%V*~0qj#PUK4s7NC?&O4Alw1yYwe{p*SqQ=@e%3}SwSzAYR)D{ z$f;UL0Iv|rW-{#9NF~HG@ck`&rbGmx4cn_MXrE`O#5uyle3eu8(=BEOf%ow#GtVQR zFT_v=5(`RxTzqVHFTV>{LkFH(?6S^bJj;cQW`95aTB?0DNw^OCDE9kSjVHs27IB*E9o0`2gMo!sOHpG zn5$D&CSt(if<}b~PU$8JTX&9^A|YplE5;_hqurP$PeumS_u8p`@rI>^oyx4MAj+o! zH$s{8?wg1mqg_sdv|sW9yu!PzxYb}qvV zkA0^6Jh@tFI4)`;d(dmWCsV~vGM zjEW9-&>D3$_@C1HsH|F>TF-MR?o(J`73g*J{)&*-LHqjQGXoyq<&QdP5-ksp=Y`VM zt;PdsV1j2(-T4DsVa($%vfRas#rLImDw@Tn{@%5Ut*kg}+Y2EGf-8)>%!9MHHM&bvomJ-#euq^y`J~&V=O_db?q99{bbGpw5i8a7OJ76$``YOBwII<)?!6a*Bg?5)3iKC`--`Xdt4iB)eV=IN-G8fYIXGQe_)?8+? zPCE+@&o(o6H;szu2c=$n_US)KE|#GfnSX5eS2%`jL|;CqM(4i$U*e~`@|~*@KBuZH zY}$Pni_d9e1+^BoOo>v-Nr-_j!FKZq2KmNq{m!6mNx99sorOknsB64A_5nr!m3!o% zR*O|oh9Bgmqp(OyKJA6AH1g)fc8N}h)j=J7nfs{ic0Dk5p>{_s(kUq8Rlvn9F3D7c z%Y_MOzWE1A^OMQ%iDI@jS6uQq6&zaTbd^~2=Wa+%wuBH?1!RtF!oPT!Lz!F2gB2c*5ekh8&!7l(`Vm)2=;NwEO z&TG4#cl8yIQLeUn;;%E>G{$k8l!E1{^~)jJMk}HT^8uyrK8>&zyAEY_yXM_g_@%R*J<;ZEA&PPvPE#!bebIovSa+NpnWFchN2HGME+}sQ2M;!4LgK7j13$hp2&6`o z9?eYyEZI&DLWyh*eL^tU6MZFf5q|X{7<;8)GW*wzd%G#_yJ#(RKzpN$1;(VxbbO?! zf?41r-!_jA!ZSJD0NXNt3L5s^DPmlgt-1Gc`1YC6Pinc8-~wYBs)m{22uT2WDqZ6d zd0VoJXB~dp_ew{Rd)2F|j|s?b@p<{6-kzeP4CP$U;dK3+zNY21$HHqtdX3=|e{`Wa zJNpWqchG}#(f;{%?LoyFkdrYV^(xw2K|U zMP?Exy~)xL^><(PodP$4g}@8~T?9&{OyQJEtC1nW+P$fdi4(SpsE1_@d)F%@syF^j zp@!vVE$Wy7;OP^2Y%NhDarVgypT?p`dQYYuTthDG{i1yIXB&l{o|&zreCYDe%!iBK zw<3gl-6a=L0$za(o<-?qSnthZyi1Vs*5aJ+SA&q?V12H9L4|vY_gofO@Mz&l@9FK8 z*T03I>CKOX@*(xqbKJG>jikKuf-)D2>URt{S-f#c+nxHuri~t)pHA5h-NL3A1+W~< z%&o3PB9^BViIE5fAEoEQRFCZ+qdlY3(b%bl27i?#@-zhNL3C)VfL9aEB+n$#Aq{7( zC>_&dwH*rU-SGdKg}yVDc)=ZZ1@-edB>U-=YWF{XQNwY(Rc507v7wJq+_vzx2_13N z;n8`9&^J^<-oM<_ZRSRd6vMhDo=AB;pMSFI*Hza_p)c(h+f5xY+U7z$2#eDTkpCoA z>!IY&n}Un`;D_-`o-n{V`l_ertQ2D$Y~4|P@$vYM_*@6tm&L`ql^2PXA6<=JH^z{E zc@jbYIA(o#siAZ=-|1&IA+{{DPZTBcUr3>Mg`3g~D?1cA#P9tOz~$b^GiX}KM*(3r zRp7|=w-sLo?B8usq|!bLaS?FonwcD=bPXb@V*{GEtEfF(*HW|u2;8M%CLL^wTO*85 zWFdxU=b27~wFvp$r@sx&tfCF{GGr!|v2R?K%P&USJz9&;bUHU!vd&*Q1I+ZO&d(p^ zg4x&)t|~<6t+lu-enl`y!c-R>(s7?S`EwPUDocdSMN$()$h+E^wcmUvf15FLU+-@V zYKJVl_2t_ltIxanZ&9`9oWxVVH*KVXJ*adKUH5D6kdI5YCt#5kuB}@+iEG0=ks-7y2L^$-# z`hKi@ySdT1i@iwotZfN9D&vaDo<5AEHLZ z<*txxlD#IL7O!>|oDE#i1l3A53h4Zn@I{mosJ9EH zJ@=KtrrgW^v3=eg0T(6aZ zf*DW+nOKh^m#`aBE4h>c!ad>R8~qydD#Itg=d^1uOVjKegl;`)rQ3ZH&E>+>Q|}{mdKFS3f;{Qjmbh;{JI4CEntL zS4vR;sOXIh;DmFZwCD^n!a7`-ut-TW|AiZD<@h&dqKweSU>gDI$o_b{vVVaanwb3z zQ9tkk5btqz0=Xsyl#%(mRKuR!a+zbsZ?;cf8Do#>2;LJnP`R?hF_hx0zi|lRD6wim z)WVjkomz4duAxN0>&L>fUczy&Ln7G?PpxW)DdO&$t?Ur;NyVCNyk4#9_<>u;2^JVw z&W{heG_+zU%Ru?@veadQlnGPxJY~lNCTv|n9%7cIC7syfC;eo?7|+aV>AKF{r&(UGND*gc<}fF&?X3sRc#&E zmKhoT3=5`c*T`9nAE5H$`^>~xf>bU4oBlLP=$9v}5nXhRgwd|wt5E}vxu^28mo2CH z@rO^bEvM~zr5}WZP#o1z%|dr0rs#>}gm+j({h*>9!W z7_CLNKLVy^ZBb=v%GHw-dj0?-t%dH-0W{o=ASG{~9i&OzXu=}1TVHvvC+MpLD$$hZ z!#aYJM=K)lA}juHOAwNDCIfd z|G9Qt&z3Js!G_$|Uv#yNcQfc=G1nyVb$0-+jqE*tPz#>y2TxF1!);;8 zF+FQ>_wwX?&XFZ@JVEGH(=@duQ+}?5t!W;(wBR-tgY|a;U|Uy#HrD-_w+!twI(tO> zdFfzt^#hWRx-OR4Sw;MqxrzE}7~5B$u)#T(1}n3z5TmTz4%Yc8v%=AJj4W#ZMXr30 z6VUT)R53&4)#p4uKU^hF70K9SO*^u}XGOnHNPpEq^_3=Uj#@rkv=5tD6EBTbrm}XS z+ev@-Ef?P|BxvawIkCz6!@=&YN8F@n)plP7+SS)4ko&>*p>5 zh?iFQOz?|oUwO|q>AJyhXP&>qq@qioV2wljUwKz7J`JCyDG#pSh9qbtjjC|_O(|}Y zxnHF~WsLz&sOmr`9$s5_MFHOA+kbZclMK0M=-SPIiz!PWNF8R*eD6IPZEHrxww+>WHXiYtpA&-j zgFIGH0TI)~N~p$rWCcGSiHhuBQF8MfRAOwo{Sx=Hcj;?Ot?u|HsG=yKP zCPqE}Wf()m`uhMTvfivGI0G3ajUU|Ful(GQHU8P5nBUw^i4II`Bz;Qo7Q}y_XFk3B=NLhR);j=U)tW%l-WwT}J zW5*O7ZjL=~*z8a1`52`oQlLASA?kPVn-VjiDvwy6u>cU}W&a}%!C(d$VYaS18k74E zNs`2G;6FmG-I%a6xC_7}LfcoJ{}BpU$L5YYdN7PYr3lJEWs!_PE06y^t&;r;29!-T z$!M-tY(sf3VVYSR-J63QgNt$`Al8#;*T(w92}#s^loIk3DDv9#lR`1-nwgHq#+9>> z&`AV>6;J;l(Ed#VNw3QyGhOQF@WYru4dmQRJH4l3G4ArAGgGuYyLtmTR0uke@dTHn zBp@;&(>i`%n7{WoDqjfeU1D2hDk1yq7s%{Y?d~Qg8K0BKCPWkw7MUE&TkKz=o&YuO>1op70_`64Q44^X1nS&0Z$8fzyytoL_AV!wsj z2lTUqWh*?7st02EUGLAaK1cfxMF@roNC+gsIw?gn0J16n>=;B>da_^erXL+RB5Mn&Z%@)Gx`f8dAchdC;-NDpE$E4F4W zETN+>{U848w-lx$9KPNFuyv2_{kc@v&WpsWf|rDQRI%w_%#ylbWxokqf%%$PnI9|o z{rF1}oFiWPGSnyze|@HCHRQAIAT`f2X|2A3c}Vf{YGkbfEEYfqoT!~|fR*{K0(|@v zyZ0I#KLk9LLIuVRI$=(Ab;X?1gzEI=?Q1Si{Z;1i6z=Kuj~fC}bh|LP-n&_P$&4wQ z3!?%pUeW5y>cJ{lyVJb~=BWl(^zHb0$618 ztVU_|CDCFPj?<)B=0Y&j@i)*K+#IQ{&0HLoeFwkWDb3e>bkNaZZ*41@!f)R|&Rt;u zZcP`+6c{bdau+D?c8h4G&Uvk$bvuRLZVHK%d8;IgnW4{F*wH~#sxX9pW~W)XLzJ^m z8okG-yRa2*|AWD>`46*qolQIL<`kq&w2Ja>Uzc<^UDMD?CXV4+hi!$jBi(x}sZP32 zh;2gnb?Y@rpv_Kgp)+oDSjDB366^kT-|wIPVWO;O%FtC5k0gZ&j?YZ27kPE6oS zp9$ZYeqIJf{M=XMC8B=19Ur|D3JYS#+-|o#lDXsOe z)&mqq?d^Z)$JaaQU!_L5`QHL|Gq^*Y;_X|0zIt#a2Pb!^4SwG&&0@tAZI7SB_kf_I z$4i+Y^{g_0d)1i=^)Nd2mACld5o)Q3#0onpR2O#i(Ok;6T4>+2TxW{zBtPv%AnHH1 za;gQ4z6U->Z5NT8G)hq>{2`(7bq>#_P$XB_Daz7rv)oKnH11^x!ppqJ#zR27tshgx z6$JsP$gyRToK%O`|F5rpp5@yuZxa$E(&O@tn*`%=Prbw2Ey4DZmf_#m@6%x~eBdNT z5=I?dX1?Izgo`d1Yj|ko6`|zD^X8*vsrlcEm#`NI_V_Ns=UiYnl)v;9KY{#X{Q$w> zag{>WRaZdyGXfzVxp$o%z}<6ia4J6U{t?D1OjY~g+aBQH>V(hjz<6XmGf-L&-=3%0 zrEanm6`2Sp%K`M*@|QY*V)YmLSJKH%+bu0AYy8-gakO5#|~y@(rabDNv8^Q3$=u%tJ=fzaqBv-3Y%KPNEyo^jl{k)4s#s5lM9xDL9_D9_^Mvlk7-|n4VO;EnaXWsSdsXU{8u- z;I?sPE@h5A6DSiK8aA7L5J>m7v6J-|n4t~qTPeW>{Y3*EzmRsW0VP40svQ&d`zn-s zwro9s-7`vBE323fR?N1yw5|Hjd0j!0RgC@qO^|rS{6TN4WJk;GL=&zs8K&Tc!;3afllEaB@o_caZ1epIxdII0l!T2 zb%nf^xHiO$@%S5>-qOd6@02TI)}g%|(=&i;RgcelHfoXpkXPCMj?k^;DFaNq-p!vP zT#=X(>(OY>t%B20A)$HD_w2#WF5zl~KH0eLNU`i z(Lv8`&xD>(xF|C5tX1WSI|m6-Eeu*pj;ca8be=ZeZMSTmWFM74aZ6CnL6q-vqF=tp z8xjh{z?==B#aT~`1AD<70CBrbegW8m#n-^7-&~UI#^#%qVD=nQQ{pi_(~;rBt7X{d zPVAHXF+F-3FX^sf>&#P)b@LPZWCM&muJ}z;gTe@9WJH(2$Jdt?n{6vXr`Sh@Nkyz< z%IY~J?q>5d-`*Q%?xIEjF`26=Jxg7*p87DjpemlB<@0>OAXx)>!nGw>Kd$0i<8S1G zRhUFB4?(%?XU0^GP!Fwz&+}ZVD1a(?zTz74EH9of!tC-(tatW53U*CSn!9dXq4Eyc z4(s8sLhvwj)EbZrPYgo;fEnno-ErJypj#&ojgmO2))M(oDH4#8eU7I!?w)mLnRr%w zzpi>;{XJqlXk5;Ka`uh8i=54gjvp}4Yt>xUgie06yA9+?nps~KfGY~%{KAbJlyAWQ zvA`{;kC}-QpU~kabd%y9%OUz!Zqk{aPTWP@PyRM|%CXs1{cL>}}bH4A= zSi8ncWx%?Y@oM*D1eU*yU5@~`onLOKL{O)^^sNrH@}n zOgO!g!gih=Rmx#*CksAm-iC`+rSQiyt?@Kfx2E{*+XcObRlmb}FAJI54#a>WgGS6) zVk@(@g+GH7_^b`&Hahq@@JkCn%B_d}qO7-#V)k@Kl4M*ne5VSQ$GFYy^w3qNl@MFT zaw&RYpF#XAMXG)L)7gEPb)#Ninw4kc4c0qGF@C8oTA4o3RrjdMAX&`|<|EF(^bahD zWzQiTdW7*%ARCaMcha{}7nkc;c*$;Ag04*LAM~oh(=(r?aLkjm$kh9YHsJIKEL(BCz5l^`z#OT)_7i_8kpkj72{j&aCJ$y zHiGgz64!9VP#wS&U0GUEDXlQYmz3~Ots99;P*4?_P_=!>T#N7fujAVb8_v$9U*G5D zOWpFw<}3lXm!n~|*u;P4gQ}685un^h|QmqP@?$ zHI86#)wuMULi6Y@^cZpwHj;GVT`t}o#CxAF2BR?1!oSZn=cqzy1D{3ky-rhPn`{NB zl3Lzk3I?Nu8G@-4U8?_NgYN_+G|EtmnLgo9=eZ_GV5W6KyqZXft4|wD>hlude#Tn0p07+uB*64loOE<5U@c1oD>Ysw8N0Pp;)8avm&K*hP;vdgL zlgNK^=L?2m__&<%6$m8{8*`hCsC)`M0&!$HRBc0@WyAih_Otzw^=+rnWCLIp4No{smx#hd+DTBSA9xiAASb-wAv;ixe?#@0;otH>ICatoVRk( z?|^gPsWQ#`*R|hUedvYkXLWjw&@)iw-qW}=Fhq1di$w+WhBdor`FIOgn*pz#seqc> zE$afKi;dibhMk_II@a+jys@pI<9vz?06MCA)JAB-BXJzLw7-(yz2r;KQgZgJixBpd zIhXkiSvY_jaaZF8WUl2J6>T~9PcB{ySPmJt3+FIP0OZUD_@Xq8%MqB@3B#6&9cYJo z97YP7w+oXjT>*fJ<2jn(t;nxY_~}CLb(z9yaG*G8P7rmxkDmHt!hEzk$bCf$ll*mo zrf=Y#FuA(w3mSF-0URk8^zF63SzP~$L_or+esQI`_Qzj#z@+*B6diJFbBTy@DT%Eh zV*nsJFGo}A7fkugmL`Y(xE{QnOVI}MZ&{5?;^n{_Z{vUCsjnx-l;~8DCs1^N7-&y; zn@Vm9-K9??!((tey#cc4{W5hTPXP01*SJ(~3&w&bM&YHKmYZAp;rI>^C?2t(Lr7-F zbRf9pRP<89i1JSY2rhT>pOKqlKtspEs}fJEr0M-IWB8EBk)LDF^L4do%LD96=t6ts znSU~^Kn$6pMdNP%i~~a|hVnrf;Gz5_ucoPTsB(Nilu1lEbLZM)#x%h6UK1D(6N%1Z ztP@h6Am%mqT*3WW^wb zsZtn+yh>Zn@B^S0GtrlrucuC4!vwOoXN8rxLC{dJz^c2Uq%1w_hl$8S9zOvGlIcj` zHBo9M`*0T4_m)IBo|Mr$i~=b+S=jk$*}IjuV+^1}(&v|F&S24`UsWl_e1H+F8{@MzLzeepp!#aP>U;9I{`D zJH4rD0WebL!p8A5MTG=`P<`^#_sEp1u9!r4zV3o&g_qW$l)}_JocpHY<+WA8S2;mc z3L=13$d0g?+xexDn`!{rr(h%@lJfM+OY!f8Fo_dotn=nt91}`XNJuC{V28^UN(nLs zorTZ!EU$Ao0gUw!HlK%NKJ&IST5La{1Ob2f(OqZEn8gKij$!kqu)D(sVtKBY`${&U zy&&sp1yW7~6ScuCVhSU3b#HO_a;++wv9UijrX$T$^Dp%I2u-R)VCPP-P5xQb!_t^5{NdExz+E)rZuV7y#@Mj>HuF8ml=GrmjY4XG!t4<)vGx<4 zBdDoRYPg6z(humlK{CJMF(eNZ04Dlu4;Y#B)_LyWvcZ;U-%CGyfVDa9vg(@(@o6e#^rG(&plk{=lE86=ebAY|k-%#u2kLIKdMav6rw1K^q3I3pSZGTTR& zEw8V@H}w{_Gzybirh(PvzmUk@mMiGJRd;dLBHp z)9_PYoMdsLy};r`@RXPcDf;zDP0SEHAJo}JdcM({t9ST7T=1I{}wHfHAh2?#jk+H_zwz*_5Xm| zJ3*t7?hy|zXLX6=*7n0e?sp+{QTTtY{xd%Kk$m`M=Z9Nlk6`zSqd;=Zi%H14BsX(u z>-Ys%9=Sy}1EGUCf%U#A1w{QYP{(DW8m7k!S&g>GCu(V0+c2fNy1AzQ&vEfUjKNxJ z!fNM!^cs9>{St*Yi>v|;as(t7G*Outf`4t;oVL1b@Nd{UMgSs}*$x8iASDaP9?0;#8FRu;Y=d-kWRmjEo#Vf)=ja!@lg)su4n-bjPQCnva|5j_! zu-87;ooqXdxDD0?um%+h!Teh>)XJfQ(kEOya0NL#mHC!x*GTJP-XD#lcb0 zw2!W%z8sX=lYCXHEFUb3YR28hqCxAeNLw>o9m_}UOq1^)d|wJDY7ZNj~C_iK-yBbeUj&f z%#a_$nm7+QwsbVjQNuF;cEw?*S#_U+$+x_R$-jlPC}#;_T(fQME5VW(Z@x6PZV_Nf zKD>?Q2ft0@Z&v(fCfz=44>;Bk<}QdlZ`>8U{wJ`<595Y|saLfsI-#eGTV{AZ`0dbP z|nmLAY)`MpUmB@ZR7aial0O1m*W)^^Z$f6dOrUBx3iqOnPBRz1;YAm z{0`!mYQEvvhSstX|6^q5UoyZZBReULHJuq3b)%X)~k|~q&R)@DBX$+bHrIC z86anCwL#_%clUbhhw3W=db=Gzk*Vg<_UG7Qk8kri;H@DcRiHXK6AuDrZwPCj z4qW>SaePnWIteq3%AXJB=M}TGLEQm}DS)#|Nzxe%)ppTuWk1U{Dvv?A;&+E5o8781 z??b)ClY!?hbJJq^-`fY;0kxVEt>cm0_!m=NcLVRY=pNr|$dm0!uW*}@1N2HrR}YJ1 zBRLO5J3eAIwbTgIJ-G;XUAe^tP*dlDYl5d!#+!08%^$jfULlXF|9i*?)KAj}!6H!L zudfDsUhCgW;eN5|e{W$^TrQaZzfX~1@&DgThb*uY=-*430hrGJKFxFlTRTZFak{nm z|GkAS0vp2qy%Zk#zvli=cK>H6ByT_$ot!}-A5dbCx^%A0nN|3Al5 Bx{Ck+ literal 0 HcmV?d00001 From ad67a33d099cc4689778f37778bf2b169a525f26 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sun, 8 Oct 2023 11:22:23 +0200 Subject: [PATCH 164/348] fix(search-backend-node): non-string field hightlight Signed-off-by: Camila Belo --- .../search-backend-node/src/engines/LunrSearchEngine.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts index ae5a541e81..02bd6f7fd7 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -329,11 +329,11 @@ export function parseHighlightFields({ const highlightedField = positions.reduce((content, pos) => { return ( - `${content.substring(0, pos[0])}${preTag}` + - `${content.substring(pos[0], pos[0] + pos[1])}` + - `${postTag}${content.substring(pos[0] + pos[1])}` + `${content.toString().substring(0, pos[0])}${preTag}` + + `${content.toString().substring(pos[0], pos[0] + pos[1])}` + + `${postTag}${content.toString().substring(pos[0] + pos[1])}` ); - }, doc[field]); + }, doc[field] ?? ''); return [field, highlightedField]; }), From e8839fe017b46cf49ff2eede1776e819df205e8c Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sun, 8 Oct 2023 11:26:12 +0200 Subject: [PATCH 165/348] feat(stackoverflow-backend): get request params from config Signed-off-by: Camila Belo --- plugins/stack-overflow-backend/config.d.ts | 7 +++++++ .../search/StackOverflowQuestionsCollatorFactory.ts | 13 +++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/stack-overflow-backend/config.d.ts b/plugins/stack-overflow-backend/config.d.ts index b97f237c19..613a7aa887 100644 --- a/plugins/stack-overflow-backend/config.d.ts +++ b/plugins/stack-overflow-backend/config.d.ts @@ -40,5 +40,12 @@ export interface Config { * @visibility secret */ apiAccessToken?: string; + + /** + * Type representing the request parameters. + */ + requestParams?: { + [key: string]: string | string[] | number; + }; }; } diff --git a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts index c5f8a8c16b..cf1e56cb28 100644 --- a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts +++ b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts @@ -54,7 +54,7 @@ export type StackOverflowQuestionsCollatorFactoryOptions = { apiKey?: string; apiAccessToken?: string; teamName?: string; - requestParams: StackOverflowQuestionsRequestParams; + requestParams?: StackOverflowQuestionsRequestParams; logger: Logger; }; @@ -81,7 +81,11 @@ export class StackOverflowQuestionsCollatorFactory this.apiAccessToken = options.apiAccessToken; this.teamName = options.teamName; this.maxPage = options.maxPage; - this.requestParams = options.requestParams; + this.requestParams = options.requestParams ?? { + tagged: ['backstage'], + site: 'stackoverflow', + pagesize: 100, + }; this.logger = options.logger.child({ documentType: this.type }); } @@ -98,12 +102,17 @@ export class StackOverflowQuestionsCollatorFactory config.getOptionalString('stackoverflow.baseUrl') || 'https://api.stackexchange.com/2.3'; const maxPage = options.maxPage || 100; + const requestParams = + config.getOptional( + 'stackoverflow.requestParams', + ); return new StackOverflowQuestionsCollatorFactory({ baseUrl, maxPage, apiKey, apiAccessToken, teamName, + requestParams, ...options, }); } From 43bcd9fcead0ae6cc9ac4a3e2b5e7f2441fa2ba5 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sun, 8 Oct 2023 11:27:50 +0200 Subject: [PATCH 166/348] feat(stackoverflow-backend): migrate collator to backend system Signed-off-by: Camila Belo --- .../alpha-api-report.md | 11 +++ plugins/stack-overflow-backend/api-report.md | 2 +- plugins/stack-overflow-backend/package.json | 23 ++++-- plugins/stack-overflow-backend/src/alpha.ts | 70 +++++++++++++++++++ 4 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 plugins/stack-overflow-backend/alpha-api-report.md create mode 100644 plugins/stack-overflow-backend/src/alpha.ts diff --git a/plugins/stack-overflow-backend/alpha-api-report.md b/plugins/stack-overflow-backend/alpha-api-report.md new file mode 100644 index 0000000000..93d4cfe5e5 --- /dev/null +++ b/plugins/stack-overflow-backend/alpha-api-report.md @@ -0,0 +1,11 @@ +## API Report File for "@backstage/plugin-stack-overflow-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +const _default: () => BackendFeature; +export default _default; +``` diff --git a/plugins/stack-overflow-backend/api-report.md b/plugins/stack-overflow-backend/api-report.md index 8c601399c1..e8fd710cf6 100644 --- a/plugins/stack-overflow-backend/api-report.md +++ b/plugins/stack-overflow-backend/api-report.md @@ -45,7 +45,7 @@ export type StackOverflowQuestionsCollatorFactoryOptions = { apiKey?: string; apiAccessToken?: string; teamName?: string; - requestParams: StackOverflowQuestionsRequestParams; + requestParams?: StackOverflowQuestionsRequestParams; logger: Logger; }; diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 320d35d3b6..53857082d2 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -5,9 +5,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "backend-plugin" @@ -33,7 +46,10 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/backend-tasks": "workspace:^", "@backstage/config": "workspace:^", + "@backstage/plugin-search-backend-node": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "node-fetch": "^2.6.7", "qs": "^6.9.4", @@ -42,7 +58,6 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@backstage/plugin-search-backend-node": "workspace:^", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/stack-overflow-backend/src/alpha.ts b/plugins/stack-overflow-backend/src/alpha.ts new file mode 100644 index 0000000000..897cbd1ea2 --- /dev/null +++ b/plugins/stack-overflow-backend/src/alpha.ts @@ -0,0 +1,70 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { readTaskScheduleDefinitionFromConfig } from '@backstage/backend-tasks'; +import { + coreServices, + createBackendModule, +} from '@backstage/backend-plugin-api'; +import { searchIndexRegistryExtensionPoint } from '@backstage/plugin-search-backend-node/alpha'; +import { StackOverflowQuestionsCollatorFactory } from './search'; + +/** + * @packageDocumentation + * A module for the search backend that exports Stack Overflow modules. + */ + +/** + * Search backend module for the Stack Overflow index. + * + * @alpha + */ +export default createBackendModule({ + moduleId: 'stackoverflowCollator', + pluginId: 'search', + register(env) { + env.registerInit({ + deps: { + config: coreServices.rootConfig, + logger: coreServices.logger, + discovery: coreServices.discovery, + scheduler: coreServices.scheduler, + indexRegistry: searchIndexRegistryExtensionPoint, + }, + async init({ config, logger, scheduler, indexRegistry }) { + const defaultSchedule = { + frequency: { minutes: 10 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 3 }, + }; + + const schedule = config.has('search.collators.stackoverflow.schedule') + ? readTaskScheduleDefinitionFromConfig( + config.getConfig('search.collators.stackoverflow.schedule'), + ) + : defaultSchedule; + + indexRegistry.addCollator({ + schedule: scheduler.createScheduledTaskRunner(schedule), + factory: StackOverflowQuestionsCollatorFactory.fromConfig(config, { + logger: loggerToWinstonLogger(logger), + }), + }); + }, + }); + }, +}); From 41c2cdf23358e13b29303e92df0da3c4674fd9cb Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sun, 8 Oct 2023 11:32:36 +0200 Subject: [PATCH 167/348] feat(backend-next): install stack overflow search module Signed-off-by: Camila Belo --- packages/backend-next/package.json | 1 + packages/backend-next/src/index.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 69aa81a9cb..41864907e5 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -56,6 +56,7 @@ "@backstage/plugin-search-backend-module-techdocs": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", "@backstage/plugin-sonarqube-backend": "workspace:^", + "@backstage/plugin-stack-overflow-backend": "workspace:^", "@backstage/plugin-techdocs-backend": "workspace:^", "@backstage/plugin-todo-backend": "workspace:^" }, diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index bdfbc2c26b..15f5ca9c38 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -46,6 +46,7 @@ backend.add(import('@backstage/plugin-search-backend-module-explore/alpha')); backend.add(import('@backstage/plugin-search-backend-module-techdocs/alpha')); backend.add(import('@backstage/plugin-search-backend/alpha')); backend.add(import('@backstage/plugin-techdocs-backend/alpha')); +backend.add(import('@backstage/plugin-stack-overflow-backend/alpha')); backend.add(import('@backstage/plugin-todo-backend')); backend.add(import('@backstage/plugin-sonarqube-backend')); From b148cdc8dbfc8889371ee221a2a1ba6075a16cf2 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sun, 8 Oct 2023 11:38:24 +0200 Subject: [PATCH 168/348] feat(stackoverflow): migrate to new frontend system Signed-off-by: Camila Belo --- plugins/stack-overflow/alpha-api-report.md | 13 ++++++ plugins/stack-overflow/package.json | 20 +++++++-- plugins/stack-overflow/src/alpha.tsx | 48 ++++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 plugins/stack-overflow/alpha-api-report.md create mode 100644 plugins/stack-overflow/src/alpha.tsx diff --git a/plugins/stack-overflow/alpha-api-report.md b/plugins/stack-overflow/alpha-api-report.md new file mode 100644 index 0000000000..84d7616759 --- /dev/null +++ b/plugins/stack-overflow/alpha-api-report.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/plugin-stack-overflow" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +const _default: BackstagePlugin; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index f60800d1f9..431f8a5b80 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -5,9 +5,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.tsx", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.tsx" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "frontend-plugin" @@ -32,6 +45,7 @@ "@backstage/config": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/plugin-home-react": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "@backstage/plugin-search-react": "workspace:^", diff --git a/plugins/stack-overflow/src/alpha.tsx b/plugins/stack-overflow/src/alpha.tsx new file mode 100644 index 0000000000..18f0a0df1c --- /dev/null +++ b/plugins/stack-overflow/src/alpha.tsx @@ -0,0 +1,48 @@ +/* + * Copyright 2023 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 { configApiRef, createApiFactory } from '@backstage/core-plugin-api'; +import { + createApiExtension, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; +import { StackOverflowClient, stackOverflowApiRef } from './api'; + +/** @alpha */ +const StackOverflowApi = createApiExtension({ + factory: createApiFactory({ + api: stackOverflowApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => StackOverflowClient.fromConfig(configApi), + }), +}); + +/** @alpha */ +const StackOverflowSearchResultListItem = createSearchResultListItemExtension({ + id: 'stack-overflow', + predicate: result => result.type === 'stack-overflow', + component: () => + import('./search/StackOverflowSearchResultListItem').then( + m => m.StackOverflowSearchResultListItem, + ), +}); + +/** @alpha */ +export default createPlugin({ + id: 'stack-overflow', + extensions: [StackOverflowApi, StackOverflowSearchResultListItem], +}); From 8b44bf58f2380d4d0c3806227325397aa5a04259 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sun, 8 Oct 2023 11:41:12 +0200 Subject: [PATCH 169/348] feat(search): add stackoverflow to types accordion Signed-off-by: Camila Belo --- plugins/search/src/alpha.tsx | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index 14e7067dfa..913a96d094 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -69,6 +69,25 @@ import { SearchType } from './components/SearchType'; import { UrlUpdater } from './components/SearchPage/SearchPage'; import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +/** @internal */ +const StackOverflowIcon = () => { + return ( + + + + + ); +}; + /** @alpha */ export const SearchApi = createApiExtension({ factory: { @@ -153,6 +172,11 @@ export const SearchPage = createPageExtension({ name: 'Architecture Decision Records', icon: , }, + { + value: 'stack-overflow', + name: 'Stack Overflow', + icon: , + }, ]} /> From b168d7e7ea16c440d26d68fc0663c5ce6ece71a3 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sun, 8 Oct 2023 12:55:20 +0200 Subject: [PATCH 170/348] chore: add changeset files Signed-off-by: Camila Belo --- .changeset/flat-ducks-buy.md | 5 +++++ .changeset/giant-cycles-end.md | 5 +++++ .changeset/mean-fans-cough.md | 5 +++++ .changeset/nice-pillows-poke.md | 5 +++++ 4 files changed, 20 insertions(+) create mode 100644 .changeset/flat-ducks-buy.md create mode 100644 .changeset/giant-cycles-end.md create mode 100644 .changeset/mean-fans-cough.md create mode 100644 .changeset/nice-pillows-poke.md diff --git a/.changeset/flat-ducks-buy.md b/.changeset/flat-ducks-buy.md new file mode 100644 index 0000000000..5c952faaf1 --- /dev/null +++ b/.changeset/flat-ducks-buy.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-node': patch +--- + +Fix highlighting for non-string fields on the `Lunr` search engine implementation. diff --git a/.changeset/giant-cycles-end.md b/.changeset/giant-cycles-end.md new file mode 100644 index 0000000000..6cd21fe54e --- /dev/null +++ b/.changeset/giant-cycles-end.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-stack-overflow-backend': patch +--- + +Migrate package to the new Frontend system, the new module is distributed with a `/alpha` subpath. diff --git a/.changeset/mean-fans-cough.md b/.changeset/mean-fans-cough.md new file mode 100644 index 0000000000..8f93cd361c --- /dev/null +++ b/.changeset/mean-fans-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Add Stack Overflow type to the default alpha search page extension types filter. diff --git a/.changeset/nice-pillows-poke.md b/.changeset/nice-pillows-poke.md new file mode 100644 index 0000000000..1a3926f371 --- /dev/null +++ b/.changeset/nice-pillows-poke.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-stack-overflow': patch +--- + +Migrate package to the new Backend system, the new module is distributed with a `/alpha` subpath. From dad7d4de5b0b0c1a6307b57cfbc75585a4666fe1 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 9 Oct 2023 08:17:02 +0200 Subject: [PATCH 171/348] chore: update yarn lock Signed-off-by: Camila Belo --- yarn.lock | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 1e2f6fdb5d..bc7aa10d86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9182,11 +9182,13 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-stack-overflow-backend@workspace:plugins/stack-overflow-backend": +"@backstage/plugin-stack-overflow-backend@workspace:^, @backstage/plugin-stack-overflow-backend@workspace:plugins/stack-overflow-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-stack-overflow-backend@workspace:plugins/stack-overflow-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-tasks": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -9209,6 +9211,7 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-home-react": "workspace:^" "@backstage/plugin-search-common": "workspace:^" "@backstage/plugin-search-react": "workspace:^" @@ -25502,6 +25505,7 @@ __metadata: "@backstage/plugin-search-backend-module-techdocs": "workspace:^" "@backstage/plugin-search-backend-node": "workspace:^" "@backstage/plugin-sonarqube-backend": "workspace:^" + "@backstage/plugin-stack-overflow-backend": "workspace:^" "@backstage/plugin-techdocs-backend": "workspace:^" "@backstage/plugin-todo-backend": "workspace:^" languageName: unknown From 847841a89d766ce460039b7202e5c7ef23286e02 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 9 Oct 2023 14:57:42 +0200 Subject: [PATCH 172/348] refactor(stack-overflow-backend): use official default request parameters Signed-off-by: Camila Belo --- .changeset/giant-cycles-end.md | 2 ++ plugins/stack-overflow-backend/README.md | 2 +- .../StackOverflowQuestionsCollatorFactory.ts | 16 +++++++++------- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.changeset/giant-cycles-end.md b/.changeset/giant-cycles-end.md index 6cd21fe54e..5d9f8149a8 100644 --- a/.changeset/giant-cycles-end.md +++ b/.changeset/giant-cycles-end.md @@ -3,3 +3,5 @@ --- Migrate package to the new Frontend system, the new module is distributed with a `/alpha` subpath. + +The search collator `requestParams` option is optional now, so its defaults to `{ order: 'desc', sort: 'activity', site: 'stackoverflow' }` as done in the `Try It` section on the [official Stack Overflow API documentation](https://api.stackexchange.com/docs/questions). diff --git a/plugins/stack-overflow-backend/README.md b/plugins/stack-overflow-backend/README.md index 4575ab58c0..5de997faa6 100644 --- a/plugins/stack-overflow-backend/README.md +++ b/plugins/stack-overflow-backend/README.md @@ -45,7 +45,7 @@ This stack overflow backend plugin is primarily responsible for the following: Before you are able to start index stack overflow questions to search, you need to go through the [search getting started guide](https://backstage.io/docs/features/search/getting-started). -When you have your `packages/backend/src/plugins/search.ts` file ready to make modifications, add the following code snippet to add the `StackOverflowQuestionsCollatorFactory`. Note that you can modify the `requestParams`. +When you have your `packages/backend/src/plugins/search.ts` file ready to make modifications, add the following code snippet to add the `StackOverflowQuestionsCollatorFactory`. Note that you can optionally modify the `requestParams`, otherwise it will defaults to `{ order: 'desc', sort: 'activity', site: 'stackoverflow' }` as done in the `Try It` section on the [official Stack Overflow API documentation](https://api.stackexchange.com/docs/questions). > Note: if your `baseUrl` is set to the external stack overflow api `https://api.stackexchange.com/2.2`, you can find optional and required parameters under the official API documentation under [`Usage of /questions GET`](https://api.stackexchange.com/docs/questions) diff --git a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts index cf1e56cb28..3c97937365 100644 --- a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts +++ b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts @@ -81,10 +81,13 @@ export class StackOverflowQuestionsCollatorFactory this.apiAccessToken = options.apiAccessToken; this.teamName = options.teamName; this.maxPage = options.maxPage; + // Sets the same default request parameters as the official API documentation + // See https://api.stackexchange.com/docs/questions this.requestParams = options.requestParams ?? { - tagged: ['backstage'], + order: 'desc', + sort: 'activity', site: 'stackoverflow', - pagesize: 100, + ...(options.requestParams ?? {}), }; this.logger = options.logger.child({ documentType: this.type }); } @@ -102,10 +105,9 @@ export class StackOverflowQuestionsCollatorFactory config.getOptionalString('stackoverflow.baseUrl') || 'https://api.stackexchange.com/2.3'; const maxPage = options.maxPage || 100; - const requestParams = - config.getOptional( - 'stackoverflow.requestParams', - ); + const requestParams = config + .getOptionalConfig('stackoverflow.requestParams') + ?.get(); return new StackOverflowQuestionsCollatorFactory({ baseUrl, maxPage, @@ -184,7 +186,7 @@ export class StackOverflowQuestionsCollatorFactory ); const data = await res.json(); - for (const question of data.items) { + for (const question of data.items ?? []) { yield { title: question.title, location: question.link, From 7b1296c57a4c5659c9c010b17ca3591869985b2b Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 9 Oct 2023 15:06:01 +0200 Subject: [PATCH 173/348] refactor(search): use string construction for non-text values Signed-off-by: Camila Belo --- plugins/search-backend-node/src/engines/LunrSearchEngine.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts index 02bd6f7fd7..27cfae3fdf 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -329,9 +329,9 @@ export function parseHighlightFields({ const highlightedField = positions.reduce((content, pos) => { return ( - `${content.toString().substring(0, pos[0])}${preTag}` + - `${content.toString().substring(pos[0], pos[0] + pos[1])}` + - `${postTag}${content.toString().substring(pos[0] + pos[1])}` + `${String(content).substring(0, pos[0])}${preTag}` + + `${String(content).substring(pos[0], pos[0] + pos[1])}` + + `${postTag}${String(content).substring(pos[0] + pos[1])}` ); }, doc[field] ?? ''); From a8a4911713c4b2f4ac4da0031caef7b1def9594f Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 9 Oct 2023 15:49:21 +0200 Subject: [PATCH 174/348] refactor: do not install stack overflow plugin on example apps Signed-off-by: Camila Belo --- packages/app-next/package.json | 1 - packages/backend-next/package.json | 1 - packages/backend-next/src/index.ts | 1 - 3 files changed, 3 deletions(-) diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 71d888ee50..5437c66272 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -68,7 +68,6 @@ "@backstage/plugin-search-react": "workspace:^", "@backstage/plugin-sentry": "workspace:^", "@backstage/plugin-shortcuts": "workspace:^", - "@backstage/plugin-stack-overflow": "workspace:^", "@backstage/plugin-stackstorm": "workspace:^", "@backstage/plugin-tech-insights": "workspace:^", "@backstage/plugin-tech-radar": "workspace:^", diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 41864907e5..69aa81a9cb 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -56,7 +56,6 @@ "@backstage/plugin-search-backend-module-techdocs": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", "@backstage/plugin-sonarqube-backend": "workspace:^", - "@backstage/plugin-stack-overflow-backend": "workspace:^", "@backstage/plugin-techdocs-backend": "workspace:^", "@backstage/plugin-todo-backend": "workspace:^" }, diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index 15f5ca9c38..bdfbc2c26b 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -46,7 +46,6 @@ backend.add(import('@backstage/plugin-search-backend-module-explore/alpha')); backend.add(import('@backstage/plugin-search-backend-module-techdocs/alpha')); backend.add(import('@backstage/plugin-search-backend/alpha')); backend.add(import('@backstage/plugin-techdocs-backend/alpha')); -backend.add(import('@backstage/plugin-stack-overflow-backend/alpha')); backend.add(import('@backstage/plugin-todo-backend')); backend.add(import('@backstage/plugin-sonarqube-backend')); From 27e22c6a21b33b6cc0162995053c5730fcad8a91 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 9 Oct 2023 16:19:16 +0200 Subject: [PATCH 175/348] feat(stackoverflow-backend): extract search stack overflow module Signed-off-by: Camila Belo --- .../.eslintrc.js | 1 + .../README.md | 30 +++++++++ .../alpha-api-report.md | 2 +- .../api-report.md | 56 ++++++++++++++++ .../catalog-info.yaml | 10 +++ .../config.d.ts | 51 +++++++++++++++ .../package.json | 65 +++++++++++++++++++ .../src/alpha.test.ts | 55 ++++++++++++++++ .../src/alpha.ts | 6 +- ...ckOverflowQuestionsCollatorFactory.test.ts | 0 .../StackOverflowQuestionsCollatorFactory.ts | 0 .../src/collators/index.ts | 22 +++++++ .../src}/index.ts | 9 ++- plugins/stack-overflow-backend/api-report.md | 59 ++++------------- plugins/stack-overflow-backend/package.json | 24 ++----- plugins/stack-overflow-backend/src/index.ts | 38 ++++++++++- yarn.lock | 26 ++++++-- 17 files changed, 377 insertions(+), 77 deletions(-) create mode 100644 plugins/search-backend-module-stack-overflow/.eslintrc.js create mode 100644 plugins/search-backend-module-stack-overflow/README.md rename plugins/{stack-overflow-backend => search-backend-module-stack-overflow}/alpha-api-report.md (75%) create mode 100644 plugins/search-backend-module-stack-overflow/api-report.md create mode 100644 plugins/search-backend-module-stack-overflow/catalog-info.yaml create mode 100644 plugins/search-backend-module-stack-overflow/config.d.ts create mode 100644 plugins/search-backend-module-stack-overflow/package.json create mode 100644 plugins/search-backend-module-stack-overflow/src/alpha.test.ts rename plugins/{stack-overflow-backend => search-backend-module-stack-overflow}/src/alpha.ts (90%) rename plugins/{stack-overflow-backend/src/search => search-backend-module-stack-overflow/src/collators}/StackOverflowQuestionsCollatorFactory.test.ts (100%) rename plugins/{stack-overflow-backend/src/search => search-backend-module-stack-overflow/src/collators}/StackOverflowQuestionsCollatorFactory.ts (100%) create mode 100644 plugins/search-backend-module-stack-overflow/src/collators/index.ts rename plugins/{stack-overflow-backend/src/search => search-backend-module-stack-overflow/src}/index.ts (76%) diff --git a/plugins/search-backend-module-stack-overflow/.eslintrc.js b/plugins/search-backend-module-stack-overflow/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/search-backend-module-stack-overflow/README.md b/plugins/search-backend-module-stack-overflow/README.md new file mode 100644 index 0000000000..cba9617ea8 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow/README.md @@ -0,0 +1,30 @@ +# search-backend-module-stack-overflow + +> DISCLAIMER: The new backend system is in alpha, and so are the search backend module support for the new backend system. We don't recommend you to migrate your backend installations to the new system yet. But if you want to experiment, you can find getting started guides below. + +This package exports a module that extends the search backend to also indexing the questions exposed by the [`Stack Overflow` API](https://api.stackexchange.com/docs/questions). + +## Installation + +Add the module package as a dependency: + +```bash +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/plugin-search-backend-module-stack-overflow +``` + +Add the collator to your backend instance, along with the search plugin itself: + +```tsx +// packages/backend/src/index.ts +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); +backend.add(import('@backstage/plugin-search-backend/alpha')); +backend.add( + import('@backstage/plugin-search-backend-module-stack-overflow/alpha'), +); +backend.start(); +``` + +You may also want to add configuration parameters to your app-config, for example for controlling the scheduled indexing interval. These parameters should be placed under the `stackoverflow` key. See [the config definition file](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-stack-overflow/config.d.ts) for more details. diff --git a/plugins/stack-overflow-backend/alpha-api-report.md b/plugins/search-backend-module-stack-overflow/alpha-api-report.md similarity index 75% rename from plugins/stack-overflow-backend/alpha-api-report.md rename to plugins/search-backend-module-stack-overflow/alpha-api-report.md index 93d4cfe5e5..9d25cb0a7d 100644 --- a/plugins/stack-overflow-backend/alpha-api-report.md +++ b/plugins/search-backend-module-stack-overflow/alpha-api-report.md @@ -1,4 +1,4 @@ -## API Report File for "@backstage/plugin-stack-overflow-backend" +## API Report File for "@backstage/plugin-search-backend-module-stack-overflow" > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). diff --git a/plugins/search-backend-module-stack-overflow/api-report.md b/plugins/search-backend-module-stack-overflow/api-report.md new file mode 100644 index 0000000000..795b30cac2 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow/api-report.md @@ -0,0 +1,56 @@ +## API Report File for "@backstage/plugin-search-backend-module-stack-overflow" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { Config } from '@backstage/config'; +import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; +import { IndexableDocument } from '@backstage/plugin-search-common'; +import { Logger } from 'winston'; +import { Readable } from 'stream'; + +// @public +export interface StackOverflowDocument extends IndexableDocument { + // (undocumented) + answers: number; + // (undocumented) + tags: string[]; +} + +// @public +export class StackOverflowQuestionsCollatorFactory + implements DocumentCollatorFactory +{ + // (undocumented) + execute(): AsyncGenerator; + // (undocumented) + static fromConfig( + config: Config, + options: StackOverflowQuestionsCollatorFactoryOptions, + ): StackOverflowQuestionsCollatorFactory; + // (undocumented) + getCollator(): Promise; + // (undocumented) + protected requestParams: StackOverflowQuestionsRequestParams; + // (undocumented) + readonly type: string; +} + +// @public +export type StackOverflowQuestionsCollatorFactoryOptions = { + baseUrl?: string; + maxPage?: number; + apiKey?: string; + apiAccessToken?: string; + teamName?: string; + requestParams?: StackOverflowQuestionsRequestParams; + logger: Logger; +}; + +// @public +export type StackOverflowQuestionsRequestParams = { + [key: string]: string | string[] | number; +}; +``` diff --git a/plugins/search-backend-module-stack-overflow/catalog-info.yaml b/plugins/search-backend-module-stack-overflow/catalog-info.yaml new file mode 100644 index 0000000000..9075d1d591 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-search-backend-module-stack-overflow + title: '@backstage/plugin-search-backend-module-stack-overflow' + description: A module for the search backend that exports stack overflow modules +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: discoverability-maintainers diff --git a/plugins/search-backend-module-stack-overflow/config.d.ts b/plugins/search-backend-module-stack-overflow/config.d.ts new file mode 100644 index 0000000000..d615179ed0 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow/config.d.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + /** + * Configuration options for the stack overflow plugin + */ + stackoverflow?: { + /** + * The base url of the Stack Overflow API used for the plugin + */ + baseUrl?: string; + + /** + * The API key to authenticate to Stack Overflow API + * @visibility secret + */ + apiKey?: string; + + /** + * The name of the team for a Stack Overflow for Teams account + */ + teamName?: string; + + /** + * The API Access Token to authenticate to Stack Overflow API + * @visibility secret + */ + apiAccessToken?: string; + + /** + * Type representing the request parameters. + */ + requestParams?: { + [key: string]: string | string[] | number; + }; + }; +} diff --git a/plugins/search-backend-module-stack-overflow/package.json b/plugins/search-backend-module-stack-overflow/package.json new file mode 100644 index 0000000000..64ff4d32d3 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow/package.json @@ -0,0 +1,65 @@ +{ + "name": "@backstage/plugin-search-backend-module-stack-overflow", + "description": "A module for the search backend that exports stack overflow modules", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } + }, + "backstage": { + "role": "backend-plugin-module" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/search-backend-module-stack-overflow" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/backend-tasks": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/plugin-search-backend-node": "workspace:^", + "@backstage/plugin-search-common": "workspace:^", + "node-fetch": "^2.6.7", + "qs": "^6.9.4", + "winston": "^3.2.1" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "msw": "^1.2.1" + }, + "files": [ + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" +} diff --git a/plugins/search-backend-module-stack-overflow/src/alpha.test.ts b/plugins/search-backend-module-stack-overflow/src/alpha.test.ts new file mode 100644 index 0000000000..1dba1ab8c0 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow/src/alpha.test.ts @@ -0,0 +1,55 @@ +/* + * Copyright 2023 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 { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import { searchIndexRegistryExtensionPoint } from '@backstage/plugin-search-backend-node/alpha'; +import searchModuleStackOverflowCollator from './alpha'; + +describe('searchModuleStackOverflowCollator', () => { + const schedule = { + frequency: { minutes: 10 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 3 }, + }; + + it('should register the stack overflow collator to the search index registry extension point with factory and schedule', async () => { + const extensionPointMock = { + addCollator: jest.fn(), + }; + + await startTestBackend({ + extensionPoints: [ + [searchIndexRegistryExtensionPoint, extensionPointMock], + ], + features: [ + searchModuleStackOverflowCollator(), + mockServices.rootConfig.factory({ + data: { + stackoverflow: { + schedule, + }, + }, + }), + ], + }); + + expect(extensionPointMock.addCollator).toHaveBeenCalledTimes(1); + expect(extensionPointMock.addCollator).toHaveBeenCalledWith({ + factory: expect.objectContaining({ type: 'stack-overflow' }), + schedule: expect.objectContaining({ run: expect.any(Function) }), + }); + }); +}); diff --git a/plugins/stack-overflow-backend/src/alpha.ts b/plugins/search-backend-module-stack-overflow/src/alpha.ts similarity index 90% rename from plugins/stack-overflow-backend/src/alpha.ts rename to plugins/search-backend-module-stack-overflow/src/alpha.ts index 897cbd1ea2..85b686c9ed 100644 --- a/plugins/stack-overflow-backend/src/alpha.ts +++ b/plugins/search-backend-module-stack-overflow/src/alpha.ts @@ -21,7 +21,7 @@ import { createBackendModule, } from '@backstage/backend-plugin-api'; import { searchIndexRegistryExtensionPoint } from '@backstage/plugin-search-backend-node/alpha'; -import { StackOverflowQuestionsCollatorFactory } from './search'; +import { StackOverflowQuestionsCollatorFactory } from './collators'; /** * @packageDocumentation @@ -52,9 +52,9 @@ export default createBackendModule({ initialDelay: { seconds: 3 }, }; - const schedule = config.has('search.collators.stackoverflow.schedule') + const schedule = config.has('stackoverflow.schedule') ? readTaskScheduleDefinitionFromConfig( - config.getConfig('search.collators.stackoverflow.schedule'), + config.getConfig('stackoverflow.schedule'), ) : defaultSchedule; diff --git a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts b/plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.test.ts similarity index 100% rename from plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts rename to plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.test.ts diff --git a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts b/plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.ts similarity index 100% rename from plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts rename to plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.ts diff --git a/plugins/search-backend-module-stack-overflow/src/collators/index.ts b/plugins/search-backend-module-stack-overflow/src/collators/index.ts new file mode 100644 index 0000000000..1170b52423 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow/src/collators/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + type StackOverflowDocument, + type StackOverflowQuestionsRequestParams, + type StackOverflowQuestionsCollatorFactoryOptions, + StackOverflowQuestionsCollatorFactory, +} from './StackOverflowQuestionsCollatorFactory'; diff --git a/plugins/stack-overflow-backend/src/search/index.ts b/plugins/search-backend-module-stack-overflow/src/index.ts similarity index 76% rename from plugins/stack-overflow-backend/src/search/index.ts rename to plugins/search-backend-module-stack-overflow/src/index.ts index ed3e05cb28..eb1f7540de 100644 --- a/plugins/stack-overflow-backend/src/search/index.ts +++ b/plugins/search-backend-module-stack-overflow/src/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2023 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. @@ -14,4 +14,9 @@ * limitations under the License. */ -export * from './StackOverflowQuestionsCollatorFactory'; +/** + * @packageDocumentation + * A module for the search backend that exports Stack Overflow modules. + */ + +export * from './collators'; diff --git a/plugins/stack-overflow-backend/api-report.md b/plugins/stack-overflow-backend/api-report.md index e8fd710cf6..d113f7a0b6 100644 --- a/plugins/stack-overflow-backend/api-report.md +++ b/plugins/stack-overflow-backend/api-report.md @@ -3,54 +3,21 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -/// +import { StackOverflowDocument as StackOverflowDocument_2 } from '@backstage/plugin-search-backend-module-stack-overflow'; +import { StackOverflowQuestionsCollatorFactory as StackOverflowQuestionsCollatorFactory_2 } from '@backstage/plugin-search-backend-module-stack-overflow'; +import { StackOverflowQuestionsRequestParams as StackOverflowQuestionsRequestParams_2 } from '@backstage/plugin-search-backend-module-stack-overflow'; -import { Config } from '@backstage/config'; -import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; -import { IndexableDocument } from '@backstage/plugin-search-common'; -import { Logger } from 'winston'; -import { Readable } from 'stream'; +// @public @deprecated (undocumented) +export type StackOverflowDocument = StackOverflowDocument_2; -// @public -export interface StackOverflowDocument extends IndexableDocument { - // (undocumented) - answers: number; - // (undocumented) - tags: string[]; -} +// @public @deprecated (undocumented) +export const StackOverflowQuestionsCollatorFactory: typeof StackOverflowQuestionsCollatorFactory_2; -// @public -export class StackOverflowQuestionsCollatorFactory - implements DocumentCollatorFactory -{ - // (undocumented) - execute(): AsyncGenerator; - // (undocumented) - static fromConfig( - config: Config, - options: StackOverflowQuestionsCollatorFactoryOptions, - ): StackOverflowQuestionsCollatorFactory; - // (undocumented) - getCollator(): Promise; - // (undocumented) - protected requestParams: StackOverflowQuestionsRequestParams; - // (undocumented) - readonly type: string; -} +// @public @deprecated (undocumented) +export type StackOverflowQuestionsCollatorFactoryOptions = + StackOverflowQuestionsCollatorFactory_2; -// @public -export type StackOverflowQuestionsCollatorFactoryOptions = { - baseUrl?: string; - maxPage?: number; - apiKey?: string; - apiAccessToken?: string; - teamName?: string; - requestParams?: StackOverflowQuestionsRequestParams; - logger: Logger; -}; - -// @public -export type StackOverflowQuestionsRequestParams = { - [key: string]: string | string[] | number; -}; +// @public @deprecated (undocumented) +export type StackOverflowQuestionsRequestParams = + StackOverflowQuestionsRequestParams_2; ``` diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 53857082d2..5235c33f1a 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -5,22 +5,9 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public" - }, - "exports": { - ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", - "./package.json": "./package.json" - }, - "typesVersions": { - "*": { - "alpha": [ - "src/alpha.ts" - ], - "package.json": [ - "package.json" - ] - } + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" }, "backstage": { "role": "backend-plugin" @@ -46,10 +33,8 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", - "@backstage/backend-plugin-api": "workspace:^", - "@backstage/backend-tasks": "workspace:^", "@backstage/config": "workspace:^", - "@backstage/plugin-search-backend-node": "workspace:^", + "@backstage/plugin-search-backend-module-stack-overflow": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "node-fetch": "^2.6.7", "qs": "^6.9.4", @@ -58,6 +43,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-search-backend-node": "workspace:^", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/stack-overflow-backend/src/index.ts b/plugins/stack-overflow-backend/src/index.ts index 6e461b8183..269748424b 100644 --- a/plugins/stack-overflow-backend/src/index.ts +++ b/plugins/stack-overflow-backend/src/index.ts @@ -20,4 +20,40 @@ * @packageDocumentation */ -export * from './search'; +import { + StackOverflowDocument as _StackOverflowDocument, + StackOverflowQuestionsRequestParams as _StackOverflowQuestionsRequestParams, + StackOverflowQuestionsCollatorFactory as _StackOverflowQuestionsCollatorFactory, + StackOverflowQuestionsCollatorFactoryOptions as _StackOverflowQuestionsCollatorFactoryOptions, +} from '@backstage/plugin-search-backend-module-stack-overflow'; + +/** + * @public + * @deprecated + * Import from `@backstage/plugin-search-backend-module-stack-overflow` instead. + */ +export type StackOverflowDocument = _StackOverflowDocument; + +/** + * @public + * @deprecated + * Import from `@backstage/plugin-search-backend-module-stack-overflow` instead. + */ +export type StackOverflowQuestionsRequestParams = + _StackOverflowQuestionsRequestParams; + +/** + * @public + * @deprecated + * Import from `@backstage/plugin-search-backend-module-stack-overflow` instead. + */ +export type StackOverflowQuestionsCollatorFactoryOptions = + _StackOverflowQuestionsCollatorFactory; + +/** + * @public + * @deprecated + * Import from `@backstage/plugin-search-backend-module-stack-overflow` instead. + */ +export const StackOverflowQuestionsCollatorFactory = + _StackOverflowQuestionsCollatorFactory; diff --git a/yarn.lock b/yarn.lock index bc7aa10d86..6e2db68238 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8847,6 +8847,25 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-search-backend-module-stack-overflow@workspace:^, @backstage/plugin-search-backend-module-stack-overflow@workspace:plugins/search-backend-module-stack-overflow": + version: 0.0.0-use.local + resolution: "@backstage/plugin-search-backend-module-stack-overflow@workspace:plugins/search-backend-module-stack-overflow" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-tasks": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/plugin-search-backend-node": "workspace:^" + "@backstage/plugin-search-common": "workspace:^" + msw: ^1.2.1 + node-fetch: ^2.6.7 + qs: ^6.9.4 + winston: ^3.2.1 + languageName: unknown + linkType: soft + "@backstage/plugin-search-backend-module-techdocs@workspace:^, @backstage/plugin-search-backend-module-techdocs@workspace:plugins/search-backend-module-techdocs": version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-module-techdocs@workspace:plugins/search-backend-module-techdocs" @@ -9182,16 +9201,15 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-stack-overflow-backend@workspace:^, @backstage/plugin-stack-overflow-backend@workspace:plugins/stack-overflow-backend": +"@backstage/plugin-stack-overflow-backend@workspace:plugins/stack-overflow-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-stack-overflow-backend@workspace:plugins/stack-overflow-backend" dependencies: "@backstage/backend-common": "workspace:^" - "@backstage/backend-plugin-api": "workspace:^" - "@backstage/backend-tasks": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" + "@backstage/plugin-search-backend-module-stack-overflow": "workspace:^" "@backstage/plugin-search-backend-node": "workspace:^" "@backstage/plugin-search-common": "workspace:^" msw: ^1.0.0 @@ -25317,7 +25335,6 @@ __metadata: "@backstage/plugin-search-react": "workspace:^" "@backstage/plugin-sentry": "workspace:^" "@backstage/plugin-shortcuts": "workspace:^" - "@backstage/plugin-stack-overflow": "workspace:^" "@backstage/plugin-stackstorm": "workspace:^" "@backstage/plugin-tech-insights": "workspace:^" "@backstage/plugin-tech-radar": "workspace:^" @@ -25505,7 +25522,6 @@ __metadata: "@backstage/plugin-search-backend-module-techdocs": "workspace:^" "@backstage/plugin-search-backend-node": "workspace:^" "@backstage/plugin-sonarqube-backend": "workspace:^" - "@backstage/plugin-stack-overflow-backend": "workspace:^" "@backstage/plugin-techdocs-backend": "workspace:^" "@backstage/plugin-todo-backend": "workspace:^" languageName: unknown From 20f8768427927c70311301568ce6e608da50c8fc Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 9 Oct 2023 16:31:36 +0200 Subject: [PATCH 176/348] refactor(search): do not add stack overflow types on the default page Signed-off-by: Camila Belo --- plugins/search/src/alpha.tsx | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index 913a96d094..14e7067dfa 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -69,25 +69,6 @@ import { SearchType } from './components/SearchType'; import { UrlUpdater } from './components/SearchPage/SearchPage'; import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; -/** @internal */ -const StackOverflowIcon = () => { - return ( - - - - - ); -}; - /** @alpha */ export const SearchApi = createApiExtension({ factory: { @@ -172,11 +153,6 @@ export const SearchPage = createPageExtension({ name: 'Architecture Decision Records', icon: , }, - { - value: 'stack-overflow', - name: 'Stack Overflow', - icon: , - }, ]} /> From 0ea51599408c1664640b11a595009daf3a61ca15 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 9 Oct 2023 16:55:34 +0200 Subject: [PATCH 177/348] fix: docs link to stack overflow collator Signed-off-by: Camila Belo --- docs/plugins/integrating-search-into-plugins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plugins/integrating-search-into-plugins.md b/docs/plugins/integrating-search-into-plugins.md index 7fb8e40b20..f2692d4e91 100644 --- a/docs/plugins/integrating-search-into-plugins.md +++ b/docs/plugins/integrating-search-into-plugins.md @@ -22,7 +22,7 @@ Imagine you have a plugin that is responsible for storing FAQ snippets in a data The search platform provides an interface (`DocumentCollatorFactory` from package `@backstage/plugin-search-common`) that allows you to do exactly that. It works by registering each of your entries as a "document" that later represents one search result each. -> You can always look at a working example, e.g. [StackOverflowQuestionsCollatorFactory](https://github.com/backstage/backstage/blob/master/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts), if you are unsure or want to follow best practices. +> You can always look at a working example, e.g. [StackOverflowQuestionsCollatorFactory](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.ts), if you are unsure or want to follow best practices. #### 1. Install collator interface dependencies From 46f0f1700eb803a416bd389cf9d713b2c41939c9 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 9 Oct 2023 17:15:15 +0200 Subject: [PATCH 178/348] fix: update changeset files Signed-off-by: Camila Belo --- .changeset/chilly-terms-behave.md | 5 +++++ .changeset/giant-cycles-end.md | 4 ++-- .changeset/mean-fans-cough.md | 5 ----- .changeset/nice-pillows-poke.md | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 .changeset/chilly-terms-behave.md delete mode 100644 .changeset/mean-fans-cough.md diff --git a/.changeset/chilly-terms-behave.md b/.changeset/chilly-terms-behave.md new file mode 100644 index 0000000000..47250364bf --- /dev/null +++ b/.changeset/chilly-terms-behave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-stack-overflow': patch +--- + +Extract a package for the Stack Overflow new backend system plugin. diff --git a/.changeset/giant-cycles-end.md b/.changeset/giant-cycles-end.md index 5d9f8149a8..6f637e05dd 100644 --- a/.changeset/giant-cycles-end.md +++ b/.changeset/giant-cycles-end.md @@ -2,6 +2,6 @@ '@backstage/plugin-stack-overflow-backend': patch --- -Migrate package to the new Frontend system, the new module is distributed with a `/alpha` subpath. +Deprecate package in favor of the new `@backstage/plugin-search-backend-module-stack-overflow` module. -The search collator `requestParams` option is optional now, so its defaults to `{ order: 'desc', sort: 'activity', site: 'stackoverflow' }` as done in the `Try It` section on the [official Stack Overflow API documentation](https://api.stackexchange.com/docs/questions). +The search collator `requestParams` option is optional now, so its default value is `{ order: 'desc', sort: 'activity', site: 'stackoverflow' }` as defined in the `Try It` section on the [official Stack Overflow API documentation](https://api.stackexchange.com/docs/questions). diff --git a/.changeset/mean-fans-cough.md b/.changeset/mean-fans-cough.md deleted file mode 100644 index 8f93cd361c..0000000000 --- a/.changeset/mean-fans-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Add Stack Overflow type to the default alpha search page extension types filter. diff --git a/.changeset/nice-pillows-poke.md b/.changeset/nice-pillows-poke.md index 1a3926f371..64034c39d2 100644 --- a/.changeset/nice-pillows-poke.md +++ b/.changeset/nice-pillows-poke.md @@ -2,4 +2,4 @@ '@backstage/plugin-stack-overflow': patch --- -Migrate package to the new Backend system, the new module is distributed with a `/alpha` subpath. +Migrate package to the new Frontend system, the new module is distributed with a `/alpha` subpath. From 0eaa698bb5a73a7f13b6bd4d1b51af84068d40f4 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 13 Oct 2023 09:38:33 +0200 Subject: [PATCH 179/348] chore(frontend-plugin-api): install frontend app api Signed-off-by: Camila Belo --- packages/frontend-plugin-api/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index baf8cb4575..9cc3355ec3 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -24,7 +24,6 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", - "@backstage/frontend-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^14.0.0", @@ -39,6 +38,7 @@ }, "dependencies": { "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-app-api": "workspace:^", "@backstage/types": "workspace:^", "@backstage/version-bridge": "workspace:^", "@types/react": "^16.13.1 || ^17.0.0", From 67cc85bb1465e342734a5cb877183849f7254a12 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 10:53:42 +0200 Subject: [PATCH 180/348] dev-utils,techdocs: use dynamic import instead of require for conditional react-dom Signed-off-by: Patrik Oldsberg --- .changeset/quick-roses-move.md | 6 +++++ packages/dev-utils/src/devApp/render.tsx | 22 ++++++++++++------- .../reader/transformers/renderReactElement.ts | 20 ++++++++++------- 3 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 .changeset/quick-roses-move.md diff --git a/.changeset/quick-roses-move.md b/.changeset/quick-roses-move.md new file mode 100644 index 0000000000..767ad0919e --- /dev/null +++ b/.changeset/quick-roses-move.md @@ -0,0 +1,6 @@ +--- +'@backstage/dev-utils': patch +'@backstage/plugin-techdocs': patch +--- + +Switched the conditional `react-dom/client` import to use `import(...)` rather than `require(...)`. diff --git a/packages/dev-utils/src/devApp/render.tsx b/packages/dev-utils/src/devApp/render.tsx index e45ba649f9..ccb1cca2e8 100644 --- a/packages/dev-utils/src/devApp/render.tsx +++ b/packages/dev-utils/src/devApp/render.tsx @@ -49,11 +49,13 @@ import { createRoutesFromChildren, Route } from 'react-router-dom'; import { SidebarThemeSwitcher } from './SidebarThemeSwitcher'; import 'react-dom'; -let ReactDOM: typeof import('react-dom') | typeof import('react-dom/client'); +let ReactDOMPromise: Promise< + typeof import('react-dom') | typeof import('react-dom/client') +>; if (process.env.HAS_REACT_DOM_CLIENT) { - ReactDOM = require('react-dom/client'); + ReactDOMPromise = import('react-dom/client'); } else { - ReactDOM = require('react-dom'); + ReactDOMPromise = import('react-dom'); } export function isReactRouterBeta(): boolean { @@ -242,11 +244,15 @@ export class DevAppBuilder { window.location.pathname = this.defaultPage; } - if ('createRoot' in ReactDOM) { - ReactDOM.createRoot(document.getElementById('root')!).render(); - } else { - ReactDOM.render(, document.getElementById('root')); - } + ReactDOMPromise.then(ReactDOM => { + if ('createRoot' in ReactDOM) { + ReactDOM.createRoot(document.getElementById('root')!).render( + , + ); + } else { + ReactDOM.render(, document.getElementById('root')); + } + }); } } diff --git a/plugins/techdocs/src/reader/transformers/renderReactElement.ts b/plugins/techdocs/src/reader/transformers/renderReactElement.ts index f9b45065f1..ff7accf6ba 100644 --- a/plugins/techdocs/src/reader/transformers/renderReactElement.ts +++ b/plugins/techdocs/src/reader/transformers/renderReactElement.ts @@ -14,18 +14,22 @@ * limitations under the License. */ -let ReactDOM: typeof import('react-dom') | typeof import('react-dom/client'); +let ReactDOMPromise: Promise< + typeof import('react-dom') | typeof import('react-dom/client') +>; if (process.env.HAS_REACT_DOM_CLIENT) { - ReactDOM = require('react-dom/client'); + ReactDOMPromise = import('react-dom/client'); } else { - ReactDOM = require('react-dom'); + ReactDOMPromise = import('react-dom'); } /** @internal */ export function renderReactElement(element: JSX.Element, root: HTMLElement) { - if ('createRoot' in ReactDOM) { - ReactDOM.createRoot(root).render(element); - } else { - ReactDOM.render(element, root); - } + ReactDOMPromise.then(ReactDOM => { + if ('createRoot' in ReactDOM) { + ReactDOM.createRoot(root).render(element); + } else { + ReactDOM.render(element, root); + } + }); } From 3c39045e2bcee481ae410e6115b8abbc449147dc Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 14 Oct 2023 12:08:57 +0200 Subject: [PATCH 181/348] refactor: rename stack overflow backend module Signed-off-by: Camila Belo --- .changeset/chilly-terms-behave.md | 2 +- .changeset/giant-cycles-end.md | 2 +- .../integrating-search-into-plugins.md | 2 +- .../.eslintrc.js | 0 .../README.md | 97 +++++++++++++++++++ .../alpha-api-report.md | 2 +- .../api-report.md | 2 +- .../catalog-info.yaml | 4 +- .../config.d.ts | 0 .../package.json | 2 +- .../src/alpha.test.ts | 0 .../src/alpha.ts | 0 ...ckOverflowQuestionsCollatorFactory.test.ts | 0 .../StackOverflowQuestionsCollatorFactory.ts | 0 .../src/collators/index.ts | 0 .../src/index.ts | 0 .../README.md | 30 ------ plugins/stack-overflow-backend/api-report.md | 6 +- plugins/stack-overflow-backend/package.json | 2 +- plugins/stack-overflow-backend/src/index.ts | 10 +- yarn.lock | 6 +- 21 files changed, 117 insertions(+), 50 deletions(-) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/.eslintrc.js (100%) create mode 100644 plugins/search-backend-module-stack-overflow-collator/README.md rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/alpha-api-report.md (92%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/api-report.md (98%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/catalog-info.yaml (79%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/config.d.ts (100%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/package.json (99%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/src/alpha.test.ts (100%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/src/alpha.ts (100%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/src/collators/StackOverflowQuestionsCollatorFactory.test.ts (100%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/src/collators/StackOverflowQuestionsCollatorFactory.ts (100%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/src/collators/index.ts (100%) rename plugins/{search-backend-module-stack-overflow => search-backend-module-stack-overflow-collator}/src/index.ts (100%) delete mode 100644 plugins/search-backend-module-stack-overflow/README.md diff --git a/.changeset/chilly-terms-behave.md b/.changeset/chilly-terms-behave.md index 47250364bf..b514bc45c8 100644 --- a/.changeset/chilly-terms-behave.md +++ b/.changeset/chilly-terms-behave.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-search-backend-module-stack-overflow': patch +'@backstage/plugin-search-backend-module-stack-overflow-collator': patch --- Extract a package for the Stack Overflow new backend system plugin. diff --git a/.changeset/giant-cycles-end.md b/.changeset/giant-cycles-end.md index 6f637e05dd..f69938ea25 100644 --- a/.changeset/giant-cycles-end.md +++ b/.changeset/giant-cycles-end.md @@ -2,6 +2,6 @@ '@backstage/plugin-stack-overflow-backend': patch --- -Deprecate package in favor of the new `@backstage/plugin-search-backend-module-stack-overflow` module. +Deprecate package in favor of the new `@backstage/plugin-search-backend-module-stack-overflow-collator` module. The search collator `requestParams` option is optional now, so its default value is `{ order: 'desc', sort: 'activity', site: 'stackoverflow' }` as defined in the `Try It` section on the [official Stack Overflow API documentation](https://api.stackexchange.com/docs/questions). diff --git a/docs/plugins/integrating-search-into-plugins.md b/docs/plugins/integrating-search-into-plugins.md index f2692d4e91..28c8b410e3 100644 --- a/docs/plugins/integrating-search-into-plugins.md +++ b/docs/plugins/integrating-search-into-plugins.md @@ -22,7 +22,7 @@ Imagine you have a plugin that is responsible for storing FAQ snippets in a data The search platform provides an interface (`DocumentCollatorFactory` from package `@backstage/plugin-search-common`) that allows you to do exactly that. It works by registering each of your entries as a "document" that later represents one search result each. -> You can always look at a working example, e.g. [StackOverflowQuestionsCollatorFactory](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.ts), if you are unsure or want to follow best practices. +> You can always look at a working example, e.g. [StackOverflowQuestionsCollatorFactory](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-stack-overflow-collator/src/collators/StackOverflowQuestionsCollatorFactory.ts), if you are unsure or want to follow best practices. #### 1. Install collator interface dependencies diff --git a/plugins/search-backend-module-stack-overflow/.eslintrc.js b/plugins/search-backend-module-stack-overflow-collator/.eslintrc.js similarity index 100% rename from plugins/search-backend-module-stack-overflow/.eslintrc.js rename to plugins/search-backend-module-stack-overflow-collator/.eslintrc.js diff --git a/plugins/search-backend-module-stack-overflow-collator/README.md b/plugins/search-backend-module-stack-overflow-collator/README.md new file mode 100644 index 0000000000..914746cbf9 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow-collator/README.md @@ -0,0 +1,97 @@ +# Stack Overflow Search Backend Module + +A plugin that provides stack overflow specific functionality that can be used in different ways (e.g. for search) to compose your Backstage App. + +## Getting started + +Before we begin, make sure: + +- You have created your own standalone Backstage app using @backstage/create-app and not using a fork of the backstage repository. If you haven't setup Backstage already, start [here](https://backstage.io/docs/getting-started/). + +To use any of the functionality this plugin provides, you need to start by configuring your App with the following config: + +```yaml +stackoverflow: + baseUrl: https://api.stackexchange.com/2.2 # alternative: your internal stack overflow instance +``` + +### Stack Overflow for Teams + +If you have a private Stack Overflow instance and/or a private Stack Overflow Team you will need to supply an API key or Personal Access Token. You can read more about how to set this up by going to [Stack Overflow's Help Page](https://stackoverflow.help/en/articles/4385859-stack-overflow-for-teams-api). + +The existing API key approach remains the default, to support the new v2.3 API and PAT authentication model you need to pass the team name and the new PAT into the existing apiAccessToken parameter to the new URL. See [15770](https://github.com/backstage/backstage/issues/15770) for more details. + +```yaml +stackoverflow: + baseUrl: https://api.stackexchange.com/2.2 # alternative: your internal stack overflow instance + apiKey: $STACK_OVERFLOW_API_KEY + apiAccessToken: $STACK_OVERFLOW_API_ACCESS_TOKEN +``` + +```yaml +stackoverflow: + baseUrl: https://api.stackoverflowteams.com/2.3 # alternative: your internal stack overflow instance + teamName: $STACK_OVERFLOW_TEAM_NAME + apiAccessToken: $STACK_OVERFLOW_API_ACCESS_TOKEN +``` + +## Areas of Responsibility + +This stack overflow backend plugin is primarily responsible for the following: + +- Provides a `StackOverflowQuestionsCollatorFactory`, which can be used in the search backend to index stack overflow questions to your Backstage Search. + +### Index Stack Overflow Questions to search + +Before you are able to start index stack overflow questions to search, you need to go through the [search getting started guide](https://backstage.io/docs/features/search/getting-started). + +When you have your `packages/backend/src/plugins/search.ts` file ready to make modifications, add the following code snippet to add the `StackOverflowQuestionsCollatorFactory`. Note that you can optionally modify the `requestParams`, otherwise it will defaults to `{ order: 'desc', sort: 'activity', site: 'stackoverflow' }` as done in the `Try It` section on the [official Stack Overflow API documentation](https://api.stackexchange.com/docs/questions). + +> Note: if your `baseUrl` is set to the external stack overflow api `https://api.stackexchange.com/2.2`, you can find optional and required parameters under the official API documentation under [`Usage of /questions GET`](https://api.stackexchange.com/docs/questions) + +```ts +indexBuilder.addCollator({ + schedule, + factory: StackOverflowQuestionsCollatorFactory.fromConfig(env.config, { + logger: env.logger, + requestParams: { + tagged: ['backstage'], + site: 'stackoverflow', + pagesize: 100, + }, + }), +}); +``` + +## New Backend System + +> DISCLAIMER: The new backend system is in alpha, and so are the search backend module support for the new backend system. We don't recommend you to migrate your backend installations to the new system yet. But if you want to experiment, you can find getting started guides below. + +This package exports a module that extends the search backend to also indexing the questions exposed by the [`Stack Overflow` API](https://api.stackexchange.com/docs/questions). + +### Installation + +Add the module package as a dependency: + +```bash +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/plugin-search-backend-module-stack-overflow-collator +``` + +Add the collator to your backend instance, along with the search plugin itself: + +```tsx +// packages/backend/src/index.ts +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); +backend.add(import('@backstage/plugin-search-backend/alpha')); +backend.add( + import( + '@backstage/plugin-search-backend-module-stack-overflow-collator/alpha' + ), +); +backend.start(); +``` + +You may also want to add configuration parameters to your app-config, for example for controlling the scheduled indexing interval. These parameters should be placed under the `stackoverflow` key. See [the config definition file](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-stack-overflow/config.d.ts) for more details. diff --git a/plugins/search-backend-module-stack-overflow/alpha-api-report.md b/plugins/search-backend-module-stack-overflow-collator/alpha-api-report.md similarity index 92% rename from plugins/search-backend-module-stack-overflow/alpha-api-report.md rename to plugins/search-backend-module-stack-overflow-collator/alpha-api-report.md index 9d25cb0a7d..a77d5e9598 100644 --- a/plugins/search-backend-module-stack-overflow/alpha-api-report.md +++ b/plugins/search-backend-module-stack-overflow-collator/alpha-api-report.md @@ -1,4 +1,4 @@ -## API Report File for "@backstage/plugin-search-backend-module-stack-overflow" +## API Report File for "@backstage/plugin-search-backend-module-stack-overflow-collator" > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). diff --git a/plugins/search-backend-module-stack-overflow/api-report.md b/plugins/search-backend-module-stack-overflow-collator/api-report.md similarity index 98% rename from plugins/search-backend-module-stack-overflow/api-report.md rename to plugins/search-backend-module-stack-overflow-collator/api-report.md index 795b30cac2..996260c4aa 100644 --- a/plugins/search-backend-module-stack-overflow/api-report.md +++ b/plugins/search-backend-module-stack-overflow-collator/api-report.md @@ -1,4 +1,4 @@ -## API Report File for "@backstage/plugin-search-backend-module-stack-overflow" +## API Report File for "@backstage/plugin-search-backend-module-stack-overflow-collator" > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). diff --git a/plugins/search-backend-module-stack-overflow/catalog-info.yaml b/plugins/search-backend-module-stack-overflow-collator/catalog-info.yaml similarity index 79% rename from plugins/search-backend-module-stack-overflow/catalog-info.yaml rename to plugins/search-backend-module-stack-overflow-collator/catalog-info.yaml index 9075d1d591..ed73bd0eca 100644 --- a/plugins/search-backend-module-stack-overflow/catalog-info.yaml +++ b/plugins/search-backend-module-stack-overflow-collator/catalog-info.yaml @@ -1,8 +1,8 @@ apiVersion: backstage.io/v1alpha1 kind: Component metadata: - name: backstage-plugin-search-backend-module-stack-overflow - title: '@backstage/plugin-search-backend-module-stack-overflow' + name: backstage-plugin-search-backend-module-stack-overflow-collator + title: '@backstage/plugin-search-backend-module-stack-overflow-collator' description: A module for the search backend that exports stack overflow modules spec: lifecycle: experimental diff --git a/plugins/search-backend-module-stack-overflow/config.d.ts b/plugins/search-backend-module-stack-overflow-collator/config.d.ts similarity index 100% rename from plugins/search-backend-module-stack-overflow/config.d.ts rename to plugins/search-backend-module-stack-overflow-collator/config.d.ts diff --git a/plugins/search-backend-module-stack-overflow/package.json b/plugins/search-backend-module-stack-overflow-collator/package.json similarity index 99% rename from plugins/search-backend-module-stack-overflow/package.json rename to plugins/search-backend-module-stack-overflow-collator/package.json index 64ff4d32d3..6e0b484e40 100644 --- a/plugins/search-backend-module-stack-overflow/package.json +++ b/plugins/search-backend-module-stack-overflow-collator/package.json @@ -1,5 +1,5 @@ { - "name": "@backstage/plugin-search-backend-module-stack-overflow", + "name": "@backstage/plugin-search-backend-module-stack-overflow-collator", "description": "A module for the search backend that exports stack overflow modules", "version": "0.0.0", "main": "src/index.ts", diff --git a/plugins/search-backend-module-stack-overflow/src/alpha.test.ts b/plugins/search-backend-module-stack-overflow-collator/src/alpha.test.ts similarity index 100% rename from plugins/search-backend-module-stack-overflow/src/alpha.test.ts rename to plugins/search-backend-module-stack-overflow-collator/src/alpha.test.ts diff --git a/plugins/search-backend-module-stack-overflow/src/alpha.ts b/plugins/search-backend-module-stack-overflow-collator/src/alpha.ts similarity index 100% rename from plugins/search-backend-module-stack-overflow/src/alpha.ts rename to plugins/search-backend-module-stack-overflow-collator/src/alpha.ts diff --git a/plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.test.ts b/plugins/search-backend-module-stack-overflow-collator/src/collators/StackOverflowQuestionsCollatorFactory.test.ts similarity index 100% rename from plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.test.ts rename to plugins/search-backend-module-stack-overflow-collator/src/collators/StackOverflowQuestionsCollatorFactory.test.ts diff --git a/plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.ts b/plugins/search-backend-module-stack-overflow-collator/src/collators/StackOverflowQuestionsCollatorFactory.ts similarity index 100% rename from plugins/search-backend-module-stack-overflow/src/collators/StackOverflowQuestionsCollatorFactory.ts rename to plugins/search-backend-module-stack-overflow-collator/src/collators/StackOverflowQuestionsCollatorFactory.ts diff --git a/plugins/search-backend-module-stack-overflow/src/collators/index.ts b/plugins/search-backend-module-stack-overflow-collator/src/collators/index.ts similarity index 100% rename from plugins/search-backend-module-stack-overflow/src/collators/index.ts rename to plugins/search-backend-module-stack-overflow-collator/src/collators/index.ts diff --git a/plugins/search-backend-module-stack-overflow/src/index.ts b/plugins/search-backend-module-stack-overflow-collator/src/index.ts similarity index 100% rename from plugins/search-backend-module-stack-overflow/src/index.ts rename to plugins/search-backend-module-stack-overflow-collator/src/index.ts diff --git a/plugins/search-backend-module-stack-overflow/README.md b/plugins/search-backend-module-stack-overflow/README.md deleted file mode 100644 index cba9617ea8..0000000000 --- a/plugins/search-backend-module-stack-overflow/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# search-backend-module-stack-overflow - -> DISCLAIMER: The new backend system is in alpha, and so are the search backend module support for the new backend system. We don't recommend you to migrate your backend installations to the new system yet. But if you want to experiment, you can find getting started guides below. - -This package exports a module that extends the search backend to also indexing the questions exposed by the [`Stack Overflow` API](https://api.stackexchange.com/docs/questions). - -## Installation - -Add the module package as a dependency: - -```bash -# From your Backstage root directory -yarn add --cwd packages/backend @backstage/plugin-search-backend-module-stack-overflow -``` - -Add the collator to your backend instance, along with the search plugin itself: - -```tsx -// packages/backend/src/index.ts -import { createBackend } from '@backstage/backend-defaults'; - -const backend = createBackend(); -backend.add(import('@backstage/plugin-search-backend/alpha')); -backend.add( - import('@backstage/plugin-search-backend-module-stack-overflow/alpha'), -); -backend.start(); -``` - -You may also want to add configuration parameters to your app-config, for example for controlling the scheduled indexing interval. These parameters should be placed under the `stackoverflow` key. See [the config definition file](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-stack-overflow/config.d.ts) for more details. diff --git a/plugins/stack-overflow-backend/api-report.md b/plugins/stack-overflow-backend/api-report.md index d113f7a0b6..14dcdf2007 100644 --- a/plugins/stack-overflow-backend/api-report.md +++ b/plugins/stack-overflow-backend/api-report.md @@ -3,9 +3,9 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { StackOverflowDocument as StackOverflowDocument_2 } from '@backstage/plugin-search-backend-module-stack-overflow'; -import { StackOverflowQuestionsCollatorFactory as StackOverflowQuestionsCollatorFactory_2 } from '@backstage/plugin-search-backend-module-stack-overflow'; -import { StackOverflowQuestionsRequestParams as StackOverflowQuestionsRequestParams_2 } from '@backstage/plugin-search-backend-module-stack-overflow'; +import { StackOverflowDocument as StackOverflowDocument_2 } from '@backstage/plugin-search-backend-module-stack-overflow-collator'; +import { StackOverflowQuestionsCollatorFactory as StackOverflowQuestionsCollatorFactory_2 } from '@backstage/plugin-search-backend-module-stack-overflow-collator'; +import { StackOverflowQuestionsRequestParams as StackOverflowQuestionsRequestParams_2 } from '@backstage/plugin-search-backend-module-stack-overflow-collator'; // @public @deprecated (undocumented) export type StackOverflowDocument = StackOverflowDocument_2; diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 5235c33f1a..c7b65a5ef5 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -34,7 +34,7 @@ "dependencies": { "@backstage/backend-common": "workspace:^", "@backstage/config": "workspace:^", - "@backstage/plugin-search-backend-module-stack-overflow": "workspace:^", + "@backstage/plugin-search-backend-module-stack-overflow-collator": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "node-fetch": "^2.6.7", "qs": "^6.9.4", diff --git a/plugins/stack-overflow-backend/src/index.ts b/plugins/stack-overflow-backend/src/index.ts index 269748424b..e676de15e2 100644 --- a/plugins/stack-overflow-backend/src/index.ts +++ b/plugins/stack-overflow-backend/src/index.ts @@ -25,19 +25,19 @@ import { StackOverflowQuestionsRequestParams as _StackOverflowQuestionsRequestParams, StackOverflowQuestionsCollatorFactory as _StackOverflowQuestionsCollatorFactory, StackOverflowQuestionsCollatorFactoryOptions as _StackOverflowQuestionsCollatorFactoryOptions, -} from '@backstage/plugin-search-backend-module-stack-overflow'; +} from '@backstage/plugin-search-backend-module-stack-overflow-collator'; /** * @public * @deprecated - * Import from `@backstage/plugin-search-backend-module-stack-overflow` instead. + * Import from `@backstage/plugin-search-backend-module-stack-overflow-collator` instead. */ export type StackOverflowDocument = _StackOverflowDocument; /** * @public * @deprecated - * Import from `@backstage/plugin-search-backend-module-stack-overflow` instead. + * Import from `@backstage/plugin-search-backend-module-stack-overflow-collator` instead. */ export type StackOverflowQuestionsRequestParams = _StackOverflowQuestionsRequestParams; @@ -45,7 +45,7 @@ export type StackOverflowQuestionsRequestParams = /** * @public * @deprecated - * Import from `@backstage/plugin-search-backend-module-stack-overflow` instead. + * Import from `@backstage/plugin-search-backend-module-stack-overflow-collator` instead. */ export type StackOverflowQuestionsCollatorFactoryOptions = _StackOverflowQuestionsCollatorFactory; @@ -53,7 +53,7 @@ export type StackOverflowQuestionsCollatorFactoryOptions = /** * @public * @deprecated - * Import from `@backstage/plugin-search-backend-module-stack-overflow` instead. + * Import from `@backstage/plugin-search-backend-module-stack-overflow-collator` instead. */ export const StackOverflowQuestionsCollatorFactory = _StackOverflowQuestionsCollatorFactory; diff --git a/yarn.lock b/yarn.lock index 6e2db68238..1267ee2cb4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8847,9 +8847,9 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-backend-module-stack-overflow@workspace:^, @backstage/plugin-search-backend-module-stack-overflow@workspace:plugins/search-backend-module-stack-overflow": +"@backstage/plugin-search-backend-module-stack-overflow-collator@workspace:^, @backstage/plugin-search-backend-module-stack-overflow-collator@workspace:plugins/search-backend-module-stack-overflow-collator": version: 0.0.0-use.local - resolution: "@backstage/plugin-search-backend-module-stack-overflow@workspace:plugins/search-backend-module-stack-overflow" + resolution: "@backstage/plugin-search-backend-module-stack-overflow-collator@workspace:plugins/search-backend-module-stack-overflow-collator" dependencies: "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" @@ -9209,7 +9209,7 @@ __metadata: "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" - "@backstage/plugin-search-backend-module-stack-overflow": "workspace:^" + "@backstage/plugin-search-backend-module-stack-overflow-collator": "workspace:^" "@backstage/plugin-search-backend-node": "workspace:^" "@backstage/plugin-search-common": "workspace:^" msw: ^1.0.0 From 95dc40505ac8bd01ec8c223a0cde04151b6c6e3d Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 14 Oct 2023 12:51:32 +0200 Subject: [PATCH 182/348] docs(stack-overflow): update api reports Signed-off-by: Camila Belo --- plugins/stack-overflow/alpha-api-report.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/stack-overflow/alpha-api-report.md b/plugins/stack-overflow/alpha-api-report.md index 84d7616759..8bf621b948 100644 --- a/plugins/stack-overflow/alpha-api-report.md +++ b/plugins/stack-overflow/alpha-api-report.md @@ -3,10 +3,12 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AnyExternalRoutes } from '@backstage/core-plugin-api'; +import { AnyRoutes } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin; export default _default; // (No @packageDocumentation comment for this package) From 3b5bef78b297df7ce846b12f2ecac91e3a34036e Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 18 Oct 2023 10:51:04 +0200 Subject: [PATCH 183/348] chore(stack-overflow-backend): deprecate entire package Signed-off-by: Camila Belo --- .../README.md | 2 +- plugins/stack-overflow-backend/README.md | 65 +------------------ plugins/stack-overflow-backend/package.json | 1 + plugins/stack-overflow-backend/src/index.ts | 5 +- plugins/stack-overflow/alpha-api-report.md | 4 +- 5 files changed, 8 insertions(+), 69 deletions(-) diff --git a/plugins/search-backend-module-stack-overflow-collator/README.md b/plugins/search-backend-module-stack-overflow-collator/README.md index 914746cbf9..5fba2a3c79 100644 --- a/plugins/search-backend-module-stack-overflow-collator/README.md +++ b/plugins/search-backend-module-stack-overflow-collator/README.md @@ -94,4 +94,4 @@ backend.add( backend.start(); ``` -You may also want to add configuration parameters to your app-config, for example for controlling the scheduled indexing interval. These parameters should be placed under the `stackoverflow` key. See [the config definition file](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-stack-overflow/config.d.ts) for more details. +You may also want to add configuration parameters to your app-config, for example for controlling the scheduled indexing interval. These parameters should be placed under the `stackoverflow` key. See [the config definition file](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-stack-overflow-collator/config.d.ts) for more details. diff --git a/plugins/stack-overflow-backend/README.md b/plugins/stack-overflow-backend/README.md index 5de997faa6..8129d36e38 100644 --- a/plugins/stack-overflow-backend/README.md +++ b/plugins/stack-overflow-backend/README.md @@ -1,64 +1,3 @@ -# Stack Overflow +# Stack Overflow Backend -A plugin that provides stack overflow specific functionality that can be used in different ways (e.g. for search) to compose your Backstage App. - -## Getting started - -Before we begin, make sure: - -- You have created your own standalone Backstage app using @backstage/create-app and not using a fork of the backstage repository. If you haven't setup Backstage already, start [here](https://backstage.io/docs/getting-started/). - -To use any of the functionality this plugin provides, you need to start by configuring your App with the following config: - -```yaml -stackoverflow: - baseUrl: https://api.stackexchange.com/2.2 # alternative: your internal stack overflow instance -``` - -### Stack Overflow for Teams - -If you have a private Stack Overflow instance and/or a private Stack Overflow Team you will need to supply an API key or Personal Access Token. You can read more about how to set this up by going to [Stack Overflow's Help Page](https://stackoverflow.help/en/articles/4385859-stack-overflow-for-teams-api). - -The existing API key approach remains the default, to support the new v2.3 API and PAT authentication model you need to pass the team name and the new PAT into the existing apiAccessToken parameter to the new URL. See [15770](https://github.com/backstage/backstage/issues/15770) for more details. - -```yaml -stackoverflow: - baseUrl: https://api.stackexchange.com/2.2 # alternative: your internal stack overflow instance - apiKey: $STACK_OVERFLOW_API_KEY - apiAccessToken: $STACK_OVERFLOW_API_ACCESS_TOKEN -``` - -```yaml -stackoverflow: - baseUrl: https://api.stackoverflowteams.com/2.3 # alternative: your internal stack overflow instance - teamName: $STACK_OVERFLOW_TEAM_NAME - apiAccessToken: $STACK_OVERFLOW_API_ACCESS_TOKEN -``` - -## Areas of Responsibility - -This stack overflow backend plugin is primarily responsible for the following: - -- Provides a `StackOverflowQuestionsCollatorFactory`, which can be used in the search backend to index stack overflow questions to your Backstage Search. - -### Index Stack Overflow Questions to search - -Before you are able to start index stack overflow questions to search, you need to go through the [search getting started guide](https://backstage.io/docs/features/search/getting-started). - -When you have your `packages/backend/src/plugins/search.ts` file ready to make modifications, add the following code snippet to add the `StackOverflowQuestionsCollatorFactory`. Note that you can optionally modify the `requestParams`, otherwise it will defaults to `{ order: 'desc', sort: 'activity', site: 'stackoverflow' }` as done in the `Try It` section on the [official Stack Overflow API documentation](https://api.stackexchange.com/docs/questions). - -> Note: if your `baseUrl` is set to the external stack overflow api `https://api.stackexchange.com/2.2`, you can find optional and required parameters under the official API documentation under [`Usage of /questions GET`](https://api.stackexchange.com/docs/questions) - -```ts -indexBuilder.addCollator({ - schedule, - factory: StackOverflowQuestionsCollatorFactory.fromConfig(env.config, { - logger: env.logger, - requestParams: { - tagged: ['backstage'], - site: 'stackoverflow', - pagesize: 100, - }, - }), -}); -``` +Deprecated, consider using `@backstage/plugin-search-backend-module-stack-overflow-collator` instead. diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index c7b65a5ef5..77ebd8c69e 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,5 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", + "description": "Deprecated, consider using @backstage/plugin-search-backend-module-stack-overflow-collator instead", "version": "0.2.10", "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/stack-overflow-backend/src/index.ts b/plugins/stack-overflow-backend/src/index.ts index e676de15e2..5ca1c8d283 100644 --- a/plugins/stack-overflow-backend/src/index.ts +++ b/plugins/stack-overflow-backend/src/index.ts @@ -15,9 +15,10 @@ */ /** - * Stack Overflow backend plugin - * * @packageDocumentation + * Stack Overflow backend plugin + * @deprecated + * Deprecated, consider using `@backstage/plugin-search-backend-module-stack-overflow-collator` instead. */ import { diff --git a/plugins/stack-overflow/alpha-api-report.md b/plugins/stack-overflow/alpha-api-report.md index 8bf621b948..167f8e1736 100644 --- a/plugins/stack-overflow/alpha-api-report.md +++ b/plugins/stack-overflow/alpha-api-report.md @@ -3,12 +3,10 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyExternalRoutes } from '@backstage/core-plugin-api'; -import { AnyRoutes } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin<{}, {}>; export default _default; // (No @packageDocumentation comment for this package) From d7a4e2225f7cadb61240cb44ff4ccef72f54f190 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 19 Oct 2023 09:10:35 +0200 Subject: [PATCH 184/348] fix: changeset package version Signed-off-by: Camila Belo --- .changeset/chilly-terms-behave.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/chilly-terms-behave.md b/.changeset/chilly-terms-behave.md index b514bc45c8..8ee1ad8375 100644 --- a/.changeset/chilly-terms-behave.md +++ b/.changeset/chilly-terms-behave.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-search-backend-module-stack-overflow-collator': patch +'@backstage/plugin-search-backend-module-stack-overflow-collator': minor --- Extract a package for the Stack Overflow new backend system plugin. From 8a7f1ba2a511973bf1f82dc408e4526c88208b5f Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 19 Oct 2023 09:11:33 +0200 Subject: [PATCH 185/348] docs(stack-overflow): add note about missing hompage card extension Signed-off-by: Camila Belo --- plugins/stack-overflow/src/alpha.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/stack-overflow/src/alpha.tsx b/plugins/stack-overflow/src/alpha.tsx index 18f0a0df1c..3708271ef1 100644 --- a/plugins/stack-overflow/src/alpha.tsx +++ b/plugins/stack-overflow/src/alpha.tsx @@ -44,5 +44,6 @@ const StackOverflowSearchResultListItem = createSearchResultListItemExtension({ /** @alpha */ export default createPlugin({ id: 'stack-overflow', + // TODO: Migrate homepage cards when the declarative homepage plugin supports them extensions: [StackOverflowApi, StackOverflowSearchResultListItem], }); From e13e43a12509f72ae8322cbab1dc1f665c8c45b5 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 19 Oct 2023 09:28:38 +0200 Subject: [PATCH 186/348] refactor(stack-overflow-backend): remove alpha subpath Signed-off-by: Camila Belo --- .../README.md | 4 +--- .../alpha-api-report.md | 11 ----------- .../api-report.md | 5 +++++ .../package.json | 19 +++---------------- .../src/index.ts | 1 + ...SearchStackOverflowCollatorModule.test.ts} | 6 +++--- .../SearchStackOverflowCollatorModule.ts} | 14 ++++---------- .../src/module/index.ts | 17 +++++++++++++++++ 8 files changed, 34 insertions(+), 43 deletions(-) delete mode 100644 plugins/search-backend-module-stack-overflow-collator/alpha-api-report.md rename plugins/search-backend-module-stack-overflow-collator/src/{alpha.test.ts => module/SearchStackOverflowCollatorModule.test.ts} (90%) rename plugins/search-backend-module-stack-overflow-collator/src/{alpha.ts => module/SearchStackOverflowCollatorModule.ts} (88%) create mode 100644 plugins/search-backend-module-stack-overflow-collator/src/module/index.ts diff --git a/plugins/search-backend-module-stack-overflow-collator/README.md b/plugins/search-backend-module-stack-overflow-collator/README.md index 5fba2a3c79..7df3229eeb 100644 --- a/plugins/search-backend-module-stack-overflow-collator/README.md +++ b/plugins/search-backend-module-stack-overflow-collator/README.md @@ -87,9 +87,7 @@ import { createBackend } from '@backstage/backend-defaults'; const backend = createBackend(); backend.add(import('@backstage/plugin-search-backend/alpha')); backend.add( - import( - '@backstage/plugin-search-backend-module-stack-overflow-collator/alpha' - ), + import('@backstage/plugin-search-backend-module-stack-overflow-collator'), ); backend.start(); ``` diff --git a/plugins/search-backend-module-stack-overflow-collator/alpha-api-report.md b/plugins/search-backend-module-stack-overflow-collator/alpha-api-report.md deleted file mode 100644 index a77d5e9598..0000000000 --- a/plugins/search-backend-module-stack-overflow-collator/alpha-api-report.md +++ /dev/null @@ -1,11 +0,0 @@ -## API Report File for "@backstage/plugin-search-backend-module-stack-overflow-collator" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; - -// @alpha -const _default: () => BackendFeature; -export default _default; -``` diff --git a/plugins/search-backend-module-stack-overflow-collator/api-report.md b/plugins/search-backend-module-stack-overflow-collator/api-report.md index 996260c4aa..9243e786ac 100644 --- a/plugins/search-backend-module-stack-overflow-collator/api-report.md +++ b/plugins/search-backend-module-stack-overflow-collator/api-report.md @@ -5,12 +5,17 @@ ```ts /// +import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; import { IndexableDocument } from '@backstage/plugin-search-common'; import { Logger } from 'winston'; import { Readable } from 'stream'; +// @public +const searchStackOverflowCollatorModule: () => BackendFeature; +export default searchStackOverflowCollatorModule; + // @public export interface StackOverflowDocument extends IndexableDocument { // (undocumented) diff --git a/plugins/search-backend-module-stack-overflow-collator/package.json b/plugins/search-backend-module-stack-overflow-collator/package.json index 6e0b484e40..14e547de8e 100644 --- a/plugins/search-backend-module-stack-overflow-collator/package.json +++ b/plugins/search-backend-module-stack-overflow-collator/package.json @@ -6,22 +6,9 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public" - }, - "exports": { - ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", - "./package.json": "./package.json" - }, - "typesVersions": { - "*": { - "alpha": [ - "src/alpha.ts" - ], - "package.json": [ - "package.json" - ] - } + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" }, "backstage": { "role": "backend-plugin-module" diff --git a/plugins/search-backend-module-stack-overflow-collator/src/index.ts b/plugins/search-backend-module-stack-overflow-collator/src/index.ts index eb1f7540de..00d57a7b27 100644 --- a/plugins/search-backend-module-stack-overflow-collator/src/index.ts +++ b/plugins/search-backend-module-stack-overflow-collator/src/index.ts @@ -20,3 +20,4 @@ */ export * from './collators'; +export { searchStackOverflowCollatorModule as default } from './module'; diff --git a/plugins/search-backend-module-stack-overflow-collator/src/alpha.test.ts b/plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.test.ts similarity index 90% rename from plugins/search-backend-module-stack-overflow-collator/src/alpha.test.ts rename to plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.test.ts index 1dba1ab8c0..a785ead6eb 100644 --- a/plugins/search-backend-module-stack-overflow-collator/src/alpha.test.ts +++ b/plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.test.ts @@ -16,9 +16,9 @@ import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { searchIndexRegistryExtensionPoint } from '@backstage/plugin-search-backend-node/alpha'; -import searchModuleStackOverflowCollator from './alpha'; +import { searchStackOverflowCollatorModule } from './SearchStackOverflowCollatorModule'; -describe('searchModuleStackOverflowCollator', () => { +describe('searchStackOverflowCollatorModule', () => { const schedule = { frequency: { minutes: 10 }, timeout: { minutes: 15 }, @@ -35,7 +35,7 @@ describe('searchModuleStackOverflowCollator', () => { [searchIndexRegistryExtensionPoint, extensionPointMock], ], features: [ - searchModuleStackOverflowCollator(), + searchStackOverflowCollatorModule(), mockServices.rootConfig.factory({ data: { stackoverflow: { diff --git a/plugins/search-backend-module-stack-overflow-collator/src/alpha.ts b/plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.ts similarity index 88% rename from plugins/search-backend-module-stack-overflow-collator/src/alpha.ts rename to plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.ts index 85b686c9ed..3ef3d72c32 100644 --- a/plugins/search-backend-module-stack-overflow-collator/src/alpha.ts +++ b/plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.ts @@ -21,20 +21,14 @@ import { createBackendModule, } from '@backstage/backend-plugin-api'; import { searchIndexRegistryExtensionPoint } from '@backstage/plugin-search-backend-node/alpha'; -import { StackOverflowQuestionsCollatorFactory } from './collators'; - -/** - * @packageDocumentation - * A module for the search backend that exports Stack Overflow modules. - */ +import { StackOverflowQuestionsCollatorFactory } from '../collators'; /** + * @public * Search backend module for the Stack Overflow index. - * - * @alpha */ -export default createBackendModule({ - moduleId: 'stackoverflowCollator', +export const searchStackOverflowCollatorModule = createBackendModule({ + moduleId: 'stackOverflowCollator', pluginId: 'search', register(env) { env.registerInit({ diff --git a/plugins/search-backend-module-stack-overflow-collator/src/module/index.ts b/plugins/search-backend-module-stack-overflow-collator/src/module/index.ts new file mode 100644 index 0000000000..ab424398e0 --- /dev/null +++ b/plugins/search-backend-module-stack-overflow-collator/src/module/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 { searchStackOverflowCollatorModule } from './SearchStackOverflowCollatorModule'; From ed71a018b1ece87f2e73e15eeac18a8555569308 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 12 Oct 2023 22:08:03 +0200 Subject: [PATCH 187/348] feat(frontend-plugin-api): improve extension boundary Signed-off-by: Camila Belo --- packages/frontend-plugin-api/package.json | 4 +- .../src/components/ErrorBoundary.tsx | 79 +++++++++++++++++++ .../src/components/ExtensionBoundary.tsx | 24 +++++- yarn.lock | 2 + 4 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 packages/frontend-plugin-api/src/components/ErrorBoundary.tsx diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 9cc3355ec3..528d86e0d1 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -24,6 +24,7 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", + "@backstage/frontend-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^14.0.0", @@ -37,10 +38,11 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "dependencies": { + "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", - "@backstage/frontend-app-api": "workspace:^", "@backstage/types": "workspace:^", "@backstage/version-bridge": "workspace:^", + "@material-ui/core": "^4.12.4", "@types/react": "^16.13.1 || ^17.0.0", "lodash": "^4.17.21", "zod": "^3.21.4", diff --git a/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx b/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000000..f9ce9c9809 --- /dev/null +++ b/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { Component, PropsWithChildren } from 'react'; +import { Button } from '@material-ui/core'; +import { BackstagePlugin } from '../wiring'; +import { ErrorPanel } from '@backstage/core-components'; + +type DefaultErrorBoundaryFallbackProps = PropsWithChildren<{ + plugin?: BackstagePlugin; + error: Error; + resetError: () => void; +}>; + +const DefaultErrorBoundaryFallback = ({ + plugin, + error, + resetError, +}: DefaultErrorBoundaryFallbackProps) => { + const title = `Error in ${plugin?.id}`; + + return ( + + + + ); +}; + +type ErrorBoundaryProps = PropsWithChildren<{ plugin?: BackstagePlugin }>; +type ErrorBoundaryState = { error?: Error }; + +/** @internal */ +export class ErrorBoundary extends Component< + ErrorBoundaryProps, + ErrorBoundaryState +> { + static getDerivedStateFromError(error: Error) { + return { error }; + } + + state: ErrorBoundaryState = { error: undefined }; + + handleErrorReset = () => { + this.setState({ error: undefined }); + }; + + render() { + const { error } = this.state; + const { plugin, children } = this.props; + + if (error) { + // TODO: use a configurable error boundary fallback + return ( + + ); + } + + return children; + } +} diff --git a/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx b/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx index c6a218c15f..796908c619 100644 --- a/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx +++ b/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx @@ -15,15 +15,35 @@ */ import React, { ReactNode } from 'react'; +import { AnalyticsContext } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '../wiring'; +import { RouteRef } from '../routing'; +import { ErrorBoundary } from './ErrorBoundary'; +import { toInternalRouteRef } from '../routing/RouteRef'; /** @public */ export interface ExtensionBoundaryProps { - children: ReactNode; + id: string; source?: BackstagePlugin; + routeRef?: RouteRef; + children: ReactNode; } /** @public */ export function ExtensionBoundary(props: ExtensionBoundaryProps) { - return <>{props.children}; + const { id, source, routeRef, children } = props; + + const attributes = { + extension: id, + pluginId: source?.id, + routeRef: routeRef + ? toInternalRouteRef(routeRef).getDescription() + : undefined, + }; + + return ( + + {children} + + ); } diff --git a/yarn.lock b/yarn.lock index 1e2f6fdb5d..8999966568 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4246,11 +4246,13 @@ __metadata: resolution: "@backstage/frontend-plugin-api@workspace:packages/frontend-plugin-api" dependencies: "@backstage/cli": "workspace:^" + "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/frontend-app-api": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@backstage/version-bridge": "workspace:^" + "@material-ui/core": ^4.12.4 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 From b2dcb92c36e8c142f1b9bb386505b31368a3cfc7 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 13 Oct 2023 15:57:50 +0200 Subject: [PATCH 188/348] test(frontend-plugin-api): cover extension boundary component Signed-off-by: Camila Belo --- .../src/components/ExtensionBoundary.test.tsx | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx diff --git a/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx b/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx new file mode 100644 index 0000000000..150ace717c --- /dev/null +++ b/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx @@ -0,0 +1,136 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useEffect } from 'react'; +import { screen, waitFor } from '@testing-library/react'; +import { + MockAnalyticsApi, + MockConfigApi, + TestApiProvider, + renderWithEffects, +} from '@backstage/test-utils'; +import { ExtensionBoundary } from './ExtensionBoundary'; +import { + Extension, + coreExtensionData, + createExtension, + createPlugin, +} from '../wiring'; +import { analyticsApiRef, useAnalytics } from '@backstage/core-plugin-api'; +import { createApp } from '@backstage/frontend-app-api'; +import { JsonObject } from '@backstage/types'; +import { createRouteRef } from '../routing'; +import { toInternalRouteRef } from '../routing/RouteRef'; + +function renderExtensionInTestApp( + extension: Extension, + options?: { + config?: JsonObject; + }, +) { + const { config = {} } = options ?? {}; + + const app = createApp({ + features: [ + createPlugin({ + id: 'plugin', + extensions: [extension], + }), + ], + configLoader: async () => new MockConfigApi(config), + }); + + return renderWithEffects(app.createRoot()); +} + +const wrapInBoundaryExtension = (element: JSX.Element) => { + const id = 'plugin.extension'; + const routeRef = createRouteRef(); + toInternalRouteRef(routeRef).setId(id); + return createExtension({ + id, + attachTo: { id: 'core.routes', input: 'routes' }, + output: { + element: coreExtensionData.reactElement, + path: coreExtensionData.routePath, + routeRef: coreExtensionData.routeRef.optional(), + }, + factory({ bind, source }) { + bind({ + routeRef, + path: '/', + element: ( + + {element} + + ), + }); + }, + }); +}; + +describe('ExtensionBoundary', () => { + it('should render children when there is no error', async () => { + const text = 'Text Component'; + const TextComponent = () => { + return

{text}

; + }; + await renderExtensionInTestApp(wrapInBoundaryExtension()); + await waitFor(() => expect(screen.getByText(text)).toBeInTheDocument()); + }); + + it('should show app error component when an error is thrown', async () => { + const error = 'Something went wrong'; + const ErrorComponent = () => { + throw new Error(error); + }; + await renderExtensionInTestApp(wrapInBoundaryExtension()); + await waitFor(() => expect(screen.getByText(error)).toBeInTheDocument()); + }); + + it('should wrap children with analytics context', async () => { + const action = 'render'; + const subject = 'analytics'; + const analyticsApiMock = new MockAnalyticsApi(); + + const AnalyticsComponent = () => { + const analytics = useAnalytics(); + useEffect(() => { + analytics.captureEvent(action, subject); + }, [analytics]); + return null; + }; + + await renderExtensionInTestApp( + wrapInBoundaryExtension( + + + , + ), + ); + + await waitFor(() => + expect(analyticsApiMock.getEvents()[0]).toMatchObject({ + action, + subject, + context: { + extension: 'plugin.extension', + routeRef: 'plugin.extension', + }, + }), + ); + }); +}); From 2610774e4b281d5239788fced55ead61104ef02c Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 12 Oct 2023 22:08:32 +0200 Subject: [PATCH 189/348] feat(frontend-plugin-api): create extension suspense Signed-off-by: Camila Belo --- .../src/components/ExtensionSuspense.tsx | 33 +++++++++++++++++++ .../src/components/index.ts | 5 +++ 2 files changed, 38 insertions(+) create mode 100644 packages/frontend-plugin-api/src/components/ExtensionSuspense.tsx diff --git a/packages/frontend-plugin-api/src/components/ExtensionSuspense.tsx b/packages/frontend-plugin-api/src/components/ExtensionSuspense.tsx new file mode 100644 index 0000000000..e80f59f09c --- /dev/null +++ b/packages/frontend-plugin-api/src/components/ExtensionSuspense.tsx @@ -0,0 +1,33 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { ReactNode, Suspense } from 'react'; +import { useApp } from '@backstage/core-plugin-api'; + +/** @public */ +export interface ExtensionSuspenseProps { + children: ReactNode; +} + +/** @public */ +export function ExtensionSuspense(props: ExtensionSuspenseProps) { + const { children } = props; + + const app = useApp(); + const { Progress } = app.getComponents(); + + return }>{children}; +} diff --git a/packages/frontend-plugin-api/src/components/index.ts b/packages/frontend-plugin-api/src/components/index.ts index 7056a59271..fecd7f36cc 100644 --- a/packages/frontend-plugin-api/src/components/index.ts +++ b/packages/frontend-plugin-api/src/components/index.ts @@ -18,3 +18,8 @@ export { ExtensionBoundary, type ExtensionBoundaryProps, } from './ExtensionBoundary'; + +export { + ExtensionSuspense, + type ExtensionSuspenseProps, +} from './ExtensionSuspense'; From 055b7aec3da8b0b04801525d8180d47ea8978d36 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 13 Oct 2023 10:56:10 +0200 Subject: [PATCH 190/348] test(frontend-plugin-api): cover extension suspense component Signed-off-by: Camila Belo --- .../src/components/ExtensionSuspense.test.tsx | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 packages/frontend-plugin-api/src/components/ExtensionSuspense.test.tsx diff --git a/packages/frontend-plugin-api/src/components/ExtensionSuspense.test.tsx b/packages/frontend-plugin-api/src/components/ExtensionSuspense.test.tsx new file mode 100644 index 0000000000..166c57b83b --- /dev/null +++ b/packages/frontend-plugin-api/src/components/ExtensionSuspense.test.tsx @@ -0,0 +1,54 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { lazy } from 'react'; +import { screen, waitFor } from '@testing-library/react'; +import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { ExtensionSuspense } from './ExtensionSuspense'; + +describe('ExtensionSuspense', () => { + it('should render the app progress component as fallback', async () => { + const LazyComponent = lazy(() => new Promise(() => {})); + + await renderWithEffects( + wrapInTestApp( + + + , + ), + ); + + expect(screen.getByTestId('progress')).toBeInTheDocument(); + }); + + it('should render the lazy loaded children component', async () => { + const LazyComponent = lazy(() => + Promise.resolve({ default: () =>
Lazy Component
}), + ); + + await renderWithEffects( + wrapInTestApp( + + + , + ), + ); + + await waitFor(() => + expect(screen.getByText('Lazy Component')).toBeInTheDocument(), + ); + }); +}); From 103b405746ada473d44cf9c01738c65010238592 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 19 Oct 2023 10:05:37 +0200 Subject: [PATCH 191/348] feat(frontend-plugin-api): use extension boundary and suspense Signed-off-by: Camila Belo --- .../src/extensions/createPageExtension.tsx | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx index 217fb33ce5..ad7db1d222 100644 --- a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx @@ -14,18 +14,21 @@ * limitations under the License. */ -import React from 'react'; -import { ExtensionBoundary } from '../components'; +import React, { lazy, useEffect } from 'react'; +import { useAnalytics } from '@backstage/core-plugin-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker'; +import { ExtensionBoundary, ExtensionSuspense } from '../components'; import { createSchemaFromZod, PortableSchema } from '../schema'; import { coreExtensionData, createExtension, Extension, ExtensionInputValues, + AnyExtensionInputMap, } from '../wiring'; -import { AnyExtensionInputMap } from '../wiring/createExtension'; -import { Expand } from '../types'; import { RouteRef } from '../routing'; +import { Expand } from '../types'; /** * Helper for creating extensions for a routable React page component. @@ -55,6 +58,10 @@ export function createPageExtension< }) => Promise; }, ): Extension { + const { id, routeRef } = options; + + const attachTo = options.attachTo ?? { id: 'core.routes', input: 'routes' }; + const configSchema = 'configSchema' in options ? options.configSchema @@ -63,33 +70,49 @@ export function createPageExtension< ) as PortableSchema); return createExtension({ - id: options.id, - attachTo: options.attachTo ?? { id: 'core.routes', input: 'routes' }, + id, + attachTo, + configSchema, + inputs: options.inputs, disabled: options.disabled, output: { element: coreExtensionData.reactElement, path: coreExtensionData.routePath, routeRef: coreExtensionData.routeRef.optional(), }, - inputs: options.inputs, - configSchema, factory({ bind, config, inputs, source }) { - const LazyComponent = React.lazy(() => + const { path } = config; + + const PageComponent = lazy(() => options .loader({ config, inputs }) .then(element => ({ default: () => element })), ); + const ExtensionComponent = () => { + const analytics = useAnalytics(); + + // This event, never exposed to end-users of the analytics API, + // helps inform which extension metadata gets associated with a + // navigation event when the route navigated to is a gathered + // mountpoint. + useEffect(() => { + analytics.captureEvent(routableExtensionRenderedEvent, ''); + }, [analytics]); + + return ; + }; + bind({ - path: config.path, + path, + routeRef, element: ( - - - - + + + + ), - routeRef: options.routeRef, }); }, }); From 42a8ef3a4f2283de29d29f73eb3b94a6203f1d72 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 13 Oct 2023 20:58:03 +0200 Subject: [PATCH 192/348] test(frontend-plugin-api): cover create page extension Signed-off-by: Camila Belo --- .../extensions/createPageExtension.test.tsx | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx index 125bf3495d..37d97e7621 100644 --- a/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx +++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx @@ -15,10 +15,23 @@ */ import React from 'react'; +import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { useAnalytics } from '@backstage/core-plugin-api'; +import { waitFor } from '@testing-library/react'; import { PortableSchema } from '../schema'; -import { coreExtensionData, createExtensionInput } from '../wiring'; +import { + ExtensionInputValues, + coreExtensionData, + createExtensionInput, + createPlugin, +} from '../wiring'; import { createPageExtension } from './createPageExtension'; +jest.mock('@backstage/core-plugin-api', () => ({ + ...jest.requireActual('@backstage/core-plugin-api'), + useAnalytics: jest.fn(), +})); + describe('createPageExtension', () => { it('creates the extension properly', () => { const configSchema: PortableSchema<{ path: string }> = { @@ -100,4 +113,35 @@ describe('createPageExtension', () => { factory: expect.any(Function), }); }); + + it('capture page view event in analytics', async () => { + const captureEvent = jest.fn(); + + (useAnalytics as jest.Mock).mockReturnValue({ + captureEvent, + }); + + const extension = createPageExtension({ + id: 'plugin.page', + defaultPath: '/', + loader: async () =>
Component
, + }); + + extension.factory({ + bind: (values: ExtensionInputValues) => + renderWithEffects( + wrapInTestApp(values.element as unknown as JSX.Element), + ), + source: createPlugin({ id: 'plugin ' }), + config: { path: '/' }, + inputs: {}, + }); + + await waitFor(() => + expect(captureEvent).toHaveBeenCalledWith( + '_ROUTABLE-EXTENSION-RENDERED', + '', + ), + ); + }); }); From c1e10b6175e59af190d005454096b36dc712527a Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 13 Oct 2023 09:23:51 +0200 Subject: [PATCH 193/348] docs(frontend-plugin-api): update api reports Signed-off-by: Camila Belo --- packages/frontend-plugin-api/api-report.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 3ed5965c99..b6f85e757b 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -338,6 +338,10 @@ export interface ExtensionBoundaryProps { // (undocumented) children: ReactNode; // (undocumented) + id: string; + // (undocumented) + routeRef?: RouteRef; + // (undocumented) source?: BackstagePlugin; } @@ -412,6 +416,17 @@ export interface ExtensionOverridesOptions { extensions: Extension[]; } +// @public (undocumented) +export function ExtensionSuspense( + props: ExtensionSuspenseProps, +): React_2.JSX.Element; + +// @public (undocumented) +export interface ExtensionSuspenseProps { + // (undocumented) + children: ReactNode; +} + // @public export interface ExternalRouteRef< TParams extends AnyRouteRefParams = AnyRouteRefParams, From 6af88a05ff23e66d1c792e8fa6ba42fed4996c19 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 14 Oct 2023 10:38:48 +0200 Subject: [PATCH 194/348] chore(frontend-plugin-api): add changeset file Signed-off-by: Camila Belo --- .changeset/sixty-tips-argue.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sixty-tips-argue.md diff --git a/.changeset/sixty-tips-argue.md b/.changeset/sixty-tips-argue.md new file mode 100644 index 0000000000..9fc965a281 --- /dev/null +++ b/.changeset/sixty-tips-argue.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Improve the extension boundary component and create a default extension suspense component. From b51919e3eb85f68916de6d930e079fa70ae8b55b Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 13 Oct 2023 09:22:21 +0200 Subject: [PATCH 195/348] refactor(search-react): use extension boundary and suspense Signed-off-by: Camila Belo --- plugins/search-react/src/alpha.tsx | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/plugins/search-react/src/alpha.tsx b/plugins/search-react/src/alpha.tsx index 366112c95e..f28bc44b0d 100644 --- a/plugins/search-react/src/alpha.tsx +++ b/plugins/search-react/src/alpha.tsx @@ -14,18 +14,18 @@ * limitations under the License. */ -import React, { lazy, Suspense } from 'react'; +import React, { lazy } from 'react'; import { ListItemProps } from '@material-ui/core'; import { ExtensionBoundary, + ExtensionSuspense, PortableSchema, createExtension, createExtensionDataRef, createSchemaFromZod, } from '@backstage/frontend-plugin-api'; -import { Progress } from '@backstage/core-components'; import { SearchDocument, SearchResult } from '@backstage/plugin-search-common'; import { SearchResultListItemExtension } from './extensions'; @@ -87,6 +87,13 @@ export type SearchResultItemExtensionOptions< export function createSearchResultListItemExtension< TConfig extends { noTrack?: boolean }, >(options: SearchResultItemExtensionOptions) { + const id = `plugin.search.result.item.${options.id}`; + + const attachTo = options.attachTo ?? { + id: 'plugin.search.page', + input: 'items', + }; + const configSchema = 'configSchema' in options ? options.configSchema @@ -95,15 +102,16 @@ export function createSearchResultListItemExtension< noTrack: z.boolean().default(false), }), ) as PortableSchema); + return createExtension({ - id: `plugin.search.result.item.${options.id}`, - attachTo: options.attachTo ?? { id: 'plugin.search.page', input: 'items' }, + id, + attachTo, configSchema, output: { item: searchResultItemExtensionData, }, factory({ bind, config, source }) { - const LazyComponent = lazy(() => + const ExtensionComponent = lazy(() => options .component({ config }) .then(component => ({ default: component })), @@ -113,16 +121,16 @@ export function createSearchResultListItemExtension< item: { predicate: options.predicate, component: props => ( - - }> + + - + - + ), }, From e7c09c4f4b60d0107dcefe23a39ece2916b49ef3 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 14 Oct 2023 10:39:27 +0200 Subject: [PATCH 196/348] chore(search-react): add changeset file Signed-off-by: Camila Belo --- .changeset/young-days-talk.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/young-days-talk.md diff --git a/.changeset/young-days-talk.md b/.changeset/young-days-talk.md new file mode 100644 index 0000000000..b7420c7894 --- /dev/null +++ b/.changeset/young-days-talk.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +Use default extensions boundary and suspense on the alpha declarative `createSearchResultListItem` extension factory. From 11555a0da0153d52fbcd57dd94b8ff632539dbf9 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 19 Oct 2023 11:32:39 +0200 Subject: [PATCH 197/348] refactor(catalog): forward plugin to extension boundary Signed-off-by: Camila Belo --- plugins/catalog/src/alpha.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index 6eda8c3d26..27ec432d07 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -36,6 +36,7 @@ import { PortableSchema, ExtensionBoundary, createExtensionInput, + ExtensionSuspense, } from '@backstage/frontend-plugin-api'; import { AsyncEntityProvider, @@ -51,7 +52,6 @@ import { rootRouteRef, viewTechDocRouteRef, } from './routes'; -import { Progress } from '@backstage/core-components'; import { useEntityFromUrl } from './components/CatalogEntityPage/useEntityFromUrl'; /** @alpha */ @@ -97,16 +97,19 @@ export function createCatalogFilterExtension< configSchema?: PortableSchema; loader: (options: { config: TConfig }) => Promise; }) { + const id = `catalog.filter.${options.id}`; + const attachTo = { id: 'plugin.catalog.page.index', input: 'filters' }; + return createExtension({ - id: `catalog.filter.${options.id}`, - attachTo: { id: 'plugin.catalog.page.index', input: 'filters' }, + id, + attachTo, inputs: options.inputs ?? {}, configSchema: options.configSchema, output: { element: coreExtensionData.reactElement, }, factory({ bind, config, source }) { - const LazyComponent = React.lazy(() => + const ExtensionComponent = React.lazy(() => options .loader({ config }) .then(element => ({ default: () => element })), @@ -114,10 +117,10 @@ export function createCatalogFilterExtension< bind({ element: ( - - }> - - + + + + ), }); From e964c17db97ad0fdb27e9e2b2b6c19ad432e3e3a Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 19 Oct 2023 11:49:47 +0200 Subject: [PATCH 198/348] chore(catalog): add changeset file Signed-off-by: Camila Belo --- .changeset/fluffy-years-shake.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fluffy-years-shake.md diff --git a/.changeset/fluffy-years-shake.md b/.changeset/fluffy-years-shake.md new file mode 100644 index 0000000000..9612690d62 --- /dev/null +++ b/.changeset/fluffy-years-shake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Use default extensions boundary and suspense on the alpha declarative `createCatalogFilterExtension` extension factory. From 0fb1d8c7f8af8f53bc6aaf2928b78c8a836612ec Mon Sep 17 00:00:00 2001 From: Ankit Anand Date: Thu, 19 Oct 2023 16:46:23 +0530 Subject: [PATCH 199/348] removed mockdir.clear, replaced addContent with setContent Signed-off-by: Ankit Anand --- .../src/actions/fetch/rails/index.test.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts index 10b8466dc2..7548ddd21d 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts @@ -73,9 +73,6 @@ describe('fetch:rails', () => { createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), }; - mockDir.clear(); - mockDir.addContent({ template: {} }); - const mockReader: UrlReader = { readUrl: jest.fn(), readTree: jest.fn(), @@ -93,7 +90,7 @@ describe('fetch:rails', () => { }); beforeEach(() => { - mockDir.addContent({ + mockDir.setContent({ result: '{}', }); jest.clearAllMocks(); From c3c5c7e514f4c5145f176c575751a8023b88b006 Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Thu, 19 Oct 2023 14:27:22 +0300 Subject: [PATCH 200/348] chore: add info about entity if tech docs building fails Signed-off-by: Heikki Hellgren --- .changeset/hip-mugs-camp.md | 5 +++++ .../src/service/DocsSynchronizer.test.ts | 2 +- .../techdocs-backend/src/service/DocsSynchronizer.ts | 10 ++++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 .changeset/hip-mugs-camp.md diff --git a/.changeset/hip-mugs-camp.md b/.changeset/hip-mugs-camp.md new file mode 100644 index 0000000000..3413b5ac0a --- /dev/null +++ b/.changeset/hip-mugs-camp.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': patch +--- + +Add info about the entity when tech docs fail to build diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts index 52a3b82651..ff714eee63 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts @@ -258,7 +258,7 @@ describe('DocsSynchronizer', () => { expect(mockResponseHandler.log).toHaveBeenCalledTimes(1); expect(mockResponseHandler.log).toHaveBeenCalledWith( expect.stringMatching( - /error.*: Failed to build the docs page: Some random error/, + /error.*: Failed to build the docs page for entity component:default\/test: Some random error/, ), ); expect(mockResponseHandler.finish).toHaveBeenCalledTimes(0); diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts index 8456f64a6a..fad915b068 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts @@ -15,7 +15,11 @@ */ import { PluginEndpointDiscovery } from '@backstage/backend-common'; -import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { + DEFAULT_NAMESPACE, + Entity, + stringifyEntityRef, +} from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { assertError, NotFoundError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; @@ -142,7 +146,9 @@ export class DocsSynchronizer { } } catch (e) { assertError(e); - const msg = `Failed to build the docs page: ${e.message}`; + const msg = `Failed to build the docs page for entity ${stringifyEntityRef( + entity, + )}: ${e.message}`; taskLogger.error(msg); this.logger.error(msg, e); error(e); From 9fdd2431d87e160a9bfdaf9b5c1f027a604cbc9d Mon Sep 17 00:00:00 2001 From: Hannes Jetter Date: Thu, 19 Oct 2023 13:26:19 +0200 Subject: [PATCH 201/348] added support for new backend Signed-off-by: Hannes Jetter --- .../src/alpha.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/plugins/search-backend-module-techdocs/src/alpha.ts b/plugins/search-backend-module-techdocs/src/alpha.ts index 1c4988cc21..950acd4039 100644 --- a/plugins/search-backend-module-techdocs/src/alpha.ts +++ b/plugins/search-backend-module-techdocs/src/alpha.ts @@ -23,11 +23,28 @@ import { loggerToWinstonLogger } from '@backstage/backend-common'; import { coreServices, createBackendModule, + createExtensionPoint, } from '@backstage/backend-plugin-api'; import { readTaskScheduleDefinitionFromConfig } from '@backstage/backend-tasks'; import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha'; import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-search-backend-module-techdocs'; import { searchIndexRegistryExtensionPoint } from '@backstage/plugin-search-backend-node/alpha'; +import { TechDocsCollatorEntityTransformer } from '@backstage/plugin-search-backend-module-techdocs'; + +/** @alpha */ +export interface TechDocsCollatorEntityTransformerExtensionPoint { + setTransformer(transformer: TechDocsCollatorEntityTransformer): void; +} + +/** + * Extension point used to customize the TechDocs collator entity transformer. + * + * @alpha + */ +export const techdocsCollatorEntityTransformerExtensionPoint = + createExtensionPoint({ + id: 'search.techdocsCollator.transformer', + }); /** * @alpha @@ -37,6 +54,22 @@ export default createBackendModule({ moduleId: 'techDocsCollator', pluginId: 'search', register(env) { + let transformer: TechDocsCollatorEntityTransformer | undefined; + + env.registerExtensionPoint( + techdocsCollatorEntityTransformerExtensionPoint, + { + setTransformer(newTransformer) { + if (transformer) { + throw new Error( + 'TechDocs collator entity transformer may only be set once', + ); + } + transformer = newTransformer; + }, + }, + ); + env.registerInit({ deps: { config: coreServices.rootConfig, @@ -75,6 +108,7 @@ export default createBackendModule({ tokenManager, logger: loggerToWinstonLogger(logger), catalogClient: catalog, + entityTransformer: transformer, }), }); }, From 816493a7c50966b4e6c5491de754f764cc6ead37 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 13:55:47 +0200 Subject: [PATCH 202/348] docs: fix links to analytics-module-ga README Signed-off-by: Patrik Oldsberg --- docs/releases/v1.9.0-changelog.md | 2 +- docs/releases/v1.9.0-next.2-changelog.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/releases/v1.9.0-changelog.md b/docs/releases/v1.9.0-changelog.md index df14c3d34d..07451f6d2c 100644 --- a/docs/releases/v1.9.0-changelog.md +++ b/docs/releases/v1.9.0-changelog.md @@ -1299,7 +1299,7 @@ - d3fea4ae0a: Internal fixes to avoid implicit usage of globals - 3280711113: Updated dependency `msw` to `^0.49.0`. - 9516b0c355: Added support for sending virtual pageviews on `search` events in order to enable - Site Search functionality in GA. For more information consult [README](/plugins/analytics-module-ga/README.md#enabling-site-search) + Site Search functionality in GA. For more information consult [README](https://github.com/backstage/backstage/blob/master/plugins/analytics-module-ga/README.md#enabling-site-search) - Updated dependencies - @backstage/core-plugin-api@1.2.0 - @backstage/core-components@0.12.1 diff --git a/docs/releases/v1.9.0-next.2-changelog.md b/docs/releases/v1.9.0-next.2-changelog.md index a410da5263..2c6d495641 100644 --- a/docs/releases/v1.9.0-next.2-changelog.md +++ b/docs/releases/v1.9.0-next.2-changelog.md @@ -525,7 +525,7 @@ ### Patch Changes - 9516b0c355: Added support for sending virtual pageviews on `search` events in order to enable - Site Search functionality in GA. For more information consult [README](/plugins/analytics-module-ga/README.md#enabling-site-search) + Site Search functionality in GA. For more information consult [README](https://github.com/backstage/backstage/blob/master/plugins/analytics-module-ga/README.md#enabling-site-search) - Updated dependencies - @backstage/core-plugin-api@1.2.0-next.2 - @backstage/core-components@0.12.1-next.2 From 1b8f005aab095f83eb3652b049b1ab9192adfb2f Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 19 Oct 2023 13:57:35 +0200 Subject: [PATCH 203/348] refactor(catalog): restore inline attachment Signed-off-by: Camila Belo --- plugins/catalog/src/alpha.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index 27ec432d07..e9cb083978 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -98,11 +98,10 @@ export function createCatalogFilterExtension< loader: (options: { config: TConfig }) => Promise; }) { const id = `catalog.filter.${options.id}`; - const attachTo = { id: 'plugin.catalog.page.index', input: 'filters' }; return createExtension({ id, - attachTo, + attachTo: { id: 'plugin.catalog.page.index', input: 'filters' }, inputs: options.inputs ?? {}, configSchema: options.configSchema, output: { From cca1afc547100a9412a75c77e3ef15cf0f04d691 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 19 Oct 2023 13:57:54 +0200 Subject: [PATCH 204/348] refactor(search): restore inline attachment Signed-off-by: Camila Belo --- plugins/search-react/src/alpha.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/search-react/src/alpha.tsx b/plugins/search-react/src/alpha.tsx index f28bc44b0d..322bd3e67b 100644 --- a/plugins/search-react/src/alpha.tsx +++ b/plugins/search-react/src/alpha.tsx @@ -89,11 +89,6 @@ export function createSearchResultListItemExtension< >(options: SearchResultItemExtensionOptions) { const id = `plugin.search.result.item.${options.id}`; - const attachTo = options.attachTo ?? { - id: 'plugin.search.page', - input: 'items', - }; - const configSchema = 'configSchema' in options ? options.configSchema @@ -105,7 +100,10 @@ export function createSearchResultListItemExtension< return createExtension({ id, - attachTo, + attachTo: options.attachTo ?? { + id: 'plugin.search.page', + input: 'items', + }, configSchema, output: { item: searchResultItemExtensionData, From 66af240ea692929df76d8f817e96595d648c44d6 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 19 Oct 2023 14:54:35 +0200 Subject: [PATCH 205/348] refactor(frontend-plugin-api): merge boundary and suspense components Signed-off-by: Camila Belo --- packages/frontend-plugin-api/api-report.md | 13 +---- .../src/components/ErrorBoundary.tsx | 3 +- .../src/components/ExtensionBoundary.test.tsx | 6 +-- .../src/components/ExtensionBoundary.tsx | 47 ++++++++++++++----- .../src/components/index.ts | 5 -- .../src/extensions/createPageExtension.tsx | 41 ++++------------ plugins/catalog/src/alpha.tsx | 5 +- plugins/search-react/src/alpha.tsx | 17 +++---- 8 files changed, 57 insertions(+), 80 deletions(-) diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index b6f85e757b..ac8d164fae 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -340,7 +340,7 @@ export interface ExtensionBoundaryProps { // (undocumented) id: string; // (undocumented) - routeRef?: RouteRef; + routable?: boolean; // (undocumented) source?: BackstagePlugin; } @@ -416,17 +416,6 @@ export interface ExtensionOverridesOptions { extensions: Extension[]; } -// @public (undocumented) -export function ExtensionSuspense( - props: ExtensionSuspenseProps, -): React_2.JSX.Element; - -// @public (undocumented) -export interface ExtensionSuspenseProps { - // (undocumented) - children: ReactNode; -} - // @public export interface ExternalRouteRef< TParams extends AnyRouteRefParams = AnyRouteRefParams, diff --git a/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx b/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx index f9ce9c9809..1191b75a1d 100644 --- a/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx +++ b/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx @@ -15,9 +15,10 @@ */ import React, { Component, PropsWithChildren } from 'react'; +// TODO: Dependency on MUI should be removed from core packages import { Button } from '@material-ui/core'; -import { BackstagePlugin } from '../wiring'; import { ErrorPanel } from '@backstage/core-components'; +import { BackstagePlugin } from '../wiring'; type DefaultErrorBoundaryFallbackProps = PropsWithChildren<{ plugin?: BackstagePlugin; diff --git a/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx b/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx index 150ace717c..704cafda2d 100644 --- a/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx +++ b/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx @@ -33,7 +33,6 @@ import { analyticsApiRef, useAnalytics } from '@backstage/core-plugin-api'; import { createApp } from '@backstage/frontend-app-api'; import { JsonObject } from '@backstage/types'; import { createRouteRef } from '../routing'; -import { toInternalRouteRef } from '../routing/RouteRef'; function renderExtensionInTestApp( extension: Extension, @@ -59,7 +58,6 @@ function renderExtensionInTestApp( const wrapInBoundaryExtension = (element: JSX.Element) => { const id = 'plugin.extension'; const routeRef = createRouteRef(); - toInternalRouteRef(routeRef).setId(id); return createExtension({ id, attachTo: { id: 'core.routes', input: 'routes' }, @@ -73,7 +71,7 @@ const wrapInBoundaryExtension = (element: JSX.Element) => { routeRef, path: '/', element: ( - + {element} ), @@ -128,7 +126,7 @@ describe('ExtensionBoundary', () => { subject, context: { extension: 'plugin.extension', - routeRef: 'plugin.extension', + routeRef: 'unknown', }, }), ); diff --git a/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx b/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx index 796908c619..a9ea297216 100644 --- a/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx +++ b/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx @@ -14,36 +14,59 @@ * limitations under the License. */ -import React, { ReactNode } from 'react'; -import { AnalyticsContext } from '@backstage/core-plugin-api'; +import React, { PropsWithChildren, ReactNode, useEffect } from 'react'; +import { AnalyticsContext, useAnalytics } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '../wiring'; -import { RouteRef } from '../routing'; import { ErrorBoundary } from './ErrorBoundary'; -import { toInternalRouteRef } from '../routing/RouteRef'; +import { ExtensionSuspense } from './ExtensionSuspense'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker'; + +type RouteTrackerProps = PropsWithChildren<{ + disableTracking?: boolean; +}>; + +const RouteTracker = (props: RouteTrackerProps) => { + const { disableTracking, children } = props; + const analytics = useAnalytics(); + + // This event, never exposed to end-users of the analytics API, + // helps inform which extension metadata gets associated with a + // navigation event when the route navigated to is a gathered + // mountpoint. + useEffect(() => { + if (disableTracking) return; + analytics.captureEvent(routableExtensionRenderedEvent, ''); + }, [analytics, disableTracking]); + + return <>{children}; +}; /** @public */ export interface ExtensionBoundaryProps { id: string; source?: BackstagePlugin; - routeRef?: RouteRef; + routable?: boolean; children: ReactNode; } /** @public */ export function ExtensionBoundary(props: ExtensionBoundaryProps) { - const { id, source, routeRef, children } = props; + const { id, source, routable, children } = props; + // Skipping "routeRef" attribute in the new system, the extension "id" should provide more insight const attributes = { extension: id, pluginId: source?.id, - routeRef: routeRef - ? toInternalRouteRef(routeRef).getDescription() - : undefined, }; return ( - - {children} - + + + + {children} + + + ); } diff --git a/packages/frontend-plugin-api/src/components/index.ts b/packages/frontend-plugin-api/src/components/index.ts index fecd7f36cc..7056a59271 100644 --- a/packages/frontend-plugin-api/src/components/index.ts +++ b/packages/frontend-plugin-api/src/components/index.ts @@ -18,8 +18,3 @@ export { ExtensionBoundary, type ExtensionBoundaryProps, } from './ExtensionBoundary'; - -export { - ExtensionSuspense, - type ExtensionSuspenseProps, -} from './ExtensionSuspense'; diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx index ad7db1d222..f05182149b 100644 --- a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx @@ -14,11 +14,8 @@ * limitations under the License. */ -import React, { lazy, useEffect } from 'react'; -import { useAnalytics } from '@backstage/core-plugin-api'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker'; -import { ExtensionBoundary, ExtensionSuspense } from '../components'; +import React, { lazy } from 'react'; +import { ExtensionBoundary } from '../components'; import { createSchemaFromZod, PortableSchema } from '../schema'; import { coreExtensionData, @@ -58,9 +55,7 @@ export function createPageExtension< }) => Promise; }, ): Extension { - const { id, routeRef } = options; - - const attachTo = options.attachTo ?? { id: 'core.routes', input: 'routes' }; + const { id } = options; const configSchema = 'configSchema' in options @@ -71,7 +66,7 @@ export function createPageExtension< return createExtension({ id, - attachTo, + attachTo: options.attachTo ?? { id: 'core.routes', input: 'routes' }, configSchema, inputs: options.inputs, disabled: options.disabled, @@ -81,36 +76,18 @@ export function createPageExtension< routeRef: coreExtensionData.routeRef.optional(), }, factory({ bind, config, inputs, source }) { - const { path } = config; - - const PageComponent = lazy(() => + const ExtensionComponent = lazy(() => options .loader({ config, inputs }) .then(element => ({ default: () => element })), ); - const ExtensionComponent = () => { - const analytics = useAnalytics(); - - // This event, never exposed to end-users of the analytics API, - // helps inform which extension metadata gets associated with a - // navigation event when the route navigated to is a gathered - // mountpoint. - useEffect(() => { - analytics.captureEvent(routableExtensionRenderedEvent, ''); - }, [analytics]); - - return ; - }; - bind({ - path, - routeRef, + path: config.path, + routeRef: options.routeRef, element: ( - - - - + + ), }); diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index e9cb083978..31551c1930 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -36,7 +36,6 @@ import { PortableSchema, ExtensionBoundary, createExtensionInput, - ExtensionSuspense, } from '@backstage/frontend-plugin-api'; import { AsyncEntityProvider, @@ -117,9 +116,7 @@ export function createCatalogFilterExtension< bind({ element: ( - - - + ), }); diff --git a/plugins/search-react/src/alpha.tsx b/plugins/search-react/src/alpha.tsx index 322bd3e67b..f937ef99cc 100644 --- a/plugins/search-react/src/alpha.tsx +++ b/plugins/search-react/src/alpha.tsx @@ -20,7 +20,6 @@ import { ListItemProps } from '@material-ui/core'; import { ExtensionBoundary, - ExtensionSuspense, PortableSchema, createExtension, createExtensionDataRef, @@ -120,15 +119,13 @@ export function createSearchResultListItemExtension< predicate: options.predicate, component: props => ( - - - - - + + + ), }, From 052998a180c8ee0b3351e26dcea849ad17d458f7 Mon Sep 17 00:00:00 2001 From: Niklas Aronsson Date: Thu, 19 Oct 2023 14:55:07 +0200 Subject: [PATCH 206/348] Use setContent instead of clear plus addContent Signed-off-by: Niklas Aronsson --- .../src/actions/fetch/cookiecutter.test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts index 3872b2e302..af63ca0e48 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts @@ -46,7 +46,7 @@ jest.mock( ); describe('fetch:cookiecutter', () => { - const mockDir = createMockDirectory(); + const mockDir = createMockDirectory({ mockOsTmpDir: true }); const integrations = ScmIntegrations.fromConfig( new ConfigReader({ integrations: { @@ -106,21 +106,20 @@ describe('fetch:cookiecutter', () => { output: jest.fn(), createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), }; - mockDir.clear(); - mockDir.addContent({ template: {} }); + mockDir.setContent({ template: {} }); commandExists.mockResolvedValue(null); // Mock when run container is called it creates some new files in the mock filesystem containerRunner.runContainer.mockImplementation(async () => { - mockDir.addContent({ + mockDir.setContent({ 'intermediate/testfile.json': '{}', }); }); // Mock when executeShellCommand is called it creates some new files in the mock filesystem executeShellCommand.mockImplementation(async () => { - mockDir.addContent({ + mockDir.setContent({ 'intermediate/testfile.json': '{}', }); }); From 81c8db208884271920b16682535fea161d77a7e1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 16:34:02 +0200 Subject: [PATCH 207/348] core-components: make RoutedTabs not explode when rendering without tabs Co-authored-by: Camila Belo Signed-off-by: Patrik Oldsberg --- .changeset/dirty-ducks-behave.md | 5 +++++ .../src/components/TabbedLayout/RoutedTabs.tsx | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .changeset/dirty-ducks-behave.md diff --git a/.changeset/dirty-ducks-behave.md b/.changeset/dirty-ducks-behave.md new file mode 100644 index 0000000000..c7bea8ea0a --- /dev/null +++ b/.changeset/dirty-ducks-behave.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fix `RoutedTabs` so that it does not explode without tabs. diff --git a/packages/core-components/src/components/TabbedLayout/RoutedTabs.tsx b/packages/core-components/src/components/TabbedLayout/RoutedTabs.tsx index 2a0b0eae28..2c727efe1b 100644 --- a/packages/core-components/src/components/TabbedLayout/RoutedTabs.tsx +++ b/packages/core-components/src/components/TabbedLayout/RoutedTabs.tsx @@ -27,8 +27,8 @@ import { SubRoute } from './types'; export function useSelectedSubRoute(subRoutes: SubRoute[]): { index: number; - route: SubRoute; - element: JSX.Element; + route?: SubRoute; + element?: JSX.Element; } { const params = useParams(); @@ -44,7 +44,7 @@ export function useSelectedSubRoute(subRoutes: SubRoute[]): { b.path.replace(/\/\*$/, '').localeCompare(a.path.replace(/\/\*$/, '')), ); - const element = useRoutes(sortedRoutes) ?? subRoutes[0].children; + const element = useRoutes(sortedRoutes) ?? subRoutes[0]?.children; // TODO(Rugvip): Once we only support v6 stable we can always prefix // This avoids having a double / prefix for react-router v6 beta, which in turn breaks @@ -98,7 +98,7 @@ export function RoutedTabs(props: { routes: SubRoute[] }) { onChange={onTabChange} /> - + {element} From dc613f9bcfcdad42e2e5911d766ca5a7ae093cd0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 17:33:37 +0200 Subject: [PATCH 208/348] frontend-app-api: fix configuration schema Signed-off-by: Patrik Oldsberg --- .changeset/olive-paws-divide.md | 5 +++++ packages/frontend-app-api/config.d.ts | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 .changeset/olive-paws-divide.md diff --git a/.changeset/olive-paws-divide.md b/.changeset/olive-paws-divide.md new file mode 100644 index 0000000000..688b6025bf --- /dev/null +++ b/.changeset/olive-paws-divide.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Updated `app.extensions` configuration schema. diff --git a/packages/frontend-app-api/config.d.ts b/packages/frontend-app-api/config.d.ts index 9ec020fa56..28355f5376 100644 --- a/packages/frontend-app-api/config.d.ts +++ b/packages/frontend-app-api/config.d.ts @@ -34,17 +34,17 @@ export interface Config { /** * @deepVisibility frontend */ - extensions?: + extensions?: Array< | string | { [extensionId: string]: | boolean - | string | { - at?: string; - extension?: string; + attachTo?: { id: string; input: string }; + disabled?: boolean; config?: unknown; }; - }; + } + >; }; } From 6c6f392c74bec7ad04d9d1ec3b95a170d1a08ed4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Oct 2023 13:03:23 +0200 Subject: [PATCH 209/348] frontend-app-api: extract extension config reading into separate module Signed-off-by: Patrik Oldsberg --- .../frontend-app-api/src/wiring/createApp.tsx | 4 +- .../graph/readAppExtensionsConfig.test.ts | 268 ++++++++++++++++++ .../wiring/graph/readAppExtensionsConfig.ts | 199 +++++++++++++ .../src/wiring/parameters.test.ts | 254 +---------------- .../frontend-app-api/src/wiring/parameters.ts | 184 +----------- 5 files changed, 471 insertions(+), 438 deletions(-) create mode 100644 packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.test.ts create mode 100644 packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.ts diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index e770a6b4c1..dc132b6654 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -35,7 +35,6 @@ import { import { ExtensionInstanceParameters, mergeExtensionParameters, - readAppExtensionParameters, } from './parameters'; import { AnyApiFactory, @@ -96,6 +95,7 @@ import { AppRouteBinder } from '../routing'; import { RoutingProvider } from '../routing/RoutingProvider'; import { resolveRouteBindings } from '../routing/resolveRouteBindings'; import { collectRouteIds } from '../routing/collectRouteIds'; +import { readAppExtensionsConfig } from './graph/readAppExtensionsConfig'; /** @public */ export interface ExtensionTreeNode { @@ -200,7 +200,7 @@ export function createInstances(options: { const extensionParams = mergeExtensionParameters({ features: options.features, builtinExtensions, - parameters: readAppExtensionParameters(options.config), + parameters: readAppExtensionsConfig(options.config), }); // TODO: validate the config of all extension instances diff --git a/packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.test.ts b/packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.test.ts new file mode 100644 index 0000000000..91f6992f29 --- /dev/null +++ b/packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.test.ts @@ -0,0 +1,268 @@ +/* + * Copyright 2023 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 { ConfigReader } from '@backstage/config'; +import { JsonValue } from '@backstage/types'; +import { + expandShorthandExtensionParameters, + readAppExtensionsConfig, +} from './readAppExtensionsConfig'; + +describe('readAppExtensionsConfig', () => { + it('should disable extension with shorthand notation', () => { + expect( + readAppExtensionsConfig( + new ConfigReader({ app: { extensions: [{ 'core.router': false }] } }), + ), + ).toEqual([ + { + id: 'core.router', + disabled: true, + }, + ]); + expect( + readAppExtensionsConfig( + new ConfigReader({ + app: { extensions: [{ 'core.router': { disabled: true } }] }, + }), + ), + ).toEqual([ + { + at: undefined, + config: undefined, + disabled: true, + id: 'core.router', + }, + ]); + }); + + it('should enable extension with shorthand notation', () => { + expect( + readAppExtensionsConfig( + new ConfigReader({ app: { extensions: ['core.router'] } }), + ), + ).toEqual([ + { + id: 'core.router', + disabled: false, + }, + ]); + expect( + readAppExtensionsConfig( + new ConfigReader({ app: { extensions: [{ 'core.router': true }] } }), + ), + ).toEqual([ + { + id: 'core.router', + disabled: false, + }, + ]); + expect( + readAppExtensionsConfig( + new ConfigReader({ + app: { extensions: [{ 'core.router': { disabled: false } }] }, + }), + ), + ).toEqual([ + { + id: 'core.router', + disabled: false, + }, + ]); + }); + + it('should not allow string keys', () => { + expect(() => + readAppExtensionsConfig( + new ConfigReader({ + app: { + extensions: [{ 'core.router': 'some-string' }], + }, + }), + ), + ).toThrow( + 'Invalid extension configuration at app.extensions[0][core.router], value must be a boolean or object', + ); + }); + + it('should not allow invalid keys', () => { + expect(() => + readAppExtensionsConfig( + new ConfigReader({ + app: { + extensions: [ + { + 'core.router/routes': { + extension: 'example-package#MyPage', + config: { foo: 'bar' }, + }, + }, + ], + }, + }), + ), + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[0], extension ID must not contain slashes; got 'core.router/routes', did you mean 'core.router'?"`, + ); + }); +}); + +describe('expandShorthandExtensionParameters', () => { + const run = (value: JsonValue) => { + return expandShorthandExtensionParameters(value, 1); + }; + + it('rejects unknown keys', () => { + expect(() => run(null)).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1], must be a string or an object"`, + ); + expect(() => run(1)).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1], must be a string or an object"`, + ); + expect(() => run([])).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1], must be a string or an object"`, + ); + }); + + it('rejects the wrong number of keys', () => { + expect(() => run({})).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1], must have exactly one key, got none"`, + ); + expect(() => run({ a: {}, b: {} })).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1], must have exactly one key, got 'a', 'b'"`, + ); + }); + + it('rejects unknown values', () => { + expect(() => run({ a: 1 })).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1][a], value must be a boolean or object"`, + ); + expect(() => run({ a: [] })).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1][a], value must be a boolean or object"`, + ); + }); + + it('supports string key', () => { + expect(run('core.router')).toEqual({ + id: 'core.router', + disabled: false, + }); + expect(() => run('')).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1], extension ID must not be empty or contain whitespace"`, + ); + expect(() => run(' a')).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1], extension ID must not be empty or contain whitespace"`, + ); + expect(() => run('core.router/routes')).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1], extension ID must not contain slashes; got 'core.router/routes', did you mean 'core.router'?"`, + ); + }); + + it('supports null value', () => { + // this is the result of typing: + // - core.router: + // The missing value is interpreted as null by the yaml parser so we deal with that + expect(run({ 'core.router': null })).toEqual({ + id: 'core.router', + disabled: false, + }); + }); + + it('supports boolean value', () => { + expect(run({ 'core.router': true })).toEqual({ + id: 'core.router', + disabled: false, + }); + expect(run({ 'core.router': false })).toEqual({ + id: 'core.router', + disabled: true, + }); + }); + + it('should not support string values', () => { + expect(() => + run({ 'core.router': 'example-package#MyRouter' }), + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1][core.router], value must be a boolean or object"`, + ); + }); + + it('supports object id only in the key', () => { + expect(() => + run({ 'core.router': { id: 'some.id' } }), + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, + ); + }); + + it('supports object attachTo', () => { + expect( + run({ + 'core.router': { attachTo: { id: 'other.root', input: 'inputs' } }, + }), + ).toEqual({ + id: 'core.router', + attachTo: { id: 'other.root', input: 'inputs' }, + }); + expect(() => + run({ + 'core.router': { + id: 'other-id', + }, + }), + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, + ); + }); + + it('supports object disabled', () => { + expect(run({ 'core.router': { disabled: true } })).toEqual({ + id: 'core.router', + disabled: true, + }); + expect(run({ 'core.router': { disabled: false } })).toEqual({ + id: 'core.router', + disabled: false, + }); + expect(() => + run({ 'core.router': { disabled: 0 } }), + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1][core.router].disabled, must be a boolean"`, + ); + }); + + it('supports object config', () => { + expect( + run({ 'core.router': { config: { disableRedirects: true } } }), + ).toEqual({ + id: 'core.router', + config: { disableRedirects: true }, + }); + expect(() => + run({ 'core.router': { config: 0 } }), + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1][core.router].config, must be an object"`, + ); + }); + + it('rejects unknown object keys', () => { + expect(() => + run({ 'core.router': { foo: { settings: true } } }), + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid extension configuration at app.extensions[1][core.router].foo, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, + ); + }); +}); diff --git a/packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.ts b/packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.ts new file mode 100644 index 0000000000..2b5b51ce92 --- /dev/null +++ b/packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.ts @@ -0,0 +1,199 @@ +/* + * Copyright 2023 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 { Config } from '@backstage/config'; +import { JsonValue } from '@backstage/types'; + +export interface ExtensionParameters { + id: string; + attachTo?: { id: string; input: string }; + disabled?: boolean; + config?: unknown; +} + +const knownExtensionParameters = ['attachTo', 'disabled', 'config']; + +// Since we'll never merge arrays in config the config reader context +// isn't too much of a help. Fall back to manual config reading logic +// as the Config interface makes it quite hard for us otherwise. +/** @internal */ +export function readAppExtensionsConfig( + rootConfig: Config, +): ExtensionParameters[] { + const arr = rootConfig.getOptional('app.extensions'); + if (!Array.isArray(arr)) { + if (arr === undefined) { + return []; + } + // This will throw, and show which part of config had the wrong type + rootConfig.getConfigArray('app.extensions'); + return []; + } + + return arr.map((arrayEntry, arrayIndex) => + expandShorthandExtensionParameters(arrayEntry, arrayIndex), + ); +} + +/** @internal */ +export function expandShorthandExtensionParameters( + arrayEntry: JsonValue, + arrayIndex: number, +): ExtensionParameters { + function errorMsg(msg: string, key?: string, prop?: string) { + return `Invalid extension configuration at app.extensions[${arrayIndex}]${ + key ? `[${key}]` : '' + }${prop ? `.${prop}` : ''}, ${msg}`; + } + + // NOTE(freben): This check is intentionally not complete and doesn't check + // whether letters and digits are used, etc. It's not up to the config reading + // logic to decide what constitutes a valid extension ID; that should be + // decided by the logic that loads and instantiates the extensions. This check + // is just here to catch real mistakes or truly conceptually wrong input. + function assertValidId(id: string) { + if (!id || id !== id.trim()) { + throw new Error( + errorMsg('extension ID must not be empty or contain whitespace'), + ); + } + + if (id.includes('/')) { + let message = `extension ID must not contain slashes; got '${id}'`; + const good = id.split('/')[0]; + if (good) { + message += `, did you mean '${good}'?`; + } + throw new Error(errorMsg(message)); + } + } + + // Example YAML: + // - entity.card.about + if (typeof arrayEntry === 'string') { + assertValidId(arrayEntry); + return { + id: arrayEntry, + disabled: false, + }; + } + + // All remaining cases are single-key objects + if ( + typeof arrayEntry !== 'object' || + arrayEntry === null || + Array.isArray(arrayEntry) + ) { + throw new Error(errorMsg('must be a string or an object')); + } + const keys = Object.keys(arrayEntry); + if (keys.length !== 1) { + const joinedKeys = keys.length ? `'${keys.join("', '")}'` : 'none'; + throw new Error(errorMsg(`must have exactly one key, got ${joinedKeys}`)); + } + + const id = String(keys[0]); + const value = arrayEntry[id]; + assertValidId(id); + + // This example covers a potentially common mistake in the syntax + // Example YAML: + // - entity.card.about: + if (value === null) { + return { + id, + disabled: false, + }; + } + + // Example YAML: + // - catalog.page.cicd: false + if (typeof value === 'boolean') { + return { + id, + disabled: !value, + }; + } + + // The remaining case is the generic object. Example YAML: + // - tech-radar.page: + // at: core.router/routes + // disabled: false + // config: + // path: /tech-radar + // width: 1500 + // height: 800 + if (typeof value !== 'object' || Array.isArray(value)) { + // We don't mention null here - we don't want people to explicitly enter + // - entity.card.about: null + throw new Error(errorMsg('value must be a boolean or object', id)); + } + + const attachTo = value.attachTo as { id: string; input: string } | undefined; + const disabled = value.disabled; + const config = value.config; + + if (attachTo !== undefined) { + if ( + attachTo === null || + typeof attachTo !== 'object' || + Array.isArray(attachTo) + ) { + throw new Error(errorMsg('must be an object', id, 'attachTo')); + } + if (typeof attachTo.id !== 'string' || attachTo.id === '') { + throw new Error( + errorMsg('must be a non-empty string', id, 'attachTo.id'), + ); + } + if (typeof attachTo.input !== 'string' || attachTo.input === '') { + throw new Error( + errorMsg('must be a non-empty string', id, 'attachTo.input'), + ); + } + } + if (disabled !== undefined && typeof disabled !== 'boolean') { + throw new Error(errorMsg('must be a boolean', id, 'disabled')); + } + if ( + config !== undefined && + (typeof config !== 'object' || config === null || Array.isArray(config)) + ) { + throw new Error(errorMsg('must be an object', id, 'config')); + } + + const unknownKeys = Object.keys(value).filter( + k => !knownExtensionParameters.includes(k), + ); + if (unknownKeys.length > 0) { + throw new Error( + errorMsg( + `unknown parameter; expected one of '${knownExtensionParameters.join( + "', '", + )}'`, + id, + unknownKeys.join(', '), + ), + ); + } + + return { + id, + attachTo, + disabled, + config, + }; +} diff --git a/packages/frontend-app-api/src/wiring/parameters.test.ts b/packages/frontend-app-api/src/wiring/parameters.test.ts index 4ee420f667..89d9c0c3f3 100644 --- a/packages/frontend-app-api/src/wiring/parameters.test.ts +++ b/packages/frontend-app-api/src/wiring/parameters.test.ts @@ -14,18 +14,12 @@ * limitations under the License. */ -import { ConfigReader } from '@backstage/config'; import { createExtensionOverrides, createPlugin, Extension, } from '@backstage/frontend-plugin-api'; -import { JsonValue } from '@backstage/types'; -import { - expandShorthandExtensionParameters, - mergeExtensionParameters, - readAppExtensionParameters, -} from './parameters'; +import { mergeExtensionParameters } from './parameters'; function makeExt( id: string, @@ -208,249 +202,3 @@ describe('mergeExtensionParameters', () => { expect(result.map(r => r.extension.id)).toEqual(['b', 'c', 'a']); }); }); - -describe('readAppExtensionParameters', () => { - it('should disable extension with shorthand notation', () => { - expect( - readAppExtensionParameters( - new ConfigReader({ app: { extensions: [{ 'core.router': false }] } }), - ), - ).toEqual([ - { - id: 'core.router', - disabled: true, - }, - ]); - expect( - readAppExtensionParameters( - new ConfigReader({ - app: { extensions: [{ 'core.router': { disabled: true } }] }, - }), - ), - ).toEqual([ - { - at: undefined, - config: undefined, - disabled: true, - id: 'core.router', - }, - ]); - }); - - it('should enable extension with shorthand notation', () => { - expect( - readAppExtensionParameters( - new ConfigReader({ app: { extensions: ['core.router'] } }), - ), - ).toEqual([ - { - id: 'core.router', - disabled: false, - }, - ]); - expect( - readAppExtensionParameters( - new ConfigReader({ app: { extensions: [{ 'core.router': true }] } }), - ), - ).toEqual([ - { - id: 'core.router', - disabled: false, - }, - ]); - expect( - readAppExtensionParameters( - new ConfigReader({ - app: { extensions: [{ 'core.router': { disabled: false } }] }, - }), - ), - ).toEqual([ - { - id: 'core.router', - disabled: false, - }, - ]); - }); - - it('should not allow string keys', () => { - expect(() => - readAppExtensionParameters( - new ConfigReader({ - app: { - extensions: [{ 'core.router': 'some-string' }], - }, - }), - ), - ).toThrow( - 'Invalid extension configuration at app.extensions[0][core.router], value must be a boolean or object', - ); - }); - - it('should not allow invalid keys', () => { - expect(() => - readAppExtensionParameters( - new ConfigReader({ - app: { - extensions: [ - { - 'core.router/routes': { - extension: 'example-package#MyPage', - config: { foo: 'bar' }, - }, - }, - ], - }, - }), - ), - ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[0], extension ID must not contain slashes; got 'core.router/routes', did you mean 'core.router'?"`, - ); - }); -}); - -describe('expandShorthandExtensionParameters', () => { - const run = (value: JsonValue) => { - return expandShorthandExtensionParameters(value, 1); - }; - - it('rejects unknown keys', () => { - expect(() => run(null)).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1], must be a string or an object"`, - ); - expect(() => run(1)).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1], must be a string or an object"`, - ); - expect(() => run([])).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1], must be a string or an object"`, - ); - }); - - it('rejects the wrong number of keys', () => { - expect(() => run({})).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1], must have exactly one key, got none"`, - ); - expect(() => run({ a: {}, b: {} })).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1], must have exactly one key, got 'a', 'b'"`, - ); - }); - - it('rejects unknown values', () => { - expect(() => run({ a: 1 })).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][a], value must be a boolean or object"`, - ); - expect(() => run({ a: [] })).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][a], value must be a boolean or object"`, - ); - }); - - it('supports string key', () => { - expect(run('core.router')).toEqual({ - id: 'core.router', - disabled: false, - }); - expect(() => run('')).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1], extension ID must not be empty or contain whitespace"`, - ); - expect(() => run(' a')).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1], extension ID must not be empty or contain whitespace"`, - ); - expect(() => run('core.router/routes')).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1], extension ID must not contain slashes; got 'core.router/routes', did you mean 'core.router'?"`, - ); - }); - - it('supports null value', () => { - // this is the result of typing: - // - core.router: - // The missing value is interpreted as null by the yaml parser so we deal with that - expect(run({ 'core.router': null })).toEqual({ - id: 'core.router', - disabled: false, - }); - }); - - it('supports boolean value', () => { - expect(run({ 'core.router': true })).toEqual({ - id: 'core.router', - disabled: false, - }); - expect(run({ 'core.router': false })).toEqual({ - id: 'core.router', - disabled: true, - }); - }); - - it('should not support string values', () => { - expect(() => - run({ 'core.router': 'example-package#MyRouter' }), - ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router], value must be a boolean or object"`, - ); - }); - - it('supports object id only in the key', () => { - expect(() => - run({ 'core.router': { id: 'some.id' } }), - ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, - ); - }); - - it('supports object attachTo', () => { - expect( - run({ - 'core.router': { attachTo: { id: 'other.root', input: 'inputs' } }, - }), - ).toEqual({ - id: 'core.router', - attachTo: { id: 'other.root', input: 'inputs' }, - }); - expect(() => - run({ - 'core.router': { - id: 'other-id', - }, - }), - ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, - ); - }); - - it('supports object disabled', () => { - expect(run({ 'core.router': { disabled: true } })).toEqual({ - id: 'core.router', - disabled: true, - }); - expect(run({ 'core.router': { disabled: false } })).toEqual({ - id: 'core.router', - disabled: false, - }); - expect(() => - run({ 'core.router': { disabled: 0 } }), - ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].disabled, must be a boolean"`, - ); - }); - - it('supports object config', () => { - expect( - run({ 'core.router': { config: { disableRedirects: true } } }), - ).toEqual({ - id: 'core.router', - config: { disableRedirects: true }, - }); - expect(() => - run({ 'core.router': { config: 0 } }), - ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].config, must be an object"`, - ); - }); - - it('rejects unknown object keys', () => { - expect(() => - run({ 'core.router': { foo: { settings: true } } }), - ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].foo, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, - ); - }); -}); diff --git a/packages/frontend-app-api/src/wiring/parameters.ts b/packages/frontend-app-api/src/wiring/parameters.ts index 911f12f416..329c9ea42a 100644 --- a/packages/frontend-app-api/src/wiring/parameters.ts +++ b/packages/frontend-app-api/src/wiring/parameters.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { Config } from '@backstage/config'; import { BackstagePlugin, Extension, @@ -22,188 +21,7 @@ import { } from '@backstage/frontend-plugin-api'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; -import { JsonValue } from '@backstage/types'; - -export interface ExtensionParameters { - id: string; - attachTo?: { id: string; input: string }; - disabled?: boolean; - config?: unknown; -} - -const knownExtensionParameters = ['attachTo', 'disabled', 'config']; - -// Since we'll never merge arrays in config the config reader context -// isn't too much of a help. Fall back to manual config reading logic -// as the Config interface makes it quite hard for us otherwise. -/** @internal */ -export function readAppExtensionParameters( - rootConfig: Config, -): ExtensionParameters[] { - const arr = rootConfig.getOptional('app.extensions'); - if (!Array.isArray(arr)) { - if (arr === undefined) { - return []; - } - // This will throw, and show which part of config had the wrong type - rootConfig.getConfigArray('app.extensions'); - return []; - } - - return arr.map((arrayEntry, arrayIndex) => - expandShorthandExtensionParameters(arrayEntry, arrayIndex), - ); -} - -/** @internal */ -export function expandShorthandExtensionParameters( - arrayEntry: JsonValue, - arrayIndex: number, -): ExtensionParameters { - function errorMsg(msg: string, key?: string, prop?: string) { - return `Invalid extension configuration at app.extensions[${arrayIndex}]${ - key ? `[${key}]` : '' - }${prop ? `.${prop}` : ''}, ${msg}`; - } - - // NOTE(freben): This check is intentionally not complete and doesn't check - // whether letters and digits are used, etc. It's not up to the config reading - // logic to decide what constitutes a valid extension ID; that should be - // decided by the logic that loads and instantiates the extensions. This check - // is just here to catch real mistakes or truly conceptually wrong input. - function assertValidId(id: string) { - if (!id || id !== id.trim()) { - throw new Error( - errorMsg('extension ID must not be empty or contain whitespace'), - ); - } - - if (id.includes('/')) { - let message = `extension ID must not contain slashes; got '${id}'`; - const good = id.split('/')[0]; - if (good) { - message += `, did you mean '${good}'?`; - } - throw new Error(errorMsg(message)); - } - } - - // Example YAML: - // - entity.card.about - if (typeof arrayEntry === 'string') { - assertValidId(arrayEntry); - return { - id: arrayEntry, - disabled: false, - }; - } - - // All remaining cases are single-key objects - if ( - typeof arrayEntry !== 'object' || - arrayEntry === null || - Array.isArray(arrayEntry) - ) { - throw new Error(errorMsg('must be a string or an object')); - } - const keys = Object.keys(arrayEntry); - if (keys.length !== 1) { - const joinedKeys = keys.length ? `'${keys.join("', '")}'` : 'none'; - throw new Error(errorMsg(`must have exactly one key, got ${joinedKeys}`)); - } - - const id = String(keys[0]); - const value = arrayEntry[id]; - assertValidId(id); - - // This example covers a potentially common mistake in the syntax - // Example YAML: - // - entity.card.about: - if (value === null) { - return { - id, - disabled: false, - }; - } - - // Example YAML: - // - catalog.page.cicd: false - if (typeof value === 'boolean') { - return { - id, - disabled: !value, - }; - } - - // The remaining case is the generic object. Example YAML: - // - tech-radar.page: - // at: core.router/routes - // disabled: false - // config: - // path: /tech-radar - // width: 1500 - // height: 800 - if (typeof value !== 'object' || Array.isArray(value)) { - // We don't mention null here - we don't want people to explicitly enter - // - entity.card.about: null - throw new Error(errorMsg('value must be a boolean or object', id)); - } - - const attachTo = value.attachTo as { id: string; input: string } | undefined; - const disabled = value.disabled; - const config = value.config; - - if (attachTo !== undefined) { - if ( - attachTo === null || - typeof attachTo !== 'object' || - Array.isArray(attachTo) - ) { - throw new Error(errorMsg('must be an object', id, 'attachTo')); - } - if (typeof attachTo.id !== 'string' || attachTo.id === '') { - throw new Error( - errorMsg('must be a non-empty string', id, 'attachTo.id'), - ); - } - if (typeof attachTo.input !== 'string' || attachTo.input === '') { - throw new Error( - errorMsg('must be a non-empty string', id, 'attachTo.input'), - ); - } - } - if (disabled !== undefined && typeof disabled !== 'boolean') { - throw new Error(errorMsg('must be a boolean', id, 'disabled')); - } - if ( - config !== undefined && - (typeof config !== 'object' || config === null || Array.isArray(config)) - ) { - throw new Error(errorMsg('must be an object', id, 'config')); - } - - const unknownKeys = Object.keys(value).filter( - k => !knownExtensionParameters.includes(k), - ); - if (unknownKeys.length > 0) { - throw new Error( - errorMsg( - `unknown parameter; expected one of '${knownExtensionParameters.join( - "', '", - )}'`, - id, - unknownKeys.join(', '), - ), - ); - } - - return { - id, - attachTo, - disabled, - config, - }; -} +import { ExtensionParameters } from './graph/readAppExtensionsConfig'; export interface ExtensionInstanceParameters { extension: Extension; From c617af1d6d0cd34d225957b547bfef2ede802e7e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Oct 2023 13:04:16 +0200 Subject: [PATCH 210/348] frontend-app-api: add initial app graph types Signed-off-by: Patrik Oldsberg --- .../src/wiring/graph/index.ts | 22 +++++++ .../src/wiring/graph/types.ts | 65 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 packages/frontend-app-api/src/wiring/graph/index.ts create mode 100644 packages/frontend-app-api/src/wiring/graph/types.ts diff --git a/packages/frontend-app-api/src/wiring/graph/index.ts b/packages/frontend-app-api/src/wiring/graph/index.ts new file mode 100644 index 0000000000..608ecb7675 --- /dev/null +++ b/packages/frontend-app-api/src/wiring/graph/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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 { + AppNode, + AppNodeEdges, + AppNodeInstance, + AppNodeSpec, +} from './types'; diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts new file mode 100644 index 0000000000..3c5cd5df1b --- /dev/null +++ b/packages/frontend-app-api/src/wiring/graph/types.ts @@ -0,0 +1,65 @@ +/* + * Copyright 2023 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 { + BackstagePlugin, + Extension, + ExtensionDataRef, +} from '@backstage/frontend-plugin-api'; + +/** + * The specification for this node in the app graph. + * @public + */ +export interface AppNodeSpec { + id: string; + attachTo: { id: string; input: string }; + extension: Extension; + disabled: boolean; + config?: unknown; + source?: BackstagePlugin; +} + +/** + * The connections from this node to other nodes. + * @public + */ +export interface AppNodeEdges { + attachedTo: { node: AppNode; input: string }; + attachments: Map; +} + +/** + * The instance of this node in the app graph. + * @public + */ +export interface AppNodeInstance { + getDataRefs(): ExtensionDataRef[]; + getData(ref: ExtensionDataRef): T | unknown; +} + +/** + * + * @public + */ +export interface AppNode { + /** The specification for how this node should be instantiated */ + spec: AppNodeSpec; + /** The edges from this node to other nodes in the app graph */ + edges: AppNodeEdges; + /** The instance of this node, if it was instantiated */ + instance?: AppNodeInstance; +} From b3977b9864b55c284fa0cec0b9e622d6381923d0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Oct 2023 13:11:11 +0200 Subject: [PATCH 211/348] frontend-app-api: refactor mergeExtensionParameters -> resolveAppNodeSpecs Signed-off-by: Patrik Oldsberg --- .../frontend-app-api/src/wiring/createApp.tsx | 21 +++++++------------ .../resolveAppNodeSpecs.test.ts} | 18 ++++++++-------- .../resolveAppNodeSpecs.ts} | 20 +++++++----------- 3 files changed, 24 insertions(+), 35 deletions(-) rename packages/frontend-app-api/src/wiring/{parameters.test.ts => graph/resolveAppNodeSpecs.test.ts} (93%) rename packages/frontend-app-api/src/wiring/{parameters.ts => graph/resolveAppNodeSpecs.ts} (93%) diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index dc132b6654..b2c82dc8cf 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -32,10 +32,7 @@ import { createExtensionInstance, ExtensionInstance, } from './createExtensionInstance'; -import { - ExtensionInstanceParameters, - mergeExtensionParameters, -} from './parameters'; +import { resolveAppNodeSpecs } from './graph/resolveAppNodeSpecs'; import { AnyApiFactory, ApiHolder, @@ -96,6 +93,7 @@ import { RoutingProvider } from '../routing/RoutingProvider'; import { resolveRouteBindings } from '../routing/resolveRouteBindings'; import { collectRouteIds } from '../routing/collectRouteIds'; import { readAppExtensionsConfig } from './graph/readAppExtensionsConfig'; +import { AppNodeSpec } from './graph'; /** @public */ export interface ExtensionTreeNode { @@ -197,7 +195,7 @@ export function createInstances(options: { // pull in default extension instance from discovered packages // apply config to adjust default extension instances and add more - const extensionParams = mergeExtensionParameters({ + const appNodeSpecs = resolveAppNodeSpecs({ features: options.features, builtinExtensions, parameters: readAppExtensionsConfig(options.config), @@ -207,11 +205,8 @@ export function createInstances(options: { // We do it at this point to ensure that merging (if any) of config has already happened // Create attachment map so that we can look attachments up during instance creation - const attachmentMap = new Map< - string, - Map - >(); - for (const instanceParams of extensionParams) { + const attachmentMap = new Map>(); + for (const instanceParams of appNodeSpecs) { const extensionId = instanceParams.attachTo.id; const pointId = instanceParams.attachTo.input; let pointMap = attachmentMap.get(extensionId); @@ -231,9 +226,7 @@ export function createInstances(options: { const instances = new Map(); - function createInstance( - instanceParams: ExtensionInstanceParameters, - ): ExtensionInstance { + function createInstance(instanceParams: AppNodeSpec): ExtensionInstance { const extensionId = instanceParams.extension.id; const existingInstance = instances.get(extensionId); if (existingInstance) { @@ -261,7 +254,7 @@ export function createInstances(options: { } const coreInstance = createInstance( - extensionParams.find(p => p.extension.id === 'core')!, + appNodeSpecs.find(p => p.extension.id === 'core')!, ); return { coreInstance, instances }; diff --git a/packages/frontend-app-api/src/wiring/parameters.test.ts b/packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.test.ts similarity index 93% rename from packages/frontend-app-api/src/wiring/parameters.test.ts rename to packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.test.ts index 89d9c0c3f3..1d3c0a26ed 100644 --- a/packages/frontend-app-api/src/wiring/parameters.test.ts +++ b/packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.test.ts @@ -19,7 +19,7 @@ import { createPlugin, Extension, } from '@backstage/frontend-plugin-api'; -import { mergeExtensionParameters } from './parameters'; +import { resolveAppNodeSpecs } from './resolveAppNodeSpecs'; function makeExt( id: string, @@ -33,10 +33,10 @@ function makeExt( } as Extension; } -describe('mergeExtensionParameters', () => { +describe('resolveAppNodeSpecs', () => { it('should filter out disabled extension instances', () => { expect( - mergeExtensionParameters({ + resolveAppNodeSpecs({ features: [], builtinExtensions: [makeExt('a', 'disabled')], parameters: [], @@ -48,7 +48,7 @@ describe('mergeExtensionParameters', () => { const a = makeExt('a'); const b = makeExt('b'); expect( - mergeExtensionParameters({ + resolveAppNodeSpecs({ features: [], builtinExtensions: [a, b], parameters: [], @@ -64,7 +64,7 @@ describe('mergeExtensionParameters', () => { const b = makeExt('b'); const pluginA = createPlugin({ id: 'test', extensions: [a] }); expect( - mergeExtensionParameters({ + resolveAppNodeSpecs({ features: [pluginA], builtinExtensions: [b], parameters: [ @@ -89,7 +89,7 @@ describe('mergeExtensionParameters', () => { const b = makeExt('b'); const plugin = createPlugin({ id: 'test', extensions: [a, b] }); expect( - mergeExtensionParameters({ + resolveAppNodeSpecs({ features: [plugin], builtinExtensions: [], parameters: [ @@ -127,7 +127,7 @@ describe('mergeExtensionParameters', () => { const a = makeExt('a', 'disabled'); const b = makeExt('b', 'disabled'); expect( - mergeExtensionParameters({ + resolveAppNodeSpecs({ features: [createPlugin({ id: 'empty', extensions: [] })], builtinExtensions: [a, b], parameters: [ @@ -155,7 +155,7 @@ describe('mergeExtensionParameters', () => { const bOverride = makeExt('b', 'disabled', 'other'); const cOverride = makeExt('c'); - const result = mergeExtensionParameters({ + const result = resolveAppNodeSpecs({ features: [ plugin, createExtensionOverrides({ @@ -188,7 +188,7 @@ describe('mergeExtensionParameters', () => { const bOverride = makeExt('b', 'disabled'); const cOverride = makeExt('a', 'disabled'); - const result = mergeExtensionParameters({ + const result = resolveAppNodeSpecs({ features: [ createPlugin({ id: 'test', extensions: [a, b, c] }), createExtensionOverrides({ diff --git a/packages/frontend-app-api/src/wiring/parameters.ts b/packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.ts similarity index 93% rename from packages/frontend-app-api/src/wiring/parameters.ts rename to packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.ts index 329c9ea42a..8cad54f4be 100644 --- a/packages/frontend-app-api/src/wiring/parameters.ts +++ b/packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.ts @@ -20,22 +20,16 @@ import { ExtensionOverrides, } from '@backstage/frontend-plugin-api'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; -import { ExtensionParameters } from './graph/readAppExtensionsConfig'; - -export interface ExtensionInstanceParameters { - extension: Extension; - source?: BackstagePlugin; - attachTo: { id: string; input: string }; - config?: unknown; -} +import { toInternalExtensionOverrides } from '../../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; +import { ExtensionParameters } from './readAppExtensionsConfig'; +import { AppNodeSpec } from './types'; /** @internal */ -export function mergeExtensionParameters(options: { +export function resolveAppNodeSpecs(options: { features: (BackstagePlugin | ExtensionOverrides)[]; builtinExtensions: Extension[]; parameters: Array; -}): ExtensionInstanceParameters[] { +}): AppNodeSpec[] { const { builtinExtensions, parameters } = options; const plugins = options.features.filter( @@ -207,8 +201,10 @@ export function mergeExtensionParameters(options: { return configuredExtensions .filter(override => !override.params.disabled) .map(param => ({ - extension: param.extension, + id: param.extension.id, attachTo: param.params.attachTo, + extension: param.extension, + disabled: param.params.disabled, source: param.params.source, config: param.params.config, })); From d2bee21c914ddbaa7a2ef613411ec3b8fc18d32d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Oct 2023 00:30:46 +0200 Subject: [PATCH 212/348] frontend-app-api: add initial app graph builder Signed-off-by: Patrik Oldsberg --- .../src/wiring/graph/buildAppGraph.test.ts | 74 +++++++++++++ .../src/wiring/graph/buildAppGraph.ts | 104 ++++++++++++++++++ .../src/wiring/graph/types.ts | 26 +++-- 3 files changed, 193 insertions(+), 11 deletions(-) create mode 100644 packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts create mode 100644 packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts new file mode 100644 index 0000000000..1d5d8f415f --- /dev/null +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts @@ -0,0 +1,74 @@ +/* + * Copyright 2023 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 { createExtension } from '@backstage/frontend-plugin-api'; +import { buildAppGraph } from './buildAppGraph'; + +const extBaseConfig = { + id: 'test', + attachTo: { id: 'root', input: 'default' }, + output: {}, + factory() {}, +}; + +const extension = createExtension(extBaseConfig); + +const baseSpec = { extension, disabled: false }; + +describe('buildAppGraph', () => { + it('creates an empty graph', () => { + const graph = buildAppGraph([]); + expect([...graph.rootNodes.keys()]).toEqual([]); + expect([...graph.orphanNodes.keys()]).toEqual([]); + }); + + it('should create a graph', () => { + const graph = buildAppGraph([ + { ...baseSpec, id: 'a' }, + { ...baseSpec, id: 'b' }, + { ...baseSpec, id: 'c' }, + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, + { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, + { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, + ]); + expect([...graph.rootNodes.keys()]).toEqual(['a', 'b', 'c']); + expect([...graph.orphanNodes.keys()]).toEqual(['dx1']); + }); + + it('should create a graph out of order', () => { + const graph = buildAppGraph([ + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, + { ...baseSpec, id: 'a' }, + { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, + { ...baseSpec, id: 'b' }, + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, + { ...baseSpec, id: 'c' }, + { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, + ]); + expect([...graph.rootNodes.keys()]).toEqual(['a', 'b', 'c']); + expect([...graph.orphanNodes.keys()]).toEqual(['dx1']); + }); + + it('throws an error when duplicated extensions are detected', () => { + expect(() => + buildAppGraph([ + { ...baseSpec, id: 'a' }, + { ...baseSpec, id: 'a' }, + ]), + ).toThrow("Unexpected duplicate extension id 'a'"); + }); +}); diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts new file mode 100644 index 0000000000..151faa0e1d --- /dev/null +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts @@ -0,0 +1,104 @@ +/* + * Copyright 2023 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 { AppNode, AppNodeEdges, AppNodeSpec } from './types'; + +type Mutable = { + -readonly [P in keyof T]: T[P]; +}; + +/** + * Build the app graph by iterating through all node specs and constructing the app + * tree with all attachments in the same order as they appear in the input specs array. + * @internal + */ +export function buildAppGraph(specs: AppNodeSpec[]) { + const nodes = new Map(); + const rootNodes = new Map(); + // While iterating through the inputs specs we keep track of all nodes that were created + // before their parent, and attach them later when the parent is created. + // As we find the parents and attach the children, we remove them from this map. This means + // that after iterating through all input specs, this will be a map for each root node. + const orphansByParent = new Map< + string /* parentId */, + { orphan: AppNode; input: string }[] + >(); + + for (const spec of specs) { + // The main check with a more helpful error message happens in resolveAppNodeSpecs + if (nodes.has(spec.id)) { + throw new Error(`Unexpected duplicate extension id '${spec.id}'`); + } + + const node: AppNode = { + spec, + edges: { + attachments: new Map(), + }, + }; + nodes.set(spec.id, node); + + if (spec.attachTo) { + const parent = nodes.get(spec.attachTo.id); + if (parent) { + (node.edges as Mutable).attachedTo = { + node: parent, + input: spec.attachTo.input, + }; + const parentInputEdges = parent.edges.attachments.get( + spec.attachTo.input, + ); + if (parentInputEdges) { + parentInputEdges.push(node); + } else { + parent.edges.attachments.set(spec.attachTo.input, [node]); + } + } else { + const orphanNodesForParent = orphansByParent.get(spec.attachTo.id); + const orphan = { orphan: node, input: spec.attachTo.input }; + if (orphanNodesForParent) { + orphanNodesForParent.push(orphan); + } else { + orphansByParent.set(spec.attachTo.id, [orphan]); + } + } + } else { + rootNodes.set(spec.id, node); + } + + const orphanedChildren = orphansByParent.get(spec.id); + if (orphanedChildren) { + orphansByParent.delete(spec.id); + for (const { orphan, input } of orphanedChildren) { + (orphan.edges as Mutable).attachedTo = { node, input }; + const attachments = node.edges.attachments.get(input); + if (attachments) { + attachments.push(orphan); + } else { + node.edges.attachments.set(input, [orphan]); + } + } + } + } + + const orphanNodes = new Map( + Array.from(orphansByParent).flatMap(([, orphans]) => + orphans.map(({ orphan }) => [orphan.spec.id, orphan]), + ), + ); + + return { rootNodes, orphanNodes }; +} diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts index 3c5cd5df1b..f6de7018f5 100644 --- a/packages/frontend-app-api/src/wiring/graph/types.ts +++ b/packages/frontend-app-api/src/wiring/graph/types.ts @@ -25,12 +25,12 @@ import { * @public */ export interface AppNodeSpec { - id: string; - attachTo: { id: string; input: string }; - extension: Extension; - disabled: boolean; - config?: unknown; - source?: BackstagePlugin; + readonly id: string; + readonly attachTo?: { id: string; input: string }; + readonly extension: Extension; + readonly disabled: boolean; + readonly config?: unknown; + readonly source?: BackstagePlugin; } /** @@ -38,8 +38,8 @@ export interface AppNodeSpec { * @public */ export interface AppNodeEdges { - attachedTo: { node: AppNode; input: string }; - attachments: Map; + readonly attachedTo?: { node: AppNode; input: string }; + readonly attachments: Map; } /** @@ -57,9 +57,13 @@ export interface AppNodeInstance { */ export interface AppNode { /** The specification for how this node should be instantiated */ - spec: AppNodeSpec; + readonly spec: AppNodeSpec; /** The edges from this node to other nodes in the app graph */ - edges: AppNodeEdges; + readonly edges: AppNodeEdges; /** The instance of this node, if it was instantiated */ - instance?: AppNodeInstance; + readonly instance?: AppNodeInstance; +} + +export interface AppGraph { + rootNodes: Map; } From 650309205b899fab980d7c20e89657191cc6328c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 17:44:29 +0200 Subject: [PATCH 213/348] frontend-app-api: move createExtensionInstance to graph Signed-off-by: Patrik Oldsberg --- .../src/routing/extractRouteInfoFromInstanceTree.ts | 2 +- packages/frontend-app-api/src/wiring/createApp.tsx | 2 +- .../src/wiring/{ => graph}/createExtensionInstance.test.ts | 0 .../src/wiring/{ => graph}/createExtensionInstance.ts | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename packages/frontend-app-api/src/wiring/{ => graph}/createExtensionInstance.test.ts (100%) rename packages/frontend-app-api/src/wiring/{ => graph}/createExtensionInstance.ts (100%) diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts index 0bf9c2d1dd..fadcb719b9 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts @@ -15,7 +15,7 @@ */ import { RouteRef, coreExtensionData } from '@backstage/frontend-plugin-api'; -import { ExtensionInstance } from '../wiring/createExtensionInstance'; +import { ExtensionInstance } from '../wiring/graph/createExtensionInstance'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toLegacyPlugin } from '../wiring/createApp'; import { BackstageRouteObject } from './types'; diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index b2c82dc8cf..485882c8eb 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -31,7 +31,7 @@ import { CoreNav } from '../extensions/CoreNav'; import { createExtensionInstance, ExtensionInstance, -} from './createExtensionInstance'; +} from './graph/createExtensionInstance'; import { resolveAppNodeSpecs } from './graph/resolveAppNodeSpecs'; import { AnyApiFactory, diff --git a/packages/frontend-app-api/src/wiring/createExtensionInstance.test.ts b/packages/frontend-app-api/src/wiring/graph/createExtensionInstance.test.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/createExtensionInstance.test.ts rename to packages/frontend-app-api/src/wiring/graph/createExtensionInstance.test.ts diff --git a/packages/frontend-app-api/src/wiring/createExtensionInstance.ts b/packages/frontend-app-api/src/wiring/graph/createExtensionInstance.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/createExtensionInstance.ts rename to packages/frontend-app-api/src/wiring/graph/createExtensionInstance.ts From 7df6a42e4ad95bacaed4403ee7cab2aac273afb8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 17:44:49 +0200 Subject: [PATCH 214/348] frontend-app-api: extract Mutable to common internal type in graph Signed-off-by: Patrik Oldsberg --- packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts | 6 +----- packages/frontend-app-api/src/wiring/graph/types.ts | 5 +++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts index 151faa0e1d..9cfb430bcb 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts @@ -14,11 +14,7 @@ * limitations under the License. */ -import { AppNode, AppNodeEdges, AppNodeSpec } from './types'; - -type Mutable = { - -readonly [P in keyof T]: T[P]; -}; +import { AppNode, AppNodeEdges, AppNodeSpec, Mutable } from './types'; /** * Build the app graph by iterating through all node specs and constructing the app diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts index f6de7018f5..88fc363d6f 100644 --- a/packages/frontend-app-api/src/wiring/graph/types.ts +++ b/packages/frontend-app-api/src/wiring/graph/types.ts @@ -20,6 +20,11 @@ import { ExtensionDataRef, } from '@backstage/frontend-plugin-api'; +/** @internal */ +export type Mutable = { + -readonly [P in keyof T]: T[P]; +}; + /** * The specification for this node in the app graph. * @public From 544968da085cca68110f42af2675ce414ab9d762 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Oct 2023 18:01:45 +0200 Subject: [PATCH 215/348] frontend-app-api: make app node serializable Signed-off-by: Patrik Oldsberg --- .../src/wiring/graph/buildAppGraph.test.ts | 57 ++++++++++++++++ .../src/wiring/graph/buildAppGraph.ts | 68 ++++++++++++++++--- .../src/wiring/graph/types.ts | 3 +- 3 files changed, 119 insertions(+), 9 deletions(-) diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts index 1d5d8f415f..21a5009a95 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts @@ -47,6 +47,49 @@ describe('buildAppGraph', () => { ]); expect([...graph.rootNodes.keys()]).toEqual(['a', 'b', 'c']); expect([...graph.orphanNodes.keys()]).toEqual(['dx1']); + + expect(JSON.parse(JSON.stringify([...graph.rootNodes.values()]))) + .toMatchInlineSnapshot(` + [ + { + "id": "a", + }, + { + "attachments": { + "x": [ + { + "id": "bx1", + }, + { + "id": "bx2", + }, + ], + "y": [ + { + "id": "by1", + }, + ], + }, + "id": "b", + }, + { + "id": "c", + }, + ] + `); + expect(String(graph.rootNodes.get('a'))).toMatchInlineSnapshot(`""`); + expect(String(graph.rootNodes.get('b'))).toMatchInlineSnapshot(` + " + x [ + + + ] + y [ + + ] + " + `); + expect(String(graph.rootNodes.get('c'))).toMatchInlineSnapshot(`""`); }); it('should create a graph out of order', () => { @@ -61,6 +104,20 @@ describe('buildAppGraph', () => { ]); expect([...graph.rootNodes.keys()]).toEqual(['a', 'b', 'c']); expect([...graph.orphanNodes.keys()]).toEqual(['dx1']); + + expect(String(graph.rootNodes.get('a'))).toMatchInlineSnapshot(`""`); + expect(String(graph.rootNodes.get('b'))).toMatchInlineSnapshot(` + " + x [ + + + ] + y [ + + ] + " + `); + expect(String(graph.rootNodes.get('c'))).toMatchInlineSnapshot(`""`); }); it('throws an error when duplicated extensions are detected', () => { diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts index 9cfb430bcb..79977f6993 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts @@ -14,14 +14,71 @@ * limitations under the License. */ -import { AppNode, AppNodeEdges, AppNodeSpec, Mutable } from './types'; +import { + AppGraph, + AppNode, + AppNodeEdges, + AppNodeInstance, + AppNodeSpec, + Mutable, +} from './types'; + +function indent(str: string) { + return str.replace(/^/gm, ' '); +} + +/** @internal */ +class SerializableAppNode implements AppNode { + public readonly spec: AppNodeSpec; + public readonly edges: AppNodeEdges = { attachments: new Map() }; + public readonly instance?: AppNodeInstance; + + constructor(spec: AppNodeSpec) { + this.spec = spec; + } + + toJSON() { + const dataRefs = this.instance && [...this.instance.getDataRefs()]; + return { + id: this.spec.id, + output: + dataRefs && dataRefs.length > 0 + ? dataRefs.map(ref => ref.id) + : undefined, + attachments: + this.edges.attachments.size > 0 + ? Object.fromEntries(this.edges.attachments) + : undefined, + }; + } + + toString() { + const dataRefs = this.instance && [...this.instance.getDataRefs()]; + const out = + dataRefs && dataRefs.length > 0 + ? ` out=[${[...dataRefs.keys()].join(', ')}]` + : ''; + + if (this.edges.attachments.size === 0) { + return `<${this.spec.id}${out} />`; + } + + return [ + `<${this.spec.id}${out}>`, + ...[...this.edges.attachments.entries()].map(([k, v]) => + indent([`${k} [`, ...v.map(e => indent(e.toString())), `]`].join('\n')), + ), + ``, + ].join('\n'); + } +} /** * Build the app graph by iterating through all node specs and constructing the app * tree with all attachments in the same order as they appear in the input specs array. * @internal */ -export function buildAppGraph(specs: AppNodeSpec[]) { +export function buildAppGraph(specs: AppNodeSpec[]): AppGraph { const nodes = new Map(); const rootNodes = new Map(); // While iterating through the inputs specs we keep track of all nodes that were created @@ -39,12 +96,7 @@ export function buildAppGraph(specs: AppNodeSpec[]) { throw new Error(`Unexpected duplicate extension id '${spec.id}'`); } - const node: AppNode = { - spec, - edges: { - attachments: new Map(), - }, - }; + const node = new SerializableAppNode(spec); nodes.set(spec.id, node); if (spec.attachTo) { diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts index 88fc363d6f..29c0028d66 100644 --- a/packages/frontend-app-api/src/wiring/graph/types.ts +++ b/packages/frontend-app-api/src/wiring/graph/types.ts @@ -52,7 +52,7 @@ export interface AppNodeEdges { * @public */ export interface AppNodeInstance { - getDataRefs(): ExtensionDataRef[]; + getDataRefs(): Iterable>; getData(ref: ExtensionDataRef): T | unknown; } @@ -71,4 +71,5 @@ export interface AppNode { export interface AppGraph { rootNodes: Map; + orphanNodes: Map; } From bb4d40b481d92f9e85157a20bc18064a7fb69adc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 01:04:50 +0200 Subject: [PATCH 216/348] frontend-app-api: refactor createExtensionInstance -> createAppNodeInstance Signed-off-by: Patrik Oldsberg --- ...onInstance.ts => createAppNodeInstance.ts} | 136 ++++++------------ 1 file changed, 41 insertions(+), 95 deletions(-) rename packages/frontend-app-api/src/wiring/graph/{createExtensionInstance.ts => createAppNodeInstance.ts} (58%) diff --git a/packages/frontend-app-api/src/wiring/graph/createExtensionInstance.ts b/packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts similarity index 58% rename from packages/frontend-app-api/src/wiring/graph/createExtensionInstance.ts rename to packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts index 767329da7f..310852cd1c 100644 --- a/packages/frontend-app-api/src/wiring/graph/createExtensionInstance.ts +++ b/packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts @@ -18,10 +18,12 @@ import { AnyExtensionDataMap, AnyExtensionInputMap, BackstagePlugin, - Extension, ExtensionDataRef, } from '@backstage/frontend-plugin-api'; import mapValues from 'lodash/mapValues'; +import { AppNode, AppNodeInstance, AppNodeSpec } from './types'; + +type AppNodeWithInstance = AppNode & { instance: AppNodeInstance }; /** @internal */ export interface ExtensionInstance { @@ -42,14 +44,14 @@ export interface ExtensionInstance { function resolveInputData( dataMap: AnyExtensionDataMap, - attachment: ExtensionInstance, + attachment: AppNodeWithInstance, inputName: string, ) { return mapValues(dataMap, ref => { - const value = attachment.getData(ref); + const value = attachment.instance.getData(ref); if (value === undefined && !ref.config.optional) { throw new Error( - `input '${inputName}' did not receive required extension data '${ref.id}' from extension '${attachment.id}'`, + `input '${inputName}' did not receive required extension data '${ref.id}' from extension '${attachment.spec.id}'`, ); } return value; @@ -58,7 +60,7 @@ function resolveInputData( function resolveInputs( inputMap: AnyExtensionInputMap, - attachments: Map, + attachments: Map, ) { const undeclaredAttachments = Array.from(attachments.entries()).filter( ([inputName]) => inputMap[inputName] === undefined, @@ -72,7 +74,7 @@ function resolveInputs( .map( ([k, exts]) => `'${k}' from extension${exts.length > 1 ? 's' : ''} '${exts - .map(e => e.id) + .map(e => e.spec.id) .join("', '")}'`, ) .join(' and ')}`, @@ -80,113 +82,54 @@ function resolveInputs( } return mapValues(inputMap, (input, inputName) => { - const attachedInstances = attachments.get(inputName) ?? []; + const attachedNodes = + attachments + .get(inputName) + ?.filter((node): node is AppNodeWithInstance => + Boolean(node.instance), + ) ?? []; + if (input.config.singleton) { - if (attachedInstances.length > 1) { + if (attachedNodes.length > 1) { + const attachedNodeIds = attachedNodes.map(e => e.spec.id); throw Error( `expected ${ input.config.optional ? 'at most' : 'exactly' - } one '${inputName}' input but received multiple: '${attachedInstances - .map(e => e.id) - .join("', '")}'`, + } one '${inputName}' input but received multiple: '${attachedNodeIds.join( + "', '", + )}'`, ); - } else if (attachedInstances.length === 0) { + } else if (attachedNodes.length === 0) { if (input.config.optional) { return undefined; } throw Error(`input '${inputName}' is required but was not received`); } - return resolveInputData( - input.extensionData, - attachedInstances[0], - inputName, - ); + return resolveInputData(input.extensionData, attachedNodes[0], inputName); } - return attachedInstances.map(attachment => + return attachedNodes.map(attachment => resolveInputData(input.extensionData, attachment, inputName), ); }); } -function indent(str: string) { - return str.replace(/^/gm, ' '); -} - -class ExtensionInstanceImpl implements ExtensionInstance { - readonly $$type = '@backstage/ExtensionInstance'; - - readonly id: string; - readonly #extensionData: Map; - readonly attachments: Map; - readonly source?: BackstagePlugin; - - constructor( - id: string, - extensionData: Map, - attachments: Map, - source: BackstagePlugin | undefined, - ) { - this.id = id; - this.#extensionData = extensionData; - this.attachments = attachments; - this.source = source; - } - - getData(ref: ExtensionDataRef): T | undefined { - return this.#extensionData.get(ref.id) as T | undefined; - } - - toJSON() { - return { - id: this.id, - output: - this.#extensionData.size > 0 - ? [...this.#extensionData.keys()] - : undefined, - attachments: - this.attachments.size > 0 - ? Object.fromEntries(this.attachments) - : undefined, - }; - } - - toString() { - const out = - this.#extensionData.size > 0 - ? ` out=[${[...this.#extensionData.keys()].join(', ')}]` - : ''; - - if (this.attachments.size === 0) { - return `<${this.id}${out} />`; - } - - return [ - `<${this.id}${out}>`, - ...[...this.attachments.entries()].map(([k, v]) => - indent([`${k} [`, ...v.map(e => indent(e.toString())), `]`].join('\n')), - ), - ``, - ].join('\n'); - } -} - /** @internal */ -export function createExtensionInstance(options: { - extension: Extension; - config: unknown; - source?: BackstagePlugin; - attachments: Map; -}): ExtensionInstance { - const { extension, config, source, attachments } = options; +export function createAppNodeInstance(options: { + spec: AppNodeSpec; + attachments: Map; +}): AppNodeInstance { + const { spec, attachments } = options; + const { id, extension, config, source } = spec; const extensionData = new Map(); + const extensionDataRefs = new Set>(); let parsedConfig: unknown; try { parsedConfig = extension.configSchema?.parse(config ?? {}); } catch (e) { throw new Error( - `Invalid configuration for extension '${extension.id}'; caused by ${e}`, + `Invalid configuration for extension '${id}'; caused by ${e}`, ); } @@ -206,22 +149,25 @@ export function createExtensionInstance(options: { ); } extensionData.set(ref.id, output); + extensionDataRefs.add(ref); } }, inputs: resolveInputs(extension.inputs, attachments), }); } catch (e) { throw new Error( - `Failed to instantiate extension '${extension.id}'${ + `Failed to instantiate extension '${id}'${ e.name === 'Error' ? `, ${e.message}` : `; caused by ${e}` }`, ); } - return new ExtensionInstanceImpl( - options.extension.id, - extensionData, - attachments, - source, - ); + return { + getDataRefs() { + return extensionDataRefs.values(); + }, + getData(ref: ExtensionDataRef): T | undefined { + return extensionData.get(ref.id) as T | undefined; + }, + }; } From 2ff857bdb4d83eba66493bec3c892a611a7b7edc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 01:22:54 +0200 Subject: [PATCH 217/348] frontend-app-api: add instantiateAppNodeTree Signed-off-by: Patrik Oldsberg --- .../wiring/graph/instantiateAppNodeTree.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts diff --git a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts new file mode 100644 index 0000000000..b01ad020b9 --- /dev/null +++ b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts @@ -0,0 +1,44 @@ +/* + * Copyright 2023 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 { createAppNodeInstance } from './createAppNodeInstance'; +import { AppNode, Mutable } from './types'; + +export function instantiateAppNodeTree(rootNode: AppNode): void { + function createInstance(node: AppNode): void { + if (node.instance) { + return; + } + if (node.spec.disabled) { + return; + } + + for (const children of node.edges.attachments.values()) { + for (const child of children) { + createInstance(child); + } + } + + (node as Mutable).instance = createAppNodeInstance({ + spec: node.spec, + attachments: node.edges.attachments, + }); + + return; + } + + createInstance(rootNode); +} From 6e6458f9c2b47b060e3739f89fda42aa7ae010f6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 10:55:55 +0200 Subject: [PATCH 218/348] frontend-app-api: tweak app graph to have an explicit root node Signed-off-by: Patrik Oldsberg --- .../frontend-app-api/src/extensions/Core.tsx | 2 +- .../src/wiring/graph/buildAppGraph.test.ts | 142 ++++++++++-------- .../src/wiring/graph/buildAppGraph.ts | 29 ++-- .../src/wiring/graph/types.ts | 6 +- 4 files changed, 104 insertions(+), 75 deletions(-) diff --git a/packages/frontend-app-api/src/extensions/Core.tsx b/packages/frontend-app-api/src/extensions/Core.tsx index 6efe3984dc..f48aa2ea6b 100644 --- a/packages/frontend-app-api/src/extensions/Core.tsx +++ b/packages/frontend-app-api/src/extensions/Core.tsx @@ -22,7 +22,7 @@ import { export const Core = createExtension({ id: 'core', - attachTo: { id: 'root', input: 'default' }, + attachTo: { id: 'root', input: 'default' }, // ignored inputs: { apis: createExtensionInput({ api: coreExtensionData.apiFactory, diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts index 21a5009a95..dc489565f4 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts @@ -19,66 +19,70 @@ import { buildAppGraph } from './buildAppGraph'; const extBaseConfig = { id: 'test', - attachTo: { id: 'root', input: 'default' }, + attachTo: { id: 'nonexistent', input: 'nonexistent' }, output: {}, factory() {}, }; const extension = createExtension(extBaseConfig); -const baseSpec = { extension, disabled: false }; +const baseSpec = { + extension, + attachTo: { id: 'nonexistent', input: 'nonexistent' }, + disabled: false, +}; describe('buildAppGraph', () => { - it('creates an empty graph', () => { - const graph = buildAppGraph([]); - expect([...graph.rootNodes.keys()]).toEqual([]); - expect([...graph.orphanNodes.keys()]).toEqual([]); + it('should fail to create an empty graph', () => { + expect(() => buildAppGraph([])).toThrow( + "No root node with id 'core' found in app graph", + ); + }); + + it('should create a graph with only one node', () => { + const graph = buildAppGraph([{ ...baseSpec, id: 'core' }]); + expect(graph.root).toEqual({ + spec: { ...baseSpec, id: 'core' }, + edges: { attachments: new Map() }, + }); + expect(Array.from(graph.orphans)).toEqual([]); }); it('should create a graph', () => { - const graph = buildAppGraph([ - { ...baseSpec, id: 'a' }, - { ...baseSpec, id: 'b' }, - { ...baseSpec, id: 'c' }, - { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, - { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, - { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, - { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, - ]); - expect([...graph.rootNodes.keys()]).toEqual(['a', 'b', 'c']); - expect([...graph.orphanNodes.keys()]).toEqual(['dx1']); - - expect(JSON.parse(JSON.stringify([...graph.rootNodes.values()]))) - .toMatchInlineSnapshot(` + const graph = buildAppGraph( [ - { - "id": "a", + { ...baseSpec, id: 'a' }, + { ...baseSpec, id: 'b' }, + { ...baseSpec, id: 'c' }, + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, + { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, + { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, + ], + 'b', + ); + + expect(JSON.parse(JSON.stringify(graph.root))).toMatchInlineSnapshot(` + { + "attachments": { + "x": [ + { + "id": "bx1", + }, + { + "id": "bx2", + }, + ], + "y": [ + { + "id": "by1", + }, + ], }, - { - "attachments": { - "x": [ - { - "id": "bx1", - }, - { - "id": "bx2", - }, - ], - "y": [ - { - "id": "by1", - }, - ], - }, - "id": "b", - }, - { - "id": "c", - }, - ] + "id": "b", + } `); - expect(String(graph.rootNodes.get('a'))).toMatchInlineSnapshot(`""`); - expect(String(graph.rootNodes.get('b'))).toMatchInlineSnapshot(` + expect(String(graph.root)).toMatchInlineSnapshot(` " x [ @@ -89,24 +93,32 @@ describe('buildAppGraph', () => { ] " `); - expect(String(graph.rootNodes.get('c'))).toMatchInlineSnapshot(`""`); + + const orphans = Array.from(graph.orphans).map(String); + expect(orphans).toMatchInlineSnapshot(` + [ + "", + "", + "", + ] + `); }); it('should create a graph out of order', () => { - const graph = buildAppGraph([ - { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, - { ...baseSpec, id: 'a' }, - { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, - { ...baseSpec, id: 'b' }, - { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, - { ...baseSpec, id: 'c' }, - { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, - ]); - expect([...graph.rootNodes.keys()]).toEqual(['a', 'b', 'c']); - expect([...graph.orphanNodes.keys()]).toEqual(['dx1']); + const graph = buildAppGraph( + [ + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, + { ...baseSpec, id: 'a' }, + { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, + { ...baseSpec, id: 'b' }, + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, + { ...baseSpec, id: 'c' }, + { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, + ], + 'b', + ); - expect(String(graph.rootNodes.get('a'))).toMatchInlineSnapshot(`""`); - expect(String(graph.rootNodes.get('b'))).toMatchInlineSnapshot(` + expect(String(graph.root)).toMatchInlineSnapshot(` " x [ @@ -117,7 +129,15 @@ describe('buildAppGraph', () => { ] " `); - expect(String(graph.rootNodes.get('c'))).toMatchInlineSnapshot(`""`); + + const orphans = Array.from(graph.orphans).map(String); + expect(orphans).toMatchInlineSnapshot(` + [ + "", + "", + "", + ] + `); }); it('throws an error when duplicated extensions are detected', () => { diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts index 79977f6993..72d4d90d48 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts @@ -78,9 +78,15 @@ class SerializableAppNode implements AppNode { * tree with all attachments in the same order as they appear in the input specs array. * @internal */ -export function buildAppGraph(specs: AppNodeSpec[]): AppGraph { +export function buildAppGraph( + specs: AppNodeSpec[], + rootNodeId = 'core', +): AppGraph { const nodes = new Map(); - const rootNodes = new Map(); + + // A node with the provided rootNodeId must be found in the graph, and it must not be attached to anything + let rootNode: AppNode | undefined = undefined; + // While iterating through the inputs specs we keep track of all nodes that were created // before their parent, and attach them later when the parent is created. // As we find the parents and attach the children, we remove them from this map. This means @@ -99,7 +105,10 @@ export function buildAppGraph(specs: AppNodeSpec[]): AppGraph { const node = new SerializableAppNode(spec); nodes.set(spec.id, node); - if (spec.attachTo) { + // TODO: For now we simply ignore the attachTo spec of the root node, but it'd be cleaner if we could avoid defining it + if (spec.id === rootNodeId) { + rootNode = node; + } else { const parent = nodes.get(spec.attachTo.id); if (parent) { (node.edges as Mutable).attachedTo = { @@ -123,8 +132,6 @@ export function buildAppGraph(specs: AppNodeSpec[]): AppGraph { orphansByParent.set(spec.attachTo.id, [orphan]); } } - } else { - rootNodes.set(spec.id, node); } const orphanedChildren = orphansByParent.get(spec.id); @@ -142,11 +149,13 @@ export function buildAppGraph(specs: AppNodeSpec[]): AppGraph { } } - const orphanNodes = new Map( - Array.from(orphansByParent).flatMap(([, orphans]) => - orphans.map(({ orphan }) => [orphan.spec.id, orphan]), - ), + const orphanNodes = Array.from(orphansByParent).flatMap(([, orphans]) => + orphans.map(({ orphan }) => orphan), ); - return { rootNodes, orphanNodes }; + if (!rootNode) { + throw new Error(`No root node with id '${rootNodeId}' found in app graph`); + } + + return { root: rootNode, orphans: orphanNodes }; } diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts index 29c0028d66..6cf4ade360 100644 --- a/packages/frontend-app-api/src/wiring/graph/types.ts +++ b/packages/frontend-app-api/src/wiring/graph/types.ts @@ -31,7 +31,7 @@ export type Mutable = { */ export interface AppNodeSpec { readonly id: string; - readonly attachTo?: { id: string; input: string }; + readonly attachTo: { id: string; input: string }; readonly extension: Extension; readonly disabled: boolean; readonly config?: unknown; @@ -70,6 +70,6 @@ export interface AppNode { } export interface AppGraph { - rootNodes: Map; - orphanNodes: Map; + root: AppNode; + orphans: Iterable; } From ff33a006a1356f59122534e31b13e113809200ca Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 11:01:30 +0200 Subject: [PATCH 219/348] frontend-app-api: add node map to app graph Signed-off-by: Patrik Oldsberg --- .../src/wiring/graph/buildAppGraph.test.ts | 21 +++++++++++++++++++ .../src/wiring/graph/buildAppGraph.ts | 2 +- .../src/wiring/graph/types.ts | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts index dc489565f4..8cf8279e96 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts @@ -46,6 +46,7 @@ describe('buildAppGraph', () => { edges: { attachments: new Map() }, }); expect(Array.from(graph.orphans)).toEqual([]); + expect(Array.from(graph.nodes.keys())).toEqual(['core']); }); it('should create a graph', () => { @@ -62,6 +63,16 @@ describe('buildAppGraph', () => { 'b', ); + expect(Array.from(graph.nodes.keys())).toEqual([ + 'a', + 'b', + 'c', + 'bx1', + 'bx2', + 'by1', + 'dx1', + ]); + expect(JSON.parse(JSON.stringify(graph.root))).toMatchInlineSnapshot(` { "attachments": { @@ -118,6 +129,16 @@ describe('buildAppGraph', () => { 'b', ); + expect(Array.from(graph.nodes.keys())).toEqual([ + 'bx2', + 'a', + 'by1', + 'b', + 'bx1', + 'c', + 'dx1', + ]); + expect(String(graph.root)).toMatchInlineSnapshot(` " x [ diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts index 72d4d90d48..f87d191908 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts @@ -157,5 +157,5 @@ export function buildAppGraph( throw new Error(`No root node with id '${rootNodeId}' found in app graph`); } - return { root: rootNode, orphans: orphanNodes }; + return { root: rootNode, nodes, orphans: orphanNodes }; } diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts index 6cf4ade360..21ea55c780 100644 --- a/packages/frontend-app-api/src/wiring/graph/types.ts +++ b/packages/frontend-app-api/src/wiring/graph/types.ts @@ -71,5 +71,6 @@ export interface AppNode { export interface AppGraph { root: AppNode; + nodes: Map; orphans: Iterable; } From 3230953cc971bfa6da8e19c0b6055c156c495352 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 11:02:24 +0200 Subject: [PATCH 220/348] frontend-app-api: switch to ReadonlyMap in app graph types Signed-off-by: Patrik Oldsberg --- packages/frontend-app-api/src/wiring/graph/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts index 21ea55c780..d7f80faa1b 100644 --- a/packages/frontend-app-api/src/wiring/graph/types.ts +++ b/packages/frontend-app-api/src/wiring/graph/types.ts @@ -44,7 +44,7 @@ export interface AppNodeSpec { */ export interface AppNodeEdges { readonly attachedTo?: { node: AppNode; input: string }; - readonly attachments: Map; + readonly attachments: ReadonlyMap; } /** @@ -71,6 +71,6 @@ export interface AppNode { export interface AppGraph { root: AppNode; - nodes: Map; + nodes: ReadonlyMap; orphans: Iterable; } From 1a9acc4ff19b6d53ba6e7ec67d0b50776a4a3928 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 11:10:26 +0200 Subject: [PATCH 221/348] frontend-app-api: refactor buildAppGraph to avoid mutability casts Signed-off-by: Patrik Oldsberg --- .../src/wiring/graph/buildAppGraph.ts | 71 ++++++++----------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts index f87d191908..06347b1ece 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts +++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts @@ -14,14 +14,7 @@ * limitations under the License. */ -import { - AppGraph, - AppNode, - AppNodeEdges, - AppNodeInstance, - AppNodeSpec, - Mutable, -} from './types'; +import { AppGraph, AppNode, AppNodeInstance, AppNodeSpec } from './types'; function indent(str: string) { return str.replace(/^/gm, ' '); @@ -30,13 +23,29 @@ function indent(str: string) { /** @internal */ class SerializableAppNode implements AppNode { public readonly spec: AppNodeSpec; - public readonly edges: AppNodeEdges = { attachments: new Map() }; + public readonly edges = { + attachedTo: undefined as { node: AppNode; input: string } | undefined, + attachments: new Map(), + }; public readonly instance?: AppNodeInstance; constructor(spec: AppNodeSpec) { this.spec = spec; } + setParent(parent: SerializableAppNode) { + const input = this.spec.attachTo.input; + + this.edges.attachedTo = { node: parent, input }; + + const parentInputEdges = parent.edges.attachments.get(input); + if (parentInputEdges) { + parentInputEdges.push(this); + } else { + parent.edges.attachments.set(input, [this]); + } + } + toJSON() { const dataRefs = this.instance && [...this.instance.getDataRefs()]; return { @@ -52,7 +61,7 @@ class SerializableAppNode implements AppNode { }; } - toString() { + toString(): string { const dataRefs = this.instance && [...this.instance.getDataRefs()]; const out = dataRefs && dataRefs.length > 0 @@ -82,7 +91,7 @@ export function buildAppGraph( specs: AppNodeSpec[], rootNodeId = 'core', ): AppGraph { - const nodes = new Map(); + const nodes = new Map(); // A node with the provided rootNodeId must be found in the graph, and it must not be attached to anything let rootNode: AppNode | undefined = undefined; @@ -93,7 +102,7 @@ export function buildAppGraph( // that after iterating through all input specs, this will be a map for each root node. const orphansByParent = new Map< string /* parentId */, - { orphan: AppNode; input: string }[] + SerializableAppNode[] >(); for (const spec of specs) { @@ -111,25 +120,13 @@ export function buildAppGraph( } else { const parent = nodes.get(spec.attachTo.id); if (parent) { - (node.edges as Mutable).attachedTo = { - node: parent, - input: spec.attachTo.input, - }; - const parentInputEdges = parent.edges.attachments.get( - spec.attachTo.input, - ); - if (parentInputEdges) { - parentInputEdges.push(node); - } else { - parent.edges.attachments.set(spec.attachTo.input, [node]); - } + node.setParent(parent); } else { const orphanNodesForParent = orphansByParent.get(spec.attachTo.id); - const orphan = { orphan: node, input: spec.attachTo.input }; if (orphanNodesForParent) { - orphanNodesForParent.push(orphan); + orphanNodesForParent.push(node); } else { - orphansByParent.set(spec.attachTo.id, [orphan]); + orphansByParent.set(spec.attachTo.id, [node]); } } } @@ -137,25 +134,19 @@ export function buildAppGraph( const orphanedChildren = orphansByParent.get(spec.id); if (orphanedChildren) { orphansByParent.delete(spec.id); - for (const { orphan, input } of orphanedChildren) { - (orphan.edges as Mutable).attachedTo = { node, input }; - const attachments = node.edges.attachments.get(input); - if (attachments) { - attachments.push(orphan); - } else { - node.edges.attachments.set(input, [orphan]); - } + for (const orphan of orphanedChildren) { + orphan.setParent(node); } } } - const orphanNodes = Array.from(orphansByParent).flatMap(([, orphans]) => - orphans.map(({ orphan }) => orphan), - ); - if (!rootNode) { throw new Error(`No root node with id '${rootNodeId}' found in app graph`); } - return { root: rootNode, nodes, orphans: orphanNodes }; + return { + root: rootNode, + nodes, + orphans: Array.from(orphansByParent.values()).flat(), + }; } From be2afe8d48597463ae17a86d8d07f75ca76526d4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 11:12:01 +0200 Subject: [PATCH 222/348] frontend-app-api: update createAppNodeInstance for ReadonlyMap + remove ExtensionInstance type Signed-off-by: Patrik Oldsberg --- .../src/wiring/graph/createAppNodeInstance.ts | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts b/packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts index 310852cd1c..22cb3d4df7 100644 --- a/packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts +++ b/packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts @@ -17,7 +17,6 @@ import { AnyExtensionDataMap, AnyExtensionInputMap, - BackstagePlugin, ExtensionDataRef, } from '@backstage/frontend-plugin-api'; import mapValues from 'lodash/mapValues'; @@ -25,23 +24,6 @@ import { AppNode, AppNodeInstance, AppNodeSpec } from './types'; type AppNodeWithInstance = AppNode & { instance: AppNodeInstance }; -/** @internal */ -export interface ExtensionInstance { - readonly $$type: '@backstage/ExtensionInstance'; - - readonly id: string; - /** - * Get concrete value for the given extension data reference. Returns undefined if no value is available. - */ - getData(ref: ExtensionDataRef): T | undefined; - /** - * Maps input names to the actual instances given to them. - */ - readonly attachments: Map; - - readonly source?: BackstagePlugin; -} - function resolveInputData( dataMap: AnyExtensionDataMap, attachment: AppNodeWithInstance, @@ -60,7 +42,7 @@ function resolveInputData( function resolveInputs( inputMap: AnyExtensionInputMap, - attachments: Map, + attachments: ReadonlyMap, ) { const undeclaredAttachments = Array.from(attachments.entries()).filter( ([inputName]) => inputMap[inputName] === undefined, @@ -117,7 +99,7 @@ function resolveInputs( /** @internal */ export function createAppNodeInstance(options: { spec: AppNodeSpec; - attachments: Map; + attachments: ReadonlyMap; }): AppNodeInstance { const { spec, attachments } = options; const { id, extension, config, source } = spec; From 2b1ceb2fe152410fa52a27f8dc5eacf62fbd84be Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 11:59:44 +0200 Subject: [PATCH 223/348] frontend-app-api: move app node instance creation into instantiateAppNodeTree Signed-off-by: Patrik Oldsberg --- .../src/wiring/graph/createAppNodeInstance.ts | 155 ---------------- .../wiring/graph/instantiateAppNodeTree.ts | 170 ++++++++++++++++-- .../src/wiring/graph/types.ts | 5 - 3 files changed, 159 insertions(+), 171 deletions(-) delete mode 100644 packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts diff --git a/packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts b/packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts deleted file mode 100644 index 22cb3d4df7..0000000000 --- a/packages/frontend-app-api/src/wiring/graph/createAppNodeInstance.ts +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2023 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 { - AnyExtensionDataMap, - AnyExtensionInputMap, - ExtensionDataRef, -} from '@backstage/frontend-plugin-api'; -import mapValues from 'lodash/mapValues'; -import { AppNode, AppNodeInstance, AppNodeSpec } from './types'; - -type AppNodeWithInstance = AppNode & { instance: AppNodeInstance }; - -function resolveInputData( - dataMap: AnyExtensionDataMap, - attachment: AppNodeWithInstance, - inputName: string, -) { - return mapValues(dataMap, ref => { - const value = attachment.instance.getData(ref); - if (value === undefined && !ref.config.optional) { - throw new Error( - `input '${inputName}' did not receive required extension data '${ref.id}' from extension '${attachment.spec.id}'`, - ); - } - return value; - }); -} - -function resolveInputs( - inputMap: AnyExtensionInputMap, - attachments: ReadonlyMap, -) { - const undeclaredAttachments = Array.from(attachments.entries()).filter( - ([inputName]) => inputMap[inputName] === undefined, - ); - // TODO: Make this a warning rather than an error - if (undeclaredAttachments.length > 0) { - throw new Error( - `received undeclared input${ - undeclaredAttachments.length > 1 ? 's' : '' - } ${undeclaredAttachments - .map( - ([k, exts]) => - `'${k}' from extension${exts.length > 1 ? 's' : ''} '${exts - .map(e => e.spec.id) - .join("', '")}'`, - ) - .join(' and ')}`, - ); - } - - return mapValues(inputMap, (input, inputName) => { - const attachedNodes = - attachments - .get(inputName) - ?.filter((node): node is AppNodeWithInstance => - Boolean(node.instance), - ) ?? []; - - if (input.config.singleton) { - if (attachedNodes.length > 1) { - const attachedNodeIds = attachedNodes.map(e => e.spec.id); - throw Error( - `expected ${ - input.config.optional ? 'at most' : 'exactly' - } one '${inputName}' input but received multiple: '${attachedNodeIds.join( - "', '", - )}'`, - ); - } else if (attachedNodes.length === 0) { - if (input.config.optional) { - return undefined; - } - throw Error(`input '${inputName}' is required but was not received`); - } - return resolveInputData(input.extensionData, attachedNodes[0], inputName); - } - - return attachedNodes.map(attachment => - resolveInputData(input.extensionData, attachment, inputName), - ); - }); -} - -/** @internal */ -export function createAppNodeInstance(options: { - spec: AppNodeSpec; - attachments: ReadonlyMap; -}): AppNodeInstance { - const { spec, attachments } = options; - const { id, extension, config, source } = spec; - const extensionData = new Map(); - const extensionDataRefs = new Set>(); - - let parsedConfig: unknown; - try { - parsedConfig = extension.configSchema?.parse(config ?? {}); - } catch (e) { - throw new Error( - `Invalid configuration for extension '${id}'; caused by ${e}`, - ); - } - - try { - extension.factory({ - source, - config: parsedConfig, - bind: namedOutputs => { - for (const [name, output] of Object.entries(namedOutputs)) { - const ref = extension.output[name]; - if (!ref) { - throw new Error(`unknown output provided via '${name}'`); - } - if (extensionData.has(ref.id)) { - throw new Error( - `duplicate extension data '${ref.id}' received via output '${name}'`, - ); - } - extensionData.set(ref.id, output); - extensionDataRefs.add(ref); - } - }, - inputs: resolveInputs(extension.inputs, attachments), - }); - } catch (e) { - throw new Error( - `Failed to instantiate extension '${id}'${ - e.name === 'Error' ? `, ${e.message}` : `; caused by ${e}` - }`, - ); - } - - return { - getDataRefs() { - return extensionDataRefs.values(); - }, - getData(ref: ExtensionDataRef): T | undefined { - return extensionData.get(ref.id) as T | undefined; - }, - }; -} diff --git a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts index b01ad020b9..ba0c85692e 100644 --- a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts +++ b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts @@ -14,30 +14,178 @@ * limitations under the License. */ -import { createAppNodeInstance } from './createAppNodeInstance'; -import { AppNode, Mutable } from './types'; +import { + AnyExtensionDataMap, + AnyExtensionInputMap, + ExtensionDataRef, +} from '@backstage/frontend-plugin-api'; +import mapValues from 'lodash/mapValues'; +import { AppNode, AppNodeInstance, AppNodeSpec } from './types'; +type Mutable = { + -readonly [P in keyof T]: T[P]; +}; + +function resolveInputData( + dataMap: AnyExtensionDataMap, + attachment: { id: string; instance: AppNodeInstance }, + inputName: string, +) { + return mapValues(dataMap, ref => { + const value = attachment.instance.getData(ref); + if (value === undefined && !ref.config.optional) { + throw new Error( + `input '${inputName}' did not receive required extension data '${ref.id}' from extension '${attachment.id}'`, + ); + } + return value; + }); +} + +function resolveInputs( + inputMap: AnyExtensionInputMap, + attachments: ReadonlyMap, +) { + const undeclaredAttachments = Array.from(attachments.entries()).filter( + ([inputName]) => inputMap[inputName] === undefined, + ); + // TODO: Make this a warning rather than an error + if (undeclaredAttachments.length > 0) { + throw new Error( + `received undeclared input${ + undeclaredAttachments.length > 1 ? 's' : '' + } ${undeclaredAttachments + .map( + ([k, exts]) => + `'${k}' from extension${exts.length > 1 ? 's' : ''} '${exts + .map(e => e.id) + .join("', '")}'`, + ) + .join(' and ')}`, + ); + } + + return mapValues(inputMap, (input, inputName) => { + const attachedNodes = attachments.get(inputName) ?? []; + + if (input.config.singleton) { + if (attachedNodes.length > 1) { + const attachedNodeIds = attachedNodes.map(e => e.id); + throw Error( + `expected ${ + input.config.optional ? 'at most' : 'exactly' + } one '${inputName}' input but received multiple: '${attachedNodeIds.join( + "', '", + )}'`, + ); + } else if (attachedNodes.length === 0) { + if (input.config.optional) { + return undefined; + } + throw Error(`input '${inputName}' is required but was not received`); + } + return resolveInputData(input.extensionData, attachedNodes[0], inputName); + } + + return attachedNodes.map(attachment => + resolveInputData(input.extensionData, attachment, inputName), + ); + }); +} + +/** @internal */ +export function createAppNodeInstance(options: { + spec: AppNodeSpec; + attachments: ReadonlyMap; +}): AppNodeInstance { + const { spec, attachments } = options; + const { id, extension, config, source } = spec; + const extensionData = new Map(); + const extensionDataRefs = new Set>(); + + let parsedConfig: unknown; + try { + parsedConfig = extension.configSchema?.parse(config ?? {}); + } catch (e) { + throw new Error( + `Invalid configuration for extension '${id}'; caused by ${e}`, + ); + } + + try { + extension.factory({ + source, + config: parsedConfig, + bind: namedOutputs => { + for (const [name, output] of Object.entries(namedOutputs)) { + const ref = extension.output[name]; + if (!ref) { + throw new Error(`unknown output provided via '${name}'`); + } + if (extensionData.has(ref.id)) { + throw new Error( + `duplicate extension data '${ref.id}' received via output '${name}'`, + ); + } + extensionData.set(ref.id, output); + extensionDataRefs.add(ref); + } + }, + inputs: resolveInputs(extension.inputs, attachments), + }); + } catch (e) { + throw new Error( + `Failed to instantiate extension '${id}'${ + e.name === 'Error' ? `, ${e.message}` : `; caused by ${e}` + }`, + ); + } + + return { + getDataRefs() { + return extensionDataRefs.values(); + }, + getData(ref: ExtensionDataRef): T | undefined { + return extensionData.get(ref.id) as T | undefined; + }, + }; +} + +/** + * Starting at the provided node, instantiate all reachable nodes in the graph that have not been disabled. + * @internal + */ export function instantiateAppNodeTree(rootNode: AppNode): void { - function createInstance(node: AppNode): void { + function createInstance(node: AppNode): AppNodeInstance | undefined { if (node.instance) { - return; + return node.instance; } if (node.spec.disabled) { - return; + return undefined; } - for (const children of node.edges.attachments.values()) { - for (const child of children) { - createInstance(child); - } + const instantiatedAttachments = new Map< + string, + { id: string; instance: AppNodeInstance }[] + >(); + + for (const [input, children] of node.edges.attachments) { + const instantiatedChildren = children.flatMap(child => { + const childInstance = createInstance(child); + if (!childInstance) { + return []; + } + return [{ id: child.spec.id, instance: childInstance }]; + }); + instantiatedAttachments.set(input, instantiatedChildren); } (node as Mutable).instance = createAppNodeInstance({ spec: node.spec, - attachments: node.edges.attachments, + attachments: instantiatedAttachments, }); - return; + return node.instance; } createInstance(rootNode); diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts index d7f80faa1b..b828c9762e 100644 --- a/packages/frontend-app-api/src/wiring/graph/types.ts +++ b/packages/frontend-app-api/src/wiring/graph/types.ts @@ -20,11 +20,6 @@ import { ExtensionDataRef, } from '@backstage/frontend-plugin-api'; -/** @internal */ -export type Mutable = { - -readonly [P in keyof T]: T[P]; -}; - /** * The specification for this node in the app graph. * @public From aded5d1ce4a47ed9284e2559f41c6dff27270343 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 12:29:32 +0200 Subject: [PATCH 224/348] frontend-app-api: migrate createExtensionInstance tests Signed-off-by: Patrik Oldsberg --- .../graph/createExtensionInstance.test.ts | 456 ------------------ .../graph/instantiateAppNodeTree.test.ts | 441 +++++++++++++++++ 2 files changed, 441 insertions(+), 456 deletions(-) delete mode 100644 packages/frontend-app-api/src/wiring/graph/createExtensionInstance.test.ts create mode 100644 packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts diff --git a/packages/frontend-app-api/src/wiring/graph/createExtensionInstance.test.ts b/packages/frontend-app-api/src/wiring/graph/createExtensionInstance.test.ts deleted file mode 100644 index 6e69e99cb7..0000000000 --- a/packages/frontend-app-api/src/wiring/graph/createExtensionInstance.test.ts +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright 2023 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 { - createExtension, - createExtensionDataRef, - createExtensionInput, - createSchemaFromZod, -} from '@backstage/frontend-plugin-api'; -import { createExtensionInstance } from './createExtensionInstance'; - -const testDataRef = createExtensionDataRef('test'); -const otherDataRef = createExtensionDataRef('other'); -const inputMirrorDataRef = createExtensionDataRef('mirror'); - -const simpleExtension = createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: { - test: testDataRef, - other: otherDataRef.optional(), - }, - configSchema: createSchemaFromZod(z => - z.object({ - output: z.string().default('test'), - other: z.number().optional(), - }), - ), - factory({ bind, config }) { - bind({ test: config.output, other: config.other }); - }, -}); - -describe('createExtensionInstance', () => { - it('should create a simple extension instance', () => { - const attachments = new Map(); - const instance = createExtensionInstance({ - attachments, - config: undefined, - extension: simpleExtension, - }); - - expect(instance.id).toBe('core.test'); - expect(instance.attachments).toBe(attachments); - expect(instance.getData(testDataRef)).toEqual('test'); - }); - - it('should create an extension with different kind of inputs', () => { - const attachments = new Map([ - [ - 'optionalSingletonPresent', - [ - createExtensionInstance({ - attachments: new Map(), - config: { output: 'optionalSingletonPresent' }, - extension: simpleExtension, - }), - ], - ], - [ - 'singleton', - [ - createExtensionInstance({ - attachments: new Map(), - config: { output: 'singleton', other: 2 }, - extension: simpleExtension, - }), - ], - ], - [ - 'many', - [ - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many1' }, - extension: simpleExtension, - }), - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many2', other: 3 }, - extension: simpleExtension, - }), - ], - ], - ]); - const instance = createExtensionInstance({ - attachments, - config: undefined, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - optionalSingletonPresent: createExtensionInput( - { - test: testDataRef, - other: otherDataRef.optional(), - }, - { singleton: true, optional: true }, - ), - optionalSingletonMissing: createExtensionInput( - { - test: testDataRef, - other: otherDataRef.optional(), - }, - { singleton: true, optional: true }, - ), - singleton: createExtensionInput( - { - test: testDataRef, - other: otherDataRef.optional(), - }, - { singleton: true }, - ), - many: createExtensionInput({ - test: testDataRef, - other: otherDataRef.optional(), - }), - }, - output: { - inputMirror: inputMirrorDataRef, - }, - factory({ bind, inputs }) { - bind({ inputMirror: inputs }); - }, - }), - }); - - expect(instance.id).toBe('core.test'); - expect(instance.attachments).toBe(attachments); - expect(instance.getData(inputMirrorDataRef)).toEqual({ - optionalSingletonPresent: { test: 'optionalSingletonPresent' }, - singleton: { test: 'singleton', other: 2 }, - many: [{ test: 'many1' }, { test: 'many2', other: 3 }], - }); - }); - - it('should refuse to create an extension with invalid config', () => { - expect(() => - createExtensionInstance({ - attachments: new Map(), - config: { other: 'not-a-number' }, - extension: simpleExtension, - }), - ).toThrow( - "Invalid configuration for extension 'core.test'; caused by Error: Expected number, received string at 'other'", - ); - }); - - it('should forward extension factory errors', () => { - expect(() => - createExtensionInstance({ - attachments: new Map(), - config: { other: 'not-a-number' }, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: {}, - factory() { - const error = new Error('NOPE'); - error.name = 'NopeError'; - throw error; - }, - }), - }), - ).toThrow( - "Failed to instantiate extension 'core.test'; caused by NopeError: NOPE", - ); - }); - - it('should refuse to create an instance with duplicate output', () => { - const attachments = new Map(); - expect(() => - createExtensionInstance({ - attachments, - config: undefined, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: { - test1: testDataRef, - test2: testDataRef, - }, - factory({ bind }) { - bind({ test1: 'test', test2: 'test2' }); - }, - }), - }), - ).toThrow( - "Failed to instantiate extension 'core.test', duplicate extension data 'test' received via output 'test2'", - ); - }); - - it('should refuse to create an instance with disconnected output data', () => { - const attachments = new Map(); - expect(() => - createExtensionInstance({ - attachments, - config: undefined, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: { - test: testDataRef, - }, - factory({ bind }) { - bind({ nonexistent: 'test' } as any); - }, - }), - }), - ).toThrow( - "Failed to instantiate extension 'core.test', unknown output provided via 'nonexistent'", - ); - }); - - it('should refuse to create an instance with missing required input', () => { - expect(() => - createExtensionInstance({ - attachments: new Map(), - config: undefined, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - singleton: createExtensionInput( - { - test: testDataRef, - }, - { singleton: true }, - ), - }, - output: {}, - factory() {}, - }), - }), - ).toThrow( - "Failed to instantiate extension 'core.test', input 'singleton' is required but was not received", - ); - }); - - it('should refuse to create an instance with undeclared inputs', () => { - expect(() => - createExtensionInstance({ - attachments: new Map([ - [ - 'declared', - [ - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many1' }, - extension: simpleExtension, - }), - ], - ], - [ - 'undeclared', - [ - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many1' }, - extension: simpleExtension, - }), - ], - ], - ]), - config: undefined, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - declared: createExtensionInput({ - test: testDataRef, - }), - }, - output: {}, - factory() {}, - }), - }), - ).toThrow( - "Failed to instantiate extension 'core.test', received undeclared input 'undeclared' from extension 'core.test'", - ); - }); - - it('should refuse to create an instance with multiple undeclared inputs', () => { - expect(() => - createExtensionInstance({ - attachments: new Map([ - [ - 'undeclared1', - [ - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many1' }, - extension: simpleExtension, - }), - ], - ], - [ - 'undeclared2', - [ - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many1' }, - extension: simpleExtension, - }), - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many1' }, - extension: simpleExtension, - }), - ], - ], - ]), - config: undefined, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: {}, - factory() {}, - }), - }), - ).toThrow( - "Failed to instantiate extension 'core.test', received undeclared inputs 'undeclared1' from extension 'core.test' and 'undeclared2' from extensions 'core.test', 'core.test'", - ); - }); - - it('should refuse to create an instance with multiple inputs for required singleton', () => { - expect(() => - createExtensionInstance({ - attachments: new Map([ - [ - 'singleton', - [ - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many1' }, - extension: simpleExtension, - }), - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many2' }, - extension: simpleExtension, - }), - ], - ], - ]), - config: undefined, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - singleton: createExtensionInput( - { - test: testDataRef, - }, - { singleton: true }, - ), - }, - output: {}, - factory() {}, - }), - }), - ).toThrow( - "Failed to instantiate extension 'core.test', expected exactly one 'singleton' input but received multiple: 'core.test', 'core.test'", - ); - }); - - it('should refuse to create an instance with multiple inputs for optional singleton', () => { - expect(() => - createExtensionInstance({ - attachments: new Map([ - [ - 'singleton', - [ - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many1' }, - extension: simpleExtension, - }), - createExtensionInstance({ - attachments: new Map(), - config: { output: 'many2' }, - extension: simpleExtension, - }), - ], - ], - ]), - config: undefined, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - singleton: createExtensionInput( - { - test: testDataRef, - }, - { singleton: true, optional: true }, - ), - }, - output: {}, - factory() {}, - }), - }), - ).toThrow( - "Failed to instantiate extension 'core.test', expected at most one 'singleton' input but received multiple: 'core.test', 'core.test'", - ); - }); - - it('should refuse to create an instance with multiple inputs that did not provide required data', () => { - expect(() => - createExtensionInstance({ - attachments: new Map([ - [ - 'singleton', - [ - createExtensionInstance({ - attachments: new Map(), - config: undefined, - extension: simpleExtension, - }), - ], - ], - ]), - config: undefined, - extension: createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - singleton: createExtensionInput( - { - other: otherDataRef, - }, - { singleton: true }, - ), - }, - output: {}, - factory() {}, - }), - }), - ).toThrow( - "Failed to instantiate extension 'core.test', input 'singleton' did not receive required extension data 'other' from extension 'core.test'", - ); - }); -}); diff --git a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts new file mode 100644 index 0000000000..ddd842c6c0 --- /dev/null +++ b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts @@ -0,0 +1,441 @@ +/* + * Copyright 2023 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 { + Extension, + createExtension, + createExtensionDataRef, + createExtensionInput, + createSchemaFromZod, +} from '@backstage/frontend-plugin-api'; +import { createAppNodeInstance } from './instantiateAppNodeTree'; +import { AppNodeInstance, AppNodeSpec } from './types'; + +const testDataRef = createExtensionDataRef('test'); +const otherDataRef = createExtensionDataRef('other'); +const inputMirrorDataRef = createExtensionDataRef('mirror'); + +const simpleExtension = createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: { + test: testDataRef, + other: otherDataRef.optional(), + }, + configSchema: createSchemaFromZod(z => + z.object({ + output: z.string().default('test'), + other: z.number().optional(), + }), + ), + factory({ bind, config }) { + bind({ test: config.output, other: config.other }); + }, +}); + +function makeSpec( + extension: Extension, + config?: TConfig, +): AppNodeSpec { + return { + id: extension.id, + attachTo: extension.attachTo, + disabled: extension.disabled, + extension, + config, + source: undefined, + }; +} + +function makeInstanceWithId( + extension: Extension, + config?: TConfig, +): { id: string; instance: AppNodeInstance } { + return { + id: extension.id, + instance: createAppNodeInstance({ + spec: makeSpec(extension, config), + attachments: new Map(), + }), + }; +} + +describe('createAppNodeInstance', () => { + it('should create a simple extension instance', () => { + const attachments = new Map(); + const instance = createAppNodeInstance({ + spec: makeSpec(simpleExtension), + attachments, + }); + + expect(Array.from(instance.getDataRefs())).toEqual([ + testDataRef, + otherDataRef.optional(), + ]); + expect(instance.getData(testDataRef)).toEqual('test'); + }); + + it('should create an extension with different kind of inputs', () => { + const attachments = new Map([ + [ + 'optionalSingletonPresent', + [ + makeInstanceWithId(simpleExtension, { + output: 'optionalSingletonPresent', + }), + ], + ], + [ + 'singleton', + [ + makeInstanceWithId(simpleExtension, { + output: 'singleton', + other: 2, + }), + ], + ], + [ + 'many', + [ + makeInstanceWithId(simpleExtension, { output: 'many1' }), + makeInstanceWithId(simpleExtension, { output: 'many2', other: 3 }), + ], + ], + ]); + const instance = createAppNodeInstance({ + attachments, + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + optionalSingletonPresent: createExtensionInput( + { + test: testDataRef, + other: otherDataRef.optional(), + }, + { singleton: true, optional: true }, + ), + optionalSingletonMissing: createExtensionInput( + { + test: testDataRef, + other: otherDataRef.optional(), + }, + { singleton: true, optional: true }, + ), + singleton: createExtensionInput( + { + test: testDataRef, + other: otherDataRef.optional(), + }, + { singleton: true }, + ), + many: createExtensionInput({ + test: testDataRef, + other: otherDataRef.optional(), + }), + }, + output: { + inputMirror: inputMirrorDataRef, + }, + factory({ bind, inputs }) { + bind({ inputMirror: inputs }); + }, + }), + ), + }); + + expect(Array.from(instance.getDataRefs())).toEqual([inputMirrorDataRef]); + expect(instance.getData(inputMirrorDataRef)).toEqual({ + optionalSingletonPresent: { test: 'optionalSingletonPresent' }, + singleton: { test: 'singleton', other: 2 }, + many: [{ test: 'many1' }, { test: 'many2', other: 3 }], + }); + }); + + it('should refuse to create an extension with invalid config', () => { + expect(() => + createAppNodeInstance({ + spec: { + ...makeSpec(simpleExtension), + config: { other: 'not-a-number' }, + }, + attachments: new Map(), + }), + ).toThrow( + "Invalid configuration for extension 'core.test'; caused by Error: Expected number, received string at 'other'", + ); + }); + + it('should forward extension factory errors', () => { + expect(() => + createAppNodeInstance({ + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: {}, + factory() { + const error = new Error('NOPE'); + error.name = 'NopeError'; + throw error; + }, + }), + ), + attachments: new Map(), + }), + ).toThrow( + "Failed to instantiate extension 'core.test'; caused by NopeError: NOPE", + ); + }); + + it('should refuse to create an instance with duplicate output', () => { + expect(() => + createAppNodeInstance({ + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: { + test1: testDataRef, + test2: testDataRef, + }, + factory({ bind }) { + bind({ test1: 'test', test2: 'test2' }); + }, + }), + ), + attachments: new Map(), + }), + ).toThrow( + "Failed to instantiate extension 'core.test', duplicate extension data 'test' received via output 'test2'", + ); + }); + + it('should refuse to create an instance with disconnected output data', () => { + expect(() => + createAppNodeInstance({ + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: { + test: testDataRef, + }, + factory({ bind }) { + bind({ nonexistent: 'test' } as any); + }, + }), + ), + attachments: new Map(), + }), + ).toThrow( + "Failed to instantiate extension 'core.test', unknown output provided via 'nonexistent'", + ); + }); + + it('should refuse to create an instance with missing required input', () => { + expect(() => + createAppNodeInstance({ + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + singleton: createExtensionInput( + { + test: testDataRef, + }, + { singleton: true }, + ), + }, + output: {}, + factory() {}, + }), + ), + attachments: new Map(), + }), + ).toThrow( + "Failed to instantiate extension 'core.test', input 'singleton' is required but was not received", + ); + }); + + it('should refuse to create an instance with undeclared inputs', () => { + expect(() => + createAppNodeInstance({ + attachments: new Map([ + [ + 'declared', + [ + makeInstanceWithId(simpleExtension, { + output: 'many1', + }), + ], + ], + [ + 'undeclared', + [ + makeInstanceWithId(simpleExtension, { + output: 'many1', + }), + ], + ], + ]), + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + declared: createExtensionInput({ + test: testDataRef, + }), + }, + output: {}, + factory() {}, + }), + ), + }), + ).toThrow( + "Failed to instantiate extension 'core.test', received undeclared input 'undeclared' from extension 'core.test'", + ); + }); + + it('should refuse to create an instance with multiple undeclared inputs', () => { + expect(() => + createAppNodeInstance({ + attachments: new Map([ + [ + 'undeclared1', + [makeInstanceWithId(simpleExtension, { output: 'many1' })], + ], + [ + 'undeclared2', + [ + makeInstanceWithId(simpleExtension, { output: 'many1' }), + makeInstanceWithId(simpleExtension, { output: 'many1' }), + ], + ], + ]), + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: {}, + factory() {}, + }), + ), + }), + ).toThrow( + "Failed to instantiate extension 'core.test', received undeclared inputs 'undeclared1' from extension 'core.test' and 'undeclared2' from extensions 'core.test', 'core.test'", + ); + }); + + it('should refuse to create an instance with multiple inputs for required singleton', () => { + expect(() => + createAppNodeInstance({ + attachments: new Map([ + [ + 'singleton', + [ + makeInstanceWithId(simpleExtension, { output: 'many1' }), + makeInstanceWithId(simpleExtension, { output: 'many2' }), + ], + ], + ]), + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + singleton: createExtensionInput( + { + test: testDataRef, + }, + { singleton: true }, + ), + }, + output: {}, + factory() {}, + }), + ), + }), + ).toThrow( + "Failed to instantiate extension 'core.test', expected exactly one 'singleton' input but received multiple: 'core.test', 'core.test'", + ); + }); + + it('should refuse to create an instance with multiple inputs for optional singleton', () => { + expect(() => + createAppNodeInstance({ + attachments: new Map([ + [ + 'singleton', + [ + makeInstanceWithId(simpleExtension, { output: 'many1' }), + makeInstanceWithId(simpleExtension, { output: 'many2' }), + ], + ], + ]), + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + singleton: createExtensionInput( + { + test: testDataRef, + }, + { singleton: true, optional: true }, + ), + }, + output: {}, + factory() {}, + }), + ), + }), + ).toThrow( + "Failed to instantiate extension 'core.test', expected at most one 'singleton' input but received multiple: 'core.test', 'core.test'", + ); + }); + + it('should refuse to create an instance with multiple inputs that did not provide required data', () => { + expect(() => + createAppNodeInstance({ + attachments: new Map([ + ['singleton', [makeInstanceWithId(simpleExtension, undefined)]], + ]), + spec: makeSpec( + createExtension({ + id: 'core.test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + singleton: createExtensionInput( + { + other: otherDataRef, + }, + { singleton: true }, + ), + }, + output: {}, + factory() {}, + }), + ), + }), + ).toThrow( + "Failed to instantiate extension 'core.test', input 'singleton' did not receive required extension data 'other' from extension 'core.test'", + ); + }); +}); From d844ec8a0be4c6d67c06110f18e12b11f503c594 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 12:52:17 +0200 Subject: [PATCH 225/348] frontend-app-api: add tests for instantiateAppNodeTree Signed-off-by: Patrik Oldsberg --- .../graph/instantiateAppNodeTree.test.ts | 123 +++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts index ddd842c6c0..43aad4f9ae 100644 --- a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts +++ b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts @@ -21,8 +21,12 @@ import { createExtensionInput, createSchemaFromZod, } from '@backstage/frontend-plugin-api'; -import { createAppNodeInstance } from './instantiateAppNodeTree'; +import { + createAppNodeInstance, + instantiateAppNodeTree, +} from './instantiateAppNodeTree'; import { AppNodeInstance, AppNodeSpec } from './types'; +import { buildAppGraph } from './buildAppGraph'; const testDataRef = createExtensionDataRef('test'); const otherDataRef = createExtensionDataRef('other'); @@ -73,6 +77,123 @@ function makeInstanceWithId( }; } +describe('instantiateAppNodeTree', () => { + it('should instantiate a single node', () => { + const graph = buildAppGraph( + [{ ...makeSpec(simpleExtension), id: 'root-node' }], + 'root-node', + ); + expect(graph.root.instance).not.toBeDefined(); + instantiateAppNodeTree(graph.root); + expect(graph.root.instance).toBeDefined(); + expect(graph.root.instance?.getData(testDataRef)).toBe('test'); + + // Multiple calls should have no effect + instantiateAppNodeTree(graph.root); + expect(graph.root.instance).toBeDefined(); + }); + + it('should not instantiate disabled nodes', () => { + const graph = buildAppGraph( + [{ ...makeSpec(simpleExtension), id: 'root-node', disabled: true }], + 'root-node', + ); + expect(graph.root.instance).not.toBeDefined(); + instantiateAppNodeTree(graph.root); + expect(graph.root.instance).not.toBeDefined(); + }); + + it('should instantiate a node with attachments', () => { + const graph = buildAppGraph( + [ + { + ...makeSpec( + createExtension({ + id: 'root-node', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + test: createExtensionInput({ test: testDataRef }), + }, + output: { + inputMirror: inputMirrorDataRef, + }, + factory({ bind, inputs }) { + bind({ inputMirror: inputs }); + }, + }), + ), + }, + { + ...makeSpec(simpleExtension), + id: 'child-node', + attachTo: { id: 'root-node', input: 'test' }, + }, + ], + 'root-node', + ); + + const childNode = graph.nodes.get('child-node'); + expect(childNode).toBeDefined(); + + expect(graph.root.instance).not.toBeDefined(); + expect(childNode?.instance).not.toBeDefined(); + instantiateAppNodeTree(graph.root); + expect(graph.root.instance).toBeDefined(); + expect(childNode?.instance).toBeDefined(); + expect(graph.root.instance?.getData(inputMirrorDataRef)).toEqual({ + test: [{ test: 'test' }], + }); + + // Multiple calls should have no effect + instantiateAppNodeTree(graph.root); + expect(graph.root.instance).toBeDefined(); + expect(childNode?.instance).toBeDefined(); + }); + + it('should not instantiate disabled attachments', () => { + const graph = buildAppGraph( + [ + { + ...makeSpec( + createExtension({ + id: 'root-node', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + test: createExtensionInput({ test: testDataRef }), + }, + output: { + inputMirror: inputMirrorDataRef, + }, + factory({ bind, inputs }) { + bind({ inputMirror: inputs }); + }, + }), + ), + }, + { + ...makeSpec(simpleExtension), + id: 'child-node', + attachTo: { id: 'root-node', input: 'test' }, + disabled: true, + }, + ], + 'root-node', + ); + + const childNode = graph.nodes.get('child-node'); + expect(childNode).toBeDefined(); + + expect(graph.root.instance).not.toBeDefined(); + expect(childNode?.instance).not.toBeDefined(); + instantiateAppNodeTree(graph.root); + expect(graph.root.instance).toBeDefined(); + expect(childNode?.instance).not.toBeDefined(); + expect(graph.root.instance?.getData(inputMirrorDataRef)).toEqual({ + test: [], + }); + }); +}); + describe('createAppNodeInstance', () => { it('should create a simple extension instance', () => { const attachments = new Map(); From 65b6a918944c7120b7ae69c218002b0e6699f6c5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 13:02:12 +0200 Subject: [PATCH 226/348] frontend-app-api: rename buildAppGraph -> resolveAppGraph Signed-off-by: Patrik Oldsberg --- .../src/wiring/graph/instantiateAppNodeTree.test.ts | 10 +++++----- ...buildAppGraph.test.ts => resolveAppGraph.test.ts} | 12 ++++++------ .../graph/{buildAppGraph.ts => resolveAppGraph.ts} | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) rename packages/frontend-app-api/src/wiring/graph/{buildAppGraph.test.ts => resolveAppGraph.test.ts} (93%) rename packages/frontend-app-api/src/wiring/graph/{buildAppGraph.ts => resolveAppGraph.ts} (99%) diff --git a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts index 43aad4f9ae..7bffc69c7c 100644 --- a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts +++ b/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts @@ -26,7 +26,7 @@ import { instantiateAppNodeTree, } from './instantiateAppNodeTree'; import { AppNodeInstance, AppNodeSpec } from './types'; -import { buildAppGraph } from './buildAppGraph'; +import { resolveAppGraph } from './resolveAppGraph'; const testDataRef = createExtensionDataRef('test'); const otherDataRef = createExtensionDataRef('other'); @@ -79,7 +79,7 @@ function makeInstanceWithId( describe('instantiateAppNodeTree', () => { it('should instantiate a single node', () => { - const graph = buildAppGraph( + const graph = resolveAppGraph( [{ ...makeSpec(simpleExtension), id: 'root-node' }], 'root-node', ); @@ -94,7 +94,7 @@ describe('instantiateAppNodeTree', () => { }); it('should not instantiate disabled nodes', () => { - const graph = buildAppGraph( + const graph = resolveAppGraph( [{ ...makeSpec(simpleExtension), id: 'root-node', disabled: true }], 'root-node', ); @@ -104,7 +104,7 @@ describe('instantiateAppNodeTree', () => { }); it('should instantiate a node with attachments', () => { - const graph = buildAppGraph( + const graph = resolveAppGraph( [ { ...makeSpec( @@ -151,7 +151,7 @@ describe('instantiateAppNodeTree', () => { }); it('should not instantiate disabled attachments', () => { - const graph = buildAppGraph( + const graph = resolveAppGraph( [ { ...makeSpec( diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts b/packages/frontend-app-api/src/wiring/graph/resolveAppGraph.test.ts similarity index 93% rename from packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts rename to packages/frontend-app-api/src/wiring/graph/resolveAppGraph.test.ts index 8cf8279e96..2d1acbbc04 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts +++ b/packages/frontend-app-api/src/wiring/graph/resolveAppGraph.test.ts @@ -15,7 +15,7 @@ */ import { createExtension } from '@backstage/frontend-plugin-api'; -import { buildAppGraph } from './buildAppGraph'; +import { resolveAppGraph } from './resolveAppGraph'; const extBaseConfig = { id: 'test', @@ -34,13 +34,13 @@ const baseSpec = { describe('buildAppGraph', () => { it('should fail to create an empty graph', () => { - expect(() => buildAppGraph([])).toThrow( + expect(() => resolveAppGraph([])).toThrow( "No root node with id 'core' found in app graph", ); }); it('should create a graph with only one node', () => { - const graph = buildAppGraph([{ ...baseSpec, id: 'core' }]); + const graph = resolveAppGraph([{ ...baseSpec, id: 'core' }]); expect(graph.root).toEqual({ spec: { ...baseSpec, id: 'core' }, edges: { attachments: new Map() }, @@ -50,7 +50,7 @@ describe('buildAppGraph', () => { }); it('should create a graph', () => { - const graph = buildAppGraph( + const graph = resolveAppGraph( [ { ...baseSpec, id: 'a' }, { ...baseSpec, id: 'b' }, @@ -116,7 +116,7 @@ describe('buildAppGraph', () => { }); it('should create a graph out of order', () => { - const graph = buildAppGraph( + const graph = resolveAppGraph( [ { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, { ...baseSpec, id: 'a' }, @@ -163,7 +163,7 @@ describe('buildAppGraph', () => { it('throws an error when duplicated extensions are detected', () => { expect(() => - buildAppGraph([ + resolveAppGraph([ { ...baseSpec, id: 'a' }, { ...baseSpec, id: 'a' }, ]), diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts b/packages/frontend-app-api/src/wiring/graph/resolveAppGraph.ts similarity index 99% rename from packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts rename to packages/frontend-app-api/src/wiring/graph/resolveAppGraph.ts index 06347b1ece..18f481fa30 100644 --- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts +++ b/packages/frontend-app-api/src/wiring/graph/resolveAppGraph.ts @@ -87,7 +87,7 @@ class SerializableAppNode implements AppNode { * tree with all attachments in the same order as they appear in the input specs array. * @internal */ -export function buildAppGraph( +export function resolveAppGraph( specs: AppNodeSpec[], rootNodeId = 'core', ): AppGraph { From 90b9ef567d88a2127568a39a6d4303f06dadb142 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 13:05:48 +0200 Subject: [PATCH 227/348] frontend-app-api: add createAppGraph Signed-off-by: Patrik Oldsberg --- .../src/wiring/graph/createAppGraph.ts | 47 +++++++++++++++++++ .../src/wiring/graph/index.ts | 1 + 2 files changed, 48 insertions(+) create mode 100644 packages/frontend-app-api/src/wiring/graph/createAppGraph.ts diff --git a/packages/frontend-app-api/src/wiring/graph/createAppGraph.ts b/packages/frontend-app-api/src/wiring/graph/createAppGraph.ts new file mode 100644 index 0000000000..4c08b7c5b4 --- /dev/null +++ b/packages/frontend-app-api/src/wiring/graph/createAppGraph.ts @@ -0,0 +1,47 @@ +/* + * Copyright 2023 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 { + BackstagePlugin, + Extension, + ExtensionOverrides, +} from '@backstage/frontend-plugin-api'; +import { readAppExtensionsConfig } from './readAppExtensionsConfig'; +import { resolveAppGraph } from './resolveAppGraph'; +import { resolveAppNodeSpecs } from './resolveAppNodeSpecs'; +import { AppGraph } from './types'; +import { Config } from '@backstage/config'; +import { instantiateAppNodeTree } from './instantiateAppNodeTree'; + +/** @internal */ +export interface CreateAppGraphOptions { + features: (BackstagePlugin | ExtensionOverrides)[]; + builtinExtensions: Extension[]; + config: Config; +} + +/** @internal */ +export function createAppGraph(options: CreateAppGraphOptions): AppGraph { + const appGraph = resolveAppGraph( + resolveAppNodeSpecs({ + features: options.features, + builtinExtensions: options.builtinExtensions, + parameters: readAppExtensionsConfig(options.config), + }), + ); + instantiateAppNodeTree(appGraph.root); + return appGraph; +} diff --git a/packages/frontend-app-api/src/wiring/graph/index.ts b/packages/frontend-app-api/src/wiring/graph/index.ts index 608ecb7675..4a3b54dffb 100644 --- a/packages/frontend-app-api/src/wiring/graph/index.ts +++ b/packages/frontend-app-api/src/wiring/graph/index.ts @@ -20,3 +20,4 @@ export type { AppNodeInstance, AppNodeSpec, } from './types'; +export { createAppGraph } from './createAppGraph'; From eb7c037e6fb93a782a367fb3d48e1ac45007328e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 13:07:15 +0200 Subject: [PATCH 228/348] frontend-app-api: fix AppNodeInstance.getData return type Signed-off-by: Patrik Oldsberg --- packages/frontend-app-api/src/wiring/graph/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts index b828c9762e..6e205db9dd 100644 --- a/packages/frontend-app-api/src/wiring/graph/types.ts +++ b/packages/frontend-app-api/src/wiring/graph/types.ts @@ -48,7 +48,7 @@ export interface AppNodeEdges { */ export interface AppNodeInstance { getDataRefs(): Iterable>; - getData(ref: ExtensionDataRef): T | unknown; + getData(ref: ExtensionDataRef): T | undefined; } /** From fd6dd7c079ad4f82377e3cf3a27c56a35c50c285 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 13:13:08 +0200 Subject: [PATCH 229/348] frontend-app-api: migrate extractRouteInfoFromInstanceTree to app graph Signed-off-by: Patrik Oldsberg --- .../extractRouteInfoFromInstanceTree.test.ts | 11 ++++++++--- .../extractRouteInfoFromInstanceTree.ts | 18 +++++++++--------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts index 0de33b50f2..d990d998b9 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts @@ -27,8 +27,12 @@ import { createPlugin, createRouteRef, } from '@backstage/frontend-plugin-api'; -import { createInstances } from '../wiring/createApp'; import { MockConfigApi } from '@backstage/test-utils'; +import { createAppGraph } from '../wiring/graph'; +import { Core } from '../extensions/Core'; +import { CoreRoutes } from '../extensions/CoreRoutes'; +import { CoreNav } from '../extensions/CoreNav'; +import { CoreLayout } from '../extensions/CoreLayout'; const ref1 = createRouteRef(); const ref2 = createRouteRef(); @@ -73,12 +77,13 @@ function routeInfoFromExtensions(extensions: Extension[]) { id: 'test', extensions, }); - const { coreInstance } = createInstances({ + const graph = createAppGraph({ config: new MockConfigApi({}), + builtinExtensions: [Core, CoreRoutes, CoreNav, CoreLayout], features: [plugin], }); - return extractRouteInfoFromInstanceTree(coreInstance); + return extractRouteInfoFromInstanceTree(graph.root); } function sortedEntries(map: Map): [RouteRef, T][] { diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts index fadcb719b9..16e0e7d8ec 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts @@ -15,10 +15,10 @@ */ import { RouteRef, coreExtensionData } from '@backstage/frontend-plugin-api'; -import { ExtensionInstance } from '../wiring/graph/createExtensionInstance'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toLegacyPlugin } from '../wiring/createApp'; import { BackstageRouteObject } from './types'; +import { AppNode } from '../wiring/graph'; // We always add a child that matches all subroutes but without any route refs. This makes // sure that we're always able to match each route no matter how deep the navigation goes. @@ -41,7 +41,7 @@ export function joinPaths(...paths: string[]): string { return normalized; } -export function extractRouteInfoFromInstanceTree(core: ExtensionInstance): { +export function extractRouteInfoFromInstanceTree(core: AppNode): { routePaths: Map; routeParents: Map; routeObjects: BackstageRouteObject[]; @@ -56,17 +56,17 @@ export function extractRouteInfoFromInstanceTree(core: ExtensionInstance): { const routeObjects = new Array(); function visit( - current: ExtensionInstance, + current: AppNode, collectedPath?: string, foundRefForCollectedPath: boolean = false, parentRef?: RouteRef, candidateParentRef?: RouteRef, parentObj?: BackstageRouteObject, ) { - const routePath = current - .getData(coreExtensionData.routePath) + const routePath = current.instance + ?.getData(coreExtensionData.routePath) ?.replace(/^\//, ''); - const routeRef = current.getData(coreExtensionData.routeRef); + const routeRef = current.instance?.getData(coreExtensionData.routeRef); const parentChildren = parentObj?.children ?? routeObjects; let currentObj = parentObj; @@ -124,12 +124,12 @@ export function extractRouteInfoFromInstanceTree(core: ExtensionInstance): { routeParents.set(routeRef, newParentRef); currentObj?.routeRefs.add(routeRef); - if (current.source) { - currentObj?.plugins.add(toLegacyPlugin(current.source)); + if (current.spec.source) { + currentObj?.plugins.add(toLegacyPlugin(current.spec.source)); } } - for (const children of current.attachments.values()) { + for (const children of current.edges.attachments.values()) { for (const child of children) { visit( child, From ea262277488df2e3b5b27dea9bfe42948176b381 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 13:17:09 +0200 Subject: [PATCH 230/348] frontend-app-api: rename extractRouteInfoFromInstanceTree -> extractRouteInfoFromAppNode Signed-off-by: Patrik Oldsberg --- packages/frontend-app-api/src/routing/RouteResolver.test.ts | 2 +- ...stanceTree.test.ts => extractRouteInfoFromAppNode.test.ts} | 4 ++-- ...InfoFromInstanceTree.ts => extractRouteInfoFromAppNode.ts} | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename packages/frontend-app-api/src/routing/{extractRouteInfoFromInstanceTree.test.ts => extractRouteInfoFromAppNode.test.ts} (98%) rename packages/frontend-app-api/src/routing/{extractRouteInfoFromInstanceTree.ts => extractRouteInfoFromAppNode.ts} (98%) diff --git a/packages/frontend-app-api/src/routing/RouteResolver.test.ts b/packages/frontend-app-api/src/routing/RouteResolver.test.ts index e37ee14929..81e9d10be4 100644 --- a/packages/frontend-app-api/src/routing/RouteResolver.test.ts +++ b/packages/frontend-app-api/src/routing/RouteResolver.test.ts @@ -24,7 +24,7 @@ import { } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { RouteResolver } from './RouteResolver'; -import { MATCH_ALL_ROUTE } from './extractRouteInfoFromInstanceTree'; +import { MATCH_ALL_ROUTE } from './extractRouteInfoFromAppNode'; const rest = { element: null, diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts similarity index 98% rename from packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts rename to packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts index d990d998b9..2eab3c8e7a 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts @@ -16,7 +16,7 @@ import React from 'react'; import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { extractRouteInfoFromInstanceTree } from './extractRouteInfoFromInstanceTree'; +import { extractRouteInfoFromAppNode } from './extractRouteInfoFromAppNode'; import { AnyRouteRefParams, Extension, @@ -83,7 +83,7 @@ function routeInfoFromExtensions(extensions: Extension[]) { features: [plugin], }); - return extractRouteInfoFromInstanceTree(graph.root); + return extractRouteInfoFromAppNode(graph.root); } function sortedEntries(map: Map): [RouteRef, T][] { diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts similarity index 98% rename from packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts rename to packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts index 16e0e7d8ec..1ecb28113b 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts @@ -41,7 +41,7 @@ export function joinPaths(...paths: string[]): string { return normalized; } -export function extractRouteInfoFromInstanceTree(core: AppNode): { +export function extractRouteInfoFromAppNode(node: AppNode): { routePaths: Map; routeParents: Map; routeObjects: BackstageRouteObject[]; @@ -143,7 +143,7 @@ export function extractRouteInfoFromInstanceTree(core: AppNode): { } } - visit(core); + visit(node); return { routePaths, routeParents, routeObjects }; } From fcf1b80beda4edbcffc1b906b50d69e47f9eb219 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 13:26:56 +0200 Subject: [PATCH 231/348] frontend-app-api: migrate createApp to use createAppGraph Signed-off-by: Patrik Oldsberg --- .../frontend-app-api/src/wiring/createApp.tsx | 150 +++++------------- 1 file changed, 44 insertions(+), 106 deletions(-) diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index 485882c8eb..1dbfb3912b 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -28,11 +28,6 @@ import { Core } from '../extensions/Core'; import { CoreRoutes } from '../extensions/CoreRoutes'; import { CoreLayout } from '../extensions/CoreLayout'; import { CoreNav } from '../extensions/CoreNav'; -import { - createExtensionInstance, - ExtensionInstance, -} from './graph/createExtensionInstance'; -import { resolveAppNodeSpecs } from './graph/resolveAppNodeSpecs'; import { AnyApiFactory, ApiHolder, @@ -82,7 +77,7 @@ import { import { BrowserRouter, Route } from 'react-router-dom'; import { SidebarItem } from '@backstage/core-components'; import { DarkTheme, LightTheme } from '../extensions/themes'; -import { extractRouteInfoFromInstanceTree } from '../routing/extractRouteInfoFromInstanceTree'; +import { extractRouteInfoFromAppNode } from '../routing/extractRouteInfoFromAppNode'; import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; import { appLanguageApiRef, @@ -92,8 +87,16 @@ import { AppRouteBinder } from '../routing'; import { RoutingProvider } from '../routing/RoutingProvider'; import { resolveRouteBindings } from '../routing/resolveRouteBindings'; import { collectRouteIds } from '../routing/collectRouteIds'; -import { readAppExtensionsConfig } from './graph/readAppExtensionsConfig'; -import { AppNodeSpec } from './graph'; +import { AppNode, createAppGraph } from './graph'; + +const builtinExtensions = [ + Core, + CoreRoutes, + CoreNav, + CoreLayout, + LightTheme, + DarkTheme, +]; /** @public */ export interface ExtensionTreeNode { @@ -114,20 +117,38 @@ export function createExtensionTree(options: { config: Config; }): ExtensionTree { const features = getAvailableFeatures(options.config); - const { instances } = createInstances({ + const graph = createAppGraph({ features, + builtinExtensions, config: options.config, }); + function convertNode(node?: AppNode): ExtensionTreeNode | undefined { + return ( + node && { + id: node.spec.id, + getData(ref: ExtensionDataRef): T | undefined { + return node.instance?.getData(ref); + }, + } + ); + } + return { getExtension(id: string): ExtensionTreeNode | undefined { - return instances.get(id); + return convertNode(graph.nodes.get(id)); }, getExtensionAttachments( id: string, inputName: string, ): ExtensionTreeNode[] { - return instances.get(id)?.attachments.get(inputName) ?? []; + return ( + graph.nodes + .get(id) + ?.edges.attachments.get(inputName) + ?.map(convertNode) + .filter((node): node is ExtensionTreeNode => Boolean(node)) ?? [] + ); }, getRootRoutes(): JSX.Element[] { return this.getExtensionAttachments('core.routes', 'routes').map(node => { @@ -177,89 +198,6 @@ export function createExtensionTree(options: { }; } -/** - * @internal - */ -export function createInstances(options: { - features: (BackstagePlugin | ExtensionOverrides)[]; - config: Config; -}) { - const builtinExtensions = [ - Core, - CoreRoutes, - CoreNav, - CoreLayout, - LightTheme, - DarkTheme, - ]; - - // pull in default extension instance from discovered packages - // apply config to adjust default extension instances and add more - const appNodeSpecs = resolveAppNodeSpecs({ - features: options.features, - builtinExtensions, - parameters: readAppExtensionsConfig(options.config), - }); - - // TODO: validate the config of all extension instances - // We do it at this point to ensure that merging (if any) of config has already happened - - // Create attachment map so that we can look attachments up during instance creation - const attachmentMap = new Map>(); - for (const instanceParams of appNodeSpecs) { - const extensionId = instanceParams.attachTo.id; - const pointId = instanceParams.attachTo.input; - let pointMap = attachmentMap.get(extensionId); - if (!pointMap) { - pointMap = new Map(); - attachmentMap.set(extensionId, pointMap); - } - - let instances = pointMap.get(pointId); - if (!instances) { - instances = []; - pointMap.set(pointId, instances); - } - - instances.push(instanceParams); - } - - const instances = new Map(); - - function createInstance(instanceParams: AppNodeSpec): ExtensionInstance { - const extensionId = instanceParams.extension.id; - const existingInstance = instances.get(extensionId); - if (existingInstance) { - return existingInstance; - } - - const attachments = new Map( - Array.from(attachmentMap.get(extensionId)?.entries() ?? []).map( - ([inputName, attachmentConfigs]) => { - return [inputName, attachmentConfigs.map(createInstance)]; - }, - ), - ); - - const newInstance = createExtensionInstance({ - extension: instanceParams.extension, - source: instanceParams.source, - config: instanceParams.config, - attachments, - }); - - instances.set(extensionId, newInstance); - - return newInstance; - } - - const coreInstance = createInstance( - appNodeSpecs.find(p => p.extension.id === 'core')!, - ); - - return { coreInstance, instances }; -} - function deduplicateFeatures( allFeatures: (BackstagePlugin | ExtensionOverrides)[], ): (BackstagePlugin | ExtensionOverrides)[] { @@ -309,8 +247,9 @@ export function createApp(options: { ...(options.features ?? []), ]); - const { coreInstance } = createInstances({ + const appGraph = createAppGraph({ features: allFeatures, + builtinExtensions, config, }); @@ -323,11 +262,11 @@ export function createApp(options: { const routeIds = collectRouteIds(allFeatures); const App = () => ( - + {/* TODO: set base path using the logic from AppRouter */} - {coreInstance.getData(coreExtensionData.reactElement)} + {appGraph.root.instance!.getData( + coreExtensionData.reactElement, + )} @@ -417,22 +358,19 @@ function createLegacyAppContext(plugins: BackstagePlugin[]): AppContext { }; } -function createApiHolder( - coreExtension: ExtensionInstance, - configApi: ConfigApi, -): ApiHolder { +function createApiHolder(core: AppNode, configApi: ConfigApi): ApiHolder { const factoryRegistry = new ApiFactoryRegistry(); const pluginApis = - coreExtension.attachments + core.edges.attachments .get('apis') - ?.map(e => e.getData(coreExtensionData.apiFactory)) + ?.map(e => e.instance?.getData(coreExtensionData.apiFactory)) .filter((x): x is AnyApiFactory => !!x) ?? []; const themeExtensions = - coreExtension.attachments + core.edges.attachments .get('themes') - ?.map(e => e.getData(coreExtensionData.theme)) + ?.map(e => e.instance?.getData(coreExtensionData.theme)) .filter((x): x is AppTheme => !!x) ?? []; for (const factory of [...defaultApis, ...pluginApis]) { From 6473b37182161d76e0a3b006dae7ef42a87ce8f4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 13:28:54 +0200 Subject: [PATCH 232/348] frontend-app-api: move graph/ to top level Signed-off-by: Patrik Oldsberg --- .../frontend-app-api/src/{wiring => }/graph/createAppGraph.ts | 0 packages/frontend-app-api/src/{wiring => }/graph/index.ts | 0 .../src/{wiring => }/graph/instantiateAppNodeTree.test.ts | 0 .../src/{wiring => }/graph/instantiateAppNodeTree.ts | 0 .../src/{wiring => }/graph/readAppExtensionsConfig.test.ts | 0 .../src/{wiring => }/graph/readAppExtensionsConfig.ts | 0 .../src/{wiring => }/graph/resolveAppGraph.test.ts | 0 .../frontend-app-api/src/{wiring => }/graph/resolveAppGraph.ts | 0 .../src/{wiring => }/graph/resolveAppNodeSpecs.test.ts | 0 .../src/{wiring => }/graph/resolveAppNodeSpecs.ts | 2 +- packages/frontend-app-api/src/{wiring => }/graph/types.ts | 0 .../src/routing/extractRouteInfoFromAppNode.test.ts | 2 +- .../frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts | 2 +- packages/frontend-app-api/src/wiring/createApp.tsx | 2 +- 14 files changed, 4 insertions(+), 4 deletions(-) rename packages/frontend-app-api/src/{wiring => }/graph/createAppGraph.ts (100%) rename packages/frontend-app-api/src/{wiring => }/graph/index.ts (100%) rename packages/frontend-app-api/src/{wiring => }/graph/instantiateAppNodeTree.test.ts (100%) rename packages/frontend-app-api/src/{wiring => }/graph/instantiateAppNodeTree.ts (100%) rename packages/frontend-app-api/src/{wiring => }/graph/readAppExtensionsConfig.test.ts (100%) rename packages/frontend-app-api/src/{wiring => }/graph/readAppExtensionsConfig.ts (100%) rename packages/frontend-app-api/src/{wiring => }/graph/resolveAppGraph.test.ts (100%) rename packages/frontend-app-api/src/{wiring => }/graph/resolveAppGraph.ts (100%) rename packages/frontend-app-api/src/{wiring => }/graph/resolveAppNodeSpecs.test.ts (100%) rename packages/frontend-app-api/src/{wiring => }/graph/resolveAppNodeSpecs.ts (98%) rename packages/frontend-app-api/src/{wiring => }/graph/types.ts (100%) diff --git a/packages/frontend-app-api/src/wiring/graph/createAppGraph.ts b/packages/frontend-app-api/src/graph/createAppGraph.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/createAppGraph.ts rename to packages/frontend-app-api/src/graph/createAppGraph.ts diff --git a/packages/frontend-app-api/src/wiring/graph/index.ts b/packages/frontend-app-api/src/graph/index.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/index.ts rename to packages/frontend-app-api/src/graph/index.ts diff --git a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts b/packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.test.ts rename to packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts diff --git a/packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts b/packages/frontend-app-api/src/graph/instantiateAppNodeTree.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/instantiateAppNodeTree.ts rename to packages/frontend-app-api/src/graph/instantiateAppNodeTree.ts diff --git a/packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.test.ts b/packages/frontend-app-api/src/graph/readAppExtensionsConfig.test.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.test.ts rename to packages/frontend-app-api/src/graph/readAppExtensionsConfig.test.ts diff --git a/packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.ts b/packages/frontend-app-api/src/graph/readAppExtensionsConfig.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/readAppExtensionsConfig.ts rename to packages/frontend-app-api/src/graph/readAppExtensionsConfig.ts diff --git a/packages/frontend-app-api/src/wiring/graph/resolveAppGraph.test.ts b/packages/frontend-app-api/src/graph/resolveAppGraph.test.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/resolveAppGraph.test.ts rename to packages/frontend-app-api/src/graph/resolveAppGraph.test.ts diff --git a/packages/frontend-app-api/src/wiring/graph/resolveAppGraph.ts b/packages/frontend-app-api/src/graph/resolveAppGraph.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/resolveAppGraph.ts rename to packages/frontend-app-api/src/graph/resolveAppGraph.ts diff --git a/packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.test.ts b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.test.ts rename to packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts diff --git a/packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts similarity index 98% rename from packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.ts rename to packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts index 8cad54f4be..51480117d7 100644 --- a/packages/frontend-app-api/src/wiring/graph/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts @@ -20,7 +20,7 @@ import { ExtensionOverrides, } from '@backstage/frontend-plugin-api'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { toInternalExtensionOverrides } from '../../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; +import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; import { ExtensionParameters } from './readAppExtensionsConfig'; import { AppNodeSpec } from './types'; diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/graph/types.ts similarity index 100% rename from packages/frontend-app-api/src/wiring/graph/types.ts rename to packages/frontend-app-api/src/graph/types.ts diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts index 2eab3c8e7a..e0adf3062a 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts @@ -28,7 +28,7 @@ import { createRouteRef, } from '@backstage/frontend-plugin-api'; import { MockConfigApi } from '@backstage/test-utils'; -import { createAppGraph } from '../wiring/graph'; +import { createAppGraph } from '../graph'; import { Core } from '../extensions/Core'; import { CoreRoutes } from '../extensions/CoreRoutes'; import { CoreNav } from '../extensions/CoreNav'; diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts index 1ecb28113b..71991ee44e 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts @@ -18,7 +18,7 @@ import { RouteRef, coreExtensionData } from '@backstage/frontend-plugin-api'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toLegacyPlugin } from '../wiring/createApp'; import { BackstageRouteObject } from './types'; -import { AppNode } from '../wiring/graph'; +import { AppNode } from '../graph'; // We always add a child that matches all subroutes but without any route refs. This makes // sure that we're always able to match each route no matter how deep the navigation goes. diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index 1dbfb3912b..4f7817314a 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -87,7 +87,7 @@ import { AppRouteBinder } from '../routing'; import { RoutingProvider } from '../routing/RoutingProvider'; import { resolveRouteBindings } from '../routing/resolveRouteBindings'; import { collectRouteIds } from '../routing/collectRouteIds'; -import { AppNode, createAppGraph } from './graph'; +import { AppNode, createAppGraph } from '../graph'; const builtinExtensions = [ Core, From 6d2258621f5e3ed4ef98e18d5478ca0e3ad9600d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 13:36:39 +0200 Subject: [PATCH 233/348] frontend-app-api: update resolveAppNodeSpecs tests Signed-off-by: Patrik Oldsberg --- .../src/graph/resolveAppNodeSpecs.test.ts | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts index 1d3c0a26ed..a3cda23113 100644 --- a/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts +++ b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts @@ -54,8 +54,18 @@ describe('resolveAppNodeSpecs', () => { parameters: [], }), ).toEqual([ - { extension: a, attachTo: { id: 'root', input: 'default' } }, - { extension: b, attachTo: { id: 'root', input: 'default' } }, + { + id: 'a', + extension: a, + attachTo: { id: 'root', input: 'default' }, + disabled: false, + }, + { + id: 'b', + extension: b, + attachTo: { id: 'root', input: 'default' }, + disabled: false, + }, ]); }); @@ -76,11 +86,18 @@ describe('resolveAppNodeSpecs', () => { }), ).toEqual([ { + id: 'a', extension: a, attachTo: { id: 'root', input: 'default' }, source: pluginA, + disabled: false, + }, + { + id: 'b', + extension: b, + attachTo: { id: 'derp', input: 'default' }, + disabled: false, }, - { extension: b, attachTo: { id: 'derp', input: 'default' } }, ]); }); @@ -109,16 +126,20 @@ describe('resolveAppNodeSpecs', () => { }), ).toEqual([ { + id: 'a', extension: a, attachTo: { id: 'root', input: 'default' }, source: plugin, config: { foo: { bar: 1 } }, + disabled: false, }, { + id: 'b', extension: b, attachTo: { id: 'root', input: 'default' }, source: plugin, config: { foo: { qux: 3 } }, + disabled: false, }, ]); }); @@ -142,8 +163,18 @@ describe('resolveAppNodeSpecs', () => { ], }), ).toEqual([ - { extension: b, attachTo: { id: 'root', input: 'default' } }, - { extension: a, attachTo: { id: 'root', input: 'default' } }, + { + id: 'b', + extension: b, + attachTo: { id: 'root', input: 'default' }, + disabled: false, + }, + { + id: 'a', + extension: a, + attachTo: { id: 'root', input: 'default' }, + disabled: false, + }, ]); }); @@ -173,10 +204,12 @@ describe('resolveAppNodeSpecs', () => { expect(result[0].source).toBe(plugin); expect(result[1]).toEqual({ + id: 'c', extension: cOverride, attachTo: { id: 'root', input: 'default' }, config: undefined, source: undefined, + disabled: false, }); }); From 5aad4f7720080956f4e646f8d029e14410f513bd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 13:37:07 +0200 Subject: [PATCH 234/348] frontend-app-api: no longer reject core extension configuration Signed-off-by: Patrik Oldsberg --- packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts index 51480117d7..d6cfcaede2 100644 --- a/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts @@ -164,13 +164,6 @@ export function resolveAppNodeSpecs(options: { for (const overrideParam of parameters) { const extensionId = overrideParam.id; - // Prevent core parametrization - if (extensionId === 'core') { - throw new Error( - "A 'core' extension configuration was detected, but the core extension is not configurable", - ); - } - const existingIndex = configuredExtensions.findIndex( e => e.extension.id === extensionId, ); From 89dc1250d86138f73b4b7e927e55c56b326291bc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 19:18:10 +0200 Subject: [PATCH 235/348] frontend-app-api: make it possible to configure which extensions are forbidden Signed-off-by: Patrik Oldsberg --- .../src/graph/createAppGraph.ts | 2 + .../src/graph/resolveAppNodeSpecs.test.ts | 41 +++++++++++++++++++ .../src/graph/resolveAppNodeSpecs.ts | 28 ++++++++----- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/packages/frontend-app-api/src/graph/createAppGraph.ts b/packages/frontend-app-api/src/graph/createAppGraph.ts index 4c08b7c5b4..cb72fa3cd1 100644 --- a/packages/frontend-app-api/src/graph/createAppGraph.ts +++ b/packages/frontend-app-api/src/graph/createAppGraph.ts @@ -40,7 +40,9 @@ export function createAppGraph(options: CreateAppGraphOptions): AppGraph { features: options.features, builtinExtensions: options.builtinExtensions, parameters: readAppExtensionsConfig(options.config), + forbidden: new Set(['core']), }), + 'core', ); instantiateAppNodeTree(appGraph.root); return appGraph; diff --git a/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts index a3cda23113..59930968c6 100644 --- a/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts +++ b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.test.ts @@ -234,4 +234,45 @@ describe('resolveAppNodeSpecs', () => { expect(result.map(r => r.extension.id)).toEqual(['b', 'c', 'a']); }); + + it('throws an error when a forbidden extension is overridden by a plugin', () => { + expect(() => + resolveAppNodeSpecs({ + features: [ + createPlugin({ id: 'test', extensions: [makeExt('forbidden')] }), + ], + builtinExtensions: [], + parameters: [], + forbidden: new Set(['forbidden']), + }), + ).toThrow( + "It is forbidden to override the following extension(s): 'forbidden', which is done by the following plugin(s): 'test'", + ); + }); + + it('throws an error when a forbidden extension is overridden by overrides', () => { + expect(() => + resolveAppNodeSpecs({ + features: [ + createExtensionOverrides({ extensions: [makeExt('forbidden')] }), + ], + builtinExtensions: [], + parameters: [], + forbidden: new Set(['forbidden']), + }), + ).toThrow( + "It is forbidden to override the following extension(s): 'forbidden', which is done by one or more extension overrides", + ); + }); + + it('throws an error when a forbidden extension is parametrized', () => { + expect(() => + resolveAppNodeSpecs({ + features: [], + builtinExtensions: [], + parameters: [{ id: 'forbidden', disabled: false }], + forbidden: new Set(['forbidden']), + }), + ).toThrow("Configuration of the 'forbidden' extension is forbidden"); + }); }); diff --git a/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts index d6cfcaede2..ca3c4fd1ea 100644 --- a/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/graph/resolveAppNodeSpecs.ts @@ -29,8 +29,9 @@ export function resolveAppNodeSpecs(options: { features: (BackstagePlugin | ExtensionOverrides)[]; builtinExtensions: Extension[]; parameters: Array; + forbidden?: Set; }): AppNodeSpec[] { - const { builtinExtensions, parameters } = options; + const { builtinExtensions, parameters, forbidden = new Set() } = options; const plugins = options.features.filter( (f): f is BackstagePlugin => f.$$type === '@backstage/BackstagePlugin', @@ -48,20 +49,21 @@ export function resolveAppNodeSpecs(options: { ); // Prevent core override - if (pluginExtensions.some(({ id }) => id === 'core')) { - const pluginIds = pluginExtensions - .filter(({ id }) => id === 'core') - .map(({ source }) => source.id); + if (pluginExtensions.some(({ id }) => forbidden.has(id))) { + const pluginsStr = pluginExtensions + .filter(({ id }) => forbidden.has(id)) + .map(({ source }) => `'${source.id}'`) + .join(', '); + const forbiddenStr = [...forbidden].map(id => `'${id}'`).join(', '); throw new Error( - `The following plugin(s) are overriding the 'core' extension which is forbidden: ${pluginIds.join( - ',', - )}`, + `It is forbidden to override the following extension(s): ${forbiddenStr}, which is done by the following plugin(s): ${pluginsStr}`, ); } - if (overrideExtensions.some(({ id }) => id === 'root')) { + if (overrideExtensions.some(({ id }) => forbidden.has(id))) { + const forbiddenStr = [...forbidden].map(id => `'${id}'`).join(', '); throw new Error( - `An extension override is overriding the 'root' extension which is forbidden`, + `It is forbidden to override the following extension(s): ${forbiddenStr}, which is done by one or more extension overrides`, ); } const overrideExtensionIds = overrideExtensions.map(({ id }) => id); @@ -164,6 +166,12 @@ export function resolveAppNodeSpecs(options: { for (const overrideParam of parameters) { const extensionId = overrideParam.id; + if (forbidden.has(extensionId)) { + throw new Error( + `Configuration of the '${extensionId}' extension is forbidden`, + ); + } + const existingIndex = configuredExtensions.findIndex( e => e.extension.id === extensionId, ); From ee39751fdffa80b0a6f0535ea520863887958fcf Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 19:20:12 +0200 Subject: [PATCH 236/348] frontend-app-api: make rootNodeId required in resolveAppGraph Signed-off-by: Patrik Oldsberg --- .../src/graph/createAppGraph.ts | 2 +- .../src/graph/instantiateAppNodeTree.test.ts | 118 ++++++++---------- .../src/graph/resolveAppGraph.test.ts | 48 ++++--- .../src/graph/resolveAppGraph.ts | 2 +- 4 files changed, 78 insertions(+), 92 deletions(-) diff --git a/packages/frontend-app-api/src/graph/createAppGraph.ts b/packages/frontend-app-api/src/graph/createAppGraph.ts index cb72fa3cd1..ace8595f53 100644 --- a/packages/frontend-app-api/src/graph/createAppGraph.ts +++ b/packages/frontend-app-api/src/graph/createAppGraph.ts @@ -36,13 +36,13 @@ export interface CreateAppGraphOptions { /** @internal */ export function createAppGraph(options: CreateAppGraphOptions): AppGraph { const appGraph = resolveAppGraph( + 'core', resolveAppNodeSpecs({ features: options.features, builtinExtensions: options.builtinExtensions, parameters: readAppExtensionsConfig(options.config), forbidden: new Set(['core']), }), - 'core', ); instantiateAppNodeTree(appGraph.root); return appGraph; diff --git a/packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts b/packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts index 7bffc69c7c..21f364dda2 100644 --- a/packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts +++ b/packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts @@ -79,10 +79,9 @@ function makeInstanceWithId( describe('instantiateAppNodeTree', () => { it('should instantiate a single node', () => { - const graph = resolveAppGraph( - [{ ...makeSpec(simpleExtension), id: 'root-node' }], - 'root-node', - ); + const graph = resolveAppGraph('root-node', [ + { ...makeSpec(simpleExtension), id: 'root-node' }, + ]); expect(graph.root.instance).not.toBeDefined(); instantiateAppNodeTree(graph.root); expect(graph.root.instance).toBeDefined(); @@ -94,43 +93,39 @@ describe('instantiateAppNodeTree', () => { }); it('should not instantiate disabled nodes', () => { - const graph = resolveAppGraph( - [{ ...makeSpec(simpleExtension), id: 'root-node', disabled: true }], - 'root-node', - ); + const graph = resolveAppGraph('root-node', [ + { ...makeSpec(simpleExtension), id: 'root-node', disabled: true }, + ]); expect(graph.root.instance).not.toBeDefined(); instantiateAppNodeTree(graph.root); expect(graph.root.instance).not.toBeDefined(); }); it('should instantiate a node with attachments', () => { - const graph = resolveAppGraph( - [ - { - ...makeSpec( - createExtension({ - id: 'root-node', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - test: createExtensionInput({ test: testDataRef }), - }, - output: { - inputMirror: inputMirrorDataRef, - }, - factory({ bind, inputs }) { - bind({ inputMirror: inputs }); - }, - }), - ), - }, - { - ...makeSpec(simpleExtension), - id: 'child-node', - attachTo: { id: 'root-node', input: 'test' }, - }, - ], - 'root-node', - ); + const graph = resolveAppGraph('root-node', [ + { + ...makeSpec( + createExtension({ + id: 'root-node', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + test: createExtensionInput({ test: testDataRef }), + }, + output: { + inputMirror: inputMirrorDataRef, + }, + factory({ bind, inputs }) { + bind({ inputMirror: inputs }); + }, + }), + ), + }, + { + ...makeSpec(simpleExtension), + id: 'child-node', + attachTo: { id: 'root-node', input: 'test' }, + }, + ]); const childNode = graph.nodes.get('child-node'); expect(childNode).toBeDefined(); @@ -151,34 +146,31 @@ describe('instantiateAppNodeTree', () => { }); it('should not instantiate disabled attachments', () => { - const graph = resolveAppGraph( - [ - { - ...makeSpec( - createExtension({ - id: 'root-node', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - test: createExtensionInput({ test: testDataRef }), - }, - output: { - inputMirror: inputMirrorDataRef, - }, - factory({ bind, inputs }) { - bind({ inputMirror: inputs }); - }, - }), - ), - }, - { - ...makeSpec(simpleExtension), - id: 'child-node', - attachTo: { id: 'root-node', input: 'test' }, - disabled: true, - }, - ], - 'root-node', - ); + const graph = resolveAppGraph('root-node', [ + { + ...makeSpec( + createExtension({ + id: 'root-node', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + test: createExtensionInput({ test: testDataRef }), + }, + output: { + inputMirror: inputMirrorDataRef, + }, + factory({ bind, inputs }) { + bind({ inputMirror: inputs }); + }, + }), + ), + }, + { + ...makeSpec(simpleExtension), + id: 'child-node', + attachTo: { id: 'root-node', input: 'test' }, + disabled: true, + }, + ]); const childNode = graph.nodes.get('child-node'); expect(childNode).toBeDefined(); diff --git a/packages/frontend-app-api/src/graph/resolveAppGraph.test.ts b/packages/frontend-app-api/src/graph/resolveAppGraph.test.ts index 2d1acbbc04..2668c51863 100644 --- a/packages/frontend-app-api/src/graph/resolveAppGraph.test.ts +++ b/packages/frontend-app-api/src/graph/resolveAppGraph.test.ts @@ -34,13 +34,13 @@ const baseSpec = { describe('buildAppGraph', () => { it('should fail to create an empty graph', () => { - expect(() => resolveAppGraph([])).toThrow( + expect(() => resolveAppGraph('core', [])).toThrow( "No root node with id 'core' found in app graph", ); }); it('should create a graph with only one node', () => { - const graph = resolveAppGraph([{ ...baseSpec, id: 'core' }]); + const graph = resolveAppGraph('core', [{ ...baseSpec, id: 'core' }]); expect(graph.root).toEqual({ spec: { ...baseSpec, id: 'core' }, edges: { attachments: new Map() }, @@ -50,18 +50,15 @@ describe('buildAppGraph', () => { }); it('should create a graph', () => { - const graph = resolveAppGraph( - [ - { ...baseSpec, id: 'a' }, - { ...baseSpec, id: 'b' }, - { ...baseSpec, id: 'c' }, - { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, - { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, - { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, - { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, - ], - 'b', - ); + const graph = resolveAppGraph('b', [ + { ...baseSpec, id: 'a' }, + { ...baseSpec, id: 'b' }, + { ...baseSpec, id: 'c' }, + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, + { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, + { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, + ]); expect(Array.from(graph.nodes.keys())).toEqual([ 'a', @@ -116,18 +113,15 @@ describe('buildAppGraph', () => { }); it('should create a graph out of order', () => { - const graph = resolveAppGraph( - [ - { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, - { ...baseSpec, id: 'a' }, - { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, - { ...baseSpec, id: 'b' }, - { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, - { ...baseSpec, id: 'c' }, - { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, - ], - 'b', - ); + const graph = resolveAppGraph('b', [ + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx2' }, + { ...baseSpec, id: 'a' }, + { ...baseSpec, attachTo: { id: 'b', input: 'y' }, id: 'by1' }, + { ...baseSpec, id: 'b' }, + { ...baseSpec, attachTo: { id: 'b', input: 'x' }, id: 'bx1' }, + { ...baseSpec, id: 'c' }, + { ...baseSpec, attachTo: { id: 'd', input: 'x' }, id: 'dx1' }, + ]); expect(Array.from(graph.nodes.keys())).toEqual([ 'bx2', @@ -163,7 +157,7 @@ describe('buildAppGraph', () => { it('throws an error when duplicated extensions are detected', () => { expect(() => - resolveAppGraph([ + resolveAppGraph('core', [ { ...baseSpec, id: 'a' }, { ...baseSpec, id: 'a' }, ]), diff --git a/packages/frontend-app-api/src/graph/resolveAppGraph.ts b/packages/frontend-app-api/src/graph/resolveAppGraph.ts index 18f481fa30..354b4c53ee 100644 --- a/packages/frontend-app-api/src/graph/resolveAppGraph.ts +++ b/packages/frontend-app-api/src/graph/resolveAppGraph.ts @@ -88,8 +88,8 @@ class SerializableAppNode implements AppNode { * @internal */ export function resolveAppGraph( + rootNodeId: string, specs: AppNodeSpec[], - rootNodeId = 'core', ): AppGraph { const nodes = new Map(); From d2e2b01ae1fa93b21eb66d0ba1cf4b655f6228a8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 19:25:52 +0200 Subject: [PATCH 237/348] frontend-app-api: move some createApp tests to createAppGraph Signed-off-by: Patrik Oldsberg --- .../src/graph/createAppGraph.test.ts | 123 +++++++++++ .../src/wiring/createApp.test.tsx | 194 +----------------- 2 files changed, 124 insertions(+), 193 deletions(-) create mode 100644 packages/frontend-app-api/src/graph/createAppGraph.test.ts diff --git a/packages/frontend-app-api/src/graph/createAppGraph.test.ts b/packages/frontend-app-api/src/graph/createAppGraph.test.ts new file mode 100644 index 0000000000..2c9f062199 --- /dev/null +++ b/packages/frontend-app-api/src/graph/createAppGraph.test.ts @@ -0,0 +1,123 @@ +/* + * Copyright 2023 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 { + createExtension, + createExtensionOverrides, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { MockConfigApi } from '@backstage/test-utils'; +import { createAppGraph } from './createAppGraph'; + +const extBase = { + id: 'test', + attachTo: { id: 'core', input: 'root' }, + output: {}, + factory() {}, +}; + +describe('createAppGraph', () => { + it('throws an error when a core extension is parametrized', () => { + const config = new MockConfigApi({ + app: { + extensions: [ + { + core: {}, + }, + ], + }, + }); + const features = [ + createPlugin({ + id: 'plugin', + extensions: [], + }), + ]; + expect(() => + createAppGraph({ features, config, builtinExtensions: [] }), + ).toThrow("Configuration of the 'core' extension is forbidden"); + }); + + it('throws an error when a core extension is overridden', () => { + const config = new MockConfigApi({}); + const features = [ + createPlugin({ + id: 'plugin', + extensions: [ + createExtension({ + id: 'core', + attachTo: { id: 'core.routes', input: 'route' }, + inputs: {}, + output: {}, + factory() {}, + }), + ], + }), + ]; + expect(() => + createAppGraph({ features, config, builtinExtensions: [] }), + ).toThrow( + "It is forbidden to override the following extension(s): 'core', which is done by the following plugin(s): 'plugin'", + ); + }); + + it('throws an error when duplicated extensions are detected', () => { + const config = new MockConfigApi({}); + + const ExtensionA = createExtension({ ...extBase, id: 'A' }); + + const ExtensionB = createExtension({ ...extBase, id: 'B' }); + + const PluginA = createPlugin({ + id: 'A', + extensions: [ExtensionA, ExtensionA], + }); + + const PluginB = createPlugin({ + id: 'B', + extensions: [ExtensionA, ExtensionB, ExtensionB], + }); + + const features = [PluginA, PluginB]; + + expect(() => + createAppGraph({ features, config, builtinExtensions: [] }), + ).toThrow( + "The following extensions are duplicated: The extension 'A' was provided 2 time(s) by the plugin 'A' and 1 time(s) by the plugin 'B', The extension 'B' was provided 2 time(s) by the plugin 'B'", + ); + }); + + it('throws an error when duplicated extension overrides are detected', () => { + expect(() => + createAppGraph({ + features: [ + createExtensionOverrides({ + extensions: [ + createExtension({ ...extBase, id: 'a' }), + createExtension({ ...extBase, id: 'a' }), + createExtension({ ...extBase, id: 'b' }), + ], + }), + createExtensionOverrides({ + extensions: [createExtension({ ...extBase, id: 'b' })], + }), + ], + config: new MockConfigApi({}), + builtinExtensions: [], + }), + ).toThrow('The following extensions had duplicate overrides: a, b'); + }); +}); diff --git a/packages/frontend-app-api/src/wiring/createApp.test.tsx b/packages/frontend-app-api/src/wiring/createApp.test.tsx index de574bc6a9..e9fb48f957 100644 --- a/packages/frontend-app-api/src/wiring/createApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.test.tsx @@ -15,123 +15,15 @@ */ import { - createExtension, - createExtensionOverrides, createPageExtension, createPlugin, - createRouteRef, createThemeExtension, } from '@backstage/frontend-plugin-api'; -import { createApp, createInstances } from './createApp'; import { screen, waitFor } from '@testing-library/react'; +import { createApp } from './createApp'; import { MockConfigApi, renderWithEffects } from '@backstage/test-utils'; import React from 'react'; -const extBaseConfig = { - id: 'test', - attachTo: { id: 'root', input: 'default' }, - output: {}, - factory() {}, -}; - -describe('createInstances', () => { - it('throws an error when a core extension is parametrized', () => { - const config = new MockConfigApi({ - app: { - extensions: [ - { - core: {}, - }, - ], - }, - }); - const features = [ - createPlugin({ - id: 'plugin', - extensions: [], - }), - ]; - expect(() => createInstances({ config, features })).toThrow( - "A 'core' extension configuration was detected, but the core extension is not configurable", - ); - }); - - it('throws an error when a core extension is overridden', () => { - const config = new MockConfigApi({}); - const features = [ - createPlugin({ - id: 'plugin', - extensions: [ - createExtension({ - id: 'core', - attachTo: { id: 'core.routes', input: 'route' }, - inputs: {}, - output: {}, - factory() {}, - }), - ], - }), - ]; - expect(() => createInstances({ config, features })).toThrow( - "The following plugin(s) are overriding the 'core' extension which is forbidden: plugin", - ); - }); - - it('throws an error when duplicated extensions are detected', () => { - const config = new MockConfigApi({}); - - const ExtensionA = createPageExtension({ - id: 'A', - defaultPath: '/', - routeRef: createRouteRef(), - loader: async () =>
Extension A
, - }); - - const ExtensionB = createPageExtension({ - id: 'B', - defaultPath: '/', - routeRef: createRouteRef(), - loader: async () =>
Extension B
, - }); - - const PluginA = createPlugin({ - id: 'A', - extensions: [ExtensionA, ExtensionA], - }); - - const PluginB = createPlugin({ - id: 'B', - extensions: [ExtensionA, ExtensionB, ExtensionB], - }); - - const features = [PluginA, PluginB]; - - expect(() => createInstances({ config, features })).toThrow( - "The following extensions are duplicated: The extension 'A' was provided 2 time(s) by the plugin 'A' and 1 time(s) by the plugin 'B', The extension 'B' was provided 2 time(s) by the plugin 'B'", - ); - }); - - it('throws an error when duplicated extension overrides are detected', () => { - expect(() => - createInstances({ - config: new MockConfigApi({}), - features: [ - createExtensionOverrides({ - extensions: [ - createExtension({ ...extBaseConfig, id: 'a' }), - createExtension({ ...extBaseConfig, id: 'a' }), - createExtension({ ...extBaseConfig, id: 'b' }), - ], - }), - createExtensionOverrides({ - extensions: [createExtension({ ...extBaseConfig, id: 'b' })], - }), - ], - }), - ).toThrow('The following extensions had duplicate overrides: a, b'); - }); -}); - describe('createApp', () => { it('should allow themes to be installed', async () => { const app = createApp({ @@ -161,90 +53,6 @@ describe('createApp', () => { await expect(screen.findByText('Derp')).resolves.toBeInTheDocument(); }); - it('should log an app', () => { - const { coreInstance } = createInstances({ - config: new MockConfigApi({}), - features: [], - }); - - expect(String(coreInstance)).toMatchInlineSnapshot(` - " - root [ - - content [ - - ] - nav [ - - ] - - ] - themes [ - - - ] - " - `); - }); - - it('should serialize an app as JSON', () => { - const { coreInstance } = createInstances({ - config: new MockConfigApi({}), - features: [], - }); - - expect(JSON.parse(JSON.stringify(coreInstance))).toMatchInlineSnapshot(` - { - "attachments": { - "root": [ - { - "attachments": { - "content": [ - { - "id": "core.routes", - "output": [ - "core.reactElement", - ], - }, - ], - "nav": [ - { - "id": "core.nav", - "output": [ - "core.reactElement", - ], - }, - ], - }, - "id": "core.layout", - "output": [ - "core.reactElement", - ], - }, - ], - "themes": [ - { - "id": "themes.light", - "output": [ - "core.theme", - ], - }, - { - "id": "themes.dark", - "output": [ - "core.theme", - ], - }, - ], - }, - "id": "core", - "output": [ - "core.reactElement", - ], - } - `); - }); - it('should deduplicate features keeping the last received one', async () => { const duplicatedFeatureId = 'test'; const app = createApp({ From 062f7a85cbf8e6612f4b1255ee8321e25720fa1e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 21:46:37 +0200 Subject: [PATCH 238/348] frontend-app-api: add graph types docs Signed-off-by: Patrik Oldsberg --- packages/frontend-app-api/src/graph/types.ts | 38 +++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/frontend-app-api/src/graph/types.ts b/packages/frontend-app-api/src/graph/types.ts index 6e205db9dd..9267f13158 100644 --- a/packages/frontend-app-api/src/graph/types.ts +++ b/packages/frontend-app-api/src/graph/types.ts @@ -20,9 +20,18 @@ import { ExtensionDataRef, } from '@backstage/frontend-plugin-api'; +/* +NOTE: These types are marked as @internal for now, but the intention is for this to be a public API in the future. +*/ + /** * The specification for this node in the app graph. - * @public + * + * @internal + * @remarks + * + * The specifications for a collection of app nodes is all the information needed + * to build the graph and instantiate the nodes. */ export interface AppNodeSpec { readonly id: string; @@ -35,7 +44,12 @@ export interface AppNodeSpec { /** * The connections from this node to other nodes. - * @public + * + * @internal + * @remarks + * + * The app node edges are resolved based on the app node specs, regardless of whether + * adjacent nodes are disabled or not. If no parent attachment is present or */ export interface AppNodeEdges { readonly attachedTo?: { node: AppNode; input: string }; @@ -44,16 +58,24 @@ export interface AppNodeEdges { /** * The instance of this node in the app graph. - * @public + * + * @internal + * @remarks + * + * The app node instance is created when the `factory` function of an extension is called. + * Instances will only be present for nodes in the app that are connected to the root + * node and not disabled */ export interface AppNodeInstance { + /** Returns a sequence of all extension data refs that were output by this instance */ getDataRefs(): Iterable>; + /** Get the output data for a single extension data ref */ getData(ref: ExtensionDataRef): T | undefined; } /** * - * @public + * @internal */ export interface AppNode { /** The specification for how this node should be instantiated */ @@ -64,8 +86,16 @@ export interface AppNode { readonly instance?: AppNodeInstance; } +/** + * The app graph containing all nodes of the app. + * + * @internal + */ export interface AppGraph { + /** The root node of the app */ root: AppNode; + /** A map of all nodes in the app by ID, including orphaned or disabled nodes */ nodes: ReadonlyMap; + /** A sequence of all nodes with a parent that is not reachable from the app root node */ orphans: Iterable; } From e28d379e32f9506d9cf67d65add82bba25534ce7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 00:17:37 +0200 Subject: [PATCH 239/348] changesets: add changeset for frontend-app-api app graph refactor Signed-off-by: Patrik Oldsberg --- .changeset/good-plums-confess.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/good-plums-confess.md diff --git a/.changeset/good-plums-confess.md b/.changeset/good-plums-confess.md new file mode 100644 index 0000000000..941adec8b3 --- /dev/null +++ b/.changeset/good-plums-confess.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Refactor internal extension instance system into an app graph. From 1f0b6b1e48b0002a2b6ef3515ac7927c38494f1e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 19:06:01 +0200 Subject: [PATCH 240/348] search: more reliable wait in test Signed-off-by: Patrik Oldsberg --- .../search/src/components/SearchModal/SearchModal.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/search/src/components/SearchModal/SearchModal.test.tsx b/plugins/search/src/components/SearchModal/SearchModal.test.tsx index 274f9e21a1..6fce560800 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.test.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { screen } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import { configApiRef } from '@backstage/core-plugin-api'; @@ -203,9 +203,9 @@ describe('SearchModal', () => { expect.objectContaining({ term: 'term' }), ); - const input = screen.getByLabelText('Search'); + const input = screen.getByLabelText('Search'); await userEvent.clear(input); - await 'a tick'; + await waitFor(() => expect(input.value).toBe('')); await userEvent.type(input, 'new term{enter}'); expect(navigate).toHaveBeenCalledWith('/search?query=new term'); From 22ca64f117c29a50301ca7c56436720c2c10b1db Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Thu, 19 Oct 2023 12:02:23 -0400 Subject: [PATCH 241/348] fix(configLoader): properly resolve targets into absolute paths Signed-off-by: Phil Kuang --- .changeset/chatty-cobras-cheer.md | 5 +++++ .../config-loader/src/sources/ConfigSources.test.ts | 12 ++++++++++-- packages/config-loader/src/sources/ConfigSources.ts | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 .changeset/chatty-cobras-cheer.md diff --git a/.changeset/chatty-cobras-cheer.md b/.changeset/chatty-cobras-cheer.md new file mode 100644 index 0000000000..c8203e58c0 --- /dev/null +++ b/.changeset/chatty-cobras-cheer.md @@ -0,0 +1,5 @@ +--- +'@backstage/config-loader': patch +--- + +Correctly resolve config targets into absolute paths diff --git a/packages/config-loader/src/sources/ConfigSources.test.ts b/packages/config-loader/src/sources/ConfigSources.test.ts index 43feb3ca27..f095bbec42 100644 --- a/packages/config-loader/src/sources/ConfigSources.test.ts +++ b/packages/config-loader/src/sources/ConfigSources.test.ts @@ -95,6 +95,14 @@ describe('ConfigSources', () => { ), ).toEqual([{ name: 'FileConfigSource', path: '/config.yaml' }]); + expect( + mergeSources( + ConfigSources.defaultForTargets({ + targets: [{ type: 'path', target: 'config.yaml' }], + }), + ), + ).toEqual([{ name: 'FileConfigSource', path: resolvePath('config.yaml') }]); + const subFunc = async () => undefined; expect( mergeSources( @@ -172,8 +180,8 @@ describe('ConfigSources', () => { }), ), ).toEqual([ - { name: 'FileConfigSource', path: 'a.yaml' }, - { name: 'FileConfigSource', path: 'b.yaml' }, + { name: 'FileConfigSource', path: resolvePath('a.yaml') }, + { name: 'FileConfigSource', path: resolvePath('b.yaml') }, { name: 'EnvConfigSource', env: { HOME: '/' } }, ]); }); diff --git a/packages/config-loader/src/sources/ConfigSources.ts b/packages/config-loader/src/sources/ConfigSources.ts index 43123f87ea..03fc6d83d6 100644 --- a/packages/config-loader/src/sources/ConfigSources.ts +++ b/packages/config-loader/src/sources/ConfigSources.ts @@ -161,7 +161,7 @@ export class ConfigSources { } return FileConfigSource.create({ watch: options.watch, - path: arg.target, + path: resolvePath(arg.target), substitutionFunc: options.substitutionFunc, }); }); From 39cd2d7a1f9e2831b00e2ec3229e8df14af592f3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Oct 2023 17:02:33 +0200 Subject: [PATCH 242/348] starting point for entity page extension API Co-authored-by: Philipp Hugenroth Co-authored-by: Vincenzo Scamporlino Co-authored-by: Camila Belo Co-authored-by: Rickard Dybeck Co-authored-by: Ben Lambert Co-authored-by: Jack Palmer Co-authored-by: Elon Jefferson Signed-off-by: Patrik Oldsberg --- plugins/catalog/src/alpha.tsx | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index 31551c1930..0753737740 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -283,3 +283,51 @@ export default createPlugin({ CatalogNavItem, ], }); + +/// IMAGINE THIS IS IN A DIFFERENT PLUGIN + +// inside the @backstage/plugin-github-pull-requests plugin +import { + createEntityCardExtension, + createEntityContentExtension, +} from '@backstage/plugin-catalog-react'; + +const githubPullRequestsPlugin = createPlugin({ + id: 'github-pull-requests', + extensions: [ + createEntityCardExtension({ + id: 'github-pull-requests', + loader: () => import('./PullRequestsCard').then(m => m.PullRequestsCard), + entityFilter: isPullRequestsAvailable, + }), + createEntityContentExtension({ + id: 'github-pull-requests', + defaultPath: 'github-pull-requests', + defaultTitle: 'GitHub Pull Requests', + loader: () => + import('./PullRequestsContent').then(m => m.PullRequestsContent), + entityFilter: isPullRequestsAvailable, + }), + ], +}); + +// /deployments +const deploymentsPlugin = createPlugin({ + id: 'github-pull-requests', + extensions: [ + createEntityCardExtension({ + id: 'github-pull-requests', + attachTo: { id: 'plugin.deployments.content', input: 'cards' }, + loader: () => import('./PullRequestsCard').then(m => m.PullRequestsCard), + entityFilter: isPullRequestsAvailable, + }), + createEntityContentExtension({ + id: 'github-pull-requests', + defaultPath: 'github-pull-requests', + defaultTitle: 'GitHub Pull Requests', + loader: () => + import('./PullRequestsContent').then(m => m.PullRequestsContent), + entityFilter: isPullRequestsAvailable, + }), + ], +}); From b34e8bf3a314537ac3fa16869072e4add05e3db5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 16:23:06 +0200 Subject: [PATCH 243/348] app-next: initial entity page implementation with cards and content Co-authored-by: Camila Belo Signed-off-by: Patrik Oldsberg --- packages/app-next/src/App.tsx | 2 + .../app-next/src/examples/entityPages.tsx | 290 ++++++++++++++++++ plugins/catalog/src/alpha.tsx | 66 +--- 3 files changed, 293 insertions(+), 65 deletions(-) create mode 100644 packages/app-next/src/examples/entityPages.tsx diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 4e42d9b268..7ff47a3e89 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -17,6 +17,7 @@ import React from 'react'; import { createApp } from '@backstage/frontend-app-api'; import { pagesPlugin } from './examples/pagesPlugin'; +import { entityPagePlugins } from './examples/entityPages'; import graphiqlPlugin from '@backstage/plugin-graphiql/alpha'; import techRadarPlugin from '@backstage/plugin-tech-radar/alpha'; import userSettingsPlugin from '@backstage/plugin-user-settings/alpha'; @@ -120,6 +121,7 @@ const app = createApp({ techdocsPlugin, userSettingsPlugin, homePlugin, + ...entityPagePlugins, ...collectedLegacyPlugins, createExtensionOverrides({ extensions: [ diff --git a/packages/app-next/src/examples/entityPages.tsx b/packages/app-next/src/examples/entityPages.tsx new file mode 100644 index 0000000000..3b5b4cceb7 --- /dev/null +++ b/packages/app-next/src/examples/entityPages.tsx @@ -0,0 +1,290 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useEffect } from 'react'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { + AnyExtensionInputMap, + Extension, + ExtensionBoundary, + ExtensionInputValues, + PortableSchema, + RouteRef, + coreExtensionData, + createExtension, + createExtensionDataRef, + createExtensionInput, + createPageExtension, + createPlugin, + createSchemaFromZod, +} from '@backstage/frontend-plugin-api'; +import { + AsyncEntityProvider, + EntityLoadingStatus, + catalogApiRef, + entityRouteRef, +} from '@backstage/plugin-catalog-react'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { Expand } from '../../../frontend-plugin-api/src/types'; +import { EntityAboutCard, EntityLayout } from '@backstage/plugin-catalog'; +import { + useApi, + errorApiRef, + useRouteRefParams, +} from '@backstage/core-plugin-api'; +import { useNavigate } from 'react-router'; +import useAsyncRetry from 'react-use/lib/useAsyncRetry'; +import Grid from '@material-ui/core/Grid'; + +export const useEntityFromUrl = (): EntityLoadingStatus => { + const { kind, namespace, name } = useRouteRefParams(entityRouteRef); + const navigate = useNavigate(); + const errorApi = useApi(errorApiRef); + const catalogApi = useApi(catalogApiRef); + + const { + value: entity, + error, + loading, + retry: refresh, + } = useAsyncRetry( + () => catalogApi.getEntityByRef({ kind, namespace, name }), + [catalogApi, kind, namespace, name], + ); + + useEffect(() => { + if (!name) { + errorApi.post(new Error('No name provided!')); + navigate('/'); + } + }, [errorApi, navigate, error, loading, entity, name]); + + return { entity, loading, error, refresh }; +}; + +export const titleExtensionDataRef = createExtensionDataRef( + 'plugin.catalog.entity.content.title', +); + +const CatalogEntityPage = createPageExtension({ + id: 'plugin.catalog.page.entity', + defaultPath: '/catalog/:namespace/:kind/:name', + routeRef: convertLegacyRouteRef(entityRouteRef), + inputs: { + contents: createExtensionInput({ + element: coreExtensionData.reactElement, + path: coreExtensionData.routePath, + routeRef: coreExtensionData.routeRef.optional(), + title: titleExtensionDataRef, + }), + }, + loader: async ({ inputs }) => { + const Component = () => { + return ( + + + {inputs.contents.map(content => ( + + {content.element} + + ))} + + + ); + }; + return ; + }, +}); + +export function createEntityCardExtension< + TConfig, + TInputs extends AnyExtensionInputMap, +>(options: { + id: string; + attachTo?: { id: string; input: string }; + disabled?: boolean; + inputs?: TInputs; + configSchema?: PortableSchema; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise; +}): Extension { + return createExtension({ + id: `entity.content.${options.id}`, + attachTo: options.attachTo ?? { + id: 'entity.content.overview', + input: 'cards', + }, + disabled: options.disabled ?? true, + output: { + element: coreExtensionData.reactElement, + }, + inputs: options.inputs, + configSchema: options.configSchema, + factory({ bind, config, inputs, source }) { + const LazyComponent = React.lazy(() => + options + .loader({ config, inputs }) + .then(element => ({ default: () => element })), + ); + + bind({ + element: ( + + + + + + ), + }); + }, + }); +} + +export function createEntityContentExtension< + TConfig extends { path: string; title: string }, + TInputs extends AnyExtensionInputMap, +>( + options: ( + | { + defaultPath: string; + defaultTitle: string; + } + | { + configSchema: PortableSchema; + } + ) & { + id: string; + attachTo?: { id: string; input: string }; + disabled?: boolean; + inputs?: TInputs; + routeRef?: RouteRef; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise; + }, +): Extension { + const configSchema = + 'configSchema' in options + ? options.configSchema + : (createSchemaFromZod(z => + z.object({ + path: z.string().default(options.defaultPath), + title: z.string().default(options.defaultTitle), + }), + ) as PortableSchema); + + return createExtension({ + id: `entity.content.${options.id}`, + attachTo: options.attachTo ?? { + id: 'plugin.catalog.page.entity', + input: 'contents', + }, + disabled: options.disabled ?? true, + output: { + element: coreExtensionData.reactElement, + path: coreExtensionData.routePath, + routeRef: coreExtensionData.routeRef.optional(), + title: titleExtensionDataRef, + }, + inputs: options.inputs, + configSchema, + factory({ bind, config, inputs, source }) { + const LazyComponent = React.lazy(() => + options + .loader({ config, inputs }) + .then(element => ({ default: () => element })), + ); + + bind({ + path: config.path, + element: ( + + + + + + ), + routeRef: options.routeRef, + title: config.title, + }); + }, + }); +} + +const entityAboutCardExtension = createEntityCardExtension({ + id: 'about', + disabled: false, + loader: async () => , + // entityFilter: isDerp, +}); + +const overviewContentExtension = createEntityContentExtension({ + id: 'overview', + defaultPath: '/', + defaultTitle: 'Overview', + disabled: false, + inputs: { + cards: createExtensionInput({ + element: coreExtensionData.reactElement, + }), + }, + loader: async ({ inputs }) => ( + + {inputs.cards.map(card => ( + + {card.element} + + ))} + + ), +}); + +const bonusTechdocsPlugin = createPlugin({ + id: 'techdocs-entity', + extensions: [ + createEntityContentExtension({ + id: 'techdocs', + defaultPath: 'docs', + defaultTitle: 'TechDocs', + disabled: false, + loader: () => + import('@backstage/plugin-techdocs').then(m => ( + + )), + // entityFilter: isPullRequestsAvailable, + }), + ], +}); + +export const entityPagePlugins = [ + createPlugin({ + id: 'entity-pages', + extensions: [ + CatalogEntityPage, + overviewContentExtension, + entityAboutCardExtension, + ], + }), + bonusTechdocsPlugin, + // deploymentsPlugin, +]; diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index 0753737740..415525ab74 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -231,22 +231,6 @@ const CatalogIndexPage = createPageExtension({ }, }); -const CatalogEntityPage = createPageExtension({ - id: 'plugin.catalog.page.entity', - defaultPath: '/catalog/:namespace/:kind/:name', - routeRef: convertLegacyRouteRef(entityRouteRef), - loader: async () => { - const Component = () => { - return ( - -
🚧 Work In Progress
-
- ); - }; - return ; - }, -}); - const CatalogNavItem = createNavItemExtension({ id: 'catalog.nav.index', routeRef: convertLegacyRouteRef(rootRouteRef), @@ -279,55 +263,7 @@ export default createPlugin({ CatalogEntityProcessingStatusFilter, CatalogEntityNamespaceFilter, CatalogIndexPage, - CatalogEntityPage, + // CatalogEntityPage, CatalogNavItem, ], }); - -/// IMAGINE THIS IS IN A DIFFERENT PLUGIN - -// inside the @backstage/plugin-github-pull-requests plugin -import { - createEntityCardExtension, - createEntityContentExtension, -} from '@backstage/plugin-catalog-react'; - -const githubPullRequestsPlugin = createPlugin({ - id: 'github-pull-requests', - extensions: [ - createEntityCardExtension({ - id: 'github-pull-requests', - loader: () => import('./PullRequestsCard').then(m => m.PullRequestsCard), - entityFilter: isPullRequestsAvailable, - }), - createEntityContentExtension({ - id: 'github-pull-requests', - defaultPath: 'github-pull-requests', - defaultTitle: 'GitHub Pull Requests', - loader: () => - import('./PullRequestsContent').then(m => m.PullRequestsContent), - entityFilter: isPullRequestsAvailable, - }), - ], -}); - -// /deployments -const deploymentsPlugin = createPlugin({ - id: 'github-pull-requests', - extensions: [ - createEntityCardExtension({ - id: 'github-pull-requests', - attachTo: { id: 'plugin.deployments.content', input: 'cards' }, - loader: () => import('./PullRequestsCard').then(m => m.PullRequestsCard), - entityFilter: isPullRequestsAvailable, - }), - createEntityContentExtension({ - id: 'github-pull-requests', - defaultPath: 'github-pull-requests', - defaultTitle: 'GitHub Pull Requests', - loader: () => - import('./PullRequestsContent').then(m => m.PullRequestsContent), - entityFilter: isPullRequestsAvailable, - }), - ], -}); From c82fc7e672d73eed1ff98a9947b7fe8a98fff1ac Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 16:42:54 +0200 Subject: [PATCH 244/348] catalog: split alpha entry point into multiple modules Co-authored-by: Camila Belo Signed-off-by: Patrik Oldsberg --- plugins/catalog/package.json | 4 +- plugins/catalog/src/alpha.tsx | 269 ------------------ .../src/alpha/builtInFilterExtensions.tsx | 121 ++++++++ .../alpha/createCatalogFilterExtension.tsx | 62 ++++ plugins/catalog/src/alpha/index.ts | 18 ++ plugins/catalog/src/alpha/plugin.tsx | 145 ++++++++++ 6 files changed, 348 insertions(+), 271 deletions(-) delete mode 100644 plugins/catalog/src/alpha.tsx create mode 100644 plugins/catalog/src/alpha/builtInFilterExtensions.tsx create mode 100644 plugins/catalog/src/alpha/createCatalogFilterExtension.tsx create mode 100644 plugins/catalog/src/alpha/index.ts create mode 100644 plugins/catalog/src/alpha/plugin.tsx diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 56ae771314..214795e73c 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -10,13 +10,13 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.tsx", + "./alpha": "./src/alpha/index.ts", "./package.json": "./package.json" }, "typesVersions": { "*": { "alpha": [ - "src/alpha.tsx" + "src/alpha/index.ts" ], "package.json": [ "package.json" diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx deleted file mode 100644 index 415525ab74..0000000000 --- a/plugins/catalog/src/alpha.tsx +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React from 'react'; -import HomeIcon from '@material-ui/icons/Home'; -import { - createApiFactory, - discoveryApiRef, - fetchApiRef, - storageApiRef, -} from '@backstage/core-plugin-api'; -import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; -import { CatalogClient } from '@backstage/catalog-client'; -import { - createSchemaFromZod, - createApiExtension, - createPageExtension, - createPlugin, - createNavItemExtension, - createExtension, - coreExtensionData, - AnyExtensionInputMap, - PortableSchema, - ExtensionBoundary, - createExtensionInput, -} from '@backstage/frontend-plugin-api'; -import { - AsyncEntityProvider, - catalogApiRef, - entityRouteRef, - starredEntitiesApiRef, -} from '@backstage/plugin-catalog-react'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; -import { DefaultStarredEntitiesApi } from './apis'; -import { - createComponentRouteRef, - createFromTemplateRouteRef, - rootRouteRef, - viewTechDocRouteRef, -} from './routes'; -import { useEntityFromUrl } from './components/CatalogEntityPage/useEntityFromUrl'; - -/** @alpha */ -export const CatalogApi = createApiExtension({ - factory: createApiFactory({ - api: catalogApiRef, - deps: { - discoveryApi: discoveryApiRef, - fetchApi: fetchApiRef, - }, - factory: ({ discoveryApi, fetchApi }) => - new CatalogClient({ discoveryApi, fetchApi }), - }), -}); - -/** @alpha */ -export const StarredEntitiesApi = createApiExtension({ - factory: createApiFactory({ - api: starredEntitiesApiRef, - deps: { storageApi: storageApiRef }, - factory: ({ storageApi }) => new DefaultStarredEntitiesApi({ storageApi }), - }), -}); - -/** @alpha */ -export const CatalogSearchResultListItemExtension = - createSearchResultListItemExtension({ - id: 'catalog', - predicate: result => result.type === 'software-catalog', - component: () => - import('./components/CatalogSearchResultListItem').then( - m => m.CatalogSearchResultListItem, - ), - }); - -/** @alpha */ -export function createCatalogFilterExtension< - TInputs extends AnyExtensionInputMap, - TConfig = never, ->(options: { - id: string; - inputs?: TInputs; - configSchema?: PortableSchema; - loader: (options: { config: TConfig }) => Promise; -}) { - const id = `catalog.filter.${options.id}`; - - return createExtension({ - id, - attachTo: { id: 'plugin.catalog.page.index', input: 'filters' }, - inputs: options.inputs ?? {}, - configSchema: options.configSchema, - output: { - element: coreExtensionData.reactElement, - }, - factory({ bind, config, source }) { - const ExtensionComponent = React.lazy(() => - options - .loader({ config }) - .then(element => ({ default: () => element })), - ); - - bind({ - element: ( - - - - ), - }); - }, - }); -} - -const CatalogEntityTagFilter = createCatalogFilterExtension({ - id: 'entity.tag', - loader: async () => { - const { EntityTagPicker } = await import('@backstage/plugin-catalog-react'); - return ; - }, -}); - -const CatalogEntityKindFilter = createCatalogFilterExtension({ - id: 'entity.kind', - configSchema: createSchemaFromZod(z => - z.object({ - initialFilter: z.string().default('component'), - }), - ), - loader: async ({ config }) => { - const { EntityKindPicker } = await import( - '@backstage/plugin-catalog-react' - ); - return ; - }, -}); - -const CatalogEntityTypeFilter = createCatalogFilterExtension({ - id: 'entity.type', - loader: async () => { - const { EntityTypePicker } = await import( - '@backstage/plugin-catalog-react' - ); - return ; - }, -}); - -const CatalogEntityOwnerFilter = createCatalogFilterExtension({ - id: 'entity.mode', - configSchema: createSchemaFromZod(z => - z.object({ - mode: z.enum(['owners-only', 'all']).optional(), - }), - ), - loader: async ({ config }) => { - const { EntityOwnerPicker } = await import( - '@backstage/plugin-catalog-react' - ); - return ; - }, -}); - -const CatalogEntityNamespaceFilter = createCatalogFilterExtension({ - id: 'entity.namespace', - loader: async () => { - const { EntityNamespacePicker } = await import( - '@backstage/plugin-catalog-react' - ); - return ; - }, -}); - -const CatalogEntityLifecycleFilter = createCatalogFilterExtension({ - id: 'entity.lifecycle', - loader: async () => { - const { EntityLifecyclePicker } = await import( - '@backstage/plugin-catalog-react' - ); - return ; - }, -}); - -const CatalogEntityProcessingStatusFilter = createCatalogFilterExtension({ - id: 'entity.processing.status', - loader: async () => { - const { EntityProcessingStatusPicker } = await import( - '@backstage/plugin-catalog-react' - ); - return ; - }, -}); - -const CatalogUserListFilter = createCatalogFilterExtension({ - id: 'user.list', - configSchema: createSchemaFromZod(z => - z.object({ - initialFilter: z.enum(['owned', 'starred', 'all']).default('owned'), - }), - ), - loader: async ({ config }) => { - const { UserListPicker } = await import('@backstage/plugin-catalog-react'); - return ; - }, -}); - -const CatalogIndexPage = createPageExtension({ - id: 'plugin.catalog.page.index', - defaultPath: '/catalog', - routeRef: convertLegacyRouteRef(rootRouteRef), - inputs: { - filters: createExtensionInput({ - element: coreExtensionData.reactElement, - }), - }, - loader: async ({ inputs }) => { - const { BaseCatalogPage } = await import('./components/CatalogPage'); - const filters = inputs.filters.map(filter => filter.element); - return {filters}} />; - }, -}); - -const CatalogNavItem = createNavItemExtension({ - id: 'catalog.nav.index', - routeRef: convertLegacyRouteRef(rootRouteRef), - title: 'Catalog', - icon: HomeIcon, -}); - -/** @alpha */ -export default createPlugin({ - id: 'catalog', - routes: { - catalogIndex: convertLegacyRouteRef(rootRouteRef), - catalogEntity: convertLegacyRouteRef(entityRouteRef), - }, - externalRoutes: { - viewTechDoc: convertLegacyRouteRef(viewTechDocRouteRef), - createComponent: convertLegacyRouteRef(createComponentRouteRef), - createFromTemplate: convertLegacyRouteRef(createFromTemplateRouteRef), - }, - extensions: [ - CatalogApi, - StarredEntitiesApi, - CatalogSearchResultListItemExtension, - CatalogEntityKindFilter, - CatalogEntityTypeFilter, - CatalogUserListFilter, - CatalogEntityOwnerFilter, - CatalogEntityLifecycleFilter, - CatalogEntityTagFilter, - CatalogEntityProcessingStatusFilter, - CatalogEntityNamespaceFilter, - CatalogIndexPage, - // CatalogEntityPage, - CatalogNavItem, - ], -}); diff --git a/plugins/catalog/src/alpha/builtInFilterExtensions.tsx b/plugins/catalog/src/alpha/builtInFilterExtensions.tsx new file mode 100644 index 0000000000..5a7575c4f5 --- /dev/null +++ b/plugins/catalog/src/alpha/builtInFilterExtensions.tsx @@ -0,0 +1,121 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { createCatalogFilterExtension } from './createCatalogFilterExtension'; +import { createSchemaFromZod } from '@backstage/frontend-plugin-api'; + +const CatalogEntityTagFilter = createCatalogFilterExtension({ + id: 'entity.tag', + loader: async () => { + const { EntityTagPicker } = await import('@backstage/plugin-catalog-react'); + return ; + }, +}); + +const CatalogEntityKindFilter = createCatalogFilterExtension({ + id: 'entity.kind', + configSchema: createSchemaFromZod(z => + z.object({ + initialFilter: z.string().default('component'), + }), + ), + loader: async ({ config }) => { + const { EntityKindPicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +const CatalogEntityTypeFilter = createCatalogFilterExtension({ + id: 'entity.type', + loader: async () => { + const { EntityTypePicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +const CatalogEntityOwnerFilter = createCatalogFilterExtension({ + id: 'entity.mode', + configSchema: createSchemaFromZod(z => + z.object({ + mode: z.enum(['owners-only', 'all']).optional(), + }), + ), + loader: async ({ config }) => { + const { EntityOwnerPicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +const CatalogEntityNamespaceFilter = createCatalogFilterExtension({ + id: 'entity.namespace', + loader: async () => { + const { EntityNamespacePicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +const CatalogEntityLifecycleFilter = createCatalogFilterExtension({ + id: 'entity.lifecycle', + loader: async () => { + const { EntityLifecyclePicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +const CatalogEntityProcessingStatusFilter = createCatalogFilterExtension({ + id: 'entity.processing.status', + loader: async () => { + const { EntityProcessingStatusPicker } = await import( + '@backstage/plugin-catalog-react' + ); + return ; + }, +}); + +const CatalogUserListFilter = createCatalogFilterExtension({ + id: 'user.list', + configSchema: createSchemaFromZod(z => + z.object({ + initialFilter: z.enum(['owned', 'starred', 'all']).default('owned'), + }), + ), + loader: async ({ config }) => { + const { UserListPicker } = await import('@backstage/plugin-catalog-react'); + return ; + }, +}); + +export const builtInFilterExtensions = [ + CatalogEntityTagFilter, + CatalogEntityKindFilter, + CatalogEntityTypeFilter, + CatalogEntityOwnerFilter, + CatalogEntityNamespaceFilter, + CatalogEntityLifecycleFilter, + CatalogEntityProcessingStatusFilter, + CatalogUserListFilter, +]; diff --git a/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx b/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx new file mode 100644 index 0000000000..5a6328078c --- /dev/null +++ b/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx @@ -0,0 +1,62 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { lazy } from 'react'; +import { + AnyExtensionInputMap, + ExtensionBoundary, + PortableSchema, + coreExtensionData, + createExtension, +} from '@backstage/frontend-plugin-api'; + +/** @alpha */ +export function createCatalogFilterExtension< + TInputs extends AnyExtensionInputMap, + TConfig = never, +>(options: { + id: string; + inputs?: TInputs; + configSchema?: PortableSchema; + loader: (options: { config: TConfig }) => Promise; +}) { + const id = `catalog.filter.${options.id}`; + + return createExtension({ + id, + attachTo: { id: 'plugin.catalog.page.index', input: 'filters' }, + inputs: options.inputs ?? {}, + configSchema: options.configSchema, + output: { + element: coreExtensionData.reactElement, + }, + factory({ bind, config, source }) { + const ExtensionComponent = lazy(() => + options + .loader({ config }) + .then(element => ({ default: () => element })), + ); + + bind({ + element: ( + + + + ), + }); + }, + }); +} diff --git a/plugins/catalog/src/alpha/index.ts b/plugins/catalog/src/alpha/index.ts new file mode 100644 index 0000000000..06a78ec6ea --- /dev/null +++ b/plugins/catalog/src/alpha/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 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 { default } from './plugin'; +export { createCatalogFilterExtension } from './createCatalogFilterExtension'; diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx new file mode 100644 index 0000000000..1716b85a81 --- /dev/null +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -0,0 +1,145 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import HomeIcon from '@material-ui/icons/Home'; +import { + createApiFactory, + discoveryApiRef, + fetchApiRef, + storageApiRef, +} from '@backstage/core-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { CatalogClient } from '@backstage/catalog-client'; +import { + createApiExtension, + createPageExtension, + createPlugin, + createNavItemExtension, + coreExtensionData, + createExtensionInput, +} from '@backstage/frontend-plugin-api'; +import { + AsyncEntityProvider, + catalogApiRef, + entityRouteRef, + starredEntitiesApiRef, +} from '@backstage/plugin-catalog-react'; +import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; +import { DefaultStarredEntitiesApi } from '../apis'; +import { + createComponentRouteRef, + createFromTemplateRouteRef, + rootRouteRef, + viewTechDocRouteRef, +} from '../routes'; +import { builtInFilterExtensions } from './builtInFilterExtensions'; +import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; + +/** @alpha */ +export const CatalogApi = createApiExtension({ + factory: createApiFactory({ + api: catalogApiRef, + deps: { + discoveryApi: discoveryApiRef, + fetchApi: fetchApiRef, + }, + factory: ({ discoveryApi, fetchApi }) => + new CatalogClient({ discoveryApi, fetchApi }), + }), +}); + +/** @alpha */ +export const StarredEntitiesApi = createApiExtension({ + factory: createApiFactory({ + api: starredEntitiesApiRef, + deps: { storageApi: storageApiRef }, + factory: ({ storageApi }) => new DefaultStarredEntitiesApi({ storageApi }), + }), +}); + +/** @alpha */ +export const CatalogSearchResultListItemExtension = + createSearchResultListItemExtension({ + id: 'catalog', + predicate: result => result.type === 'software-catalog', + component: () => + import('../components/CatalogSearchResultListItem').then( + m => m.CatalogSearchResultListItem, + ), + }); + +const CatalogIndexPage = createPageExtension({ + id: 'plugin.catalog.page.index', + defaultPath: '/catalog', + routeRef: convertLegacyRouteRef(rootRouteRef), + inputs: { + filters: createExtensionInput({ + element: coreExtensionData.reactElement, + }), + }, + loader: async ({ inputs }) => { + const { BaseCatalogPage } = await import('../components/CatalogPage'); + const filters = inputs.filters.map(filter => filter.element); + return {filters}} />; + }, +}); + +const CatalogEntityPage = createPageExtension({ + id: 'plugin.catalog.page.entity', + defaultPath: '/catalog/:namespace/:kind/:name', + routeRef: convertLegacyRouteRef(entityRouteRef), + loader: async () => { + const Component = () => { + return ( + +
🚧 Work In Progress
+
+ ); + }; + return ; + }, +}); + +const CatalogNavItem = createNavItemExtension({ + id: 'catalog.nav.index', + routeRef: convertLegacyRouteRef(rootRouteRef), + title: 'Catalog', + icon: HomeIcon, +}); + +/** @alpha */ +export default createPlugin({ + id: 'catalog', + routes: { + catalogIndex: convertLegacyRouteRef(rootRouteRef), + catalogEntity: convertLegacyRouteRef(entityRouteRef), + }, + externalRoutes: { + viewTechDoc: convertLegacyRouteRef(viewTechDocRouteRef), + createComponent: convertLegacyRouteRef(createComponentRouteRef), + createFromTemplate: convertLegacyRouteRef(createFromTemplateRouteRef), + }, + extensions: [ + CatalogApi, + StarredEntitiesApi, + CatalogSearchResultListItemExtension, + CatalogIndexPage, + CatalogEntityPage, + CatalogNavItem, + ...builtInFilterExtensions, + ], +}); From 0bf6ebda889bfe17f6c444ba720883f918c28a6e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 19 Oct 2023 17:04:30 +0200 Subject: [PATCH 245/348] catalog,catalog-react,techdocs: extract experimental entity page implementation from app-next Co-authored-by: Camila Belo Signed-off-by: Patrik Oldsberg --- .changeset/mighty-crews-attack.md | 5 + .changeset/nice-apes-kneel.md | 5 + .changeset/old-apricots-taste.md | 5 + packages/app-next/app-config.yaml | 9 +- packages/app-next/src/App.tsx | 19 +- .../app-next/src/examples/entityPages.tsx | 290 ------------------ plugins/catalog-react/alpha-api-report.md | 65 ++++ plugins/catalog-react/package.json | 5 +- plugins/catalog-react/src/alpha.tsx | 158 ++++++++++ plugins/catalog/alpha-api-report.md | 11 - plugins/catalog/package.json | 4 +- .../{catalog-react => catalog}/src/alpha.ts | 4 +- plugins/catalog/src/alpha/plugin.tsx | 60 +++- plugins/techdocs/src/alpha.tsx | 14 + yarn.lock | 1 + 15 files changed, 326 insertions(+), 329 deletions(-) create mode 100644 .changeset/mighty-crews-attack.md create mode 100644 .changeset/nice-apes-kneel.md create mode 100644 .changeset/old-apricots-taste.md delete mode 100644 packages/app-next/src/examples/entityPages.tsx create mode 100644 plugins/catalog-react/src/alpha.tsx rename plugins/{catalog-react => catalog}/src/alpha.ts (85%) diff --git a/.changeset/mighty-crews-attack.md b/.changeset/mighty-crews-attack.md new file mode 100644 index 0000000000..c0b8587fe0 --- /dev/null +++ b/.changeset/mighty-crews-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Initial entity page implementation for new frontend system at `/alpha`, with an overview page enabled by default and the about card available as an optional card. diff --git a/.changeset/nice-apes-kneel.md b/.changeset/nice-apes-kneel.md new file mode 100644 index 0000000000..1ecff9d223 --- /dev/null +++ b/.changeset/nice-apes-kneel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Added entity page content for the new plugin exported via `/alpha`. diff --git a/.changeset/old-apricots-taste.md b/.changeset/old-apricots-taste.md new file mode 100644 index 0000000000..544ba11536 --- /dev/null +++ b/.changeset/old-apricots-taste.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Added new APIs at the `/alpha` subpath for creating entity page cards and content for the new frontend system. diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index 6f6081fece..0c75e1c96c 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -4,12 +4,17 @@ app: routes: bindings: plugin.pages.externalRoutes.pageX: plugin.pages.routes.pageX - # waiting for https://github.com/backstage/backstage/pull/20605 - # catalog.externalRoutes.viewTechDoc: techdocs.routes.docRoot + plugin.catalog.externalRoutes.viewTechDoc: plugin.techdocs.routes.docRoot extensions: - apis.plugin.graphiql.browse.gitlab: true + # Entity page cards + - 'entity.cards.about' + + # Entity page content + - 'entity.content.techdocs' + # scmAuthExtension: >- # createScmAuthExtension({ # id: 'apis.scmAuth.addons.ghe', diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 7ff47a3e89..1275722da4 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -17,7 +17,6 @@ import React from 'react'; import { createApp } from '@backstage/frontend-app-api'; import { pagesPlugin } from './examples/pagesPlugin'; -import { entityPagePlugins } from './examples/entityPages'; import graphiqlPlugin from '@backstage/plugin-graphiql/alpha'; import techRadarPlugin from '@backstage/plugin-tech-radar/alpha'; import userSettingsPlugin from '@backstage/plugin-user-settings/alpha'; @@ -30,11 +29,8 @@ import { createExtension, createApiExtension, createExtensionOverrides, - createPageExtension, } from '@backstage/frontend-plugin-api'; -import { entityRouteRef } from '@backstage/plugin-catalog-react'; import techdocsPlugin from '@backstage/plugin-techdocs/alpha'; -import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; import { homePage } from './HomePage'; import { collectLegacyRoutes } from '@backstage/core-compat-api'; import { FlatRoutes } from '@backstage/core-app-api'; @@ -76,13 +72,6 @@ TODO: /* app.tsx */ -const entityPageExtension = createPageExtension({ - id: 'catalog:entity', - defaultPath: '/catalog/:namespace/:kind/:name', - routeRef: convertLegacyRouteRef(entityRouteRef), - loader: async () =>
Just a temporary mocked entity page
, -}); - const homePageExtension = createExtension({ id: 'myhomepage', attachTo: { id: 'home', input: 'props' }, @@ -121,15 +110,9 @@ const app = createApp({ techdocsPlugin, userSettingsPlugin, homePlugin, - ...entityPagePlugins, ...collectedLegacyPlugins, createExtensionOverrides({ - extensions: [ - entityPageExtension, - homePageExtension, - scmAuthExtension, - scmIntegrationApi, - ], + extensions: [homePageExtension, scmAuthExtension, scmIntegrationApi], }), ], /* Handled through config instead */ diff --git a/packages/app-next/src/examples/entityPages.tsx b/packages/app-next/src/examples/entityPages.tsx deleted file mode 100644 index 3b5b4cceb7..0000000000 --- a/packages/app-next/src/examples/entityPages.tsx +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React, { useEffect } from 'react'; -import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; -import { - AnyExtensionInputMap, - Extension, - ExtensionBoundary, - ExtensionInputValues, - PortableSchema, - RouteRef, - coreExtensionData, - createExtension, - createExtensionDataRef, - createExtensionInput, - createPageExtension, - createPlugin, - createSchemaFromZod, -} from '@backstage/frontend-plugin-api'; -import { - AsyncEntityProvider, - EntityLoadingStatus, - catalogApiRef, - entityRouteRef, -} from '@backstage/plugin-catalog-react'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { Expand } from '../../../frontend-plugin-api/src/types'; -import { EntityAboutCard, EntityLayout } from '@backstage/plugin-catalog'; -import { - useApi, - errorApiRef, - useRouteRefParams, -} from '@backstage/core-plugin-api'; -import { useNavigate } from 'react-router'; -import useAsyncRetry from 'react-use/lib/useAsyncRetry'; -import Grid from '@material-ui/core/Grid'; - -export const useEntityFromUrl = (): EntityLoadingStatus => { - const { kind, namespace, name } = useRouteRefParams(entityRouteRef); - const navigate = useNavigate(); - const errorApi = useApi(errorApiRef); - const catalogApi = useApi(catalogApiRef); - - const { - value: entity, - error, - loading, - retry: refresh, - } = useAsyncRetry( - () => catalogApi.getEntityByRef({ kind, namespace, name }), - [catalogApi, kind, namespace, name], - ); - - useEffect(() => { - if (!name) { - errorApi.post(new Error('No name provided!')); - navigate('/'); - } - }, [errorApi, navigate, error, loading, entity, name]); - - return { entity, loading, error, refresh }; -}; - -export const titleExtensionDataRef = createExtensionDataRef( - 'plugin.catalog.entity.content.title', -); - -const CatalogEntityPage = createPageExtension({ - id: 'plugin.catalog.page.entity', - defaultPath: '/catalog/:namespace/:kind/:name', - routeRef: convertLegacyRouteRef(entityRouteRef), - inputs: { - contents: createExtensionInput({ - element: coreExtensionData.reactElement, - path: coreExtensionData.routePath, - routeRef: coreExtensionData.routeRef.optional(), - title: titleExtensionDataRef, - }), - }, - loader: async ({ inputs }) => { - const Component = () => { - return ( - - - {inputs.contents.map(content => ( - - {content.element} - - ))} - - - ); - }; - return ; - }, -}); - -export function createEntityCardExtension< - TConfig, - TInputs extends AnyExtensionInputMap, ->(options: { - id: string; - attachTo?: { id: string; input: string }; - disabled?: boolean; - inputs?: TInputs; - configSchema?: PortableSchema; - loader: (options: { - config: TConfig; - inputs: Expand>; - }) => Promise; -}): Extension { - return createExtension({ - id: `entity.content.${options.id}`, - attachTo: options.attachTo ?? { - id: 'entity.content.overview', - input: 'cards', - }, - disabled: options.disabled ?? true, - output: { - element: coreExtensionData.reactElement, - }, - inputs: options.inputs, - configSchema: options.configSchema, - factory({ bind, config, inputs, source }) { - const LazyComponent = React.lazy(() => - options - .loader({ config, inputs }) - .then(element => ({ default: () => element })), - ); - - bind({ - element: ( - - - - - - ), - }); - }, - }); -} - -export function createEntityContentExtension< - TConfig extends { path: string; title: string }, - TInputs extends AnyExtensionInputMap, ->( - options: ( - | { - defaultPath: string; - defaultTitle: string; - } - | { - configSchema: PortableSchema; - } - ) & { - id: string; - attachTo?: { id: string; input: string }; - disabled?: boolean; - inputs?: TInputs; - routeRef?: RouteRef; - loader: (options: { - config: TConfig; - inputs: Expand>; - }) => Promise; - }, -): Extension { - const configSchema = - 'configSchema' in options - ? options.configSchema - : (createSchemaFromZod(z => - z.object({ - path: z.string().default(options.defaultPath), - title: z.string().default(options.defaultTitle), - }), - ) as PortableSchema); - - return createExtension({ - id: `entity.content.${options.id}`, - attachTo: options.attachTo ?? { - id: 'plugin.catalog.page.entity', - input: 'contents', - }, - disabled: options.disabled ?? true, - output: { - element: coreExtensionData.reactElement, - path: coreExtensionData.routePath, - routeRef: coreExtensionData.routeRef.optional(), - title: titleExtensionDataRef, - }, - inputs: options.inputs, - configSchema, - factory({ bind, config, inputs, source }) { - const LazyComponent = React.lazy(() => - options - .loader({ config, inputs }) - .then(element => ({ default: () => element })), - ); - - bind({ - path: config.path, - element: ( - - - - - - ), - routeRef: options.routeRef, - title: config.title, - }); - }, - }); -} - -const entityAboutCardExtension = createEntityCardExtension({ - id: 'about', - disabled: false, - loader: async () => , - // entityFilter: isDerp, -}); - -const overviewContentExtension = createEntityContentExtension({ - id: 'overview', - defaultPath: '/', - defaultTitle: 'Overview', - disabled: false, - inputs: { - cards: createExtensionInput({ - element: coreExtensionData.reactElement, - }), - }, - loader: async ({ inputs }) => ( - - {inputs.cards.map(card => ( - - {card.element} - - ))} - - ), -}); - -const bonusTechdocsPlugin = createPlugin({ - id: 'techdocs-entity', - extensions: [ - createEntityContentExtension({ - id: 'techdocs', - defaultPath: 'docs', - defaultTitle: 'TechDocs', - disabled: false, - loader: () => - import('@backstage/plugin-techdocs').then(m => ( - - )), - // entityFilter: isPullRequestsAvailable, - }), - ], -}); - -export const entityPagePlugins = [ - createPlugin({ - id: 'entity-pages', - extensions: [ - CatalogEntityPage, - overviewContentExtension, - entityAboutCardExtension, - ], - }), - bonusTechdocsPlugin, - // deploymentsPlugin, -]; diff --git a/plugins/catalog-react/alpha-api-report.md b/plugins/catalog-react/alpha-api-report.md index f9b740c07c..120e162c84 100644 --- a/plugins/catalog-react/alpha-api-report.md +++ b/plugins/catalog-react/alpha-api-report.md @@ -3,8 +3,73 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +/// + +import { AnyExtensionInputMap } from '@backstage/frontend-plugin-api'; +import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { Entity } from '@backstage/catalog-model'; +import { Extension } from '@backstage/frontend-plugin-api'; +import { ExtensionInputValues } from '@backstage/frontend-plugin-api'; +import { PortableSchema } from '@backstage/frontend-plugin-api'; import { ResourcePermission } from '@backstage/plugin-permission-common'; +import { RouteRef } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +export function createEntityCardExtension< + TConfig, + TInputs extends AnyExtensionInputMap, +>(options: { + id: string; + attachTo?: { + id: string; + input: string; + }; + disabled?: boolean; + inputs?: TInputs; + configSchema?: PortableSchema; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise; +}): Extension; + +// @alpha (undocumented) +export function createEntityContentExtension< + TConfig extends { + path: string; + title: string; + }, + TInputs extends AnyExtensionInputMap, +>( + options: ( + | { + defaultPath: string; + defaultTitle: string; + } + | { + configSchema: PortableSchema; + } + ) & { + id: string; + attachTo?: { + id: string; + input: string; + }; + disabled?: boolean; + inputs?: TInputs; + routeRef?: RouteRef; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise; + }, +): Extension; + +// @alpha (undocumented) +export const entityContentTitleExtensionDataRef: ConfigurableExtensionDataRef< + string, + {} +>; // @alpha export function isOwnerOf(owner: Entity, entity: Entity): boolean; diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index bb18160595..70fa5e9614 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -10,13 +10,13 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", + "./alpha": "./src/alpha.tsx", "./package.json": "./package.json" }, "typesVersions": { "*": { "alpha": [ - "src/alpha.ts" + "src/alpha.tsx" ], "package.json": [ "package.json" @@ -51,6 +51,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", diff --git a/plugins/catalog-react/src/alpha.tsx b/plugins/catalog-react/src/alpha.tsx new file mode 100644 index 0000000000..d2eeb8f5f3 --- /dev/null +++ b/plugins/catalog-react/src/alpha.tsx @@ -0,0 +1,158 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { + AnyExtensionInputMap, + Extension, + ExtensionBoundary, + ExtensionInputValues, + PortableSchema, + RouteRef, + coreExtensionData, + createExtension, + createExtensionDataRef, + createSchemaFromZod, +} from '@backstage/frontend-plugin-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { Expand } from '../../../packages/frontend-plugin-api/src/types'; + +export { isOwnerOf } from './utils'; +export { useEntityPermission } from './hooks/useEntityPermission'; + +/** @alpha */ +export const entityContentTitleExtensionDataRef = + createExtensionDataRef('plugin.catalog.entity.content.title'); + +/** @alpha */ +export function createEntityCardExtension< + TConfig, + TInputs extends AnyExtensionInputMap, +>(options: { + id: string; + attachTo?: { id: string; input: string }; + disabled?: boolean; + inputs?: TInputs; + configSchema?: PortableSchema; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise; +}): Extension { + const id = `entity.cards.${options.id}`; + + return createExtension({ + id, + attachTo: options.attachTo ?? { + id: 'entity.content.overview', + input: 'cards', + }, + disabled: options.disabled ?? true, + output: { + element: coreExtensionData.reactElement, + }, + inputs: options.inputs, + configSchema: options.configSchema, + factory({ bind, config, inputs, source }) { + const ExtensionComponent = React.lazy(() => + options + .loader({ config, inputs }) + .then(element => ({ default: () => element })), + ); + + bind({ + element: ( + + + + ), + }); + }, + }); +} + +/** @alpha */ +export function createEntityContentExtension< + TConfig extends { path: string; title: string }, + TInputs extends AnyExtensionInputMap, +>( + options: ( + | { + defaultPath: string; + defaultTitle: string; + } + | { + configSchema: PortableSchema; + } + ) & { + id: string; + attachTo?: { id: string; input: string }; + disabled?: boolean; + inputs?: TInputs; + routeRef?: RouteRef; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise; + }, +): Extension { + const id = `entity.content.${options.id}`; + + const configSchema = + 'configSchema' in options + ? options.configSchema + : (createSchemaFromZod(z => + z.object({ + path: z.string().default(options.defaultPath), + title: z.string().default(options.defaultTitle), + }), + ) as PortableSchema); + + return createExtension({ + id, + attachTo: options.attachTo ?? { + id: 'plugin.catalog.page.entity', + input: 'contents', + }, + disabled: options.disabled ?? true, + output: { + element: coreExtensionData.reactElement, + path: coreExtensionData.routePath, + routeRef: coreExtensionData.routeRef.optional(), + title: entityContentTitleExtensionDataRef, + }, + inputs: options.inputs, + configSchema, + factory({ bind, config, inputs, source }) { + const LazyComponent = React.lazy(() => + options + .loader({ config, inputs }) + .then(element => ({ default: () => element })), + ); + + bind({ + path: config.path, + element: ( + + + + ), + routeRef: options.routeRef, + title: config.title, + }); + }, + }); +} diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/alpha-api-report.md index aba33fc092..43e589bdc3 100644 --- a/plugins/catalog/alpha-api-report.md +++ b/plugins/catalog/alpha-api-report.md @@ -12,14 +12,6 @@ import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { PortableSchema } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; -// @alpha (undocumented) -export const CatalogApi: Extension<{}>; - -// @alpha (undocumented) -export const CatalogSearchResultListItemExtension: Extension<{ - noTrack?: boolean | undefined; -}>; - // @alpha (undocumented) export function createCatalogFilterExtension< TInputs extends AnyExtensionInputMap, @@ -62,8 +54,5 @@ const _default: BackstagePlugin< >; export default _default; -// @alpha (undocumented) -export const StarredEntitiesApi: Extension<{}>; - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 214795e73c..9b879e3c50 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -10,13 +10,13 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha/index.ts", + "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, "typesVersions": { "*": { "alpha": [ - "src/alpha/index.ts" + "src/alpha.ts" ], "package.json": [ "package.json" diff --git a/plugins/catalog-react/src/alpha.ts b/plugins/catalog/src/alpha.ts similarity index 85% rename from plugins/catalog-react/src/alpha.ts rename to plugins/catalog/src/alpha.ts index e8ff21609e..e80f131817 100644 --- a/plugins/catalog-react/src/alpha.ts +++ b/plugins/catalog/src/alpha.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { isOwnerOf } from './utils'; -export { useEntityPermission } from './hooks/useEntityPermission'; +export * from './alpha/index'; +export { default } from './alpha/index'; diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index 1716b85a81..d9d2878213 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -38,6 +38,11 @@ import { entityRouteRef, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; +import { + createEntityContentExtension, + createEntityCardExtension, + entityContentTitleExtensionDataRef, +} from '@backstage/plugin-catalog-react/alpha'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; import { DefaultStarredEntitiesApi } from '../apis'; import { @@ -48,6 +53,7 @@ import { } from '../routes'; import { builtInFilterExtensions } from './builtInFilterExtensions'; import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; +import Grid from '@material-ui/core/Grid'; /** @alpha */ export const CatalogApi = createApiExtension({ @@ -102,11 +108,30 @@ const CatalogEntityPage = createPageExtension({ id: 'plugin.catalog.page.entity', defaultPath: '/catalog/:namespace/:kind/:name', routeRef: convertLegacyRouteRef(entityRouteRef), - loader: async () => { + inputs: { + contents: createExtensionInput({ + element: coreExtensionData.reactElement, + path: coreExtensionData.routePath, + routeRef: coreExtensionData.routeRef.optional(), + title: entityContentTitleExtensionDataRef, + }), + }, + loader: async ({ inputs }) => { + const { EntityLayout } = await import('../components/EntityLayout'); const Component = () => { return ( -
🚧 Work In Progress
+ + {inputs.contents.map(content => ( + + {content.element} + + ))} +
); }; @@ -114,6 +139,35 @@ const CatalogEntityPage = createPageExtension({ }, }); +const EntityAboutCard = createEntityCardExtension({ + id: 'about', + loader: async () => + import('../components/AboutCard').then(m => ( + + )), +}); + +const OverviewEntityContent = createEntityContentExtension({ + id: 'overview', + defaultPath: '/', + defaultTitle: 'Overview', + disabled: false, + inputs: { + cards: createExtensionInput({ + element: coreExtensionData.reactElement, + }), + }, + loader: async ({ inputs }) => ( + + {inputs.cards.map(card => ( + + {card.element} + + ))} + + ), +}); + const CatalogNavItem = createNavItemExtension({ id: 'catalog.nav.index', routeRef: convertLegacyRouteRef(rootRouteRef), @@ -140,6 +194,8 @@ export default createPlugin({ CatalogIndexPage, CatalogEntityPage, CatalogNavItem, + OverviewEntityContent, + EntityAboutCard, ...builtInFilterExtensions, ], }); diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx index b7ccb0b12c..ceb5f47364 100644 --- a/plugins/techdocs/src/alpha.tsx +++ b/plugins/techdocs/src/alpha.tsx @@ -42,6 +42,7 @@ import { rootDocsRouteRef, rootRouteRef, } from './routes'; +import { createEntityContentExtension } from '@backstage/plugin-catalog-react/alpha'; /** @alpha */ const techDocsStorage = createApiExtension({ @@ -141,6 +142,18 @@ const TechDocsReaderPage = createPageExtension({ )), }); +/** + * Component responsible for rendering techdocs on entity pages + * + * @alpha + */ +const TechDocsEntityContent = createEntityContentExtension({ + id: 'techdocs', + defaultPath: 'docs', + defaultTitle: 'TechDocs', + loader: () => import('./Router').then(m => ), +}); + /** @alpha */ const TechDocsNavItem = createNavItemExtension({ id: 'plugin.techdocs.nav.index', @@ -158,6 +171,7 @@ export default createPlugin({ TechDocsNavItem, TechDocsIndexPage, TechDocsReaderPage, + TechDocsEntityContent, TechDocsSearchResultListItemExtension, ], routes: { diff --git a/yarn.lock b/yarn.lock index 059c18d859..3075745d85 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5837,6 +5837,7 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" From a9611d42518156fc568ddf023713e345be99720f Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 20 Oct 2023 09:52:47 +0200 Subject: [PATCH 246/348] fix(catalog-react): make entity content routable Signed-off-by: Camila Belo --- plugins/catalog-react/src/alpha.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/catalog-react/src/alpha.tsx b/plugins/catalog-react/src/alpha.tsx index d2eeb8f5f3..58762b1994 100644 --- a/plugins/catalog-react/src/alpha.tsx +++ b/plugins/catalog-react/src/alpha.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React from 'react'; +import React, { lazy } from 'react'; import { AnyExtensionInputMap, Extension, @@ -67,7 +67,7 @@ export function createEntityCardExtension< inputs: options.inputs, configSchema: options.configSchema, factory({ bind, config, inputs, source }) { - const ExtensionComponent = React.lazy(() => + const ExtensionComponent = lazy(() => options .loader({ config, inputs }) .then(element => ({ default: () => element })), @@ -137,7 +137,7 @@ export function createEntityContentExtension< inputs: options.inputs, configSchema, factory({ bind, config, inputs, source }) { - const LazyComponent = React.lazy(() => + const ExtensionComponent = lazy(() => options .loader({ config, inputs }) .then(element => ({ default: () => element })), @@ -145,13 +145,13 @@ export function createEntityContentExtension< bind({ path: config.path, + title: config.title, + routeRef: options.routeRef, element: ( - - + + ), - routeRef: options.routeRef, - title: config.title, }); }, }); From 6bf7561d3c264d8c3bc03ca8443d72e6ff82ce81 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 20 Oct 2023 11:42:19 +0200 Subject: [PATCH 247/348] cli: fix package detection breaking if package.json is not available Signed-off-by: Patrik Oldsberg --- .changeset/rich-pugs-chew.md | 5 +++ .../cli/src/lib/bundler/packageDetection.ts | 38 ++++++++++--------- 2 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 .changeset/rich-pugs-chew.md diff --git a/.changeset/rich-pugs-chew.md b/.changeset/rich-pugs-chew.md new file mode 100644 index 0000000000..6c5aa0af62 --- /dev/null +++ b/.changeset/rich-pugs-chew.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +The experimental package detection will now ignore packages that don't make `package.json` available. diff --git a/packages/cli/src/lib/bundler/packageDetection.ts b/packages/cli/src/lib/bundler/packageDetection.ts index 2095fe23e7..3aa0955c06 100644 --- a/packages/cli/src/lib/bundler/packageDetection.ts +++ b/packages/cli/src/lib/bundler/packageDetection.ts @@ -77,24 +77,28 @@ async function detectPackages( return []; } - const depPackageJson: BackstagePackageJson = require(require.resolve( - `${depName}/package.json`, - { paths: [targetPath] }, - )); - if ( - ['frontend-plugin', 'frontend-plugin-module'].includes( - depPackageJson.backstage?.role ?? '', - ) - ) { - // Include alpha entry point if available. If there's no default export it will be ignored - const exp = depPackageJson.exports; - if (exp && typeof exp === 'object' && './alpha' in exp) { - return [ - { name: depName, import: depName }, - { name: depName, export: './alpha', import: `${depName}/alpha` }, - ]; + try { + const depPackageJson: BackstagePackageJson = require(require.resolve( + `${depName}/package.json`, + { paths: [targetPath] }, + )); + if ( + ['frontend-plugin', 'frontend-plugin-module'].includes( + depPackageJson.backstage?.role ?? '', + ) + ) { + // Include alpha entry point if available. If there's no default export it will be ignored + const exp = depPackageJson.exports; + if (exp && typeof exp === 'object' && './alpha' in exp) { + return [ + { name: depName, import: depName }, + { name: depName, export: './alpha', import: `${depName}/alpha` }, + ]; + } + return [{ name: depName, import: depName }]; } - return [{ name: depName, import: depName }]; + } catch { + /* ignore packages that don't make package.json available */ } return []; }); From f75caf9f3d3e9b5352686c9fe4f9fd35abc43716 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 20 Oct 2023 12:44:25 +0200 Subject: [PATCH 248/348] search-react: fix search bar race Signed-off-by: Patrik Oldsberg --- .changeset/real-carrots-brake.md | 5 ++++ .../components/SearchBar/SearchBar.test.tsx | 1 - .../src/components/SearchBar/SearchBar.tsx | 27 +++++++++++++++---- .../SearchModal/SearchModal.test.tsx | 3 +-- 4 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 .changeset/real-carrots-brake.md diff --git a/.changeset/real-carrots-brake.md b/.changeset/real-carrots-brake.md new file mode 100644 index 0000000000..e9ae1f0c27 --- /dev/null +++ b/.changeset/real-carrots-brake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +Fixed a rare occurrence where a race in the search bar could throw away user input or cause the clear button not to work. diff --git a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx index d9b29584f8..8a3dd84286 100644 --- a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx +++ b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx @@ -339,7 +339,6 @@ describe('SearchBar', () => { value = 'new value'; await user.clear(textbox); - await waitFor(() => expect(textbox.value).toBe('')); // make sure new term is captured await user.type(textbox, value); diff --git a/plugins/search-react/src/components/SearchBar/SearchBar.tsx b/plugins/search-react/src/components/SearchBar/SearchBar.tsx index cfd0538694..d101efa669 100644 --- a/plugins/search-react/src/components/SearchBar/SearchBar.tsx +++ b/plugins/search-react/src/components/SearchBar/SearchBar.tsx @@ -30,6 +30,7 @@ import React, { KeyboardEvent, useCallback, useEffect, + useRef, useState, } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; @@ -88,14 +89,28 @@ export const SearchBarBase: ForwardRefExoticComponent = const configApi = useApi(configApiRef); const [value, setValue] = useState(''); + const forwardedValueRef = useRef(''); useEffect(() => { - setValue(prevValue => - prevValue !== defaultValue ? String(defaultValue) : prevValue, - ); - }, [defaultValue]); + setValue(prevValue => { + // We only update the value if our current value is the same as it was + // for the most recent onChange call. Otherwise it means that the users + // has continued typing and we should not replace their input. + if (prevValue === forwardedValueRef.current) { + return String(defaultValue); + } + return prevValue; + }); + }, [defaultValue, forwardedValueRef]); - useDebounce(() => onChange(value), debounceTime, [value]); + useDebounce( + () => { + forwardedValueRef.current = value; + onChange(value); + }, + debounceTime, + [value], + ); const handleChange = useCallback( (e: ChangeEvent) => { @@ -115,7 +130,9 @@ export const SearchBarBase: ForwardRefExoticComponent = ); const handleClear = useCallback(() => { + forwardedValueRef.current = ''; onChange(''); + setValue(''); if (onClear) { onClear(); } diff --git a/plugins/search/src/components/SearchModal/SearchModal.test.tsx b/plugins/search/src/components/SearchModal/SearchModal.test.tsx index 6fce560800..0d0bfdef5c 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.test.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { screen, waitFor } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import { configApiRef } from '@backstage/core-plugin-api'; @@ -205,7 +205,6 @@ describe('SearchModal', () => { const input = screen.getByLabelText('Search'); await userEvent.clear(input); - await waitFor(() => expect(input.value).toBe('')); await userEvent.type(input, 'new term{enter}'); expect(navigate).toHaveBeenCalledWith('/search?query=new term'); From ec779d4d8cc14aea51930ad0b372683465387607 Mon Sep 17 00:00:00 2001 From: Josh Uvi Date: Fri, 20 Oct 2023 12:16:40 +0100 Subject: [PATCH 249/348] added new backend system package to code-coverage-backend Signed-off-by: Josh Uvi --- plugins/code-coverage-backend/package.json | 1 + yarn.lock | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 9ee98d52ad..d1fa4e4aed 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -30,6 +30,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 0096b61d7e..6ba1771c8e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6096,6 +6096,7 @@ __metadata: resolution: "@backstage/plugin-code-coverage-backend@workspace:plugins/code-coverage-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" From 11f671eaa94c06f9a73ffceeabefbf0cc1e0ff87 Mon Sep 17 00:00:00 2001 From: Josh Uvi Date: Fri, 20 Oct 2023 12:22:09 +0100 Subject: [PATCH 250/348] Added support for new backend system Signed-off-by: Josh Uvi --- .changeset/large-forks-arrive.md | 5 ++ plugins/code-coverage-backend/README.md | 23 ++++++++ plugins/code-coverage-backend/api-report.md | 5 ++ plugins/code-coverage-backend/src/index.ts | 1 + plugins/code-coverage-backend/src/plugin.ts | 60 +++++++++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 .changeset/large-forks-arrive.md create mode 100644 plugins/code-coverage-backend/src/plugin.ts diff --git a/.changeset/large-forks-arrive.md b/.changeset/large-forks-arrive.md new file mode 100644 index 0000000000..3490a87128 --- /dev/null +++ b/.changeset/large-forks-arrive.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-code-coverage-backend': patch +--- + +Added support for new backend system diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md index 54cf201015..4d5c473c56 100644 --- a/plugins/code-coverage-backend/README.md +++ b/plugins/code-coverage-backend/README.md @@ -67,6 +67,29 @@ diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts apiRouter.use(notFoundHandler()); ``` +## New Backend System + +The code coverage backend plugin has support for the [new backend system](https://backstage.io/docs/backend-system/), here's how you can set that up: + +In your `packages/backend/src/index.ts` make the following changes: + +```diff + import { createBackend } from '@backstage/backend-defaults'; ++ import { codeCoveragePlugin } from '@backstage/plugin-code-coverage-backend'; + const backend = createBackend(); + // ... other feature additions ++ backend.add(codeCoveragePlugin()); + backend.start(); +``` + +Alternatively, you can actually remove the import line above, and do this instead. + +```diff + backend.add(explorePlugin()); ++ backend.add(import('@backstage/plugin-explore-backend')); + +``` + ## Configuring your entity In order to use this plugin, you must set the `backstage.io/code-coverage` annotation. diff --git a/plugins/code-coverage-backend/api-report.md b/plugins/code-coverage-backend/api-report.md index 440af50714..8a64361391 100644 --- a/plugins/code-coverage-backend/api-report.md +++ b/plugins/code-coverage-backend/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import express from 'express'; @@ -11,6 +12,10 @@ import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; +// @public +const codeCoveragePlugin: () => BackendFeature; +export default codeCoveragePlugin; + // @public export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/code-coverage-backend/src/index.ts b/plugins/code-coverage-backend/src/index.ts index 8511c9b71e..31de2ab3e3 100644 --- a/plugins/code-coverage-backend/src/index.ts +++ b/plugins/code-coverage-backend/src/index.ts @@ -22,3 +22,4 @@ export { createRouter } from './service/router'; export type { RouterOptions } from './service/router'; +export { codeCoveragePlugin as default } from './plugin'; diff --git a/plugins/code-coverage-backend/src/plugin.ts b/plugins/code-coverage-backend/src/plugin.ts new file mode 100644 index 0000000000..340280795f --- /dev/null +++ b/plugins/code-coverage-backend/src/plugin.ts @@ -0,0 +1,60 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * Code coverage backend plugin + * + * @public + */ +export const codeCoveragePlugin = createBackendPlugin({ + pluginId: 'codeCoverage', + register(env) { + env.registerInit({ + deps: { + config: coreServices.rootConfig, + logger: coreServices.logger, + urlReader: coreServices.urlReader, + httpRouter: coreServices.httpRouter, + discovery: coreServices.discovery, + database: coreServices.database, + }, + async init({ + config, + logger, + urlReader, + httpRouter, + discovery, + database, + }) { + httpRouter.use( + await createRouter({ + config, + logger: loggerToWinstonLogger(logger), + urlReader, + discovery, + database, + }), + ); + }, + }); + }, +}); From 5c5a5a8207b7cd271c13ac752463085203665715 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 18 Sep 2023 13:18:29 +0200 Subject: [PATCH 251/348] feat: work on enable vite Signed-off-by: blam --- packages/cli/package.json | 2 + packages/cli/src/lib/bundler/server.ts | 143 ++++++++++++++++--------- 2 files changed, 93 insertions(+), 52 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 419b02d929..1a1909a87c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -68,6 +68,7 @@ "@types/webpack-env": "^1.15.2", "@typescript-eslint/eslint-plugin": "6.7.5", "@typescript-eslint/parser": "^6.7.2", + "@vitejs/plugin-react": "^4.0.4", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "^3.0.0-rc.4", "bfj": "^7.0.2", @@ -132,6 +133,7 @@ "tar": "^6.1.12", "terser-webpack-plugin": "^5.1.3", "util": "^0.12.3", + "vite": "^4.4.9", "webpack": "^5.70.0", "webpack-dev-server": "^4.7.3", "webpack-node-externals": "^3.0.0", diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index 78f6bb7823..7cf089607c 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -22,6 +22,8 @@ import uniq from 'lodash/uniq'; import openBrowser from 'react-dev-utils/openBrowser'; import webpack from 'webpack'; import WebpackDevServer from 'webpack-dev-server'; +import vite from 'vite'; +import react from '@vitejs/plugin-react'; import { forbiddenDuplicatesFilter, @@ -77,7 +79,7 @@ export async function serveBundle(options: ServeOptions) { const { name } = await fs.readJson(libPaths.resolveTarget('package.json')); - let server: WebpackDevServer | undefined = undefined; + let server: WebpackDevServer | vite.ViteDevServer | undefined = undefined; let latestFrontendAppConfigs: AppConfig[] = []; const cliConfig = await loadCliConfig({ @@ -86,7 +88,15 @@ export async function serveBundle(options: ServeOptions) { withFilteredKeys: true, watch(appConfigs) { latestFrontendAppConfigs = appConfigs; - server?.invalidate(); + if (server) { + if ('invalidate' in server) { + server?.invalidate(); + } + + if ('restart' in server) { + server?.restart(); + } + } }, }); latestFrontendAppConfigs = cliConfig.frontendAppConfigs; @@ -123,7 +133,15 @@ export async function serveBundle(options: ServeOptions) { config: fullConfig, targetPath: paths.targetPath, watch() { - server?.invalidate(); + if (server) { + if ('invalidate' in server) { + server?.invalidate(); + } + + if ('restart' in server) { + server?.restart(); + } + } }, }); @@ -139,58 +157,79 @@ export async function serveBundle(options: ServeOptions) { additionalEntryPoints: detectedModulesEntryPoint, }); - const compiler = webpack(config); - - server = new WebpackDevServer( - { - hot: !process.env.CI, - devMiddleware: { - publicPath: config.output?.publicPath as string, - stats: 'errors-warnings', + if (process.env.EXPERIMENTAL_VITE) { + server = await vite.createServer({ + plugins: [react()], + server: { + host, + port, }, - static: paths.targetPublic - ? { - publicPath: config.output?.publicPath as string, - directory: paths.targetPublic, - } - : undefined, - historyApiFallback: { - // Paths with dots should still use the history fallback. - // See https://github.com/facebookincubator/create-react-app/issues/387. - disableDotRule: true, - - // The index needs to be rewritten relative to the new public path, including subroutes. - index: `${config.output?.publicPath}index.html`, + build: { + commonjsOptions: { + include: ['*'], + transformMixedEsModules: true, + }, }, - https: - url.protocol === 'https:' - ? { - cert: fullConfig.getString('app.https.certificate.cert'), - key: fullConfig.getString('app.https.certificate.key'), - } - : false, - host, - port, - proxy: targetPkg.proxy, - // When the dev server is behind a proxy, the host and public hostname differ - allowedHosts: [url.hostname], - client: { - webSocketURL: 'auto://0.0.0.0:0/ws', - }, - } as any, - compiler as any, - ); - - await new Promise((resolve, reject) => { - server?.startCallback((err?: Error) => { - if (err) { - reject(err); - return; - } - - openBrowser(url.href); - resolve(); + publicDir: paths.targetPublic, }); + } else { + const compiler = webpack(config); + + server = new WebpackDevServer( + { + hot: !process.env.CI, + devMiddleware: { + publicPath: config.output?.publicPath as string, + stats: 'errors-warnings', + }, + static: paths.targetPublic + ? { + publicPath: config.output?.publicPath as string, + directory: paths.targetPublic, + } + : undefined, + historyApiFallback: { + // Paths with dots should still use the history fallback. + // See https://github.com/facebookincubator/create-react-app/issues/387. + disableDotRule: true, + + // The index needs to be rewritten relative to the new public path, including subroutes. + index: `${config.output?.publicPath}index.html`, + }, + https: + url.protocol === 'https:' + ? { + cert: fullConfig.getString('app.https.certificate.cert'), + key: fullConfig.getString('app.https.certificate.key'), + } + : false, + host, + port, + proxy: targetPkg.proxy, + // When the dev server is behind a proxy, the host and public hostname differ + allowedHosts: [url.hostname], + client: { + webSocketURL: 'auto://0.0.0.0:0/ws', + }, + } as any, + compiler as any, + ); + } + + await new Promise(async (resolve, reject) => { + if (process.env.EXPERIMENTAL_VITE) { + await (server as vite.ViteDevServer).listen(); + resolve(); + } else { + (server as WebpackDevServer).startCallback((err?: Error) => { + if (err) { + reject(err); + return; + } + }); + } + openBrowser(url.href); + resolve(); }); const waitForExit = async () => { From 0e6fc26cbf55e338579b6c93de18dfef0b5ffe5f Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 21 Sep 2023 13:33:41 +0200 Subject: [PATCH 252/348] chore: some more vite work Signed-off-by: blam --- packages/cli/package.json | 4 +++ packages/cli/src/lib/bundler/server.ts | 43 +++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 1a1909a87c..ae181bceef 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -42,11 +42,13 @@ "@backstage/types": "workspace:^", "@esbuild-kit/cjs-loader": "^2.4.1", "@esbuild-kit/esm-loader": "^2.5.5", + "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@manypkg/get-packages": "^1.1.3", "@octokit/graphql": "^5.0.0", "@octokit/graphql-schema": "^13.7.0", "@octokit/oauth-app": "^4.2.0", "@octokit/request": "^6.0.0", + "@originjs/vite-plugin-commonjs": "^1.0.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@rollup/plugin-commonjs": "^23.0.0", "@rollup/plugin-json": "^5.0.0", @@ -134,6 +136,8 @@ "terser-webpack-plugin": "^5.1.3", "util": "^0.12.3", "vite": "^4.4.9", + "vite-plugin-node-polyfills": "^0.14.1", + "vite-plugin-svgr": "^4.0.0", "webpack": "^5.70.0", "webpack-dev-server": "^4.7.3", "webpack-node-externals": "^3.0.0", diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index 7cf089607c..455c18d3c2 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -36,6 +36,10 @@ import { createConfig, resolveBaseUrl } from './config'; import { createDetectedModulesEntryPoint } from './packageDetection'; import { resolveBundlingPaths } from './paths'; import { ServeOptions } from './types'; +import { nodePolyfills as viteNodePolyfills } from 'vite-plugin-node-polyfills'; +import { esbuildCommonjs, viteCommonjs } from '@originjs/vite-plugin-commonjs'; +import pluginSvgr from 'vite-plugin-svgr'; +import vitePluginSvgr from 'vite-plugin-svgr'; export async function serveBundle(options: ServeOptions) { const paths = resolveBundlingPaths(options); @@ -159,11 +163,47 @@ export async function serveBundle(options: ServeOptions) { if (process.env.EXPERIMENTAL_VITE) { server = await vite.createServer({ - plugins: [react()], + define: { + global: 'globalThis', + APP_CONFIG: JSON.stringify(cliConfig.frontendAppConfigs), + }, + resolve: { + alias: { + 'node-fetch': 'cross-fetch', + }, + }, + plugins: [ + react(), + vitePluginSvgr(), + viteCommonjs(), + viteNodePolyfills(), + { + name: 'transform-index-html', + configureServer(s) { + s.middlewares.use(async (req, res, next) => { + if (req.url === '/') { + res.end( + await s.transformIndexHtml( + req.url, + await fs.readFile(paths.targetHtml, 'utf-8'), + ), + ); + } else { + next(); + } + }); + }, + }, + ], server: { host, port, }, + optimizeDeps: { + esbuildOptions: { + plugins: [esbuildCommonjs(['!nano-css'])], + }, + }, build: { commonjsOptions: { include: ['*'], @@ -171,6 +211,7 @@ export async function serveBundle(options: ServeOptions) { }, }, publicDir: paths.targetPublic, + root: paths.targetPath, }); } else { const compiler = webpack(config); From b3989e18a1b4ab41f10a80288cc138d44c5f4f98 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 2 Oct 2023 15:32:51 +0200 Subject: [PATCH 253/348] chore: some little trickery Signed-off-by: blam --- packages/cli/package.json | 1 + packages/cli/src/lib/bundler/server.ts | 20 ++------------------ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index ae181bceef..e2f26b8000 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -136,6 +136,7 @@ "terser-webpack-plugin": "^5.1.3", "util": "^0.12.3", "vite": "^4.4.9", + "vite-plugin-html-template": "^1.2.0", "vite-plugin-node-polyfills": "^0.14.1", "vite-plugin-svgr": "^4.0.0", "webpack": "^5.70.0", diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index 455c18d3c2..48a020ecf2 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -38,7 +38,7 @@ import { resolveBundlingPaths } from './paths'; import { ServeOptions } from './types'; import { nodePolyfills as viteNodePolyfills } from 'vite-plugin-node-polyfills'; import { esbuildCommonjs, viteCommonjs } from '@originjs/vite-plugin-commonjs'; -import pluginSvgr from 'vite-plugin-svgr'; +import htmlTemplate from 'vite-plugin-html-template'; import vitePluginSvgr from 'vite-plugin-svgr'; export async function serveBundle(options: ServeOptions) { @@ -177,23 +177,7 @@ export async function serveBundle(options: ServeOptions) { vitePluginSvgr(), viteCommonjs(), viteNodePolyfills(), - { - name: 'transform-index-html', - configureServer(s) { - s.middlewares.use(async (req, res, next) => { - if (req.url === '/') { - res.end( - await s.transformIndexHtml( - req.url, - await fs.readFile(paths.targetHtml, 'utf-8'), - ), - ); - } else { - next(); - } - }); - }, - }, + htmlTemplate(), ], server: { host, From 605c0d171bf2a5e76ad804b24d9d64de27b1fbeb Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 2 Oct 2023 15:51:56 +0200 Subject: [PATCH 254/348] chore: more small work Signed-off-by: blam --- packages/app/public/index.html | 44 +- packages/cli/src/lib/bundler/server.ts | 8 +- yarn.lock | 1084 ++++++++++++++++++++++-- 3 files changed, 1009 insertions(+), 127 deletions(-) diff --git a/packages/app/public/index.html b/packages/app/public/index.html index a3c3ef19b8..4e22ba45e8 100644 --- a/packages/app/public/index.html +++ b/packages/app/public/index.html @@ -41,43 +41,6 @@ href="<%= publicPath %>/safari-pinned-tab.svg" color="#5bbad5" /> - <%= config.getString('app.title') %> - - <% if (config.has('app.datadogRum')) { %> - - <% } %> @@ -93,5 +56,12 @@ To begin the development, run `yarn start`. To create a production bundle, use `yarn build`. --> + + + + <% } %> @@ -56,12 +93,5 @@ To begin the development, run `yarn start`. To create a production bundle, use `yarn build`. --> - - - `; + + if (req.url === '/') { + res.end(await s.transformIndexHtml(req.url, rendered)); + } else { + next(); + } + }); + }, +}); diff --git a/yarn.lock b/yarn.lock index 98e0a6358b..eb2088e9cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3833,6 +3833,7 @@ __metadata: "@swc/jest": ^0.2.22 "@types/cross-spawn": ^6.0.2 "@types/diff": ^5.0.0 + "@types/ejs": ^3.1.3 "@types/express": ^4.17.6 "@types/fs-extra": ^9.0.1 "@types/http-proxy": ^1.17.4 @@ -3865,6 +3866,7 @@ __metadata: ctrlc-windows: ^2.1.0 del: ^7.0.0 diff: ^5.0.0 + ejs: ^3.1.9 esbuild: ^0.19.0 esbuild-loader: ^2.18.0 eslint: ^8.6.0 @@ -3922,6 +3924,7 @@ __metadata: type-fest: ^2.19.0 util: ^0.12.3 vite: ^4.4.9 + vite-plugin-html: ^3.2.0 vite-plugin-html-template: ^1.2.0 vite-plugin-node-polyfills: ^0.14.1 vite-plugin-svgr: ^4.0.0 @@ -15035,7 +15038,7 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^4.1.1, @rollup/pluginutils@npm:^4.2.1": +"@rollup/pluginutils@npm:^4.1.1, @rollup/pluginutils@npm:^4.2.0, @rollup/pluginutils@npm:^4.2.1": version: 4.2.1 resolution: "@rollup/pluginutils@npm:4.2.1" dependencies: @@ -17617,6 +17620,13 @@ __metadata: languageName: node linkType: hard +"@types/ejs@npm:^3.1.3": + version: 3.1.3 + resolution: "@types/ejs@npm:3.1.3" + checksum: b1b1c6c9d331d237523ebc410789f42edcdbb1d4cdd4a7a37ac61d2ce9c3fbcfbfe7d7f1a7f61c9334812347a0036afd52258ad2198f85545ebfb26d63475a75 + languageName: node + linkType: hard + "@types/es-aggregate-error@npm:^1.0.2": version: 1.0.2 resolution: "@types/es-aggregate-error@npm:1.0.2" @@ -22617,6 +22627,13 @@ __metadata: languageName: node linkType: hard +"connect-history-api-fallback@npm:^1.6.0": + version: 1.6.0 + resolution: "connect-history-api-fallback@npm:1.6.0" + checksum: 804ca2be28c999032ecd37a9f71405e5d7b7a4b3defcebbe41077bb8c5a0a150d7b59f51dcc33b2de30bc7e217a31d10f8cfad27e8e74c2fc7655eeba82d6e7e + languageName: node + linkType: hard + "connect-history-api-fallback@npm:^2.0.0": version: 2.0.0 resolution: "connect-history-api-fallback@npm:2.0.0" @@ -22634,7 +22651,7 @@ __metadata: languageName: node linkType: hard -"consola@npm:^2.15.0": +"consola@npm:^2.15.0, consola@npm:^2.15.3": version: 2.15.3 resolution: "consola@npm:2.15.3" checksum: 8ef7a09b703ec67ac5c389a372a33b6dc97eda6c9876443a60d76a3076eea0259e7f67a4e54fd5a52f97df73690822d090cf8b7e102b5761348afef7c6d03e28 @@ -23123,16 +23140,16 @@ __metadata: languageName: node linkType: hard -"css-select@npm:^4.1.3": - version: 4.1.3 - resolution: "css-select@npm:4.1.3" +"css-select@npm:^4.1.3, css-select@npm:^4.2.1": + version: 4.3.0 + resolution: "css-select@npm:4.3.0" dependencies: boolbase: ^1.0.0 - css-what: ^5.0.0 - domhandler: ^4.2.0 - domutils: ^2.6.0 - nth-check: ^2.0.0 - checksum: 40928f1aa6c71faf36430e7f26bcbb8ab51d07b98b754caacb71906400a195df5e6c7020a94f2982f02e52027b9bd57c99419220cf7020968c3415f14e4be5f8 + css-what: ^6.0.1 + domhandler: ^4.3.1 + domutils: ^2.8.0 + nth-check: ^2.0.1 + checksum: d6202736839194dd7f910320032e7cfc40372f025e4bf21ca5bf6eb0a33264f322f50ba9c0adc35dadd342d3d6fae5ca244779a4873afbfa76561e343f2058e0 languageName: node linkType: hard @@ -23196,14 +23213,7 @@ __metadata: languageName: node linkType: hard -"css-what@npm:^5.0.0": - version: 5.1.0 - resolution: "css-what@npm:5.1.0" - checksum: 0b75d1bac95c885c168573c85744a6c6843d8c33345f54f717218b37ea6296b0e99bb12105930ea170fd4a921990392a7c790c16c585c1d8960c49e2b7ec39f7 - languageName: node - linkType: hard - -"css-what@npm:^6.1.0": +"css-what@npm:^6.0.1, css-what@npm:^6.1.0": version: 6.1.0 resolution: "css-what@npm:6.1.0" checksum: b975e547e1e90b79625918f84e67db5d33d896e6de846c9b584094e529f0c63e2ab85ee33b9daffd05bff3a146a1916bec664e18bb76dd5f66cbff9fc13b2bbe @@ -24218,12 +24228,12 @@ __metadata: languageName: node linkType: hard -"domhandler@npm:^4.0.0, domhandler@npm:^4.2.0": - version: 4.3.0 - resolution: "domhandler@npm:4.3.0" +"domhandler@npm:^4.0.0, domhandler@npm:^4.2.0, domhandler@npm:^4.3.1": + version: 4.3.1 + resolution: "domhandler@npm:4.3.1" dependencies: domelementtype: ^2.2.0 - checksum: d2a2dbf40dd99abf936b65ad83c6b530afdb3605a87cad37a11b5d9220e68423ebef1b86c89e0f6d93ffaf315cc327cf1a988652e7a9a95cce539e3984f4c64d + checksum: 4c665ceed016e1911bf7d1dadc09dc888090b64dee7851cccd2fcf5442747ec39c647bb1cb8c8919f8bbdd0f0c625a6bafeeed4b2d656bbecdbae893f43ffaaa languageName: node linkType: hard @@ -24250,7 +24260,7 @@ __metadata: languageName: node linkType: hard -"domutils@npm:^2.5.2, domutils@npm:^2.6.0": +"domutils@npm:^2.5.2, domutils@npm:^2.8.0": version: 2.8.0 resolution: "domutils@npm:2.8.0" dependencies: @@ -24291,6 +24301,13 @@ __metadata: languageName: node linkType: hard +"dotenv-expand@npm:^8.0.2": + version: 8.0.3 + resolution: "dotenv-expand@npm:8.0.3" + checksum: 128ce90ac825b543de3ece0154a51b056ab0dc36bb26d97a68cd0b8707327ecd3c182fb6ac63b26a0fcdfa85064419906a1065cb634f1f9dc08ad311375f1fc0 + languageName: node + linkType: hard + "dotenv@npm:^16.0.0": version: 16.0.0 resolution: "dotenv@npm:16.0.0" @@ -24411,14 +24428,14 @@ __metadata: languageName: node linkType: hard -"ejs@npm:^3.1.6": - version: 3.1.7 - resolution: "ejs@npm:3.1.7" +"ejs@npm:^3.1.6, ejs@npm:^3.1.9": + version: 3.1.9 + resolution: "ejs@npm:3.1.9" dependencies: jake: ^10.8.5 bin: ejs: bin/cli.js - checksum: fe40764af39955ce8f8b116716fc8b911959946698edb49ecab85df597746c07aa65d5b74ead28a1e2ffa75b0f92d9bedd752f1c29437da6137b3518271e988c + checksum: af6f10eb815885ff8a8cfacc42c6b6cf87daf97a4884f87a30e0c3271fedd85d76a3a297d9c33a70e735b97ee632887f85e32854b9cdd3a2d97edf931519a35f languageName: node linkType: hard @@ -28473,7 +28490,7 @@ __metadata: languageName: node linkType: hard -"html-minifier-terser@npm:^6.0.2": +"html-minifier-terser@npm:^6.0.2, html-minifier-terser@npm:^6.1.0": version: 6.1.0 resolution: "html-minifier-terser@npm:6.1.0" dependencies: @@ -34214,6 +34231,16 @@ __metadata: languageName: node linkType: hard +"node-html-parser@npm:^5.3.3": + version: 5.4.2 + resolution: "node-html-parser@npm:5.4.2" + dependencies: + css-select: ^4.2.1 + he: 1.2.0 + checksum: 2d2391147c83b402786eeab95d23ea4e24ca8608e0e70a2823bfd4f2a248be13a8cc31acfd55a0109e051131e4f0c17d7ada8d999ce70ff2e342ab0110f5da59 + languageName: node + linkType: hard + "node-html-parser@npm:^6.1.1": version: 6.1.5 resolution: "node-html-parser@npm:6.1.5" @@ -34557,7 +34584,7 @@ __metadata: languageName: node linkType: hard -"nth-check@npm:^2.0.0, nth-check@npm:^2.0.1": +"nth-check@npm:^2.0.1": version: 2.1.1 resolution: "nth-check@npm:2.1.1" dependencies: @@ -35670,6 +35697,13 @@ __metadata: languageName: node linkType: hard +"pathe@npm:^0.2.0": + version: 0.2.0 + resolution: "pathe@npm:0.2.0" + checksum: 9a8149ce152088f30d15b0b03a7c128ba21f16b4dc1f3f90fe38eee9f6d0f1d6da8e4e47bd2a4f9e14aaac7c30ed01cfc86216479011de2bdc598b65e6f19f41 + languageName: node + linkType: hard + "pause@npm:0.0.1": version: 0.0.1 resolution: "pause@npm:0.0.1" @@ -42799,6 +42833,28 @@ __metadata: languageName: node linkType: hard +"vite-plugin-html@npm:^3.2.0": + version: 3.2.0 + resolution: "vite-plugin-html@npm:3.2.0" + dependencies: + "@rollup/pluginutils": ^4.2.0 + colorette: ^2.0.16 + connect-history-api-fallback: ^1.6.0 + consola: ^2.15.3 + dotenv: ^16.0.0 + dotenv-expand: ^8.0.2 + ejs: ^3.1.6 + fast-glob: ^3.2.11 + fs-extra: ^10.0.1 + html-minifier-terser: ^6.1.0 + node-html-parser: ^5.3.3 + pathe: ^0.2.0 + peerDependencies: + vite: ">=2.0.0" + checksum: f5222247b65da1c36215f0b2f509fd3975a7426b8d44546beb49f3ba51ee87b3a6b6e6afc9e7567a0d8bd1016631f2db3f934808f62a7c8f7f83fa83d8561d2d + languageName: node + linkType: hard + "vite-plugin-node-polyfills@npm:^0.14.1": version: 0.14.1 resolution: "vite-plugin-node-polyfills@npm:0.14.1" From cf3fe0510f708d19713cd940ad0bbc92eb672c6c Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 3 Oct 2023 12:16:54 +0200 Subject: [PATCH 256/348] chore: initial version of vite Signed-off-by: blam --- packages/cli/package.json | 2 - yarn.lock | 85 ++------------------------------------- 2 files changed, 4 insertions(+), 83 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index d2e0b9e8ec..86d1ae5fa9 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -137,8 +137,6 @@ "terser-webpack-plugin": "^5.1.3", "util": "^0.12.3", "vite": "^4.4.9", - "vite-plugin-html": "^3.2.0", - "vite-plugin-html-template": "^1.2.0", "vite-plugin-node-polyfills": "^0.14.1", "vite-plugin-svgr": "^4.0.0", "webpack": "^5.70.0", diff --git a/yarn.lock b/yarn.lock index eb2088e9cc..118e8dba2b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3924,8 +3924,6 @@ __metadata: type-fest: ^2.19.0 util: ^0.12.3 vite: ^4.4.9 - vite-plugin-html: ^3.2.0 - vite-plugin-html-template: ^1.2.0 vite-plugin-node-polyfills: ^0.14.1 vite-plugin-svgr: ^4.0.0 webpack: ^5.70.0 @@ -15038,7 +15036,7 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^4.1.1, @rollup/pluginutils@npm:^4.2.0, @rollup/pluginutils@npm:^4.2.1": +"@rollup/pluginutils@npm:^4.1.1, @rollup/pluginutils@npm:^4.2.1": version: 4.2.1 resolution: "@rollup/pluginutils@npm:4.2.1" dependencies: @@ -22627,13 +22625,6 @@ __metadata: languageName: node linkType: hard -"connect-history-api-fallback@npm:^1.6.0": - version: 1.6.0 - resolution: "connect-history-api-fallback@npm:1.6.0" - checksum: 804ca2be28c999032ecd37a9f71405e5d7b7a4b3defcebbe41077bb8c5a0a150d7b59f51dcc33b2de30bc7e217a31d10f8cfad27e8e74c2fc7655eeba82d6e7e - languageName: node - linkType: hard - "connect-history-api-fallback@npm:^2.0.0": version: 2.0.0 resolution: "connect-history-api-fallback@npm:2.0.0" @@ -22651,7 +22642,7 @@ __metadata: languageName: node linkType: hard -"consola@npm:^2.15.0, consola@npm:^2.15.3": +"consola@npm:^2.15.0": version: 2.15.3 resolution: "consola@npm:2.15.3" checksum: 8ef7a09b703ec67ac5c389a372a33b6dc97eda6c9876443a60d76a3076eea0259e7f67a4e54fd5a52f97df73690822d090cf8b7e102b5761348afef7c6d03e28 @@ -23140,7 +23131,7 @@ __metadata: languageName: node linkType: hard -"css-select@npm:^4.1.3, css-select@npm:^4.2.1": +"css-select@npm:^4.1.3": version: 4.3.0 resolution: "css-select@npm:4.3.0" dependencies: @@ -24301,13 +24292,6 @@ __metadata: languageName: node linkType: hard -"dotenv-expand@npm:^8.0.2": - version: 8.0.3 - resolution: "dotenv-expand@npm:8.0.3" - checksum: 128ce90ac825b543de3ece0154a51b056ab0dc36bb26d97a68cd0b8707327ecd3c182fb6ac63b26a0fcdfa85064419906a1065cb634f1f9dc08ad311375f1fc0 - languageName: node - linkType: hard - "dotenv@npm:^16.0.0": version: 16.0.0 resolution: "dotenv@npm:16.0.0" @@ -28490,7 +28474,7 @@ __metadata: languageName: node linkType: hard -"html-minifier-terser@npm:^6.0.2, html-minifier-terser@npm:^6.1.0": +"html-minifier-terser@npm:^6.0.2": version: 6.1.0 resolution: "html-minifier-terser@npm:6.1.0" dependencies: @@ -34231,16 +34215,6 @@ __metadata: languageName: node linkType: hard -"node-html-parser@npm:^5.3.3": - version: 5.4.2 - resolution: "node-html-parser@npm:5.4.2" - dependencies: - css-select: ^4.2.1 - he: 1.2.0 - checksum: 2d2391147c83b402786eeab95d23ea4e24ca8608e0e70a2823bfd4f2a248be13a8cc31acfd55a0109e051131e4f0c17d7ada8d999ce70ff2e342ab0110f5da59 - languageName: node - linkType: hard - "node-html-parser@npm:^6.1.1": version: 6.1.5 resolution: "node-html-parser@npm:6.1.5" @@ -35697,13 +35671,6 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^0.2.0": - version: 0.2.0 - resolution: "pathe@npm:0.2.0" - checksum: 9a8149ce152088f30d15b0b03a7c128ba21f16b4dc1f3f90fe38eee9f6d0f1d6da8e4e47bd2a4f9e14aaac7c30ed01cfc86216479011de2bdc598b65e6f19f41 - languageName: node - linkType: hard - "pause@npm:0.0.1": version: 0.0.1 resolution: "pause@npm:0.0.1" @@ -39610,19 +39577,6 @@ __metadata: languageName: node linkType: hard -"shelljs@npm:0.8.4": - version: 0.8.4 - resolution: "shelljs@npm:0.8.4" - dependencies: - glob: ^7.0.0 - interpret: ^1.0.0 - rechoir: ^0.6.2 - bin: - shjs: bin/shjs - checksum: 27f83206ef6a4f5b74a493726c3e6b4c3e07a9c2aac94c5e692d800a61353c18a8234967bd8523b1346abe718beb563843687fb57f466529ba06db3cae6f0bb3 - languageName: node - linkType: hard - "shelljs@npm:^0.8.5": version: 0.8.5 resolution: "shelljs@npm:0.8.5" @@ -42824,37 +42778,6 @@ __metadata: languageName: node linkType: hard -"vite-plugin-html-template@npm:^1.2.0": - version: 1.2.0 - resolution: "vite-plugin-html-template@npm:1.2.0" - dependencies: - shelljs: 0.8.4 - checksum: ca157c02b13cded3136818ee399e5a1caccb41836d4407680c16c4ad3449aab7fc6b1f62376a2cc9620dff6a5144c831a44dbdf21f85eb19b0cdc768480f2aad - languageName: node - linkType: hard - -"vite-plugin-html@npm:^3.2.0": - version: 3.2.0 - resolution: "vite-plugin-html@npm:3.2.0" - dependencies: - "@rollup/pluginutils": ^4.2.0 - colorette: ^2.0.16 - connect-history-api-fallback: ^1.6.0 - consola: ^2.15.3 - dotenv: ^16.0.0 - dotenv-expand: ^8.0.2 - ejs: ^3.1.6 - fast-glob: ^3.2.11 - fs-extra: ^10.0.1 - html-minifier-terser: ^6.1.0 - node-html-parser: ^5.3.3 - pathe: ^0.2.0 - peerDependencies: - vite: ">=2.0.0" - checksum: f5222247b65da1c36215f0b2f509fd3975a7426b8d44546beb49f3ba51ee87b3a6b6e6afc9e7567a0d8bd1016631f2db3f934808f62a7c8f7f83fa83d8561d2d - languageName: node - linkType: hard - "vite-plugin-node-polyfills@npm:^0.14.1": version: 0.14.1 resolution: "vite-plugin-node-polyfills@npm:0.14.1" From e14cbf563d2e6d2f62a415e21f581f1ffbc158d1 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 3 Oct 2023 12:18:11 +0200 Subject: [PATCH 257/348] chore: added chantgeset Signed-off-by: blam --- .changeset/swift-mice-care.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/swift-mice-care.md diff --git a/.changeset/swift-mice-care.md b/.changeset/swift-mice-care.md new file mode 100644 index 0000000000..1d0d7d8703 --- /dev/null +++ b/.changeset/swift-mice-care.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Added `EXPERIMENTAL_VITE` flag for using [vite](https://vitejs.dev) as dev server instead of Webpack From f014a14c83fdc132c4d2a6fd66942e6bb1af878e Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 3 Oct 2023 12:22:02 +0200 Subject: [PATCH 258/348] chore: remove superfluous dependency Signed-off-by: blam --- packages/cli/package.json | 1 - yarn.lock | 10 ---------- 2 files changed, 11 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 86d1ae5fa9..c7d0aff18a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -42,7 +42,6 @@ "@backstage/types": "workspace:^", "@esbuild-kit/cjs-loader": "^2.4.1", "@esbuild-kit/esm-loader": "^2.5.5", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@manypkg/get-packages": "^1.1.3", "@octokit/graphql": "^5.0.0", "@octokit/graphql-schema": "^13.7.0", diff --git a/yarn.lock b/yarn.lock index 118e8dba2b..2b18799361 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3807,7 +3807,6 @@ __metadata: "@backstage/types": "workspace:^" "@esbuild-kit/cjs-loader": ^2.4.1 "@esbuild-kit/esm-loader": ^2.5.5 - "@esbuild-plugins/node-globals-polyfill": ^0.2.3 "@manypkg/get-packages": ^1.1.3 "@octokit/graphql": ^5.0.0 "@octokit/graphql-schema": ^13.7.0 @@ -10758,15 +10757,6 @@ __metadata: languageName: node linkType: hard -"@esbuild-plugins/node-globals-polyfill@npm:^0.2.3": - version: 0.2.3 - resolution: "@esbuild-plugins/node-globals-polyfill@npm:0.2.3" - peerDependencies: - esbuild: "*" - checksum: f83eeaa382680b26a3b1cf6c396450332c41d2dc0f9fd935d3f4bacf5412bef7383d2aeb4246a858781435b7c005a570dadc81051f8a038f1ef2111f17d3d8b0 - languageName: node - linkType: hard - "@esbuild/android-arm64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/android-arm64@npm:0.16.17" From f93f44e9265dccd1a8b1abe250f5fc1a459caf50 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 4 Oct 2023 10:11:24 +0200 Subject: [PATCH 259/348] chore: fixing typings Signed-off-by: blam Signed-off-by: blam --- packages/cli/src/lib/bundler/viteTransformHtml.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/lib/bundler/viteTransformHtml.ts b/packages/cli/src/lib/bundler/viteTransformHtml.ts index 9d18e75ff9..fcbced3c40 100644 --- a/packages/cli/src/lib/bundler/viteTransformHtml.ts +++ b/packages/cli/src/lib/bundler/viteTransformHtml.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { JsonObject } from '@backstage/types'; + import { PluginOption } from 'vite'; import fs from 'fs/promises'; import { render } from 'ejs'; @@ -26,7 +26,7 @@ export const viteTransformHtml = ({ }: { targetHtml: string; entryPath: string; - data: JsonObject; + data: any; }): PluginOption => ({ name: 'backstage:transform:html', configureServer(s) { From e7b7373d34c7bd03c50c5c94458e1e5170ab2b6a Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 08:47:23 +0200 Subject: [PATCH 260/348] chore: tidying up a little more and removing superfluous config Signed-off-by: blam --- packages/cli/package.json | 2 +- packages/cli/src/lib/bundler/server.ts | 33 +- .../cli/src/lib/bundler/viteTransformHtml.ts | 45 --- yarn.lock | 315 ++++-------------- 4 files changed, 81 insertions(+), 314 deletions(-) delete mode 100644 packages/cli/src/lib/bundler/viteTransformHtml.ts diff --git a/packages/cli/package.json b/packages/cli/package.json index c7d0aff18a..e8a9c5df2d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -82,7 +82,6 @@ "css-loader": "^6.5.1", "ctrlc-windows": "^2.1.0", "diff": "^5.0.0", - "ejs": "^3.1.9", "esbuild": "^0.19.0", "esbuild-loader": "^2.18.0", "eslint": "^8.6.0", @@ -136,6 +135,7 @@ "terser-webpack-plugin": "^5.1.3", "util": "^0.12.3", "vite": "^4.4.9", + "vite-plugin-html": "^3.2.0", "vite-plugin-node-polyfills": "^0.14.1", "vite-plugin-svgr": "^4.0.0", "webpack": "^5.70.0", diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index 8ccb7991ff..e1da630c53 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -24,6 +24,10 @@ import webpack from 'webpack'; import WebpackDevServer from 'webpack-dev-server'; import vite from 'vite'; import react from '@vitejs/plugin-react'; +import { nodePolyfills as viteNodePolyfills } from 'vite-plugin-node-polyfills'; +import { createHtmlPlugin } from 'vite-plugin-html'; +import { viteCommonjs } from '@originjs/vite-plugin-commonjs'; +import vitePluginSvgr from 'vite-plugin-svgr'; import { forbiddenDuplicatesFilter, @@ -36,10 +40,6 @@ import { createConfig, resolveBaseUrl } from './config'; import { createDetectedModulesEntryPoint } from './packageDetection'; import { resolveBundlingPaths } from './paths'; import { ServeOptions } from './types'; -import { nodePolyfills as viteNodePolyfills } from 'vite-plugin-node-polyfills'; -import { esbuildCommonjs, viteCommonjs } from '@originjs/vite-plugin-commonjs'; -import { viteTransformHtml } from './viteTransformHtml'; -import vitePluginSvgr from 'vite-plugin-svgr'; export async function serveBundle(options: ServeOptions) { const paths = resolveBundlingPaths(options); @@ -178,12 +178,14 @@ export async function serveBundle(options: ServeOptions) { vitePluginSvgr(), viteCommonjs(), viteNodePolyfills(), - viteTransformHtml({ - entryPath: paths.targetEntry, - targetHtml: paths.targetHtml, - data: { - config: frontendConfig, - publicPath: config.output?.publicPath, + createHtmlPlugin({ + entry: paths.targetEntry, + template: 'public/index.html', + inject: { + data: { + config: frontendConfig, + publicPath: config.output?.publicPath, + }, }, }), ], @@ -191,17 +193,6 @@ export async function serveBundle(options: ServeOptions) { host, port, }, - optimizeDeps: { - esbuildOptions: { - plugins: [esbuildCommonjs(['!nano-css'])], - }, - }, - build: { - commonjsOptions: { - include: ['*'], - transformMixedEsModules: true, - }, - }, publicDir: paths.targetPublic, root: paths.targetPath, }); diff --git a/packages/cli/src/lib/bundler/viteTransformHtml.ts b/packages/cli/src/lib/bundler/viteTransformHtml.ts deleted file mode 100644 index fcbced3c40..0000000000 --- a/packages/cli/src/lib/bundler/viteTransformHtml.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2023 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 { PluginOption } from 'vite'; -import fs from 'fs/promises'; -import { render } from 'ejs'; -import { relative } from 'path'; - -export const viteTransformHtml = ({ - targetHtml, - entryPath, - data, -}: { - targetHtml: string; - entryPath: string; - data: any; -}): PluginOption => ({ - name: 'backstage:transform:html', - configureServer(s) { - s.middlewares.use(async (req, res, next) => { - const html = await fs.readFile(targetHtml, 'utf-8'); - const rendered = `${render(html, data)} - `; - - if (req.url === '/') { - res.end(await s.transformIndexHtml(req.url, rendered)); - } else { - next(); - } - }); - }, -}); diff --git a/yarn.lock b/yarn.lock index 2b18799361..689543fa43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,3 +1,6 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + __metadata: version: 6 cacheKey: 8 @@ -3849,8 +3852,8 @@ __metadata: "@types/terser-webpack-plugin": ^5.0.4 "@types/webpack-env": ^1.15.2 "@types/yarnpkg__lockfile": ^1.1.4 - "@typescript-eslint/eslint-plugin": ^5.9.0 - "@typescript-eslint/parser": ^5.9.0 + "@typescript-eslint/eslint-plugin": 6.7.5 + "@typescript-eslint/parser": ^6.7.2 "@vitejs/plugin-react": ^4.0.4 "@yarnpkg/lockfile": ^1.1.0 "@yarnpkg/parsers": ^3.0.0-rc.4 @@ -3865,7 +3868,6 @@ __metadata: ctrlc-windows: ^2.1.0 del: ^7.0.0 diff: ^5.0.0 - ejs: ^3.1.9 esbuild: ^0.19.0 esbuild-loader: ^2.18.0 eslint: ^8.6.0 @@ -3923,6 +3925,7 @@ __metadata: type-fest: ^2.19.0 util: ^0.12.3 vite: ^4.4.9 + vite-plugin-html: ^3.2.0 vite-plugin-node-polyfills: ^0.14.1 vite-plugin-svgr: ^4.0.0 webpack: ^5.70.0 @@ -10974,13 +10977,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.15.18": - version: 0.15.18 - resolution: "@esbuild/linux-loong64@npm:0.15.18" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - "@esbuild/linux-loong64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-loong64@npm:0.16.17" @@ -15026,7 +15022,7 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^4.1.1, @rollup/pluginutils@npm:^4.2.1": +"@rollup/pluginutils@npm:^4.1.1, @rollup/pluginutils@npm:^4.2.0, @rollup/pluginutils@npm:^4.2.1": version: 4.2.1 resolution: "@rollup/pluginutils@npm:4.2.1" dependencies: @@ -22615,6 +22611,13 @@ __metadata: languageName: node linkType: hard +"connect-history-api-fallback@npm:^1.6.0": + version: 1.6.0 + resolution: "connect-history-api-fallback@npm:1.6.0" + checksum: 804ca2be28c999032ecd37a9f71405e5d7b7a4b3defcebbe41077bb8c5a0a150d7b59f51dcc33b2de30bc7e217a31d10f8cfad27e8e74c2fc7655eeba82d6e7e + languageName: node + linkType: hard + "connect-history-api-fallback@npm:^2.0.0": version: 2.0.0 resolution: "connect-history-api-fallback@npm:2.0.0" @@ -22632,7 +22635,7 @@ __metadata: languageName: node linkType: hard -"consola@npm:^2.15.0": +"consola@npm:^2.15.0, consola@npm:^2.15.3": version: 2.15.3 resolution: "consola@npm:2.15.3" checksum: 8ef7a09b703ec67ac5c389a372a33b6dc97eda6c9876443a60d76a3076eea0259e7f67a4e54fd5a52f97df73690822d090cf8b7e102b5761348afef7c6d03e28 @@ -23121,7 +23124,7 @@ __metadata: languageName: node linkType: hard -"css-select@npm:^4.1.3": +"css-select@npm:^4.1.3, css-select@npm:^4.2.1": version: 4.3.0 resolution: "css-select@npm:4.3.0" dependencies: @@ -24282,6 +24285,13 @@ __metadata: languageName: node linkType: hard +"dotenv-expand@npm:^8.0.2": + version: 8.0.3 + resolution: "dotenv-expand@npm:8.0.3" + checksum: 128ce90ac825b543de3ece0154a51b056ab0dc36bb26d97a68cd0b8707327ecd3c182fb6ac63b26a0fcdfa85064419906a1065cb634f1f9dc08ad311375f1fc0 + languageName: node + linkType: hard + "dotenv@npm:^16.0.0": version: 16.0.0 resolution: "dotenv@npm:16.0.0" @@ -24402,7 +24412,7 @@ __metadata: languageName: node linkType: hard -"ejs@npm:^3.1.6, ejs@npm:^3.1.9": +"ejs@npm:^3.1.6": version: 3.1.9 resolution: "ejs@npm:3.1.9" dependencies: @@ -24773,13 +24783,6 @@ __metadata: languageName: node linkType: hard -"esbuild-android-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-android-64@npm:0.15.18" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - "esbuild-android-arm64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-android-arm64@npm:0.14.54" @@ -24787,13 +24790,6 @@ __metadata: languageName: node linkType: hard -"esbuild-android-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-android-arm64@npm:0.15.18" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - "esbuild-darwin-64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-darwin-64@npm:0.14.54" @@ -24801,13 +24797,6 @@ __metadata: languageName: node linkType: hard -"esbuild-darwin-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-darwin-64@npm:0.15.18" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - "esbuild-darwin-arm64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-darwin-arm64@npm:0.14.54" @@ -24815,13 +24804,6 @@ __metadata: languageName: node linkType: hard -"esbuild-darwin-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-darwin-arm64@npm:0.15.18" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - "esbuild-freebsd-64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-freebsd-64@npm:0.14.54" @@ -24829,13 +24811,6 @@ __metadata: languageName: node linkType: hard -"esbuild-freebsd-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-freebsd-64@npm:0.15.18" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - "esbuild-freebsd-arm64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-freebsd-arm64@npm:0.14.54" @@ -24843,13 +24818,6 @@ __metadata: languageName: node linkType: hard -"esbuild-freebsd-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-freebsd-arm64@npm:0.15.18" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - "esbuild-linux-32@npm:0.14.54": version: 0.14.54 resolution: "esbuild-linux-32@npm:0.14.54" @@ -24857,13 +24825,6 @@ __metadata: languageName: node linkType: hard -"esbuild-linux-32@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-32@npm:0.15.18" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - "esbuild-linux-64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-linux-64@npm:0.14.54" @@ -24871,13 +24832,6 @@ __metadata: languageName: node linkType: hard -"esbuild-linux-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-64@npm:0.15.18" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - "esbuild-linux-arm64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-linux-arm64@npm:0.14.54" @@ -24885,13 +24839,6 @@ __metadata: languageName: node linkType: hard -"esbuild-linux-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-arm64@npm:0.15.18" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - "esbuild-linux-arm@npm:0.14.54": version: 0.14.54 resolution: "esbuild-linux-arm@npm:0.14.54" @@ -24899,13 +24846,6 @@ __metadata: languageName: node linkType: hard -"esbuild-linux-arm@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-arm@npm:0.15.18" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - "esbuild-linux-mips64le@npm:0.14.54": version: 0.14.54 resolution: "esbuild-linux-mips64le@npm:0.14.54" @@ -24913,13 +24853,6 @@ __metadata: languageName: node linkType: hard -"esbuild-linux-mips64le@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-mips64le@npm:0.15.18" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - "esbuild-linux-ppc64le@npm:0.14.54": version: 0.14.54 resolution: "esbuild-linux-ppc64le@npm:0.14.54" @@ -24927,13 +24860,6 @@ __metadata: languageName: node linkType: hard -"esbuild-linux-ppc64le@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-ppc64le@npm:0.15.18" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - "esbuild-linux-riscv64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-linux-riscv64@npm:0.14.54" @@ -24941,13 +24867,6 @@ __metadata: languageName: node linkType: hard -"esbuild-linux-riscv64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-riscv64@npm:0.15.18" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - "esbuild-linux-s390x@npm:0.14.54": version: 0.14.54 resolution: "esbuild-linux-s390x@npm:0.14.54" @@ -24955,13 +24874,6 @@ __metadata: languageName: node linkType: hard -"esbuild-linux-s390x@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-s390x@npm:0.15.18" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - "esbuild-loader@npm:^2.18.0": version: 2.21.0 resolution: "esbuild-loader@npm:2.21.0" @@ -24985,13 +24897,6 @@ __metadata: languageName: node linkType: hard -"esbuild-netbsd-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-netbsd-64@npm:0.15.18" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - "esbuild-openbsd-64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-openbsd-64@npm:0.14.54" @@ -24999,13 +24904,6 @@ __metadata: languageName: node linkType: hard -"esbuild-openbsd-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-openbsd-64@npm:0.15.18" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - "esbuild-sunos-64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-sunos-64@npm:0.14.54" @@ -25013,13 +24911,6 @@ __metadata: languageName: node linkType: hard -"esbuild-sunos-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-sunos-64@npm:0.15.18" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - "esbuild-windows-32@npm:0.14.54": version: 0.14.54 resolution: "esbuild-windows-32@npm:0.14.54" @@ -25027,13 +24918,6 @@ __metadata: languageName: node linkType: hard -"esbuild-windows-32@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-windows-32@npm:0.15.18" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - "esbuild-windows-64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-windows-64@npm:0.14.54" @@ -25041,13 +24925,6 @@ __metadata: languageName: node linkType: hard -"esbuild-windows-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-windows-64@npm:0.15.18" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "esbuild-windows-arm64@npm:0.14.54": version: 0.14.54 resolution: "esbuild-windows-arm64@npm:0.14.54" @@ -25055,13 +24932,6 @@ __metadata: languageName: node linkType: hard -"esbuild-windows-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-windows-arm64@npm:0.15.18" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - "esbuild@npm:^0.14.14": version: 0.14.54 resolution: "esbuild@npm:0.14.54" @@ -25213,7 +25083,7 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.18.10": +"esbuild@npm:^0.18.10, esbuild@npm:~0.18.20": version: 0.18.20 resolution: "esbuild@npm:0.18.20" dependencies: @@ -25367,83 +25237,6 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:~0.18.20": - version: 0.18.20 - resolution: "esbuild@npm:0.18.20" - dependencies: - "@esbuild/android-arm": 0.18.20 - "@esbuild/android-arm64": 0.18.20 - "@esbuild/android-x64": 0.18.20 - "@esbuild/darwin-arm64": 0.18.20 - "@esbuild/darwin-x64": 0.18.20 - "@esbuild/freebsd-arm64": 0.18.20 - "@esbuild/freebsd-x64": 0.18.20 - "@esbuild/linux-arm": 0.18.20 - "@esbuild/linux-arm64": 0.18.20 - "@esbuild/linux-ia32": 0.18.20 - "@esbuild/linux-loong64": 0.18.20 - "@esbuild/linux-mips64el": 0.18.20 - "@esbuild/linux-ppc64": 0.18.20 - "@esbuild/linux-riscv64": 0.18.20 - "@esbuild/linux-s390x": 0.18.20 - "@esbuild/linux-x64": 0.18.20 - "@esbuild/netbsd-x64": 0.18.20 - "@esbuild/openbsd-x64": 0.18.20 - "@esbuild/sunos-x64": 0.18.20 - "@esbuild/win32-arm64": 0.18.20 - "@esbuild/win32-ia32": 0.18.20 - "@esbuild/win32-x64": 0.18.20 - dependenciesMeta: - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 5d253614e50cdb6ec22095afd0c414f15688e7278a7eb4f3720a6dd1306b0909cf431e7b9437a90d065a31b1c57be60130f63fe3e8d0083b588571f31ee6ec7b - languageName: node - linkType: hard - "escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1" @@ -28464,7 +28257,7 @@ __metadata: languageName: node linkType: hard -"html-minifier-terser@npm:^6.0.2": +"html-minifier-terser@npm:^6.0.2, html-minifier-terser@npm:^6.1.0": version: 6.1.0 resolution: "html-minifier-terser@npm:6.1.0" dependencies: @@ -34205,6 +33998,16 @@ __metadata: languageName: node linkType: hard +"node-html-parser@npm:^5.3.3": + version: 5.4.2 + resolution: "node-html-parser@npm:5.4.2" + dependencies: + css-select: ^4.2.1 + he: 1.2.0 + checksum: 2d2391147c83b402786eeab95d23ea4e24ca8608e0e70a2823bfd4f2a248be13a8cc31acfd55a0109e051131e4f0c17d7ada8d999ce70ff2e342ab0110f5da59 + languageName: node + linkType: hard + "node-html-parser@npm:^6.1.1": version: 6.1.5 resolution: "node-html-parser@npm:6.1.5" @@ -35661,6 +35464,13 @@ __metadata: languageName: node linkType: hard +"pathe@npm:^0.2.0": + version: 0.2.0 + resolution: "pathe@npm:0.2.0" + checksum: 9a8149ce152088f30d15b0b03a7c128ba21f16b4dc1f3f90fe38eee9f6d0f1d6da8e4e47bd2a4f9e14aaac7c30ed01cfc86216479011de2bdc598b65e6f19f41 + languageName: node + linkType: hard + "pause@npm:0.0.1": version: 0.0.1 resolution: "pause@npm:0.0.1" @@ -36445,17 +36255,6 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.1.0, postcss@npm:^8.4.21": - version: 8.4.31 - resolution: "postcss@npm:8.4.31" - dependencies: - nanoid: ^3.3.6 - picocolors: ^1.0.0 - source-map-js: ^1.0.2 - checksum: 1d8611341b073143ad90486fcdfeab49edd243377b1f51834dc4f6d028e82ce5190e4f11bb2633276864503654fb7cab28e67abdc0fbf9d1f88cad4a0ff0beea - languageName: node - linkType: hard - "postcss@npm:^8.1.0, postcss@npm:^8.4.21, postcss@npm:^8.4.27": version: 8.4.31 resolution: "postcss@npm:8.4.31" @@ -42768,6 +42567,28 @@ __metadata: languageName: node linkType: hard +"vite-plugin-html@npm:^3.2.0": + version: 3.2.0 + resolution: "vite-plugin-html@npm:3.2.0" + dependencies: + "@rollup/pluginutils": ^4.2.0 + colorette: ^2.0.16 + connect-history-api-fallback: ^1.6.0 + consola: ^2.15.3 + dotenv: ^16.0.0 + dotenv-expand: ^8.0.2 + ejs: ^3.1.6 + fast-glob: ^3.2.11 + fs-extra: ^10.0.1 + html-minifier-terser: ^6.1.0 + node-html-parser: ^5.3.3 + pathe: ^0.2.0 + peerDependencies: + vite: ">=2.0.0" + checksum: f5222247b65da1c36215f0b2f509fd3975a7426b8d44546beb49f3ba51ee87b3a6b6e6afc9e7567a0d8bd1016631f2db3f934808f62a7c8f7f83fa83d8561d2d + languageName: node + linkType: hard + "vite-plugin-node-polyfills@npm:^0.14.1": version: 0.14.1 resolution: "vite-plugin-node-polyfills@npm:0.14.1" @@ -42796,8 +42617,8 @@ __metadata: linkType: hard "vite@npm:^4.4.9": - version: 4.4.9 - resolution: "vite@npm:4.4.9" + version: 4.4.11 + resolution: "vite@npm:4.4.11" dependencies: esbuild: ^0.18.10 fsevents: ~2.3.2 @@ -42831,7 +42652,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: c511024ceae39c68c7dbf2ac4381ee655cd7bb62cf43867a14798bc835d3320b8fa7867a336143c30825c191c1fb4e9aa3348fce831ab617e96203080d3d2908 + checksum: c22145c8385343a629cd546054b9da6eee60327540102bdfd1ad897fd2e78e0763ce6a18a9d84fdefde9da8fd2427d3bec9eb2697b47cf4068c7b4b52f7e3e6a languageName: node linkType: hard From 5c0e295c2a80b8df0756337cd75aa8c624868aba Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 08:48:39 +0200 Subject: [PATCH 261/348] chore: fix ejs Signed-off-by: blam --- packages/cli/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index e8a9c5df2d..aac991f7f0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -159,7 +159,6 @@ "@backstage/theme": "workspace:^", "@types/cross-spawn": "^6.0.2", "@types/diff": "^5.0.0", - "@types/ejs": "^3.1.3", "@types/express": "^4.17.6", "@types/fs-extra": "^9.0.1", "@types/http-proxy": "^1.17.4", From e53067c4d8b47bc1c7c6a9096e843efc6b50d937 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 09:11:51 +0200 Subject: [PATCH 262/348] chore: fix yarn.lock dirt Signed-off-by: blam --- .github/vale/Vocab/Backstage/accept.txt | 1 + yarn.lock | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index 1a028d1387..e1c65fec06 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -430,6 +430,7 @@ Valentina validator validators varchar +vite VMware Vodafone VPCs diff --git a/yarn.lock b/yarn.lock index 689543fa43..75dc30f83a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3835,7 +3835,6 @@ __metadata: "@swc/jest": ^0.2.22 "@types/cross-spawn": ^6.0.2 "@types/diff": ^5.0.0 - "@types/ejs": ^3.1.3 "@types/express": ^4.17.6 "@types/fs-extra": ^9.0.1 "@types/http-proxy": ^1.17.4 @@ -17604,13 +17603,6 @@ __metadata: languageName: node linkType: hard -"@types/ejs@npm:^3.1.3": - version: 3.1.3 - resolution: "@types/ejs@npm:3.1.3" - checksum: b1b1c6c9d331d237523ebc410789f42edcdbb1d4cdd4a7a37ac61d2ce9c3fbcfbfe7d7f1a7f61c9334812347a0036afd52258ad2198f85545ebfb26d63475a75 - languageName: node - linkType: hard - "@types/es-aggregate-error@npm:^1.0.2": version: 1.0.2 resolution: "@types/es-aggregate-error@npm:1.0.2" From 78561f8a29e67418d470f0efcf1a13fb5437485e Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 10:41:06 +0200 Subject: [PATCH 263/348] chore: remove svgr support Signed-off-by: blam --- packages/cli/package.json | 2 +- packages/cli/src/lib/bundler/server.ts | 5 +- yarn.lock | 160 +++---------------------- 3 files changed, 17 insertions(+), 150 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index aac991f7f0..80db8fb005 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -137,7 +137,6 @@ "vite": "^4.4.9", "vite-plugin-html": "^3.2.0", "vite-plugin-node-polyfills": "^0.14.1", - "vite-plugin-svgr": "^4.0.0", "webpack": "^5.70.0", "webpack-dev-server": "^4.7.3", "webpack-node-externals": "^3.0.0", @@ -159,6 +158,7 @@ "@backstage/theme": "workspace:^", "@types/cross-spawn": "^6.0.2", "@types/diff": "^5.0.0", + "@types/ejs": "^3.1.3", "@types/express": "^4.17.6", "@types/fs-extra": "^9.0.1", "@types/http-proxy": "^1.17.4", diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index e1da630c53..219b589723 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -27,7 +27,6 @@ import react from '@vitejs/plugin-react'; import { nodePolyfills as viteNodePolyfills } from 'vite-plugin-node-polyfills'; import { createHtmlPlugin } from 'vite-plugin-html'; import { viteCommonjs } from '@originjs/vite-plugin-commonjs'; -import vitePluginSvgr from 'vite-plugin-svgr'; import { forbiddenDuplicatesFilter, @@ -161,6 +160,7 @@ export async function serveBundle(options: ServeOptions) { additionalEntryPoints: detectedModulesEntryPoint, }); + console.log(paths.targetHtml); if (process.env.EXPERIMENTAL_VITE) { server = await vite.createServer({ define: { @@ -175,12 +175,11 @@ export async function serveBundle(options: ServeOptions) { }, plugins: [ react(), - vitePluginSvgr(), viteCommonjs(), viteNodePolyfills(), createHtmlPlugin({ entry: paths.targetEntry, - template: 'public/index.html', + template: `public/index.html`, inject: { data: { config: frontendConfig, diff --git a/yarn.lock b/yarn.lock index 75dc30f83a..ddc4c0b2c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1827,7 +1827,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.14.0, @babel/core@npm:^7.19.6, @babel/core@npm:^7.21.3, @babel/core@npm:^7.22.20": +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.14.0, @babel/core@npm:^7.19.6, @babel/core@npm:^7.22.20": version: 7.23.0 resolution: "@babel/core@npm:7.23.0" dependencies: @@ -3414,7 +3414,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": version: 7.23.0 resolution: "@babel/types@npm:7.23.0" dependencies: @@ -3835,6 +3835,7 @@ __metadata: "@swc/jest": ^0.2.22 "@types/cross-spawn": ^6.0.2 "@types/diff": ^5.0.0 + "@types/ejs": ^3.1.3 "@types/express": ^4.17.6 "@types/fs-extra": ^9.0.1 "@types/http-proxy": ^1.17.4 @@ -3926,7 +3927,6 @@ __metadata: vite: ^4.4.9 vite-plugin-html: ^3.2.0 vite-plugin-node-polyfills: ^0.14.1 - vite-plugin-svgr: ^4.0.0 webpack: ^5.70.0 webpack-dev-server: ^4.7.3 webpack-node-externals: ^3.0.0 @@ -15031,7 +15031,7 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^5.0.1, @rollup/pluginutils@npm:^5.0.4": +"@rollup/pluginutils@npm:^5.0.1": version: 5.0.4 resolution: "@rollup/pluginutils@npm:5.0.4" dependencies: @@ -16062,15 +16062,6 @@ __metadata: languageName: node linkType: hard -"@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 3fc8e35d16f5abe0af5efe5851f27581225ac405d6a1ca44cda0df064cddfcc29a428c48c2e4bef6cebf627c9ac2f652a096030edb02cf5a120ce28d3c234710 - languageName: node - linkType: hard - "@svgr/babel-plugin-add-jsx-attribute@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/babel-plugin-add-jsx-attribute@npm:6.5.1" @@ -16080,7 +16071,7 @@ __metadata: languageName: node linkType: hard -"@svgr/babel-plugin-remove-jsx-attribute@npm:*, @svgr/babel-plugin-remove-jsx-attribute@npm:8.0.0": +"@svgr/babel-plugin-remove-jsx-attribute@npm:*": version: 8.0.0 resolution: "@svgr/babel-plugin-remove-jsx-attribute@npm:8.0.0" peerDependencies: @@ -16089,7 +16080,7 @@ __metadata: languageName: node linkType: hard -"@svgr/babel-plugin-remove-jsx-empty-expression@npm:*, @svgr/babel-plugin-remove-jsx-empty-expression@npm:8.0.0": +"@svgr/babel-plugin-remove-jsx-empty-expression@npm:*": version: 8.0.0 resolution: "@svgr/babel-plugin-remove-jsx-empty-expression@npm:8.0.0" peerDependencies: @@ -16098,15 +16089,6 @@ __metadata: languageName: node linkType: hard -"@svgr/babel-plugin-replace-jsx-attribute-value@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-replace-jsx-attribute-value@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 1edda65ef4f4dd8f021143c8ec276a08f6baa6f733b8e8ee2e7775597bf6b97afb47fdeefd579d6ae6c959fe2e634f55cd61d99377631212228c8cfb351b8921 - languageName: node - linkType: hard - "@svgr/babel-plugin-replace-jsx-attribute-value@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/babel-plugin-replace-jsx-attribute-value@npm:6.5.1" @@ -16116,15 +16098,6 @@ __metadata: languageName: node linkType: hard -"@svgr/babel-plugin-svg-dynamic-title@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-svg-dynamic-title@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 876cec891488992e6a9aebb8155e2bea4ec461b4718c51de36e988e00e271c6d9d01ef6be17b9effd44b2b3d7db0b41c161a5904a46ae6f38b26b387ad7f3709 - languageName: node - linkType: hard - "@svgr/babel-plugin-svg-dynamic-title@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/babel-plugin-svg-dynamic-title@npm:6.5.1" @@ -16134,15 +16107,6 @@ __metadata: languageName: node linkType: hard -"@svgr/babel-plugin-svg-em-dimensions@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-svg-em-dimensions@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: be0e2d391164428327d9ec469a52cea7d93189c6b0e2c290999e048f597d777852f701c64dca44cd45b31ed14a7f859520326e2e4ad7c3a4545d0aa235bc7e9a - languageName: node - linkType: hard - "@svgr/babel-plugin-svg-em-dimensions@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/babel-plugin-svg-em-dimensions@npm:6.5.1" @@ -16152,15 +16116,6 @@ __metadata: languageName: node linkType: hard -"@svgr/babel-plugin-transform-react-native-svg@npm:8.1.0": - version: 8.1.0 - resolution: "@svgr/babel-plugin-transform-react-native-svg@npm:8.1.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 85b434a57572f53bd2b9f0606f253e1fcf57b4a8c554ec3f2d43ed17f50d8cae200cb3aaf1ec9d626e1456e8b135dce530ae047eb0bed6d4bf98a752d6640459 - languageName: node - linkType: hard - "@svgr/babel-plugin-transform-react-native-svg@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/babel-plugin-transform-react-native-svg@npm:6.5.1" @@ -16170,15 +16125,6 @@ __metadata: languageName: node linkType: hard -"@svgr/babel-plugin-transform-svg-component@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-transform-svg-component@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 04e2023d75693eeb0890341c40e449881184663056c249be7e5c80168e4aabb0fadd255e8d5d2dbf54b8c2a6e700efba994377135bfa4060dc4a2e860116ef8c - languageName: node - linkType: hard - "@svgr/babel-plugin-transform-svg-component@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/babel-plugin-transform-svg-component@npm:6.5.1" @@ -16188,24 +16134,6 @@ __metadata: languageName: node linkType: hard -"@svgr/babel-preset@npm:8.1.0": - version: 8.1.0 - resolution: "@svgr/babel-preset@npm:8.1.0" - dependencies: - "@svgr/babel-plugin-add-jsx-attribute": 8.0.0 - "@svgr/babel-plugin-remove-jsx-attribute": 8.0.0 - "@svgr/babel-plugin-remove-jsx-empty-expression": 8.0.0 - "@svgr/babel-plugin-replace-jsx-attribute-value": 8.0.0 - "@svgr/babel-plugin-svg-dynamic-title": 8.0.0 - "@svgr/babel-plugin-svg-em-dimensions": 8.0.0 - "@svgr/babel-plugin-transform-react-native-svg": 8.1.0 - "@svgr/babel-plugin-transform-svg-component": 8.0.0 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 3a67930f080b8891e1e8e2595716b879c944d253112bae763dce59807ba23454d162216c8d66a0a0e3d4f38a649ecd6c387e545d1e1261dd69a68e9a3392ee08 - languageName: node - linkType: hard - "@svgr/babel-preset@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/babel-preset@npm:6.5.1" @@ -16237,29 +16165,6 @@ __metadata: languageName: node linkType: hard -"@svgr/core@npm:^8.1.0": - version: 8.1.0 - resolution: "@svgr/core@npm:8.1.0" - dependencies: - "@babel/core": ^7.21.3 - "@svgr/babel-preset": 8.1.0 - camelcase: ^6.2.0 - cosmiconfig: ^8.1.3 - snake-case: ^3.0.4 - checksum: da4a12865c7dc59829d58df8bd232d6c85b7115fda40da0d2f844a1a51886e2e945560596ecfc0345d37837ac457de86a931e8b8d8550e729e0c688c02250d8a - languageName: node - linkType: hard - -"@svgr/hast-util-to-babel-ast@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/hast-util-to-babel-ast@npm:8.0.0" - dependencies: - "@babel/types": ^7.21.3 - entities: ^4.4.0 - checksum: 88401281a38bbc7527e65ff5437970414391a86158ef4b4046c89764c156d2d39ecd7cce77be8a51994c9fb3249170cb1eb8b9128b62faaa81743ef6ed3534ab - languageName: node - linkType: hard - "@svgr/hast-util-to-babel-ast@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/hast-util-to-babel-ast@npm:6.5.1" @@ -16284,20 +16189,6 @@ __metadata: languageName: node linkType: hard -"@svgr/plugin-jsx@npm:^8.1.0": - version: 8.1.0 - resolution: "@svgr/plugin-jsx@npm:8.1.0" - dependencies: - "@babel/core": ^7.21.3 - "@svgr/babel-preset": 8.1.0 - "@svgr/hast-util-to-babel-ast": 8.0.0 - svg-parser: ^2.0.4 - peerDependencies: - "@svgr/core": "*" - checksum: 0418a9780753d3544912ee2dad5d2cf8d12e1ba74df8053651b3886aeda54d5f0f7d2dece0af5e0d838332c4f139a57f0dabaa3ca1afa4d1a765efce6a7656f2 - languageName: node - linkType: hard - "@svgr/plugin-svgo@npm:6.5.x, @svgr/plugin-svgo@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/plugin-svgo@npm:6.5.1" @@ -17603,6 +17494,13 @@ __metadata: languageName: node linkType: hard +"@types/ejs@npm:^3.1.3": + version: 3.1.3 + resolution: "@types/ejs@npm:3.1.3" + checksum: b1b1c6c9d331d237523ebc410789f42edcdbb1d4cdd4a7a37ac61d2ce9c3fbcfbfe7d7f1a7f61c9334812347a0036afd52258ad2198f85545ebfb26d63475a75 + languageName: node + linkType: hard + "@types/es-aggregate-error@npm:^1.0.2": version: 1.0.2 resolution: "@types/es-aggregate-error@npm:1.0.2" @@ -22869,23 +22767,6 @@ __metadata: languageName: node linkType: hard -"cosmiconfig@npm:^8.1.3": - version: 8.3.6 - resolution: "cosmiconfig@npm:8.3.6" - dependencies: - import-fresh: ^3.3.0 - js-yaml: ^4.1.0 - parse-json: ^5.2.0 - path-type: ^4.0.0 - peerDependencies: - typescript: ">=4.9.5" - peerDependenciesMeta: - typescript: - optional: true - checksum: dc339ebea427898c9e03bf01b56ba7afbac07fc7d2a2d5a15d6e9c14de98275a9565da949375aee1809591c152c0a3877bb86dbeaf74d5bd5aaa79955ad9e7a0 - languageName: node - linkType: hard - "cpu-features@npm:0.0.2": version: 0.0.2 resolution: "cpu-features@npm:0.0.2" @@ -28628,7 +28509,7 @@ __metadata: languageName: node linkType: hard -"import-fresh@npm:^3.1.0, import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": +"import-fresh@npm:^3.1.0, import-fresh@npm:^3.2.1": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" dependencies: @@ -42595,19 +42476,6 @@ __metadata: languageName: node linkType: hard -"vite-plugin-svgr@npm:^4.0.0": - version: 4.1.0 - resolution: "vite-plugin-svgr@npm:4.1.0" - dependencies: - "@rollup/pluginutils": ^5.0.4 - "@svgr/core": ^8.1.0 - "@svgr/plugin-jsx": ^8.1.0 - peerDependencies: - vite: ^2.6.0 || 3 || 4 - checksum: b2896d851a75d86d9b21b8a64c8bc8090601d6b26fcfb4739b84314dbb8b426daa7ad451e02e54ce8ae4f8473e19990caa362e2a3e9a22ee1cea0eb27c15f018 - languageName: node - linkType: hard - "vite@npm:^4.4.9": version: 4.4.11 resolution: "vite@npm:4.4.11" From a665f954a01336aadfc819bcfdf94e637007200e Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 10:42:05 +0200 Subject: [PATCH 264/348] chore: don't need templating here Signed-off-by: blam --- packages/cli/src/lib/bundler/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index 219b589723..4390ffd176 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -179,7 +179,7 @@ export async function serveBundle(options: ServeOptions) { viteNodePolyfills(), createHtmlPlugin({ entry: paths.targetEntry, - template: `public/index.html`, + template: 'public/index.html', inject: { data: { config: frontendConfig, From a2cdb7c22ee7e257727f19c7f4c9d557abfefd61 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 10:48:11 +0200 Subject: [PATCH 265/348] chore: add a comment Signed-off-by: blam --- packages/cli/src/lib/bundler/server.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index 4390ffd176..a6fa159440 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -179,6 +179,8 @@ export async function serveBundle(options: ServeOptions) { viteNodePolyfills(), createHtmlPlugin({ entry: paths.targetEntry, + // todo(blam): we should look at contributing to the plugin here + // to support absolute paths, but works in the interim at least. template: 'public/index.html', inject: { data: { From 2d5ec21f5cc3db61a5a032489dc8442561720a41 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 10:51:45 +0200 Subject: [PATCH 266/348] chore: remove needless optional chaining Signed-off-by: blam --- packages/cli/src/lib/bundler/server.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index a6fa159440..076a54cd1a 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -93,11 +93,11 @@ export async function serveBundle(options: ServeOptions) { latestFrontendAppConfigs = appConfigs; if (server) { if ('invalidate' in server) { - server?.invalidate(); + server.invalidate(); } if ('restart' in server) { - server?.restart(); + server.restart(); } } }, @@ -138,11 +138,11 @@ export async function serveBundle(options: ServeOptions) { watch() { if (server) { if ('invalidate' in server) { - server?.invalidate(); + server.invalidate(); } if ('restart' in server) { - server?.restart(); + server.restart(); } } }, From 6436c5ac6faa5d903a2de83846fad4683e455240 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 13:13:27 +0200 Subject: [PATCH 267/348] chore: cleanup Signed-off-by: blam --- packages/cli/src/lib/bundler/server.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index 076a54cd1a..ece9b4a6d1 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -244,6 +244,7 @@ export async function serveBundle(options: ServeOptions) { await new Promise(async (resolve, reject) => { if (process.env.EXPERIMENTAL_VITE) { await (server as vite.ViteDevServer).listen(); + (server as vite.ViteDevServer).openBrowser(); resolve(); } else { (server as WebpackDevServer).startCallback((err?: Error) => { @@ -251,10 +252,10 @@ export async function serveBundle(options: ServeOptions) { reject(err); return; } + openBrowser(url.href); + resolve(); }); } - openBrowser(url.href); - resolve(); }); const waitForExit = async () => { From b4e21496d7e69ffe6eebe9d1dba9aac2b7cbec5c Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 16:29:35 +0200 Subject: [PATCH 268/348] feat: simplfy even further! Signed-off-by: blam --- packages/cli/package.json | 1 - packages/cli/src/lib/bundler/server.ts | 12 +- .../src/legacy/TaskPage/TaskPage.tsx | 4 +- yarn.lock | 231 ------------------ 4 files changed, 3 insertions(+), 245 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 80db8fb005..4f26a72785 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -47,7 +47,6 @@ "@octokit/graphql-schema": "^13.7.0", "@octokit/oauth-app": "^4.2.0", "@octokit/request": "^6.0.0", - "@originjs/vite-plugin-commonjs": "^1.0.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@rollup/plugin-commonjs": "^23.0.0", "@rollup/plugin-json": "^5.0.0", diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index ece9b4a6d1..ead1343f0d 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -26,7 +26,6 @@ import vite from 'vite'; import react from '@vitejs/plugin-react'; import { nodePolyfills as viteNodePolyfills } from 'vite-plugin-node-polyfills'; import { createHtmlPlugin } from 'vite-plugin-html'; -import { viteCommonjs } from '@originjs/vite-plugin-commonjs'; import { forbiddenDuplicatesFilter, @@ -160,26 +159,19 @@ export async function serveBundle(options: ServeOptions) { additionalEntryPoints: detectedModulesEntryPoint, }); - console.log(paths.targetHtml); if (process.env.EXPERIMENTAL_VITE) { server = await vite.createServer({ define: { - global: 'globalThis', + global: 'window', 'process.argv': JSON.stringify(process.argv), 'process.env.APP_CONFIG': JSON.stringify(cliConfig.frontendAppConfigs), }, - resolve: { - alias: { - 'node-fetch': 'cross-fetch', - }, - }, plugins: [ react(), - viteCommonjs(), viteNodePolyfills(), createHtmlPlugin({ entry: paths.targetEntry, - // todo(blam): we should look at contributing to the plugin here + // todo(blam): we should look at contributing to thPe plugin here // to support absolute paths, but works in the interim at least. template: 'public/index.html', inject: { diff --git a/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx index 846e5a861f..e2165ed358 100644 --- a/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx @@ -64,9 +64,7 @@ import { selectedTemplateRouteRef, } from '../../routes'; import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; - -// typings are wrong for this library, so fallback to not parsing types. -const humanizeDuration = require('humanize-duration'); +import humanizeDuration from 'humanize-duration'; const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/yarn.lock b/yarn.lock index ddc4c0b2c0..94655c7aef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3815,7 +3815,6 @@ __metadata: "@octokit/graphql-schema": ^13.7.0 "@octokit/oauth-app": ^4.2.0 "@octokit/request": ^6.0.0 - "@originjs/vite-plugin-commonjs": ^1.0.3 "@pmmmwh/react-refresh-webpack-plugin": ^0.5.7 "@rollup/plugin-commonjs": ^23.0.0 "@rollup/plugin-json": ^5.0.0 @@ -10969,13 +10968,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.14.54": - version: 0.14.54 - resolution: "@esbuild/linux-loong64@npm:0.14.54" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - "@esbuild/linux-loong64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-loong64@npm:0.16.17" @@ -14510,15 +14502,6 @@ __metadata: languageName: node linkType: hard -"@originjs/vite-plugin-commonjs@npm:^1.0.3": - version: 1.0.3 - resolution: "@originjs/vite-plugin-commonjs@npm:1.0.3" - dependencies: - esbuild: ^0.14.14 - checksum: e4cd22a73e2be726fc78f794942333b8c6ede20c7b57edebe3d7bf52119532ef3206142f36498fbb22fb34fc706d30cd5efb10d1d84bf8d11be09ed7b90b8aaf - languageName: node - linkType: hard - "@parcel/watcher@npm:^2.1.0": version: 2.1.0 resolution: "@parcel/watcher@npm:2.1.0" @@ -24649,104 +24632,6 @@ __metadata: languageName: node linkType: hard -"esbuild-android-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-android-64@npm:0.14.54" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"esbuild-android-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-android-arm64@npm:0.14.54" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-darwin-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-darwin-64@npm:0.14.54" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"esbuild-darwin-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-darwin-arm64@npm:0.14.54" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-freebsd-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-freebsd-64@npm:0.14.54" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"esbuild-freebsd-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-freebsd-arm64@npm:0.14.54" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-linux-32@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-32@npm:0.14.54" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"esbuild-linux-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-64@npm:0.14.54" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"esbuild-linux-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-arm64@npm:0.14.54" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-linux-arm@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-arm@npm:0.14.54" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"esbuild-linux-mips64le@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-mips64le@npm:0.14.54" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"esbuild-linux-ppc64le@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-ppc64le@npm:0.14.54" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"esbuild-linux-riscv64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-riscv64@npm:0.14.54" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"esbuild-linux-s390x@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-s390x@npm:0.14.54" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - "esbuild-loader@npm:^2.18.0": version: 2.21.0 resolution: "esbuild-loader@npm:2.21.0" @@ -24763,122 +24648,6 @@ __metadata: languageName: node linkType: hard -"esbuild-netbsd-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-netbsd-64@npm:0.14.54" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"esbuild-openbsd-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-openbsd-64@npm:0.14.54" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"esbuild-sunos-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-sunos-64@npm:0.14.54" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"esbuild-windows-32@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-windows-32@npm:0.14.54" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"esbuild-windows-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-windows-64@npm:0.14.54" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"esbuild-windows-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-windows-arm64@npm:0.14.54" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"esbuild@npm:^0.14.14": - version: 0.14.54 - resolution: "esbuild@npm:0.14.54" - dependencies: - "@esbuild/linux-loong64": 0.14.54 - esbuild-android-64: 0.14.54 - esbuild-android-arm64: 0.14.54 - esbuild-darwin-64: 0.14.54 - esbuild-darwin-arm64: 0.14.54 - esbuild-freebsd-64: 0.14.54 - esbuild-freebsd-arm64: 0.14.54 - esbuild-linux-32: 0.14.54 - esbuild-linux-64: 0.14.54 - esbuild-linux-arm: 0.14.54 - esbuild-linux-arm64: 0.14.54 - esbuild-linux-mips64le: 0.14.54 - esbuild-linux-ppc64le: 0.14.54 - esbuild-linux-riscv64: 0.14.54 - esbuild-linux-s390x: 0.14.54 - esbuild-netbsd-64: 0.14.54 - esbuild-openbsd-64: 0.14.54 - esbuild-sunos-64: 0.14.54 - esbuild-windows-32: 0.14.54 - esbuild-windows-64: 0.14.54 - esbuild-windows-arm64: 0.14.54 - dependenciesMeta: - "@esbuild/linux-loong64": - optional: true - esbuild-android-64: - optional: true - esbuild-android-arm64: - optional: true - esbuild-darwin-64: - optional: true - esbuild-darwin-arm64: - optional: true - esbuild-freebsd-64: - optional: true - esbuild-freebsd-arm64: - optional: true - esbuild-linux-32: - optional: true - esbuild-linux-64: - optional: true - esbuild-linux-arm: - optional: true - esbuild-linux-arm64: - optional: true - esbuild-linux-mips64le: - optional: true - esbuild-linux-ppc64le: - optional: true - esbuild-linux-riscv64: - optional: true - esbuild-linux-s390x: - optional: true - esbuild-netbsd-64: - optional: true - esbuild-openbsd-64: - optional: true - esbuild-sunos-64: - optional: true - esbuild-windows-32: - optional: true - esbuild-windows-64: - optional: true - esbuild-windows-arm64: - optional: true - bin: - esbuild: bin/esbuild - checksum: 49e360b1185c797f5ca3a7f5f0a75121494d97ddf691f65ed1796e6257d318f928342a97f559bb8eced6a90cf604dd22db4a30e0dbbf15edd9dbf22459b639af - languageName: node - linkType: hard - "esbuild@npm:^0.16.17": version: 0.16.17 resolution: "esbuild@npm:0.16.17" From 2dddc5de00b0861ad9ef380dca93f35ae7d0ece8 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 12 Oct 2023 16:42:48 +0200 Subject: [PATCH 269/348] chore: add changeset Signed-off-by: blam --- .changeset/cold-pigs-end.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/cold-pigs-end.md diff --git a/.changeset/cold-pigs-end.md b/.changeset/cold-pigs-end.md new file mode 100644 index 0000000000..13c391ea25 --- /dev/null +++ b/.changeset/cold-pigs-end.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-home': patch +--- + +Remove usages of `require` From 788eb72840dbd3b5356b551a8a9f8c7876dc6977 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 18 Oct 2023 14:03:23 +0200 Subject: [PATCH 270/348] chore: fix Signed-off-by: blam Signed-off-by: blam --- packages/cli/package.json | 1 + packages/cli/src/lib/bundler/server.ts | 15 ++-- yarn.lock | 111 ++++++++++--------------- 3 files changed, 57 insertions(+), 70 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 4f26a72785..bf5597940b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -134,6 +134,7 @@ "terser-webpack-plugin": "^5.1.3", "util": "^0.12.3", "vite": "^4.4.9", + "vite-plugin-commonjs": "^0.10.0", "vite-plugin-html": "^3.2.0", "vite-plugin-node-polyfills": "^0.14.1", "webpack": "^5.70.0", diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index ead1343f0d..14714a3d6e 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -23,9 +23,10 @@ import openBrowser from 'react-dev-utils/openBrowser'; import webpack from 'webpack'; import WebpackDevServer from 'webpack-dev-server'; import vite from 'vite'; -import react from '@vitejs/plugin-react'; +import viteReact from '@vitejs/plugin-react'; +import viteCommonJs from 'vite-plugin-commonjs'; import { nodePolyfills as viteNodePolyfills } from 'vite-plugin-node-polyfills'; -import { createHtmlPlugin } from 'vite-plugin-html'; +import { createHtmlPlugin as viteHtml } from 'vite-plugin-html'; import { forbiddenDuplicatesFilter, @@ -167,9 +168,13 @@ export async function serveBundle(options: ServeOptions) { 'process.env.APP_CONFIG': JSON.stringify(cliConfig.frontendAppConfigs), }, plugins: [ - react(), + viteReact(), viteNodePolyfills(), - createHtmlPlugin({ + viteCommonJs({ + // todo(blam): this is ugly to work around for just running in the backstage/backstage repo. + filter: id => id.endsWith('renderReactElement.ts'), + }), + viteHtml({ entry: paths.targetEntry, // todo(blam): we should look at contributing to thPe plugin here // to support absolute paths, but works in the interim at least. @@ -236,7 +241,7 @@ export async function serveBundle(options: ServeOptions) { await new Promise(async (resolve, reject) => { if (process.env.EXPERIMENTAL_VITE) { await (server as vite.ViteDevServer).listen(); - (server as vite.ViteDevServer).openBrowser(); + openBrowser(url.href); resolve(); } else { (server as WebpackDevServer).startCallback((err?: Error) => { diff --git a/yarn.lock b/yarn.lock index 94655c7aef..cab00c9c3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1800,16 +1800,6 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.22.10, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.8.3": - version: 7.22.13 - resolution: "@babel/code-frame@npm:7.22.13" - dependencies: - "@babel/highlight": ^7.22.13 - chalk: ^2.4.2 - checksum: 22e342c8077c8b77eeb11f554ecca2ba14153f707b85294fcf6070b6f6150aae88a7b7436dd88d8c9289970585f3fe5b9b941c5aa3aa26a6d5a8ef3f292da058 - languageName: node - linkType: hard - "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.8.3": version: 7.22.13 resolution: "@babel/code-frame@npm:7.22.13" @@ -1850,18 +1840,6 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.22.10, @babel/generator@npm:^7.23.0, @babel/generator@npm:^7.7.2": - version: 7.23.0 - resolution: "@babel/generator@npm:7.23.0" - dependencies: - "@babel/types": ^7.23.0 - "@jridgewell/gen-mapping": ^0.3.2 - "@jridgewell/trace-mapping": ^0.3.17 - jsesc: ^2.5.1 - checksum: 8efe24adad34300f1f8ea2add420b28171a646edc70f2a1b3e1683842f23b8b7ffa7e35ef0119294e1901f45bfea5b3dc70abe1f10a1917ccdfb41bed69be5f1 - languageName: node - linkType: hard - "@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.23.0, @babel/generator@npm:^7.7.2": version: 7.23.0 resolution: "@babel/generator@npm:7.23.0" @@ -2143,15 +2121,6 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.15, @babel/parser@npm:^7.22.11, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/parser@npm:7.23.0" - bin: - parser: ./bin/babel-parser.js - checksum: 453fdf8b9e2c2b7d7b02139e0ce003d1af21947bbc03eb350fb248ee335c9b85e4ab41697ddbdd97079698de825a265e45a0846bb2ed47a2c7c1df833f42a354 - languageName: node - linkType: hard - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.22.5" @@ -3378,24 +3347,6 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.22.11, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.2": - version: 7.23.2 - resolution: "@babel/traverse@npm:7.23.2" - dependencies: - "@babel/code-frame": ^7.22.13 - "@babel/generator": ^7.23.0 - "@babel/helper-environment-visitor": ^7.22.20 - "@babel/helper-function-name": ^7.23.0 - "@babel/helper-hoist-variables": ^7.22.5 - "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/parser": ^7.23.0 - "@babel/types": ^7.23.0 - debug: ^4.1.0 - globals: ^11.1.0 - checksum: 26a1eea0dde41ab99dde8b9773a013a0dc50324e5110a049f5d634e721ff08afffd54940b3974a20308d7952085ac769689369e9127dea655f868c0f6e1ab35d - languageName: node - linkType: hard - "@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.23.0, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.2": version: 7.23.0 resolution: "@babel/traverse@npm:7.23.0" @@ -3425,17 +3376,6 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.20.0, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.11, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.23.0 - resolution: "@babel/types@npm:7.23.0" - dependencies: - "@babel/helper-string-parser": ^7.22.5 - "@babel/helper-validator-identifier": ^7.22.20 - to-fast-properties: ^2.0.0 - checksum: 215fe04bd7feef79eeb4d33374b39909ce9cad1611c4135a4f7fdf41fe3280594105af6d7094354751514625ea92d0875aba355f53e86a92600f290e77b0e604 - languageName: node - linkType: hard - "@backstage/app-defaults@workspace:^, @backstage/app-defaults@workspace:packages/app-defaults": version: 0.0.0-use.local resolution: "@backstage/app-defaults@workspace:packages/app-defaults" @@ -3924,6 +3864,7 @@ __metadata: type-fest: ^2.19.0 util: ^0.12.3 vite: ^4.4.9 + vite-plugin-commonjs: ^0.10.0 vite-plugin-html: ^3.2.0 vite-plugin-node-polyfills: ^0.14.1 webpack: ^5.70.0 @@ -12803,13 +12744,20 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.13": +"@jridgewell/sourcemap-codec@npm:1.4.14": version: 1.4.14 resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" checksum: 61100637b6d173d3ba786a5dff019e1a74b1f394f323c1fee337ff390239f053b87266c7a948777f4b1ee68c01a8ad0ab61e5ff4abb5a012a0b091bec391ab97 languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.13, @jridgewell/sourcemap-codec@npm:^1.4.15": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:0.3.9": version: 0.3.9 resolution: "@jridgewell/trace-mapping@npm:0.3.9" @@ -19601,12 +19549,12 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.7.1, acorn@npm:^8.9.0": - version: 8.9.0 - resolution: "acorn@npm:8.9.0" +"acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.10.0 + resolution: "acorn@npm:8.10.0" bin: acorn: bin/acorn - checksum: 25dfb94952386ecfb847e61934de04a4e7c2dc21c2e700fc4e2ef27ce78cb717700c4c4f279cd630bb4774948633c3859fc16063ec8573bda4568e0a312e6744 + checksum: 538ba38af0cc9e5ef983aee196c4b8b4d87c0c94532334fa7e065b2c8a1f85863467bb774231aae91613fcda5e68740c15d97b1967ae3394d20faddddd8af61d languageName: node linkType: hard @@ -31881,6 +31829,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.1": + version: 0.30.5 + resolution: "magic-string@npm:0.30.5" + dependencies: + "@jridgewell/sourcemap-codec": ^1.4.15 + checksum: da10fecff0c0a7d3faf756913ce62bd6d5e7b0402be48c3b27bfd651b90e29677e279069a63b764bcdc1b8ecdcdb898f29a5c5ec510f2323e8d62ee057a6eb18 + languageName: node + linkType: hard + "make-dir@npm:^2.0.0, make-dir@npm:^2.1.0": version: 2.1.0 resolution: "make-dir@npm:2.1.0" @@ -42209,6 +42166,30 @@ __metadata: languageName: node linkType: hard +"vite-plugin-commonjs@npm:^0.10.0": + version: 0.10.0 + resolution: "vite-plugin-commonjs@npm:0.10.0" + dependencies: + acorn: ^8.8.2 + fast-glob: ^3.2.12 + magic-string: ^0.30.1 + vite-plugin-dynamic-import: ^1.5.0 + checksum: 3cb9a78d477a3bf7b15bd39c73058c7a5277a9be68528276fa885b4abe9ace801073dc587648248bb749cf070eb817f0ec34d8d32c0c4aac4000b23048776c2b + languageName: node + linkType: hard + +"vite-plugin-dynamic-import@npm:^1.5.0": + version: 1.5.0 + resolution: "vite-plugin-dynamic-import@npm:1.5.0" + dependencies: + acorn: ^8.8.2 + es-module-lexer: ^1.2.1 + fast-glob: ^3.2.12 + magic-string: ^0.30.1 + checksum: 68efd897daa0c72a9f9d3481095dd3f7ec9a822be5a15eef60413734a4c894c5bbd1c1762f02daeef5df59cef212c9f1e7e056315e2a7780816ccafe5c74da6e + languageName: node + linkType: hard + "vite-plugin-html@npm:^3.2.0": version: 3.2.0 resolution: "vite-plugin-html@npm:3.2.0" From 1a5ecd034a1bb85d1f6841b214123e4d41895d26 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 19 Oct 2023 13:49:07 +0200 Subject: [PATCH 271/348] chore: refactor and remove cjs Signed-off-by: blam --- .changeset/cold-pigs-end.md | 7 ---- packages/cli/package.json | 1 - packages/cli/src/lib/bundler/config.ts | 10 +---- .../cli/src/lib/bundler/hasReactDomClient.ts | 23 +++++++++++ packages/cli/src/lib/bundler/server.ts | 19 ++++------ yarn.lock | 38 +------------------ 6 files changed, 34 insertions(+), 64 deletions(-) delete mode 100644 .changeset/cold-pigs-end.md create mode 100644 packages/cli/src/lib/bundler/hasReactDomClient.ts diff --git a/.changeset/cold-pigs-end.md b/.changeset/cold-pigs-end.md deleted file mode 100644 index 13c391ea25..0000000000 --- a/.changeset/cold-pigs-end.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-home': patch ---- - -Remove usages of `require` diff --git a/packages/cli/package.json b/packages/cli/package.json index bf5597940b..4f26a72785 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -134,7 +134,6 @@ "terser-webpack-plugin": "^5.1.3", "util": "^0.12.3", "vite": "^4.4.9", - "vite-plugin-commonjs": "^0.10.0", "vite-plugin-html": "^3.2.0", "vite-plugin-node-polyfills": "^0.14.1", "webpack": "^5.70.0", diff --git a/packages/cli/src/lib/bundler/config.ts b/packages/cli/src/lib/bundler/config.ts index 534ffe8c58..542cc83ce9 100644 --- a/packages/cli/src/lib/bundler/config.ts +++ b/packages/cli/src/lib/bundler/config.ts @@ -39,6 +39,7 @@ import { runPlain } from '../run'; import { transforms } from './transforms'; import { version } from '../../lib/version'; import yn from 'yn'; +import { hasReactDomClient } from './hasReactDomClient'; const BUILD_CACHE_ENV_VAR = 'BACKSTAGE_CLI_EXPERIMENTAL_BUILD_CACHE'; @@ -81,15 +82,6 @@ async function readBuildInfo() { }; } -function hasReactDomClient() { - try { - require.resolve('react-dom/client'); - return true; - } catch { - return false; - } -} - export async function createConfig( paths: BundlingPaths, options: BundlingOptions, diff --git a/packages/cli/src/lib/bundler/hasReactDomClient.ts b/packages/cli/src/lib/bundler/hasReactDomClient.ts new file mode 100644 index 0000000000..e7ef7bbac9 --- /dev/null +++ b/packages/cli/src/lib/bundler/hasReactDomClient.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2023 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 function hasReactDomClient() { + try { + require.resolve('react-dom/client'); + return true; + } catch { + return false; + } +} diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index 14714a3d6e..f7847c710e 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -24,7 +24,6 @@ import webpack from 'webpack'; import WebpackDevServer from 'webpack-dev-server'; import vite from 'vite'; import viteReact from '@vitejs/plugin-react'; -import viteCommonJs from 'vite-plugin-commonjs'; import { nodePolyfills as viteNodePolyfills } from 'vite-plugin-node-polyfills'; import { createHtmlPlugin as viteHtml } from 'vite-plugin-html'; @@ -39,6 +38,7 @@ import { createConfig, resolveBaseUrl } from './config'; import { createDetectedModulesEntryPoint } from './packageDetection'; import { resolveBundlingPaths } from './paths'; import { ServeOptions } from './types'; +import { hasReactDomClient } from './hasReactDomClient'; export async function serveBundle(options: ServeOptions) { const paths = resolveBundlingPaths(options); @@ -166,14 +166,13 @@ export async function serveBundle(options: ServeOptions) { global: 'window', 'process.argv': JSON.stringify(process.argv), 'process.env.APP_CONFIG': JSON.stringify(cliConfig.frontendAppConfigs), + // This allows for conditional imports of react-dom/client, since there's no way + // to check for presence of it in source code without module resolution errors. + 'process.env.HAS_REACT_DOM_CLIENT': JSON.stringify(hasReactDomClient()), }, plugins: [ viteReact(), viteNodePolyfills(), - viteCommonJs({ - // todo(blam): this is ugly to work around for just running in the backstage/backstage repo. - filter: id => id.endsWith('renderReactElement.ts'), - }), viteHtml({ entry: paths.targetEntry, // todo(blam): we should look at contributing to thPe plugin here @@ -233,26 +232,24 @@ export async function serveBundle(options: ServeOptions) { client: { webSocketURL: 'auto://0.0.0.0:0/ws', }, - } as any, - compiler as any, + }, + compiler, ); } await new Promise(async (resolve, reject) => { if (process.env.EXPERIMENTAL_VITE) { await (server as vite.ViteDevServer).listen(); - openBrowser(url.href); - resolve(); } else { (server as WebpackDevServer).startCallback((err?: Error) => { if (err) { reject(err); return; } - openBrowser(url.href); - resolve(); }); } + openBrowser(url.href); + resolve(); }); const waitForExit = async () => { diff --git a/yarn.lock b/yarn.lock index cab00c9c3b..f82582ba47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3864,7 +3864,6 @@ __metadata: type-fest: ^2.19.0 util: ^0.12.3 vite: ^4.4.9 - vite-plugin-commonjs: ^0.10.0 vite-plugin-html: ^3.2.0 vite-plugin-node-polyfills: ^0.14.1 webpack: ^5.70.0 @@ -12751,7 +12750,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.13, @jridgewell/sourcemap-codec@npm:^1.4.15": +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.13": version: 1.4.15 resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 @@ -19549,7 +19548,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": +"acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.7.1, acorn@npm:^8.9.0": version: 8.10.0 resolution: "acorn@npm:8.10.0" bin: @@ -31829,15 +31828,6 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.1": - version: 0.30.5 - resolution: "magic-string@npm:0.30.5" - dependencies: - "@jridgewell/sourcemap-codec": ^1.4.15 - checksum: da10fecff0c0a7d3faf756913ce62bd6d5e7b0402be48c3b27bfd651b90e29677e279069a63b764bcdc1b8ecdcdb898f29a5c5ec510f2323e8d62ee057a6eb18 - languageName: node - linkType: hard - "make-dir@npm:^2.0.0, make-dir@npm:^2.1.0": version: 2.1.0 resolution: "make-dir@npm:2.1.0" @@ -42166,30 +42156,6 @@ __metadata: languageName: node linkType: hard -"vite-plugin-commonjs@npm:^0.10.0": - version: 0.10.0 - resolution: "vite-plugin-commonjs@npm:0.10.0" - dependencies: - acorn: ^8.8.2 - fast-glob: ^3.2.12 - magic-string: ^0.30.1 - vite-plugin-dynamic-import: ^1.5.0 - checksum: 3cb9a78d477a3bf7b15bd39c73058c7a5277a9be68528276fa885b4abe9ace801073dc587648248bb749cf070eb817f0ec34d8d32c0c4aac4000b23048776c2b - languageName: node - linkType: hard - -"vite-plugin-dynamic-import@npm:^1.5.0": - version: 1.5.0 - resolution: "vite-plugin-dynamic-import@npm:1.5.0" - dependencies: - acorn: ^8.8.2 - es-module-lexer: ^1.2.1 - fast-glob: ^3.2.12 - magic-string: ^0.30.1 - checksum: 68efd897daa0c72a9f9d3481095dd3f7ec9a822be5a15eef60413734a4c894c5bbd1c1762f02daeef5df59cef212c9f1e7e056315e2a7780816ccafe5c74da6e - languageName: node - linkType: hard - "vite-plugin-html@npm:^3.2.0": version: 3.2.0 resolution: "vite-plugin-html@npm:3.2.0" From 57f765f727d73ad947dc59353f44d16061a9dc47 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 20 Oct 2023 11:13:26 +0200 Subject: [PATCH 272/348] wip: move Signed-off-by: blam --- packages/app/package.json | 4 ++ packages/cli/package.json | 22 +++++++--- packages/cli/src/lib/bundler/server.ts | 57 ++++++++++++-------------- yarn.lock | 20 +++++++-- 4 files changed, 63 insertions(+), 40 deletions(-) diff --git a/packages/app/package.json b/packages/app/package.json index df48491481..9c6b578cd8 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -93,12 +93,16 @@ "@roadiehq/backstage-plugin-github-insights": "^2.0.5", "@roadiehq/backstage-plugin-github-pull-requests": "^2.2.7", "@roadiehq/backstage-plugin-travis-ci": "^2.0.5", + "@vitejs/plugin-react": "^4.0.4", "history": "^5.0.0", "react": "^18.0.2", "react-dom": "^18.0.2", "react-router": "^6.3.0", "react-router-dom": "^6.3.0", "react-use": "^17.2.4", + "vite": "^4.4.9", + "vite-plugin-html": "^3.2.0", + "vite-plugin-node-polyfills": "^0.14.1", "zen-observable": "^0.10.0" }, "devDependencies": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 4f26a72785..4f08231f7e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -68,7 +68,6 @@ "@types/webpack-env": "^1.15.2", "@typescript-eslint/eslint-plugin": "6.7.5", "@typescript-eslint/parser": "^6.7.2", - "@vitejs/plugin-react": "^4.0.4", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "^3.0.0-rc.4", "bfj": "^7.0.2", @@ -133,9 +132,6 @@ "tar": "^6.1.12", "terser-webpack-plugin": "^5.1.3", "util": "^0.12.3", - "vite": "^4.4.9", - "vite-plugin-html": "^3.2.0", - "vite-plugin-node-polyfills": "^0.14.1", "webpack": "^5.70.0", "webpack-dev-server": "^4.7.3", "webpack-node-externals": "^3.0.0", @@ -179,11 +175,27 @@ "type-fest": "^2.19.0" }, "peerDependencies": { - "@microsoft/api-extractor": "^7.21.2" + "@microsoft/api-extractor": "^7.21.2", + "@vitejs/plugin-react": "^4.0.4", + "vite": "^4.4.9", + "vite-plugin-html": "^3.2.0", + "vite-plugin-node-polyfills": "^0.14.1" }, "peerDependenciesMeta": { "@microsoft/api-extractor": { "optional": true + }, + "@vitejs/plugin-react": { + "optional": true + }, + "vite": { + "optional": true + }, + "vite-plugin-html": { + "optional": true + }, + "vite-plugin-node-polyfills": { + "optional": true } }, "files": [ diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index f7847c710e..b4d613bcb7 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -22,10 +22,6 @@ import uniq from 'lodash/uniq'; import openBrowser from 'react-dev-utils/openBrowser'; import webpack from 'webpack'; import WebpackDevServer from 'webpack-dev-server'; -import vite from 'vite'; -import viteReact from '@vitejs/plugin-react'; -import { nodePolyfills as viteNodePolyfills } from 'vite-plugin-node-polyfills'; -import { createHtmlPlugin as viteHtml } from 'vite-plugin-html'; import { forbiddenDuplicatesFilter, @@ -82,7 +78,9 @@ export async function serveBundle(options: ServeOptions) { const { name } = await fs.readJson(libPaths.resolveTarget('package.json')); - let server: WebpackDevServer | vite.ViteDevServer | undefined = undefined; + let webpackServer: WebpackDevServer | undefined = undefined; + // let viteServer: import('vite').ViteDevServer | undefined = undefined; + let latestFrontendAppConfigs: AppConfig[] = []; const cliConfig = await loadCliConfig({ @@ -91,15 +89,9 @@ export async function serveBundle(options: ServeOptions) { withFilteredKeys: true, watch(appConfigs) { latestFrontendAppConfigs = appConfigs; - if (server) { - if ('invalidate' in server) { - server.invalidate(); - } - if ('restart' in server) { - server.restart(); - } - } + webpackServer?.invalidate(); + viteServer?.restart(); }, }); latestFrontendAppConfigs = cliConfig.frontendAppConfigs; @@ -136,15 +128,8 @@ export async function serveBundle(options: ServeOptions) { config: fullConfig, targetPath: paths.targetPath, watch() { - if (server) { - if ('invalidate' in server) { - server.invalidate(); - } - - if ('restart' in server) { - server.restart(); - } - } + webpackServer?.invalidate(); + viteServer?.restart(); }, }); @@ -161,7 +146,14 @@ export async function serveBundle(options: ServeOptions) { }); if (process.env.EXPERIMENTAL_VITE) { - server = await vite.createServer({ + // const { default: vite } = await import('vite'); + // // Annoyting that this doesn't work. `package.json` is not declared in `exports`. + // // const { default: viteReact } = require('@vitejs/plugin-react'); + // const { nodePolyfills: viteNodePolyfills } = await import( + // 'vite-plugin-node-polyfills' + // ); + // const { createHtmlPlugin: viteHtml } = await import('vite-plugin-html'); + viteServer = await vite.createServer({ define: { global: 'window', 'process.argv': JSON.stringify(process.argv), @@ -196,7 +188,7 @@ export async function serveBundle(options: ServeOptions) { } else { const compiler = webpack(config); - server = new WebpackDevServer( + webpackServer = new WebpackDevServer( { hot: !process.env.CI, devMiddleware: { @@ -237,25 +229,28 @@ export async function serveBundle(options: ServeOptions) { ); } + await viteServer?.listen(); await new Promise(async (resolve, reject) => { - if (process.env.EXPERIMENTAL_VITE) { - await (server as vite.ViteDevServer).listen(); - } else { - (server as WebpackDevServer).startCallback((err?: Error) => { + if (webpackServer) { + webpackServer.startCallback((err?: Error) => { if (err) { reject(err); return; } + resolve(); }); + } else { + resolve(); } - openBrowser(url.href); - resolve(); }); + openBrowser(url.href); + const waitForExit = async () => { for (const signal of ['SIGINT', 'SIGTERM'] as const) { process.on(signal, () => { - server?.close(); + webpackServer?.close(); + viteServer?.close(); // exit instead of resolve. The process is shutting down and resolving a promise here logs an error process.exit(); }); diff --git a/yarn.lock b/yarn.lock index f82582ba47..0242c61e33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3793,7 +3793,6 @@ __metadata: "@types/yarnpkg__lockfile": ^1.1.4 "@typescript-eslint/eslint-plugin": 6.7.5 "@typescript-eslint/parser": ^6.7.2 - "@vitejs/plugin-react": ^4.0.4 "@yarnpkg/lockfile": ^1.1.0 "@yarnpkg/parsers": ^3.0.0-rc.4 bfj: ^7.0.2 @@ -3863,9 +3862,6 @@ __metadata: ts-node: ^10.0.0 type-fest: ^2.19.0 util: ^0.12.3 - vite: ^4.4.9 - vite-plugin-html: ^3.2.0 - vite-plugin-node-polyfills: ^0.14.1 webpack: ^5.70.0 webpack-dev-server: ^4.7.3 webpack-node-externals: ^3.0.0 @@ -3875,9 +3871,21 @@ __metadata: zod: ^3.21.4 peerDependencies: "@microsoft/api-extractor": ^7.21.2 + "@vitejs/plugin-react": ^4.0.4 + vite: ^4.4.9 + vite-plugin-html: ^3.2.0 + vite-plugin-node-polyfills: ^0.14.1 peerDependenciesMeta: "@microsoft/api-extractor": optional: true + "@vitejs/plugin-react": + optional: true + vite: + optional: true + vite-plugin-html: + optional: true + vite-plugin-node-polyfills: + optional: true bin: backstage-cli: bin/backstage-cli languageName: unknown @@ -25571,6 +25579,7 @@ __metadata: "@types/react": "*" "@types/react-dom": "*" "@types/zen-observable": ^0.8.0 + "@vitejs/plugin-react": ^4.0.4 cross-env: ^7.0.0 history: ^5.0.0 react: ^18.0.2 @@ -25578,6 +25587,9 @@ __metadata: react-router: ^6.3.0 react-router-dom: ^6.3.0 react-use: ^17.2.4 + vite: ^4.4.9 + vite-plugin-html: ^3.2.0 + vite-plugin-node-polyfills: ^0.14.1 zen-observable: ^0.10.0 languageName: unknown linkType: soft From 57d0c77b37df778b0236f193f49b4a53571c06cf Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 20 Oct 2023 14:03:35 +0200 Subject: [PATCH 273/348] chore: revert comments Signed-off-by: blam --- packages/cli/src/lib/bundler/server.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index b4d613bcb7..bd70b2b074 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -79,7 +79,7 @@ export async function serveBundle(options: ServeOptions) { const { name } = await fs.readJson(libPaths.resolveTarget('package.json')); let webpackServer: WebpackDevServer | undefined = undefined; - // let viteServer: import('vite').ViteDevServer | undefined = undefined; + let viteServer: import('vite').ViteDevServer | undefined = undefined; let latestFrontendAppConfigs: AppConfig[] = []; @@ -146,13 +146,12 @@ export async function serveBundle(options: ServeOptions) { }); if (process.env.EXPERIMENTAL_VITE) { - // const { default: vite } = await import('vite'); - // // Annoyting that this doesn't work. `package.json` is not declared in `exports`. - // // const { default: viteReact } = require('@vitejs/plugin-react'); - // const { nodePolyfills: viteNodePolyfills } = await import( - // 'vite-plugin-node-polyfills' - // ); - // const { createHtmlPlugin: viteHtml } = await import('vite-plugin-html'); + const { default: vite } = await import('vite'); + const { default: viteReact } = await import('@vitejs/plugin-react'); + const { nodePolyfills: viteNodePolyfills } = await import( + 'vite-plugin-node-polyfills' + ); + const { createHtmlPlugin: viteHtml } = await import('vite-plugin-html'); viteServer = await vite.createServer({ define: { global: 'window', From 7cd34392f5426bc32e106a523ad2913e7fbeacc7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 20 Oct 2023 14:26:06 +0200 Subject: [PATCH 274/348] cli: fix backend start hanging Signed-off-by: Patrik Oldsberg --- .changeset/wise-waves-approve.md | 5 +++++ .../cli/src/lib/experimental/startBackendExperimental.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/wise-waves-approve.md diff --git a/.changeset/wise-waves-approve.md b/.changeset/wise-waves-approve.md new file mode 100644 index 0000000000..f543f8918c --- /dev/null +++ b/.changeset/wise-waves-approve.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Ignore `stdin` when spawning backend child process for the `start` command. Fixing an issue where backend startup would hang. diff --git a/packages/cli/src/lib/experimental/startBackendExperimental.ts b/packages/cli/src/lib/experimental/startBackendExperimental.ts index c4271deb3d..f649c24637 100644 --- a/packages/cli/src/lib/experimental/startBackendExperimental.ts +++ b/packages/cli/src/lib/experimental/startBackendExperimental.ts @@ -95,7 +95,7 @@ export async function startBackendExperimental(options: BackendServeOptions) { process.execPath, [...loaderArgs, ...optionArgs, options.entry, ...userArgs], { - stdio: ['inherit', 'inherit', 'inherit', 'ipc'], + stdio: ['ignore', 'inherit', 'inherit', 'ipc'], env: { ...process.env, BACKSTAGE_CLI_CHANNEL: '1', From 96bd67dbedd67b73d9c10fd8f8dd0a1df001b553 Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Fri, 20 Oct 2023 09:09:46 -0400 Subject: [PATCH 275/348] Add tests for navigation scrolling logic in TechDocsReaderPageContent Signed-off-by: Sydney Achinger --- .../TechDocsReaderPageContent.test.tsx | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx index 3e5a4c73c3..401e1e0bb8 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx @@ -33,6 +33,10 @@ jest.mock('../useReaderState', () => ({ ...jest.requireActual('../useReaderState'), useReaderState: (...args: any[]) => useReaderState(...args), })); +jest.mock('@backstage/plugin-techdocs-react', () => ({ + ...jest.requireActual('@backstage/plugin-techdocs-react'), + useShadowDomStylesLoading: jest.fn().mockReturnValue(false), +})); import { TechDocsReaderPageContent } from './TechDocsReaderPageContent'; @@ -84,6 +88,10 @@ const Wrapper = ({ ); describe('', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + it('should render techdocs page content', async () => { getEntityMetadata.mockResolvedValue(mockEntityMetadata); getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); @@ -151,4 +159,65 @@ describe('', () => { }); }); }); + + it('should scroll to hash if hash is present in url', async () => { + jest.spyOn(document, 'querySelector'); + + const mockScrollIntoView = jest.fn(); + const h2 = document.createElement('h2'); + h2.innerText = 'emojis'; + h2.id = 'emojis'; + h2.scrollIntoView = mockScrollIntoView; + const mockTechDocsPage = document.createElement('html'); + mockTechDocsPage.appendChild(h2); + + getEntityMetadata.mockResolvedValue(mockEntityMetadata); + getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); + useTechDocsReaderDom.mockReturnValue(mockTechDocsPage); + useReaderState.mockReturnValue({ state: 'cached' }); + + window.location.hash = '#emojis'; + + await act(async () => { + const rendered = await renderInTestApp( + + + , + ); + + await waitFor(() => { + expect( + rendered.getByTestId('techdocs-native-shadowroot'), + ).toBeInTheDocument(); + expect(mockScrollIntoView).toHaveBeenCalled(); + expect(document.querySelector).not.toHaveBeenCalledWith('header'); + }); + }); + + window.location.hash = ''; + }); + + it('should scroll to header if hash is not present in url', async () => { + jest.spyOn(document, 'querySelector'); + + getEntityMetadata.mockResolvedValue(mockEntityMetadata); + getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); + useTechDocsReaderDom.mockReturnValue(document.createElement('html')); + useReaderState.mockReturnValue({ state: 'cached' }); + + await act(async () => { + const rendered = await renderInTestApp( + + + , + ); + + await waitFor(() => { + expect( + rendered.getByTestId('techdocs-native-shadowroot'), + ).toBeInTheDocument(); + expect(document.querySelector).toHaveBeenCalledWith('header'); + }); + }); + }); }); From f8727ad228c9f90202c944e6e5c802b334557186 Mon Sep 17 00:00:00 2001 From: parmar-abhinav Date: Fri, 20 Oct 2023 19:36:29 +0530 Subject: [PATCH 276/348] Add examples for publish:github:pull-request scaffolder action Signed-off-by: parmar-abhinav --- .changeset/wise-weeks-design.md | 5 + .../githubPullRequest.examples.test.ts | 552 ++++++++++++++++++ .../publish/githubPullRequest.examples.ts | 206 +++++++ .../builtin/publish/githubPullRequest.ts | 2 + 4 files changed, 765 insertions(+) create mode 100644 .changeset/wise-weeks-design.md create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.test.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.ts diff --git a/.changeset/wise-weeks-design.md b/.changeset/wise-weeks-design.md new file mode 100644 index 0000000000..657a8e23d5 --- /dev/null +++ b/.changeset/wise-weeks-design.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Add examples for `publish:github:pull-request` scaffolder action & improve related tests diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.test.ts new file mode 100644 index 0000000000..3f13f2ab67 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.test.ts @@ -0,0 +1,552 @@ +/* + * Copyright 2023 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 { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { + DefaultGithubCredentialsProvider, + GithubCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; +import { PassThrough } from 'stream'; +import { + OctokitWithPullRequestPluginClient, + createPublishGithubPullRequestAction, +} from './githubPullRequest'; +import yaml from 'yaml'; +import { examples } from './githubPullRequest.examples'; +import { createMockDirectory } from '@backstage/backend-test-utils'; + +const mockOctokit = { + rest: { + pulls: { + requestReviewers: jest.fn(), + }, + }, +}; + +jest.mock('octokit', () => ({ + Octokit: class { + constructor() { + return mockOctokit; + } + }, +})); + +describe('publish:github:pull-request examples', () => { + const config = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + }); + const integrations = ScmIntegrations.fromConfig(config); + let githubCredentialsProvider: GithubCredentialsProvider; + let action: TemplateAction; + + const mockContext = { + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + let fakeClient: { + createPullRequest: jest.Mock; + rest: { + pulls: { requestReviewers: jest.Mock }; + }; + }; + const mockDir = createMockDirectory(); + const workspacePath = mockDir.resolve('workspace'); + + beforeEach(() => { + mockDir.clear(); + jest.resetAllMocks(); + githubCredentialsProvider = + DefaultGithubCredentialsProvider.fromIntegrations(integrations); + fakeClient = { + createPullRequest: jest.fn(async (_: any) => { + return { + url: 'https://api.github.com/myorg/myrepo/pull/123', + headers: {}, + status: 201, + data: { + html_url: 'https://github.com/myorg/myrepo/pull/123', + number: 123, + base: { + ref: 'main', + }, + }, + }; + }), + rest: { + pulls: { + requestReviewers: jest.fn(async (_: any) => ({ data: {} })), + }, + }, + }; + + const clientFactory = jest.fn( + async () => fakeClient as unknown as OctokitWithPullRequestPluginClient, + ); + + mockDir.setContent({ + [workspacePath]: { 'file.txt': 'Hello there!' }, + }); + + action = createPublishGithubPullRequestAction({ + integrations, + githubCredentialsProvider, + clientFactory, + }); + }); + + afterEach(jest.resetAllMocks); + + it('Create a pull request', async () => { + const input = yaml.parse(examples[0].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: undefined, + changes: [ + { + commit: 'Create my new app', + files: { + 'file.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + expect(fakeClient.rest.pulls.requestReviewers).not.toHaveBeenCalled(); + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); + + it('Create a pull request with target branch name', async () => { + const input = yaml.parse(examples[1].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: undefined, + base: 'test', + changes: [ + { + commit: 'Create my new app', + files: { + 'file.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + expect(fakeClient.rest.pulls.requestReviewers).not.toHaveBeenCalled(); + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); + + it('Create a pull request as draft', async () => { + const input = yaml.parse(examples[2].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: true, + changes: [ + { + commit: 'Create my new app', + files: { + 'file.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + expect(fakeClient.rest.pulls.requestReviewers).not.toHaveBeenCalled(); + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); + + it('Create a pull request with target path', async () => { + const input = yaml.parse(examples[3].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: undefined, + changes: [ + { + commit: 'Create my new app', + files: { + 'targetPath/file.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + + expect(fakeClient.rest.pulls.requestReviewers).not.toHaveBeenCalled(); + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); + + it('Create a pull request with source path', async () => { + mockDir.setContent({ + [workspacePath]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + const input = yaml.parse(examples[4].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: undefined, + changes: [ + { + commit: 'Create my new app', + files: { + 'foo.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + + expect(fakeClient.rest.pulls.requestReviewers).not.toHaveBeenCalled(); + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); + + it('Create a pull request with token', async () => { + const input = yaml.parse(examples[5].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: undefined, + changes: [ + { + commit: 'Create my new app', + files: { + 'file.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + + expect(fakeClient.rest.pulls.requestReviewers).not.toHaveBeenCalled(); + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); + + it('Create a pull request with reviewers', async () => { + const input = yaml.parse(examples[6].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: undefined, + changes: [ + { + commit: 'Create my new app', + files: { + 'file.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + + expect(fakeClient.rest.pulls.requestReviewers).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + pull_number: 123, + reviewers: ['foobar'], + }); + + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); + + it('Create a pull request with team reviewers', async () => { + const input = yaml.parse(examples[7].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: undefined, + changes: [ + { + commit: 'Create my new app', + files: { + 'file.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + + expect(fakeClient.rest.pulls.requestReviewers).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + pull_number: 123, + team_reviewers: ['team-foo'], + }); + + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); + + it('Create a pull request with commit message', async () => { + const input = yaml.parse(examples[8].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: undefined, + changes: [ + { + commit: 'Custom commit message', + files: { + 'file.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + + expect(fakeClient.rest.pulls.requestReviewers).not.toHaveBeenCalled(); + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); + + it('Create a pull request with all parameters', async () => { + mockDir.setContent({ + [workspacePath]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + const input = yaml.parse(examples[9].example).steps[0].input; + + await action.handler({ + ...mockContext, + workspacePath, + input, + }); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + title: 'Create my new app', + body: 'This PR is really good', + head: 'new-app', + draft: true, + base: 'test', + changes: [ + { + commit: 'Commit for foo changes', + files: { + 'targetPath/foo.txt': { + content: Buffer.from('Hello there!').toString('base64'), + encoding: 'base64', + mode: '100644', + }, + }, + }, + ], + }); + + expect(fakeClient.rest.pulls.requestReviewers).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + pull_number: 123, + reviewers: ['foobar'], + team_reviewers: ['team-foo'], + }); + + expect(mockContext.output).toHaveBeenCalledTimes(3); + expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main'); + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.ts new file mode 100644 index 0000000000..d6138b262b --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.ts @@ -0,0 +1,206 @@ +/* + * Copyright 2023 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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: 'Create a pull request', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + }, + }, + ], + }), + }, + { + description: 'Create a pull request with target branch name', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest with target branch name', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + targetBranchName: 'test', + }, + }, + ], + }), + }, + { + description: 'Create a pull request as draft', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest as draft', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + draft: true, + }, + }, + ], + }), + }, + { + description: 'Create a pull request with target path', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest with target path', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + targetPath: 'targetPath', + }, + }, + ], + }), + }, + { + description: 'Create a pull request with source path', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest with source path', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + sourcePath: 'source', + }, + }, + ], + }), + }, + { + description: 'Create a pull request with token', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + token: 'gph_YourGitHubToken', + }, + }, + ], + }), + }, + { + description: 'Create a pull request with reviewers', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest with reviewers', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + reviewers: ['foobar'], + }, + }, + ], + }), + }, + { + description: 'Create a pull request with team reviewers', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest with team reviewers', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + teamReviewers: ['team-foo'], + }, + }, + ], + }), + }, + { + description: 'Create a pull request with commit message', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + commitMessage: 'Custom commit message', + }, + }, + ], + }), + }, + { + description: 'Create a pull request with all parameters', + example: yaml.stringify({ + steps: [ + { + action: 'publish:github:pull-request', + name: 'Create a pull reuqest', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + branchName: 'new-app', + title: 'Create my new app', + description: 'This PR is really good', + targetBranchName: 'test', + draft: true, + targetPath: 'targetPath', + sourcePath: 'source', + token: 'gph_YourGitHubToken', + reviewers: ['foobar'], + teamReviewers: ['team-foo'], + commitMessage: 'Commit for foo changes', + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts index 167fedc88e..a02f21cfc2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts @@ -31,6 +31,7 @@ import { serializeDirectoryContents, } from '../../../../lib/files'; import { Logger } from 'winston'; +import { examples } from './githubPullRequest.examples'; export type Encoding = 'utf-8' | 'base64'; @@ -143,6 +144,7 @@ export const createPublishGithubPullRequestAction = ( commitMessage?: string; }>({ id: 'publish:github:pull-request', + examples, schema: { input: { required: ['repoUrl', 'title', 'description', 'branchName'], From 597f3a86bfe2bf6e9b6db24c04e8a520248fb414 Mon Sep 17 00:00:00 2001 From: Adam Harvey <33203301+adamdmharvey@users.noreply.github.com> Date: Fri, 20 Oct 2023 10:39:46 -0400 Subject: [PATCH 277/348] fix(create-app): Don't suggest install if already installed Signed-off-by: Adam Harvey <33203301+adamdmharvey@users.noreply.github.com> --- packages/create-app/src/createApp.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-app/src/createApp.ts b/packages/create-app/src/createApp.ts index efa299a3c9..baf80fd4d7 100644 --- a/packages/create-app/src/createApp.ts +++ b/packages/create-app/src/createApp.ts @@ -131,7 +131,7 @@ export default async (opts: OptionValues): Promise => { ); Task.log(); Task.section('All set! Now you might want to'); - if (!opts.skipInstall) { + if (opts.skipInstall) { Task.log( ` Install the dependencies: ${chalk.cyan( `cd ${opts.path ?? answers.name} && yarn install`, From ae1602e54d814c22596a3d4e7be91e33294c2be6 Mon Sep 17 00:00:00 2001 From: Adam Harvey <33203301+adamdmharvey@users.noreply.github.com> Date: Fri, 20 Oct 2023 10:41:05 -0400 Subject: [PATCH 278/348] chore: Add changeset Signed-off-by: Adam Harvey <33203301+adamdmharvey@users.noreply.github.com> --- .changeset/real-jars-yawn.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/real-jars-yawn.md diff --git a/.changeset/real-jars-yawn.md b/.changeset/real-jars-yawn.md new file mode 100644 index 0000000000..a89a687971 --- /dev/null +++ b/.changeset/real-jars-yawn.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +If create app installs dependencies, don't suggest to user that they also need to do it. From 018007bdb8a395c9d5bfa0cd5becde27814fdc9c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 20 Oct 2023 16:52:25 +0200 Subject: [PATCH 279/348] bump backstage/actions to v0.6.5 Signed-off-by: Patrik Oldsberg --- .github/workflows/automate_changeset_feedback.yml | 2 +- .github/workflows/ci.yml | 6 +++--- .github/workflows/cron.yml | 2 +- .github/workflows/deploy_docker-image.yml | 2 +- .github/workflows/deploy_nightly.yml | 2 +- .github/workflows/deploy_packages.yml | 4 ++-- .github/workflows/issue.yaml | 2 +- .github/workflows/pr-review-comment.yaml | 2 +- .github/workflows/pr.yaml | 2 +- .github/workflows/sync_code-formatting.yml | 2 +- .github/workflows/sync_snyk-github-issues.yml | 2 +- .github/workflows/uffizzi-build.yml | 2 +- .github/workflows/verify_accessibility.yml | 2 +- .github/workflows/verify_e2e-kubernetes.yml | 2 +- .github/workflows/verify_e2e-linux.yml | 2 +- .github/workflows/verify_e2e-windows.yml | 2 +- .github/workflows/verify_storybook.yml | 2 +- 17 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index 483d59dc8c..eac020cb8e 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -34,7 +34,7 @@ jobs: ref: 'refs/pull/${{ github.event.pull_request.number }}/merge' - name: fetch base run: git fetch --depth 1 origin ${{ github.base_ref }} - - uses: backstage/actions/changeset-feedback@v0.6.4 + - uses: backstage/actions/changeset-feedback@v0.6.5 name: Generate feedback with: diff-ref: 'origin/master' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81ea6f96d2..23e81192c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -76,7 +76,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -207,7 +207,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 2874be512c..79cfe9d790 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -13,7 +13,7 @@ jobs: with: egress-policy: audit - - uses: backstage/actions/cron@v0.6.4 + - uses: backstage/actions/cron@v0.6.5 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 30e7badcd0..69776da2d9 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -31,7 +31,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index d5fe9f5a64..7184557e12 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -27,7 +27,7 @@ jobs: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v18.x diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index f5ebfd7ee2..32f4b139f2 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -68,7 +68,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -150,7 +150,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 1c1c028f20..f5150a3a01 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -15,4 +15,4 @@ jobs: egress-policy: audit - name: Issue sync - uses: backstage/actions/issue-sync@v0.6.4 + uses: backstage/actions/issue-sync@v0.6.5 diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index e557c85d51..8d66567ff4 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -40,7 +40,7 @@ jobs: const prNumber = artifact.name.slice('pr_number-'.length) core.setOutput('pr-number', prNumber); - - uses: backstage/actions/re-review@v0.6.4 + - uses: backstage/actions/re-review@v0.6.5 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 8c99f105a9..89193c30ab 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -23,7 +23,7 @@ jobs: egress-policy: audit - name: PR sync - uses: backstage/actions/pr-sync@v0.6.4 + uses: backstage/actions/pr-sync@v0.6.5 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index fa8d91f25a..610ad323e2 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -25,7 +25,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 690e2fb76e..2be954746b 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -24,7 +24,7 @@ jobs: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v18.x diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index 3107b87b8f..375c6bdcd2 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -34,7 +34,7 @@ jobs: registry-url: https://registry.npmjs.org/ - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: linux-v18 diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index d53f3834d2..f34f2f5506 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -30,7 +30,7 @@ jobs: with: node-version: 18.x - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v18.x - name: run Lighthouse CI diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index cddd6589d7..ea77609614 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -35,7 +35,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 744a5d7e74..6b61053628 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -57,7 +57,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index 1385983c24..7ee5e596c5 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -78,7 +78,7 @@ jobs: uses: browser-actions/setup-chrome@803ef6dfb4fdf22089c9563225d95e4a515820a0 # latest - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index f0354df296..e992a2d658 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -42,7 +42,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@v0.6.5 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: storybook yarn install From eb1a28276de69dcf391ec4eae3bc6c442c64c034 Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Fri, 20 Oct 2023 11:10:51 -0400 Subject: [PATCH 280/348] Update tests to fix build. Signed-off-by: Sydney Achinger --- .../TechDocsReaderPageContent.test.tsx | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx index 425bb61be8..adef2f64d0 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx @@ -172,20 +172,18 @@ describe('', () => { window.location.hash = '#emojis'; - await act(async () => { - const rendered = await renderInTestApp( - - - , - ); + const rendered = await renderInTestApp( + + + , + ); - await waitFor(() => { - expect( - rendered.getByTestId('techdocs-native-shadowroot'), - ).toBeInTheDocument(); - expect(mockScrollIntoView).toHaveBeenCalled(); - expect(document.querySelector).not.toHaveBeenCalledWith('header'); - }); + await waitFor(() => { + expect( + rendered.getByTestId('techdocs-native-shadowroot'), + ).toBeInTheDocument(); + expect(mockScrollIntoView).toHaveBeenCalled(); + expect(document.querySelector).not.toHaveBeenCalledWith('header'); }); window.location.hash = ''; @@ -199,19 +197,17 @@ describe('', () => { useTechDocsReaderDom.mockReturnValue(document.createElement('html')); useReaderState.mockReturnValue({ state: 'cached' }); - await act(async () => { - const rendered = await renderInTestApp( - - - , - ); + const rendered = await renderInTestApp( + + + , + ); - await waitFor(() => { - expect( - rendered.getByTestId('techdocs-native-shadowroot'), - ).toBeInTheDocument(); - expect(document.querySelector).toHaveBeenCalledWith('header'); - }); + await waitFor(() => { + expect( + rendered.getByTestId('techdocs-native-shadowroot'), + ).toBeInTheDocument(); + expect(document.querySelector).toHaveBeenCalledWith('header'); }); }); }); From 57fda44b90b2936961a40719740ec12ab5b3b3aa Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Fri, 20 Oct 2023 13:03:10 -0400 Subject: [PATCH 281/348] Upgrade GraphiQL to 3.0.6 Signed-off-by: Taras Mankovski --- .changeset/four-files-behave.md | 5 + plugins/graphiql/package.json | 2 +- .../GraphiQLBrowser/GraphiQLBrowser.tsx | 7 +- yarn.lock | 940 +++++++++++++++++- 4 files changed, 926 insertions(+), 28 deletions(-) create mode 100644 .changeset/four-files-behave.md diff --git a/.changeset/four-files-behave.md b/.changeset/four-files-behave.md new file mode 100644 index 0000000000..3e218aa7e8 --- /dev/null +++ b/.changeset/four-files-behave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-graphiql': patch +--- + +Upgrade to GraphiQL 3.0.6 diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 52cff1fdb7..409b3e99f7 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -54,7 +54,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@types/react": "^16.13.1 || ^17.0.0", - "graphiql": "^1.5.12", + "graphiql": "^3.0.6", "graphql": "^16.0.0", "graphql-ws": "^5.4.1", "react-use": "^17.2.4" diff --git a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx index dd38f513be..40c2c168a8 100644 --- a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx +++ b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx @@ -77,12 +77,7 @@ export const GraphiQLBrowser = (props: GraphiQLBrowserProps) => {
- +
diff --git a/yarn.lock b/yarn.lock index 3075745d85..3b5c2c7866 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3305,12 +3305,12 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.1, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.23.1 - resolution: "@babel/runtime@npm:7.23.1" +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.1, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.23.2 + resolution: "@babel/runtime@npm:7.23.2" dependencies: regenerator-runtime: ^0.14.0 - checksum: 0cd0d43e6e7dc7f9152fda8c8312b08321cda2f56ef53d6c22ebdd773abdc6f5d0a69008de90aa41908d00e2c1facb24715ff121274e689305c858355ff02c70 + checksum: 6c4df4839ec75ca10175f636d6362f91df8a3137f86b38f6cd3a4c90668a0fe8e9281d320958f4fbd43b394988958585a17c3aab2a4ea6bf7316b22916a371fb languageName: node linkType: hard @@ -7117,7 +7117,7 @@ __metadata: "@types/codemirror": ^5.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 - graphiql: ^1.5.12 + graphiql: ^3.0.6 graphql: ^16.0.0 graphql-ws: ^5.4.1 msw: ^1.0.0 @@ -10520,6 +10520,15 @@ __metadata: languageName: node linkType: hard +"@emotion/is-prop-valid@npm:^0.8.2": + version: 0.8.8 + resolution: "@emotion/is-prop-valid@npm:0.8.8" + dependencies: + "@emotion/memoize": 0.7.4 + checksum: bb7ec6d48c572c540e24e47cc94fc2f8dec2d6a342ae97bc9c8b6388d9b8d283862672172a1bb62d335c02662afe6291e10c71e9b8642664a8b43416cdceffac + languageName: node + linkType: hard + "@emotion/is-prop-valid@npm:^1.1.0, @emotion/is-prop-valid@npm:^1.2.1": version: 1.2.1 resolution: "@emotion/is-prop-valid@npm:1.2.1" @@ -10529,6 +10538,13 @@ __metadata: languageName: node linkType: hard +"@emotion/memoize@npm:0.7.4": + version: 0.7.4 + resolution: "@emotion/memoize@npm:0.7.4" + checksum: 4e3920d4ec95995657a37beb43d3f4b7d89fed6caa2b173a4c04d10482d089d5c3ea50bbc96618d918b020f26ed6e9c4026bbd45433566576c1f7b056c3271dc + languageName: node + linkType: hard + "@emotion/memoize@npm:^0.8.1": version: 0.8.1 resolution: "@emotion/memoize@npm:0.8.1" @@ -11251,7 +11267,7 @@ __metadata: languageName: node linkType: hard -"@floating-ui/react-dom@npm:^2.0.2": +"@floating-ui/react-dom@npm:^2.0.0, @floating-ui/react-dom@npm:^2.0.2": version: 2.0.2 resolution: "@floating-ui/react-dom@npm:2.0.2" dependencies: @@ -11427,6 +11443,33 @@ __metadata: languageName: node linkType: hard +"@graphiql/react@npm:^0.19.4": + version: 0.19.4 + resolution: "@graphiql/react@npm:0.19.4" + dependencies: + "@graphiql/toolkit": ^0.9.1 + "@headlessui/react": ^1.7.15 + "@radix-ui/react-dialog": ^1.0.4 + "@radix-ui/react-dropdown-menu": ^2.0.5 + "@radix-ui/react-tooltip": ^1.0.6 + "@radix-ui/react-visually-hidden": ^1.0.3 + "@types/codemirror": ^5.60.8 + clsx: ^1.2.1 + codemirror: ^5.65.3 + codemirror-graphql: ^2.0.10 + copy-to-clipboard: ^3.2.0 + framer-motion: ^6.5.1 + graphql-language-service: ^5.2.0 + markdown-it: ^12.2.0 + set-value: ^4.1.0 + peerDependencies: + graphql: ^15.5.0 || ^16.0.0 + react: ^16.8.0 || ^17 || ^18 + react-dom: ^16.8.0 || ^17 || ^18 + checksum: 08eb53fc0449d5814ba92faff8e03ba77e97ecd4d3d473d115d1219e52b59d9a1cc1b0f34c41315b3a0185fb862646c1affd2094e1f5f524328a95c8e4e8b591 + languageName: node + linkType: hard + "@graphiql/toolkit@npm:^0.6.1": version: 0.6.1 resolution: "@graphiql/toolkit@npm:0.6.1" @@ -11440,6 +11483,22 @@ __metadata: languageName: node linkType: hard +"@graphiql/toolkit@npm:^0.9.1": + version: 0.9.1 + resolution: "@graphiql/toolkit@npm:0.9.1" + dependencies: + "@n1ru4l/push-pull-async-iterable-iterator": ^3.1.0 + meros: ^1.1.4 + peerDependencies: + graphql: ^15.5.0 || ^16.0.0 + graphql-ws: ">= 4.5.0" + peerDependenciesMeta: + graphql-ws: + optional: true + checksum: 5328426051b7f9a9ffbd569c950d1a103ce0e2ee7b5d7a57f3d899488ad43d1a5101e8aeced7416e106c7687d67bb7981aa7e87dea5b0f17b77569aa738bf3b5 + languageName: node + linkType: hard + "@graphql-codegen/cli@npm:^3.0.0": version: 3.3.1 resolution: "@graphql-codegen/cli@npm:3.3.1" @@ -12222,6 +12281,18 @@ __metadata: languageName: node linkType: hard +"@headlessui/react@npm:^1.7.15": + version: 1.7.17 + resolution: "@headlessui/react@npm:1.7.17" + dependencies: + client-only: ^0.0.1 + peerDependencies: + react: ^16 || ^17 || ^18 + react-dom: ^16 || ^17 || ^18 + checksum: 0cdb67747e7f606f78214dac0b48573247779e70534b4471515c094b74addda173dc6a9847d33aea9c6e6bc151016c034125328953077e32aa7947ebabed91f7 + languageName: node + linkType: hard + "@humanwhocodes/config-array@npm:^0.11.11": version: 0.11.11 resolution: "@humanwhocodes/config-array@npm:0.11.11" @@ -13358,6 +13429,71 @@ __metadata: languageName: node linkType: hard +"@motionone/animation@npm:^10.12.0": + version: 10.16.3 + resolution: "@motionone/animation@npm:10.16.3" + dependencies: + "@motionone/easing": ^10.16.3 + "@motionone/types": ^10.16.3 + "@motionone/utils": ^10.16.3 + tslib: ^2.3.1 + checksum: 797cacea335e6f892af27579eff51450dcf18c5bbc5c0ca44a000929b21857f4afb974ffb411c4935bfbd01ef2ddb3ef542ba3313ae66e1e5392b5d314df6ad3 + languageName: node + linkType: hard + +"@motionone/dom@npm:10.12.0": + version: 10.12.0 + resolution: "@motionone/dom@npm:10.12.0" + dependencies: + "@motionone/animation": ^10.12.0 + "@motionone/generators": ^10.12.0 + "@motionone/types": ^10.12.0 + "@motionone/utils": ^10.12.0 + hey-listen: ^1.0.8 + tslib: ^2.3.1 + checksum: 123356f28e44362c4f081aae3df22e576f46bfcb07e01257b2ac64a115668448f29b8de67e4b6e692c5407cffb78ffe7cf9fa1bc064007482bab5dd23a69d380 + languageName: node + linkType: hard + +"@motionone/easing@npm:^10.16.3": + version: 10.16.3 + resolution: "@motionone/easing@npm:10.16.3" + dependencies: + "@motionone/utils": ^10.16.3 + tslib: ^2.3.1 + checksum: 03e2460cdd35ee4967a86ce28ffbaaaca589263f659f652801cf6bd667baba9b3d5ce6d134df6b64413b60b34dd21d7c38b0cd8a4c3e1ed789789cdb971905b2 + languageName: node + linkType: hard + +"@motionone/generators@npm:^10.12.0": + version: 10.16.4 + resolution: "@motionone/generators@npm:10.16.4" + dependencies: + "@motionone/types": ^10.16.3 + "@motionone/utils": ^10.16.3 + tslib: ^2.3.1 + checksum: 185091c5cfbe67c38e84bf3920d1b5862e5d7eb624136494a7e4779b2f9d06855ebe3e633d95dcc5a1735d92d59d1ae28a0724c2f9d8bddd60fc9bc3603fab48 + languageName: node + linkType: hard + +"@motionone/types@npm:^10.12.0, @motionone/types@npm:^10.16.3": + version: 10.16.3 + resolution: "@motionone/types@npm:10.16.3" + checksum: ff38982f5aff2c0abbc3051c843d186d6f954c971e97dd6fced97a4ef50ee04f6e49607541ebb80e14dd143cf63553c388392110e270d04eca23f6b529f7f321 + languageName: node + linkType: hard + +"@motionone/utils@npm:^10.12.0, @motionone/utils@npm:^10.16.3": + version: 10.16.3 + resolution: "@motionone/utils@npm:10.16.3" + dependencies: + "@motionone/types": ^10.16.3 + hey-listen: ^1.0.8 + tslib: ^2.3.1 + checksum: d06025911c54c2217c98026cd38d4d681268a2b9b2830ac7342820881ba6be09721dd03626f52547749ead0543d5e2f2a69c9270ffdeaabc0949f7afb3233817 + languageName: node + linkType: hard + "@mswjs/cookies@npm:^0.2.2": version: 0.2.2 resolution: "@mswjs/cookies@npm:0.2.2" @@ -14598,6 +14734,564 @@ __metadata: languageName: node linkType: hard +"@radix-ui/primitive@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/primitive@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + checksum: 2b93e161d3fdabe9a64919def7fa3ceaecf2848341e9211520c401181c9eaebb8451c630b066fad2256e5c639c95edc41de0ba59c40eff37e799918d019822d1 + languageName: node + linkType: hard + +"@radix-ui/react-arrow@npm:1.0.3": + version: 1.0.3 + resolution: "@radix-ui/react-arrow@npm:1.0.3" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-primitive": 1.0.3 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 8cca086f0dbb33360e3c0142adf72f99fc96352d7086d6c2356dbb2ea5944cfb720a87d526fc48087741c602cd8162ca02b0af5e6fdf5f56d20fddb44db8b4c3 + languageName: node + linkType: hard + +"@radix-ui/react-collection@npm:1.0.3": + version: 1.0.3 + resolution: "@radix-ui/react-collection@npm:1.0.3" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-context": 1.0.1 + "@radix-ui/react-primitive": 1.0.3 + "@radix-ui/react-slot": 1.0.2 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: acfbc9b0b2c553d343c22f02c9f098bc5cfa99e6e48df91c0d671855013f8b877ade9c657b7420a7aa523b5aceadea32a60dd72c23b1291f415684fb45d00cff + languageName: node + linkType: hard + +"@radix-ui/react-compose-refs@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-compose-refs@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 2b9a613b6db5bff8865588b6bf4065f73021b3d16c0a90b2d4c23deceeb63612f1f15de188227ebdc5f88222cab031be617a9dd025874c0487b303be3e5cc2a8 + languageName: node + linkType: hard + +"@radix-ui/react-context@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-context@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 60e9b81d364f40c91a6213ec953f7c64fcd9d75721205a494a5815b3e5ae0719193429b62ee6c7002cd6aaf70f8c0e2f08bdbaba9ffcc233044d32b56d2127d1 + languageName: node + linkType: hard + +"@radix-ui/react-dialog@npm:^1.0.4": + version: 1.0.5 + resolution: "@radix-ui/react-dialog@npm:1.0.5" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/primitive": 1.0.1 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-context": 1.0.1 + "@radix-ui/react-dismissable-layer": 1.0.5 + "@radix-ui/react-focus-guards": 1.0.1 + "@radix-ui/react-focus-scope": 1.0.4 + "@radix-ui/react-id": 1.0.1 + "@radix-ui/react-portal": 1.0.4 + "@radix-ui/react-presence": 1.0.1 + "@radix-ui/react-primitive": 1.0.3 + "@radix-ui/react-slot": 1.0.2 + "@radix-ui/react-use-controllable-state": 1.0.1 + aria-hidden: ^1.1.1 + react-remove-scroll: 2.5.5 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 3d11ca31afb794a6dd286005ab7894cb0ce7bc2de5481de98900470b11d495256401306763de030f5e35aa545ff90d34632ffd54a1b29bf55afba813be4bb84a + languageName: node + linkType: hard + +"@radix-ui/react-direction@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-direction@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 5336a8b0d4f1cde585d5c2b4448af7b3d948bb63a1aadb37c77771b0e5902dc6266e409cf35fd0edaca7f33e26424be19e64fb8f9d7f7be2d6f1714ea2764210 + languageName: node + linkType: hard + +"@radix-ui/react-dismissable-layer@npm:1.0.5": + version: 1.0.5 + resolution: "@radix-ui/react-dismissable-layer@npm:1.0.5" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/primitive": 1.0.1 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-primitive": 1.0.3 + "@radix-ui/react-use-callback-ref": 1.0.1 + "@radix-ui/react-use-escape-keydown": 1.0.3 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: e73cf4bd3763f4d55b1bea7486a9700384d7d94dc00b1d5a75e222b2f1e4f32bc667a206ca4ed3baaaf7424dce7a239afd0ba59a6f0d89c3462c4e6e8d029a04 + languageName: node + linkType: hard + +"@radix-ui/react-dropdown-menu@npm:^2.0.5": + version: 2.0.6 + resolution: "@radix-ui/react-dropdown-menu@npm:2.0.6" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/primitive": 1.0.1 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-context": 1.0.1 + "@radix-ui/react-id": 1.0.1 + "@radix-ui/react-menu": 2.0.6 + "@radix-ui/react-primitive": 1.0.3 + "@radix-ui/react-use-controllable-state": 1.0.1 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 1433e04234c29ae688b1d50b4a5ad0fd67e2627a5ea2e5f60fec6e4307e673ef35a703672eae0d61d96156c59084bbb19de9f9b9936b3fc351917dfe41dcf403 + languageName: node + linkType: hard + +"@radix-ui/react-focus-guards@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-focus-guards@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 1f8ca8f83b884b3612788d0742f3f054e327856d90a39841a47897dbed95e114ee512362ae314177de226d05310047cabbf66b686ae86ad1b65b6b295be24ef7 + languageName: node + linkType: hard + +"@radix-ui/react-focus-scope@npm:1.0.4": + version: 1.0.4 + resolution: "@radix-ui/react-focus-scope@npm:1.0.4" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-primitive": 1.0.3 + "@radix-ui/react-use-callback-ref": 1.0.1 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 3481db1a641513a572734f0bcb0e47fefeba7bccd6ec8dde19f520719c783ef0b05a55ef0d5292078ed051cc5eda46b698d5d768da02e26e836022f46b376fd1 + languageName: node + linkType: hard + +"@radix-ui/react-id@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-id@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-use-layout-effect": 1.0.1 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 446a453d799cc790dd2a1583ff8328da88271bff64530b5a17c102fa7fb35eece3cf8985359d416f65e330cd81aa7b8fe984ea125fc4f4eaf4b3801d698e49fe + languageName: node + linkType: hard + +"@radix-ui/react-menu@npm:2.0.6": + version: 2.0.6 + resolution: "@radix-ui/react-menu@npm:2.0.6" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/primitive": 1.0.1 + "@radix-ui/react-collection": 1.0.3 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-context": 1.0.1 + "@radix-ui/react-direction": 1.0.1 + "@radix-ui/react-dismissable-layer": 1.0.5 + "@radix-ui/react-focus-guards": 1.0.1 + "@radix-ui/react-focus-scope": 1.0.4 + "@radix-ui/react-id": 1.0.1 + "@radix-ui/react-popper": 1.1.3 + "@radix-ui/react-portal": 1.0.4 + "@radix-ui/react-presence": 1.0.1 + "@radix-ui/react-primitive": 1.0.3 + "@radix-ui/react-roving-focus": 1.0.4 + "@radix-ui/react-slot": 1.0.2 + "@radix-ui/react-use-callback-ref": 1.0.1 + aria-hidden: ^1.1.1 + react-remove-scroll: 2.5.5 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: a43fb560dbb5a4ddc43ea4e2434a9f517bbbcbf8b12e1e74c1e36666ad321aef7e39f91770140c106fe6f34e237102be8a02f3bc5588e6c06a709e20580c5e82 + languageName: node + linkType: hard + +"@radix-ui/react-popper@npm:1.1.3": + version: 1.1.3 + resolution: "@radix-ui/react-popper@npm:1.1.3" + dependencies: + "@babel/runtime": ^7.13.10 + "@floating-ui/react-dom": ^2.0.0 + "@radix-ui/react-arrow": 1.0.3 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-context": 1.0.1 + "@radix-ui/react-primitive": 1.0.3 + "@radix-ui/react-use-callback-ref": 1.0.1 + "@radix-ui/react-use-layout-effect": 1.0.1 + "@radix-ui/react-use-rect": 1.0.1 + "@radix-ui/react-use-size": 1.0.1 + "@radix-ui/rect": 1.0.1 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: b18a15958623f9222b6ed3e24b9fbcc2ba67b8df5a5272412f261de1592b3f05002af1c8b94c065830c3c74267ce00cf6c1d70d4d507ec92ba639501f98aa348 + languageName: node + linkType: hard + +"@radix-ui/react-portal@npm:1.0.4": + version: 1.0.4 + resolution: "@radix-ui/react-portal@npm:1.0.4" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-primitive": 1.0.3 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: c4cf35e2f26a89703189d0eef3ceeeb706ae0832e98e558730a5e929ca7c72c7cb510413a24eca94c7732f8d659a1e81942bec7b90540cb73ce9e4885d040b64 + languageName: node + linkType: hard + +"@radix-ui/react-presence@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-presence@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-use-layout-effect": 1.0.1 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: ed2ff9faf9e4257a4065034d3771459e5a91c2d840b2fcec94661761704dbcb65bcdd927d28177a2a129b3dab5664eb90a9b88309afe0257a9f8ba99338c0d95 + languageName: node + linkType: hard + +"@radix-ui/react-primitive@npm:1.0.3": + version: 1.0.3 + resolution: "@radix-ui/react-primitive@npm:1.0.3" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-slot": 1.0.2 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 9402bc22923c8e5c479051974a721c301535c36521c0237b83e5fa213d013174e77f3ad7905e6d60ef07e14f88ec7f4ea69891dc7a2b39047f8d3640e8f8d713 + languageName: node + linkType: hard + +"@radix-ui/react-roving-focus@npm:1.0.4": + version: 1.0.4 + resolution: "@radix-ui/react-roving-focus@npm:1.0.4" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/primitive": 1.0.1 + "@radix-ui/react-collection": 1.0.3 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-context": 1.0.1 + "@radix-ui/react-direction": 1.0.1 + "@radix-ui/react-id": 1.0.1 + "@radix-ui/react-primitive": 1.0.3 + "@radix-ui/react-use-callback-ref": 1.0.1 + "@radix-ui/react-use-controllable-state": 1.0.1 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 69b1c82c2d9db3ba71549a848f2704200dab1b2cd22d050c1e081a78b9a567dbfdc7fd0403ee010c19b79652de69924d8ca2076cd031d6552901e4213493ffc7 + languageName: node + linkType: hard + +"@radix-ui/react-slot@npm:1.0.2": + version: 1.0.2 + resolution: "@radix-ui/react-slot@npm:1.0.2" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-compose-refs": 1.0.1 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: edf5edf435ff594bea7e198bf16d46caf81b6fb559493acad4fa8c308218896136acb16f9b7238c788fd13e94a904f2fd0b6d834e530e4cae94522cdb8f77ce9 + languageName: node + linkType: hard + +"@radix-ui/react-tooltip@npm:^1.0.6": + version: 1.0.7 + resolution: "@radix-ui/react-tooltip@npm:1.0.7" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/primitive": 1.0.1 + "@radix-ui/react-compose-refs": 1.0.1 + "@radix-ui/react-context": 1.0.1 + "@radix-ui/react-dismissable-layer": 1.0.5 + "@radix-ui/react-id": 1.0.1 + "@radix-ui/react-popper": 1.1.3 + "@radix-ui/react-portal": 1.0.4 + "@radix-ui/react-presence": 1.0.1 + "@radix-ui/react-primitive": 1.0.3 + "@radix-ui/react-slot": 1.0.2 + "@radix-ui/react-use-controllable-state": 1.0.1 + "@radix-ui/react-visually-hidden": 1.0.3 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 894d448c69a3e4d7626759f9f6c7997018fe8ef9cde098393bd83e10743d493dfd284eef041e46accc45486d5a5cd5f76d97f56afbdace7aed6e0cb14007bf15 + languageName: node + linkType: hard + +"@radix-ui/react-use-callback-ref@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-use-callback-ref@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: b9fd39911c3644bbda14a84e4fca080682bef84212b8d8931fcaa2d2814465de242c4cfd8d7afb3020646bead9c5e539d478cea0a7031bee8a8a3bb164f3bc4c + languageName: node + linkType: hard + +"@radix-ui/react-use-controllable-state@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-use-controllable-state@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-use-callback-ref": 1.0.1 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: dee2be1937d293c3a492cb6d279fc11495a8f19dc595cdbfe24b434e917302f9ac91db24e8cc5af9a065f3f209c3423115b5442e65a5be9fd1e9091338972be9 + languageName: node + linkType: hard + +"@radix-ui/react-use-escape-keydown@npm:1.0.3": + version: 1.0.3 + resolution: "@radix-ui/react-use-escape-keydown@npm:1.0.3" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-use-callback-ref": 1.0.1 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: c6ed0d9ce780f67f924980eb305af1f6cce2a8acbaf043a58abe0aa3cc551d9aa76ccee14531df89bbee302ead7ecc7fce330886f82d4672c5eda52f357ef9b8 + languageName: node + linkType: hard + +"@radix-ui/react-use-layout-effect@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-use-layout-effect@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: bed9c7e8de243a5ec3b93bb6a5860950b0dba359b6680c84d57c7a655e123dec9b5891c5dfe81ab970652e7779fe2ad102a23177c7896dde95f7340817d47ae5 + languageName: node + linkType: hard + +"@radix-ui/react-use-rect@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-use-rect@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/rect": 1.0.1 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 433f07e61e04eb222349825bb05f3591fca131313a1d03709565d6226d8660bd1d0423635553f95ee4fcc25c8f2050972d848808d753c388e2a9ae191ebf17f3 + languageName: node + linkType: hard + +"@radix-ui/react-use-size@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/react-use-size@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-use-layout-effect": 1.0.1 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 6cc150ad1e9fa85019c225c5a5d50a0af6cdc4653dad0c21b4b40cd2121f36ee076db326c43e6bc91a69766ccff5a84e917d27970176b592577deea3c85a3e26 + languageName: node + linkType: hard + +"@radix-ui/react-visually-hidden@npm:1.0.3, @radix-ui/react-visually-hidden@npm:^1.0.3": + version: 1.0.3 + resolution: "@radix-ui/react-visually-hidden@npm:1.0.3" + dependencies: + "@babel/runtime": ^7.13.10 + "@radix-ui/react-primitive": 1.0.3 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 2e9d0c8253f97e7d6ffb2e52a5cfd40ba719f813b39c3e2e42c496d54408abd09ef66b5aec4af9b8ab0553215e32452a5d0934597a49c51dd90dc39181ed0d57 + languageName: node + linkType: hard + +"@radix-ui/rect@npm:1.0.1": + version: 1.0.1 + resolution: "@radix-ui/rect@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.13.10 + checksum: aeec13b234a946052512d05239067d2d63422f9ec70bf2fe7acfd6b9196693fc33fbaf43c2667c167f777d90a095c6604eb487e0bce79e230b6df0f6cacd6a55 + languageName: node + linkType: hard + "@react-hookz/deep-equal@npm:^1.0.4": version: 1.0.4 resolution: "@react-hookz/deep-equal@npm:1.0.4" @@ -17061,12 +17755,21 @@ __metadata: languageName: node linkType: hard -"@types/codemirror@npm:^5.0.0": - version: 5.60.10 - resolution: "@types/codemirror@npm:5.60.10" +"@types/codemirror@npm:^0.0.90": + version: 0.0.90 + resolution: "@types/codemirror@npm:0.0.90" dependencies: "@types/tern": "*" - checksum: c5977db03939f2a208f0ec7958be70b4fb205dd3f3122b2175ff28287a5424da95f9030b2838c61d37e6278ec53795861dec12439967c1e1da885b2b2a65b299 + checksum: f4594b9bc95306bbbe24d967e0749e28fe7b1e461c41621429b8c8bc295bda1704d99c1d7d5496efd987ee80d24f055155ddd742fa0c975cd69f279ccdaa0af9 + languageName: node + linkType: hard + +"@types/codemirror@npm:^5.0.0, @types/codemirror@npm:^5.60.8": + version: 5.60.12 + resolution: "@types/codemirror@npm:5.60.12" + dependencies: + "@types/tern": "*" + checksum: dff22f32ea42ccd3f9bfcf408631f94a11ffb4614ff4fa8cc55adf7da6e7ba96650533b8dd27d037242747bdaa85141e93520f84409db7bc394862a174a10e1e languageName: node linkType: hard @@ -19871,6 +20574,15 @@ __metadata: languageName: node linkType: hard +"aria-hidden@npm:^1.1.1": + version: 1.2.3 + resolution: "aria-hidden@npm:1.2.3" + dependencies: + tslib: ^2.0.0 + checksum: 7d7d211629eef315e94ed3b064c6823d13617e609d3f9afab1c2ed86399bb8e90405f9bdd358a85506802766f3ecb468af985c67c846045a34b973bcc0289db9 + languageName: node + linkType: hard + "aria-query@npm:5.1.3, aria-query@npm:^5.0.0, aria-query@npm:^5.1.3": version: 5.1.3 resolution: "aria-query@npm:5.1.3" @@ -21826,7 +22538,7 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^1.0.2, clsx@npm:^1.0.4, clsx@npm:^1.1.1": +"clsx@npm:^1.0.2, clsx@npm:^1.0.4, clsx@npm:^1.1.1, clsx@npm:^1.2.1": version: 1.2.1 resolution: "clsx@npm:1.2.1" checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12 @@ -21890,6 +22602,20 @@ __metadata: languageName: node linkType: hard +"codemirror-graphql@npm:^2.0.10": + version: 2.0.10 + resolution: "codemirror-graphql@npm:2.0.10" + dependencies: + "@types/codemirror": ^0.0.90 + graphql-language-service: 5.2.0 + peerDependencies: + "@codemirror/language": 6.0.0 + codemirror: ^5.65.3 + graphql: ^15.5.0 || ^16.0.0 + checksum: d14e680168f407fd3d6ab09d88ea33640dd39f84d9ceb1ce605d9687d459fd08787109800a9847bbce72122e3318e975b255f65ddb19725d7a12781f4bf26506 + languageName: node + linkType: hard + "codemirror@npm:^5.65.3": version: 5.65.3 resolution: "codemirror@npm:5.65.3" @@ -23680,6 +24406,13 @@ __metadata: languageName: node linkType: hard +"detect-node-es@npm:^1.1.0": + version: 1.1.0 + resolution: "detect-node-es@npm:1.1.0" + checksum: e46307d7264644975b71c104b9f028ed1d3d34b83a15b8a22373640ce5ea630e5640b1078b8ea15f202b54641da71e4aa7597093bd4b91f113db520a26a37449 + languageName: node + linkType: hard + "detect-node@npm:^2.0.4": version: 2.0.4 resolution: "detect-node@npm:2.0.4" @@ -26535,6 +27268,36 @@ __metadata: languageName: node linkType: hard +"framer-motion@npm:^6.5.1": + version: 6.5.1 + resolution: "framer-motion@npm:6.5.1" + dependencies: + "@emotion/is-prop-valid": ^0.8.2 + "@motionone/dom": 10.12.0 + framesync: 6.0.1 + hey-listen: ^1.0.8 + popmotion: 11.0.3 + style-value-types: 5.0.0 + tslib: ^2.1.0 + peerDependencies: + react: ">=16.8 || ^17.0.0 || ^18.0.0" + react-dom: ">=16.8 || ^17.0.0 || ^18.0.0" + dependenciesMeta: + "@emotion/is-prop-valid": + optional: true + checksum: 737959063137b4ccafe01e0ac0c9e5a9531bf3f729f62c34ca7a5d7955e6664f70affd22b044f7db51df41acb21d120a4f71a860e17a80c4db766ad66f2153a1 + languageName: node + linkType: hard + +"framesync@npm:6.0.1": + version: 6.0.1 + resolution: "framesync@npm:6.0.1" + dependencies: + tslib: ^2.1.0 + checksum: a23ebe8f7e20a32c0b99c2f8175b6f07af3ec6316aad52a2316316a6d011d717af8d2175dcc2827031c59fabb30232ed3e19a720a373caba7f070e1eae436325 + languageName: node + linkType: hard + "fresh@npm:0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" @@ -26814,6 +27577,13 @@ __metadata: languageName: node linkType: hard +"get-nonce@npm:^1.0.0": + version: 1.0.1 + resolution: "get-nonce@npm:1.0.1" + checksum: e2614e43b4694c78277bb61b0f04583d45786881289285c73770b07ded246a98be7e1f78b940c80cbe6f2b07f55f0b724e6db6fd6f1bcbd1e8bdac16521074ed + languageName: node + linkType: hard + "get-package-type@npm:^0.1.0": version: 0.1.0 resolution: "get-package-type@npm:0.1.0" @@ -27198,7 +27968,7 @@ __metadata: languageName: node linkType: hard -"graphiql@npm:^1.5.12, graphiql@npm:^1.8.8": +"graphiql@npm:^1.8.8": version: 1.11.5 resolution: "graphiql@npm:1.11.5" dependencies: @@ -27215,6 +27985,22 @@ __metadata: languageName: node linkType: hard +"graphiql@npm:^3.0.6": + version: 3.0.6 + resolution: "graphiql@npm:3.0.6" + dependencies: + "@graphiql/react": ^0.19.4 + "@graphiql/toolkit": ^0.9.1 + graphql-language-service: ^5.2.0 + markdown-it: ^12.2.0 + peerDependencies: + graphql: ^15.5.0 || ^16.0.0 + react: ^16.8.0 || ^17 || ^18 + react-dom: ^16.8.0 || ^17 || ^18 + checksum: 34d35ca4b46ce1e0cef0362f15d091481d2275e4a5b537b5715cfbaee15b1e114c31f35a63558a6f74a754687fbf4bc977411818af34e2e471a96902370c40f2 + languageName: node + linkType: hard + "graphlib@npm:^2.1.8": version: 2.1.8 resolution: "graphlib@npm:2.1.8" @@ -27249,17 +28035,17 @@ __metadata: languageName: node linkType: hard -"graphql-language-service@npm:^5.0.6": - version: 5.0.6 - resolution: "graphql-language-service@npm:5.0.6" +"graphql-language-service@npm:5.2.0, graphql-language-service@npm:^5.0.6, graphql-language-service@npm:^5.2.0": + version: 5.2.0 + resolution: "graphql-language-service@npm:5.2.0" dependencies: nullthrows: ^1.0.0 - vscode-languageserver-types: ^3.15.1 + vscode-languageserver-types: ^3.17.1 peerDependencies: graphql: ^15.5.0 || ^16.0.0 bin: graphql: dist/temp-bin.js - checksum: a7155ba934aa428278cce0f460fa3b8b12020a26a0355e60738974617a66d9b2f1bb7d41cbd72a1620a29e61f10ca438cbf72cbf2405b8f653edddfc69fec02a + checksum: b053c6b7158d0ee7a3e55391bfd8be956fc5380211ca586b3a252007845e119540fb40efcc438975eaebc5ef25f46973f7ff4d9543c66e14ebd992957e0299b7 languageName: node linkType: hard @@ -27627,6 +28413,13 @@ __metadata: languageName: node linkType: hard +"hey-listen@npm:^1.0.8": + version: 1.0.8 + resolution: "hey-listen@npm:1.0.8" + checksum: 6bad60b367688f5348e25e7ca3276a74b59ac5a09b0455e6ff8ab7d4a9e38cd2116c708a7dcd8a954d27253ce1d8717ec891d175723ea739885b828cf44e4072 + languageName: node + linkType: hard + "highlight.js@npm:^10.1.0, highlight.js@npm:^10.4.1, highlight.js@npm:^10.6.0, highlight.js@npm:^10.7.2, highlight.js@npm:~10.7.0": version: 10.7.3 resolution: "highlight.js@npm:10.7.3" @@ -35259,6 +36052,18 @@ __metadata: languageName: node linkType: hard +"popmotion@npm:11.0.3": + version: 11.0.3 + resolution: "popmotion@npm:11.0.3" + dependencies: + framesync: 6.0.1 + hey-listen: ^1.0.8 + style-value-types: 5.0.0 + tslib: ^2.1.0 + checksum: 9fe7d03b4ec0e85bfb9dadc23b745147bfe42e16f466ba06e6327197d0e38b72015afc2f918a8051dedc3680310417f346ffdc463be6518e2e92e98f48e30268 + languageName: node + linkType: hard + "popper.js@npm:1.16.1-lts": version: 1.16.1-lts resolution: "popper.js@npm:1.16.1-lts" @@ -36867,6 +37672,41 @@ __metadata: languageName: node linkType: hard +"react-remove-scroll-bar@npm:^2.3.3": + version: 2.3.4 + resolution: "react-remove-scroll-bar@npm:2.3.4" + dependencies: + react-style-singleton: ^2.2.1 + tslib: ^2.0.0 + peerDependencies: + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: b5ce5f2f98d65c97a3e975823ae4043a4ba2a3b63b5ba284b887e7853f051b5cd6afb74abde6d57b421931c52f2e1fdbb625dc858b1cb5a32c27c14ab85649d4 + languageName: node + linkType: hard + +"react-remove-scroll@npm:2.5.5": + version: 2.5.5 + resolution: "react-remove-scroll@npm:2.5.5" + dependencies: + react-remove-scroll-bar: ^2.3.3 + react-style-singleton: ^2.2.1 + tslib: ^2.1.0 + use-callback-ref: ^1.3.0 + use-sidecar: ^1.1.2 + peerDependencies: + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 2c7fe9cbd766f5e54beb4bec2e2efb2de3583037b23fef8fa511ab426ed7f1ae992382db5acd8ab5bfb030a4b93a06a2ebca41377d6eeaf0e6791bb0a59616a4 + languageName: node + linkType: hard + "react-resizable@npm:^3.0.4, react-resizable@npm:^3.0.5": version: 3.0.5 resolution: "react-resizable@npm:3.0.5" @@ -37000,6 +37840,23 @@ __metadata: languageName: node linkType: hard +"react-style-singleton@npm:^2.2.1": + version: 2.2.1 + resolution: "react-style-singleton@npm:2.2.1" + dependencies: + get-nonce: ^1.0.0 + invariant: ^2.2.4 + tslib: ^2.0.0 + peerDependencies: + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 7ee8ef3aab74c7ae1d70ff34a27643d11ba1a8d62d072c767827d9ff9a520905223e567002e0bf6c772929d8ea1c781a3ba0cc4a563e92b1e3dc2eaa817ecbe8 + languageName: node + linkType: hard + "react-syntax-highlighter@npm:^15.4.5, react-syntax-highlighter@npm:^15.5.0": version: 15.5.0 resolution: "react-syntax-highlighter@npm:15.5.0" @@ -39863,6 +40720,16 @@ __metadata: languageName: node linkType: hard +"style-value-types@npm:5.0.0": + version: 5.0.0 + resolution: "style-value-types@npm:5.0.0" + dependencies: + hey-listen: ^1.0.8 + tslib: ^2.1.0 + checksum: 16d198302cd102edf9dba94e7752a2364c93b1eaa5cc7c32b42b28eef4af4ccb5149a3f16bc2a256adc02616a2404f4612bd15f3081c1e8ca06132cae78be6c0 + languageName: node + linkType: hard + "styled-components@npm:^5.3.3": version: 5.3.11 resolution: "styled-components@npm:5.3.11" @@ -41570,6 +42437,21 @@ __metadata: languageName: node linkType: hard +"use-callback-ref@npm:^1.3.0": + version: 1.3.0 + resolution: "use-callback-ref@npm:1.3.0" + dependencies: + tslib: ^2.0.0 + peerDependencies: + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 7913df383a5a6fcb399212eedefaac2e0c6f843555202d4e3010bac3848afe38ecaa3d0d6500ad1d936fbeffd637e6c517e68edb024af5e6beca7f27f3ce7b21 + languageName: node + linkType: hard + "use-composed-ref@npm:^1.3.0": version: 1.3.0 resolution: "use-composed-ref@npm:1.3.0" @@ -41648,6 +42530,22 @@ __metadata: languageName: node linkType: hard +"use-sidecar@npm:^1.1.2": + version: 1.1.2 + resolution: "use-sidecar@npm:1.1.2" + dependencies: + detect-node-es: ^1.1.0 + tslib: ^2.0.0 + peerDependencies: + "@types/react": ^16.9.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 925d1922f9853e516eaad526b6fed1be38008073067274f0ecc3f56b17bb8ab63480140dd7c271f94150027c996cea4efe83d3e3525e8f3eda22055f6a39220b + languageName: node + linkType: hard + "use-sync-external-store@npm:^1.0.0, use-sync-external-store@npm:^1.2.0": version: 1.2.0 resolution: "use-sync-external-store@npm:1.2.0" @@ -41974,10 +42872,10 @@ __metadata: languageName: node linkType: hard -"vscode-languageserver-types@npm:^3.15.1": - version: 3.15.1 - resolution: "vscode-languageserver-types@npm:3.15.1" - checksum: 28c1cb0d5b7ad7c719015a6eb5f774c000fe68c41bbd4a3fd0cbe6d862f27eec075d6bfb14c9d86c22d0e8711c2df8194295bf1e7d6ac0c359cab348c5e14887 +"vscode-languageserver-types@npm:^3.17.1": + version: 3.17.5 + resolution: "vscode-languageserver-types@npm:3.17.5" + checksum: 79b420e7576398d396579ca3a461c9ed70e78db4403cd28bbdf4d3ed2b66a2b4114031172e51fad49f0baa60a2180132d7cb2ea35aa3157d7af3c325528210ac languageName: node linkType: hard From ec61acd4997d0385ebf150a5722ae229851594f6 Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Fri, 20 Oct 2023 13:21:48 -0400 Subject: [PATCH 282/348] Changed from patch to minor Signed-off-by: Taras Mankovski --- .changeset/four-files-behave.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/four-files-behave.md b/.changeset/four-files-behave.md index 3e218aa7e8..0430bd98d8 100644 --- a/.changeset/four-files-behave.md +++ b/.changeset/four-files-behave.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-graphiql': patch +'@backstage/plugin-graphiql': minor --- -Upgrade to GraphiQL 3.0.6 +Upgrade to GraphiQL to 3.0.6 From edccfd966200cac8e7fb9b088c7d3830f20baa91 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 20 Oct 2023 17:34:08 +0000 Subject: [PATCH 283/348] chore(deps): update github/codeql-action action to v2.22.4 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- .github/workflows/sync_snyk-monitor.yml | 2 +- .github/workflows/verify_codeql.yml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index c9078f0086..0f99453bba 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -66,6 +66,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@fdcae64e1484d349b3366718cdfef3d404390e85 # v2.22.1 + uses: github/codeql-action/upload-sarif@49abf0ba24d0b7953cb586944e918a0b92074c80 # v2.22.4 with: sarif_file: results.sarif diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index 6450b1bd51..84b2b3387b 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -58,6 +58,6 @@ jobs: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} NODE_OPTIONS: --max-old-space-size=7168 - name: Upload Snyk report - uses: github/codeql-action/upload-sarif@v2.21.8 + uses: github/codeql-action/upload-sarif@v2.22.4 with: sarif_file: snyk.sarif diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index 666bd5f0f4..fb29fb78e1 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -55,7 +55,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2.21.8 + uses: github/codeql-action/init@v2.22.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -66,7 +66,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2.21.8 + uses: github/codeql-action/autobuild@v2.22.4 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -80,4 +80,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2.21.8 + uses: github/codeql-action/analyze@v2.22.4 From 361bb34d8eeb6c2d1bdfcd5521744ca2f0594eef Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Fri, 25 Aug 2023 14:03:17 -0500 Subject: [PATCH 284/348] Refactored annotation values Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/poor-seahorses-rush.md | 5 + .../EntityPageAzurePipelines.tsx | 4 +- .../src/components/ReadmeCard/ReadmeCard.tsx | 18 +- plugins/azure-devops/src/constants.ts | 2 + plugins/azure-devops/src/hooks/index.ts | 1 - plugins/azure-devops/src/hooks/useGitTags.ts | 11 +- .../src/hooks/useProjectRepoFromEntity.ts | 47 ---- .../azure-devops/src/hooks/usePullRequests.ts | 11 +- .../azure-devops/src/hooks/useRepoBuilds.ts | 11 +- .../getAnnotationValuesFromEntity.test.ts | 230 ++++++++++++++++++ ...ty.ts => getAnnotationValuesFromEntity.ts} | 29 ++- plugins/azure-devops/src/utils/index.ts | 2 +- 12 files changed, 292 insertions(+), 79 deletions(-) create mode 100644 .changeset/poor-seahorses-rush.md delete mode 100644 plugins/azure-devops/src/hooks/useProjectRepoFromEntity.ts create mode 100644 plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts rename plugins/azure-devops/src/utils/{getAnnotationFromEntity.ts => getAnnotationValuesFromEntity.ts} (72%) diff --git a/.changeset/poor-seahorses-rush.md b/.changeset/poor-seahorses-rush.md new file mode 100644 index 0000000000..55313f706d --- /dev/null +++ b/.changeset/poor-seahorses-rush.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-azure-devops': patch +--- + +Consolidated getting the annotation values into a single function to help with future changes diff --git a/plugins/azure-devops/src/components/EntityPageAzurePipelines/EntityPageAzurePipelines.tsx b/plugins/azure-devops/src/components/EntityPageAzurePipelines/EntityPageAzurePipelines.tsx index ad278e3fc4..02a61a9a9a 100644 --- a/plugins/azure-devops/src/components/EntityPageAzurePipelines/EntityPageAzurePipelines.tsx +++ b/plugins/azure-devops/src/components/EntityPageAzurePipelines/EntityPageAzurePipelines.tsx @@ -16,14 +16,14 @@ import { BuildTable } from '../BuildTable/BuildTable'; import React from 'react'; -import { getAnnotationFromEntity } from '../../utils/getAnnotationFromEntity'; +import { getAnnotationValuesFromEntity } from '../../utils/getAnnotationValuesFromEntity'; import { useBuildRuns } from '../../hooks/useBuildRuns'; import { useEntity } from '@backstage/plugin-catalog-react'; export const EntityPageAzurePipelines = (props: { defaultLimit?: number }) => { const { entity } = useEntity(); - const { project, repo, definition } = getAnnotationFromEntity(entity); + const { project, repo, definition } = getAnnotationValuesFromEntity(entity); const { items, loading, error } = useBuildRuns( project, diff --git a/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx b/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx index d06726e929..d9afe8db5a 100644 --- a/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx +++ b/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx @@ -23,11 +23,11 @@ import { ErrorPanel, } from '@backstage/core-components'; import { useEntity } from '@backstage/plugin-catalog-react'; -import { useProjectRepoFromEntity } from '../../hooks'; import { useApi } from '@backstage/core-plugin-api'; import React from 'react'; import { azureDevOpsApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; +import { getAnnotationValuesFromEntity } from '../../utils'; const useStyles = makeStyles(theme => ({ readMe: { @@ -87,16 +87,14 @@ export const ReadmeCard = (props: Props) => { const classes = useStyles(); const api = useApi(azureDevOpsApiRef); const { entity } = useEntity(); - const { project, repo } = useProjectRepoFromEntity(entity); + const { project, repo } = getAnnotationValuesFromEntity(entity); - const { loading, error, value } = useAsync( - () => - api.getReadme({ - project, - repo, - }), - [api, project, repo, entity], - ); + const { loading, error, value } = useAsync(async () => { + if (repo) { + return await api.getReadme({ project, repo }); + } + return undefined; + }, [api, project, repo, entity]); if (loading) { return ; diff --git a/plugins/azure-devops/src/constants.ts b/plugins/azure-devops/src/constants.ts index 95e5be4930..765f5a965b 100644 --- a/plugins/azure-devops/src/constants.ts +++ b/plugins/azure-devops/src/constants.ts @@ -16,6 +16,8 @@ export const AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION = 'dev.azure.com/build-definition'; +export const AZURE_DEVOPS_ORGANIZATION_ANNOTATION = + 'dev.azure.com/organization'; export const AZURE_DEVOPS_PROJECT_ANNOTATION = 'dev.azure.com/project'; export const AZURE_DEVOPS_REPO_ANNOTATION = 'dev.azure.com/project-repo'; export const AZURE_DEVOPS_DEFAULT_TOP: number = 10; diff --git a/plugins/azure-devops/src/hooks/index.ts b/plugins/azure-devops/src/hooks/index.ts index a3864c21f7..0b745ba586 100644 --- a/plugins/azure-devops/src/hooks/index.ts +++ b/plugins/azure-devops/src/hooks/index.ts @@ -16,7 +16,6 @@ export * from './useAllTeams'; export * from './useDashboardPullRequests'; -export * from './useProjectRepoFromEntity'; export * from './usePullRequests'; export * from './useRepoBuilds'; export * from './useUserEmail'; diff --git a/plugins/azure-devops/src/hooks/useGitTags.ts b/plugins/azure-devops/src/hooks/useGitTags.ts index b940a7105d..f36f9224aa 100644 --- a/plugins/azure-devops/src/hooks/useGitTags.ts +++ b/plugins/azure-devops/src/hooks/useGitTags.ts @@ -20,7 +20,7 @@ import { Entity } from '@backstage/catalog-model'; import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; -import { useProjectRepoFromEntity } from './useProjectRepoFromEntity'; +import { getAnnotationValuesFromEntity } from '../utils'; export function useGitTags(entity: Entity): { items?: GitTag[]; @@ -28,10 +28,13 @@ export function useGitTags(entity: Entity): { error?: Error; } { const api = useApi(azureDevOpsApiRef); - const { project, repo } = useProjectRepoFromEntity(entity); + const { project, repo } = getAnnotationValuesFromEntity(entity); - const { value, loading, error } = useAsync(() => { - return api.getGitTags(project, repo); + const { value, loading, error } = useAsync(async () => { + if (repo) { + return await api.getGitTags(project, repo); + } + return undefined; }, [api, project, repo]); return { diff --git a/plugins/azure-devops/src/hooks/useProjectRepoFromEntity.ts b/plugins/azure-devops/src/hooks/useProjectRepoFromEntity.ts deleted file mode 100644 index b484bca009..0000000000 --- a/plugins/azure-devops/src/hooks/useProjectRepoFromEntity.ts +++ /dev/null @@ -1,47 +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 { Entity } from '@backstage/catalog-model'; -import { AZURE_DEVOPS_REPO_ANNOTATION } from '../constants'; - -export function useProjectRepoFromEntity(entity: Entity): { - project: string; - repo: string; -} { - const [project, repo] = ( - entity.metadata.annotations?.[AZURE_DEVOPS_REPO_ANNOTATION] ?? '' - ).split('/'); - - if (!project && !repo) { - throw new Error( - 'Value for annotation dev.azure.com/project-repo was not in the correct format: /', - ); - } - - if (!project) { - throw new Error( - 'Project Name for annotation dev.azure.com/project-repo was not found; expected format is: /', - ); - } - - if (!repo) { - throw new Error( - 'Repo Name for annotation dev.azure.com/project-repo was not found; expected format is: /', - ); - } - - return { project, repo }; -} diff --git a/plugins/azure-devops/src/hooks/usePullRequests.ts b/plugins/azure-devops/src/hooks/usePullRequests.ts index 9ddca9650b..c412836ae5 100644 --- a/plugins/azure-devops/src/hooks/usePullRequests.ts +++ b/plugins/azure-devops/src/hooks/usePullRequests.ts @@ -25,7 +25,7 @@ import { Entity } from '@backstage/catalog-model'; import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; -import { useProjectRepoFromEntity } from './useProjectRepoFromEntity'; +import { getAnnotationValuesFromEntity } from '../utils'; export function usePullRequests( entity: Entity, @@ -44,10 +44,13 @@ export function usePullRequests( }; const api = useApi(azureDevOpsApiRef); - const { project, repo } = useProjectRepoFromEntity(entity); + const { project, repo } = getAnnotationValuesFromEntity(entity); - const { value, loading, error } = useAsync(() => { - return api.getPullRequests(project, repo, options); + const { value, loading, error } = useAsync(async () => { + if (repo) { + return await api.getPullRequests(project, repo, options); + } + return undefined; }, [api, project, repo, top, status]); return { diff --git a/plugins/azure-devops/src/hooks/useRepoBuilds.ts b/plugins/azure-devops/src/hooks/useRepoBuilds.ts index e0fe8c2093..4ba88bd5fb 100644 --- a/plugins/azure-devops/src/hooks/useRepoBuilds.ts +++ b/plugins/azure-devops/src/hooks/useRepoBuilds.ts @@ -24,7 +24,7 @@ import { Entity } from '@backstage/catalog-model'; import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; -import { useProjectRepoFromEntity } from './useProjectRepoFromEntity'; +import { getAnnotationValuesFromEntity } from '../utils'; export function useRepoBuilds( entity: Entity, @@ -40,10 +40,13 @@ export function useRepoBuilds( }; const api = useApi(azureDevOpsApiRef); - const { project, repo } = useProjectRepoFromEntity(entity); + const { project, repo } = getAnnotationValuesFromEntity(entity); - const { value, loading, error } = useAsync(() => { - return api.getRepoBuilds(project, repo, options); + const { value, loading, error } = useAsync(async () => { + if (repo) { + return await api.getRepoBuilds(project, repo, options); + } + return undefined; }, [api, project, repo, entity]); return { diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts new file mode 100644 index 0000000000..a34dab9db5 --- /dev/null +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts @@ -0,0 +1,230 @@ +/* + * 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 { Entity } from '@backstage/catalog-model'; +import { getAnnotationValuesFromEntity } from './getAnnotationValuesFromEntity'; + +describe('getAnnotationValuesFromEntity', () => { + describe('with valid project-repo annotation', () => { + it('should return project and repo', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'projectName/repoName', + }, + }, + }; + const { project, repo, definition, org } = + getAnnotationValuesFromEntity(entity); + expect(project).toEqual('projectName'); + expect(repo).toEqual('repoName'); + expect(definition).toEqual(undefined); + expect(org).toEqual(undefined); + }); + }); + + describe('with invalid project-repo annotation', () => { + it('should throw incorrect format error', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'project', + }, + }, + }; + + const test = () => { + return getAnnotationValuesFromEntity(entity); + }; + + expect(test).toThrow( + 'Value for annotation dev.azure.com/project-repo was not in the correct format: /', + ); + }); + }); + + describe('with project-repo annotation missing project', () => { + it('should throw missing project error', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': '/repo', + }, + }, + }; + + const test = () => { + return getAnnotationValuesFromEntity(entity); + }; + + expect(test).toThrow( + 'Project Name for annotation dev.azure.com/project-repo was not found; expected format is: /', + ); + }); + }); + + describe('with project-repo annotation missing repo', () => { + it('should throw missing repo error', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'project/', + }, + }, + }; + + const test = () => { + return getAnnotationValuesFromEntity(entity); + }; + + expect(test).toThrow( + 'Repo Name for annotation dev.azure.com/project-repo was not found; expected format is: /', + ); + }); + }); + + describe('with valid project and build-definition annotations', () => { + it('should return project and definition', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-build-definition', + annotations: { + 'dev.azure.com/project': 'projectName', + 'dev.azure.com/build-definition': 'buildDefinitionName', + }, + }, + }; + const { project, repo, definition, org } = + getAnnotationValuesFromEntity(entity); + expect(project).toEqual('projectName'); + expect(repo).toEqual(undefined); + expect(definition).toEqual('buildDefinitionName'); + expect(org).toEqual(undefined); + }); + }); + + describe('with only project annotation', () => { + it('should return project and definition', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project', + annotations: { + 'dev.azure.com/project': 'projectName', + }, + }, + }; + const test = () => { + return getAnnotationValuesFromEntity(entity); + }; + + expect(test).toThrow( + 'Value for annotation dev.azure.com/build-definition was not found', + ); + }); + }); + + describe('with only build-definition annotation', () => { + it('should return project and definition', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'build-definition', + annotations: { + 'dev.azure.com/build-definition': 'buildDefinitionName', + }, + }, + }; + const test = () => { + return getAnnotationValuesFromEntity(entity); + }; + + expect(test).toThrow( + 'Value for annotation dev.azure.com/project was not found', + ); + }); + }); + + describe('with valid project-repo and org annotations', () => { + it('should return project, repo, and org', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'projectName/repoName', + 'dev.azure.com/organization': 'organizationName', + }, + }, + }; + const { project, repo, definition, org } = + getAnnotationValuesFromEntity(entity); + expect(project).toEqual('projectName'); + expect(repo).toEqual('repoName'); + expect(definition).toEqual(undefined); + expect(org).toEqual('organizationName'); + }); + }); + + describe('with valid project, build-definition, and org annotations', () => { + it('should return project, definition, and org', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-build-definition', + annotations: { + 'dev.azure.com/project': 'projectName', + 'dev.azure.com/build-definition': 'buildDefinitionName', + 'dev.azure.com/organization': 'organizationName', + }, + }, + }; + const { project, repo, definition, org } = + getAnnotationValuesFromEntity(entity); + expect(project).toEqual('projectName'); + expect(repo).toEqual(undefined); + expect(definition).toEqual('buildDefinitionName'); + expect(org).toEqual('organizationName'); + }); + }); +}); diff --git a/plugins/azure-devops/src/utils/getAnnotationFromEntity.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts similarity index 72% rename from plugins/azure-devops/src/utils/getAnnotationFromEntity.ts rename to plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts index 41cc1e6628..1070983b27 100644 --- a/plugins/azure-devops/src/utils/getAnnotationFromEntity.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts @@ -16,23 +16,28 @@ import { AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION, + AZURE_DEVOPS_ORGANIZATION_ANNOTATION, AZURE_DEVOPS_PROJECT_ANNOTATION, AZURE_DEVOPS_REPO_ANNOTATION, } from '../constants'; import { Entity } from '@backstage/catalog-model'; -export function getAnnotationFromEntity(entity: Entity): { +export function getAnnotationValuesFromEntity(entity: Entity): { project: string; repo?: string; definition?: string; + org?: string; } { + const org = + entity.metadata.annotations?.[AZURE_DEVOPS_ORGANIZATION_ANNOTATION]; + const annotation = entity.metadata.annotations?.[AZURE_DEVOPS_REPO_ANNOTATION]; if (annotation) { const { project, repo } = getProjectRepo(annotation); const definition = undefined; - return { project, repo, definition }; + return { project, repo, definition, org }; } const project = @@ -50,20 +55,32 @@ export function getAnnotationFromEntity(entity: Entity): { } const repo = undefined; - return { project, repo, definition }; + return { project, repo, definition, org }; } function getProjectRepo(annotation: string): { project: string; repo: string; } { - const [project, repo] = annotation.split('/'); - - if (!project && !repo) { + if (!annotation.includes('/')) { throw new Error( 'Value for annotation dev.azure.com/project-repo was not in the correct format: /', ); } + const [project, repo] = annotation.split('/'); + + if (!project) { + throw new Error( + 'Project Name for annotation dev.azure.com/project-repo was not found; expected format is: /', + ); + } + + if (!repo) { + throw new Error( + 'Repo Name for annotation dev.azure.com/project-repo was not found; expected format is: /', + ); + } + return { project, repo }; } diff --git a/plugins/azure-devops/src/utils/index.ts b/plugins/azure-devops/src/utils/index.ts index 8655b261c3..998bb0e23d 100644 --- a/plugins/azure-devops/src/utils/index.ts +++ b/plugins/azure-devops/src/utils/index.ts @@ -17,4 +17,4 @@ export * from './arrayHas'; export * from './equalsIgnoreCase'; export * from './getDurationFromDates'; -export * from './getAnnotationFromEntity'; +export * from './getAnnotationValuesFromEntity'; From 9987f11687fe9ce0d4f95dfd131f1779f5b7d517 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Sat, 26 Aug 2023 17:12:48 -0500 Subject: [PATCH 285/348] Refactor to also return host Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- plugins/azure-devops/src/constants.ts | 3 +- .../getAnnotationValuesFromEntity.test.ts | 100 +++++++++++++++--- .../utils/getAnnotationValuesFromEntity.ts | 61 ++++++++--- 3 files changed, 137 insertions(+), 27 deletions(-) diff --git a/plugins/azure-devops/src/constants.ts b/plugins/azure-devops/src/constants.ts index 765f5a965b..aba0ec093a 100644 --- a/plugins/azure-devops/src/constants.ts +++ b/plugins/azure-devops/src/constants.ts @@ -16,8 +16,7 @@ export const AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION = 'dev.azure.com/build-definition'; -export const AZURE_DEVOPS_ORGANIZATION_ANNOTATION = - 'dev.azure.com/organization'; +export const AZURE_DEVOPS_HOST_ORG_ANNOTATION = 'dev.azure.com/host-org'; export const AZURE_DEVOPS_PROJECT_ANNOTATION = 'dev.azure.com/project'; export const AZURE_DEVOPS_REPO_ANNOTATION = 'dev.azure.com/project-repo'; export const AZURE_DEVOPS_DEFAULT_TOP: number = 10; diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts index a34dab9db5..5584567188 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts @@ -31,11 +31,12 @@ describe('getAnnotationValuesFromEntity', () => { }, }, }; - const { project, repo, definition, org } = + const { project, repo, definition, host, org } = getAnnotationValuesFromEntity(entity); expect(project).toEqual('projectName'); expect(repo).toEqual('repoName'); expect(definition).toEqual(undefined); + expect(host).toEqual(undefined); expect(org).toEqual(undefined); }); }); @@ -126,17 +127,18 @@ describe('getAnnotationValuesFromEntity', () => { }, }, }; - const { project, repo, definition, org } = + const { project, repo, definition, host, org } = getAnnotationValuesFromEntity(entity); expect(project).toEqual('projectName'); expect(repo).toEqual(undefined); expect(definition).toEqual('buildDefinitionName'); + expect(host).toEqual(undefined); expect(org).toEqual(undefined); }); }); describe('with only project annotation', () => { - it('should return project and definition', () => { + it('should should throw annotation not found error', () => { const entity: Entity = { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', @@ -159,7 +161,7 @@ describe('getAnnotationValuesFromEntity', () => { }); describe('with only build-definition annotation', () => { - it('should return project and definition', () => { + it('should should throw annotation not found error', () => { const entity: Entity = { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', @@ -181,8 +183,8 @@ describe('getAnnotationValuesFromEntity', () => { }); }); - describe('with valid project-repo and org annotations', () => { - it('should return project, repo, and org', () => { + describe('with valid project-repo and host-org annotations', () => { + it('should return project, repo, host, and org', () => { const entity: Entity = { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', @@ -191,21 +193,22 @@ describe('getAnnotationValuesFromEntity', () => { name: 'project-repo', annotations: { 'dev.azure.com/project-repo': 'projectName/repoName', - 'dev.azure.com/organization': 'organizationName', + 'dev.azure.com/host-org': 'hostName/organizationName', }, }, }; - const { project, repo, definition, org } = + const { project, repo, definition, host, org } = getAnnotationValuesFromEntity(entity); expect(project).toEqual('projectName'); expect(repo).toEqual('repoName'); expect(definition).toEqual(undefined); + expect(host).toEqual('hostName'); expect(org).toEqual('organizationName'); }); }); - describe('with valid project, build-definition, and org annotations', () => { - it('should return project, definition, and org', () => { + describe('with valid project, build-definition, and host-org annotations', () => { + it('should return project, definition, host and org', () => { const entity: Entity = { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', @@ -215,16 +218,89 @@ describe('getAnnotationValuesFromEntity', () => { annotations: { 'dev.azure.com/project': 'projectName', 'dev.azure.com/build-definition': 'buildDefinitionName', - 'dev.azure.com/organization': 'organizationName', + 'dev.azure.com/host-org': 'hostName/organizationName', }, }, }; - const { project, repo, definition, org } = + const { project, repo, definition, host, org } = getAnnotationValuesFromEntity(entity); expect(project).toEqual('projectName'); expect(repo).toEqual(undefined); expect(definition).toEqual('buildDefinitionName'); + expect(host).toEqual('hostName'); expect(org).toEqual('organizationName'); }); }); + + describe('with invalid host-org annotation', () => { + it('should throw incorrect format error', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'host-org', + annotations: { + 'dev.azure.com/host-org': 'host', + }, + }, + }; + + const test = () => { + return getAnnotationValuesFromEntity(entity); + }; + + expect(test).toThrow( + 'Value for annotation dev.azure.com/host-org was not in the correct format: /', + ); + }); + }); + + describe('with host-rg annotation missing host', () => { + it('should throw missing project error', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'host-org', + annotations: { + 'dev.azure.com/host-org': '/org', + }, + }, + }; + + const test = () => { + return getAnnotationValuesFromEntity(entity); + }; + + expect(test).toThrow( + 'Host for annotation dev.azure.com/host-org was not found; expected format is: /', + ); + }); + }); + + describe('with host-org annotation missing org', () => { + it('should throw missing repo error', () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'host-org', + annotations: { + 'dev.azure.com/host-org': 'host/', + }, + }, + }; + + const test = () => { + return getAnnotationValuesFromEntity(entity); + }; + + expect(test).toThrow( + 'Organization for annotation dev.azure.com/host-org was not found; expected format is: /', + ); + }); + }); }); diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts index 1070983b27..8ce096d3c5 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts @@ -16,7 +16,7 @@ import { AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION, - AZURE_DEVOPS_ORGANIZATION_ANNOTATION, + AZURE_DEVOPS_HOST_ORG_ANNOTATION, AZURE_DEVOPS_PROJECT_ANNOTATION, AZURE_DEVOPS_REPO_ANNOTATION, } from '../constants'; @@ -27,35 +27,39 @@ export function getAnnotationValuesFromEntity(entity: Entity): { project: string; repo?: string; definition?: string; + host?: string; org?: string; } { - const org = - entity.metadata.annotations?.[AZURE_DEVOPS_ORGANIZATION_ANNOTATION]; + const hostOrgAnnotation = + entity.metadata.annotations?.[AZURE_DEVOPS_HOST_ORG_ANNOTATION]; + const { host, org } = getHostOrg(hostOrgAnnotation); - const annotation = + const projectRepoAnnotation = entity.metadata.annotations?.[AZURE_DEVOPS_REPO_ANNOTATION]; - if (annotation) { - const { project, repo } = getProjectRepo(annotation); + if (projectRepoAnnotation) { + const { project, repo } = getProjectRepo(projectRepoAnnotation); const definition = undefined; - return { project, repo, definition, org }; + return { project, repo, definition, host, org }; } const project = entity.metadata.annotations?.[AZURE_DEVOPS_PROJECT_ANNOTATION]; if (!project) { - throw new Error('Value for annotation dev.azure.com/project was not found'); + throw new Error( + `Value for annotation ${AZURE_DEVOPS_PROJECT_ANNOTATION} was not found`, + ); } const definition = entity.metadata.annotations?.[AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION]; if (!definition) { throw new Error( - 'Value for annotation dev.azure.com/build-definition was not found', + `Value for annotation ${AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION} was not found`, ); } const repo = undefined; - return { project, repo, definition, org }; + return { project, repo, definition, host, org }; } function getProjectRepo(annotation: string): { @@ -64,7 +68,7 @@ function getProjectRepo(annotation: string): { } { if (!annotation.includes('/')) { throw new Error( - 'Value for annotation dev.azure.com/project-repo was not in the correct format: /', + `Value for annotation ${AZURE_DEVOPS_REPO_ANNOTATION} was not in the correct format: /`, ); } @@ -72,15 +76,46 @@ function getProjectRepo(annotation: string): { if (!project) { throw new Error( - 'Project Name for annotation dev.azure.com/project-repo was not found; expected format is: /', + `Project Name for annotation ${AZURE_DEVOPS_REPO_ANNOTATION} was not found; expected format is: /`, ); } if (!repo) { throw new Error( - 'Repo Name for annotation dev.azure.com/project-repo was not found; expected format is: /', + `Repo Name for annotation ${AZURE_DEVOPS_REPO_ANNOTATION} was not found; expected format is: /`, ); } return { project, repo }; } + +function getHostOrg(annotation?: string): { + host?: string; + org?: string; +} { + if (!annotation) { + return { host: undefined, org: undefined }; + } + + if (!annotation.includes('/')) { + throw new Error( + `Value for annotation ${AZURE_DEVOPS_HOST_ORG_ANNOTATION} was not in the correct format: /`, + ); + } + + const [host, org] = annotation.split('/'); + + if (!host) { + throw new Error( + `Host for annotation ${AZURE_DEVOPS_HOST_ORG_ANNOTATION} was not found; expected format is: /`, + ); + } + + if (!org) { + throw new Error( + `Organization for annotation ${AZURE_DEVOPS_HOST_ORG_ANNOTATION} was not found; expected format is: /`, + ); + } + + return { host, org }; +} From 904d7f12408d24e98e26df5a116cbb36be0a93c1 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Fri, 1 Sep 2023 12:59:49 -0500 Subject: [PATCH 286/348] Initial improvements from feedback Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .../getAnnotationValuesFromEntity.test.ts | 62 ++++++++++--------- .../utils/getAnnotationValuesFromEntity.ts | 36 ++++++----- 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts index 5584567188..0d7a11f48b 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts @@ -31,13 +31,14 @@ describe('getAnnotationValuesFromEntity', () => { }, }, }; - const { project, repo, definition, host, org } = - getAnnotationValuesFromEntity(entity); - expect(project).toEqual('projectName'); - expect(repo).toEqual('repoName'); - expect(definition).toEqual(undefined); - expect(host).toEqual(undefined); - expect(org).toEqual(undefined); + const values = getAnnotationValuesFromEntity(entity); + expect(values).toEqual({ + project: 'projectName', + repo: 'repoName', + definition: undefined, + host: undefined, + org: undefined, + }); }); }); @@ -127,13 +128,14 @@ describe('getAnnotationValuesFromEntity', () => { }, }, }; - const { project, repo, definition, host, org } = - getAnnotationValuesFromEntity(entity); - expect(project).toEqual('projectName'); - expect(repo).toEqual(undefined); - expect(definition).toEqual('buildDefinitionName'); - expect(host).toEqual(undefined); - expect(org).toEqual(undefined); + const values = getAnnotationValuesFromEntity(entity); + expect(values).toEqual({ + project: 'projectName', + repo: undefined, + definition: 'buildDefinitionName', + host: undefined, + org: undefined, + }); }); }); @@ -197,13 +199,14 @@ describe('getAnnotationValuesFromEntity', () => { }, }, }; - const { project, repo, definition, host, org } = - getAnnotationValuesFromEntity(entity); - expect(project).toEqual('projectName'); - expect(repo).toEqual('repoName'); - expect(definition).toEqual(undefined); - expect(host).toEqual('hostName'); - expect(org).toEqual('organizationName'); + const values = getAnnotationValuesFromEntity(entity); + expect(values).toEqual({ + project: 'projectName', + repo: 'repoName', + definition: undefined, + host: 'hostName', + org: 'organizationName', + }); }); }); @@ -222,13 +225,14 @@ describe('getAnnotationValuesFromEntity', () => { }, }, }; - const { project, repo, definition, host, org } = - getAnnotationValuesFromEntity(entity); - expect(project).toEqual('projectName'); - expect(repo).toEqual(undefined); - expect(definition).toEqual('buildDefinitionName'); - expect(host).toEqual('hostName'); - expect(org).toEqual('organizationName'); + const values = getAnnotationValuesFromEntity(entity); + expect(values).toEqual({ + project: 'projectName', + repo: undefined, + definition: 'buildDefinitionName', + host: 'hostName', + org: 'organizationName', + }); }); }); @@ -256,7 +260,7 @@ describe('getAnnotationValuesFromEntity', () => { }); }); - describe('with host-rg annotation missing host', () => { + describe('with host-org annotation missing host', () => { it('should throw missing project error', () => { const entity: Entity = { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts index 8ce096d3c5..7099352524 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts @@ -30,16 +30,16 @@ export function getAnnotationValuesFromEntity(entity: Entity): { host?: string; org?: string; } { - const hostOrgAnnotation = - entity.metadata.annotations?.[AZURE_DEVOPS_HOST_ORG_ANNOTATION]; - const { host, org } = getHostOrg(hostOrgAnnotation); + const { host, org } = getHostOrg(entity.metadata.annotations); - const projectRepoAnnotation = - entity.metadata.annotations?.[AZURE_DEVOPS_REPO_ANNOTATION]; - if (projectRepoAnnotation) { - const { project, repo } = getProjectRepo(projectRepoAnnotation); - const definition = undefined; - return { project, repo, definition, host, org }; + const projectRepoValues = getProjectRepo(entity.metadata.annotations); + if (projectRepoValues.project && projectRepoValues.repo) { + return { + project: projectRepoValues.project, + repo: projectRepoValues.repo, + host, + org, + }; } const project = @@ -57,15 +57,18 @@ export function getAnnotationValuesFromEntity(entity: Entity): { `Value for annotation ${AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION} was not found`, ); } - - const repo = undefined; - return { project, repo, definition, host, org }; + return { project, definition, host, org }; } -function getProjectRepo(annotation: string): { - project: string; - repo: string; +function getProjectRepo(annotations?: Record): { + project?: string; + repo?: string; } { + const annotation = annotations?.[AZURE_DEVOPS_REPO_ANNOTATION]; + if (!annotation) { + return { project: undefined, repo: undefined }; + } + if (!annotation.includes('/')) { throw new Error( `Value for annotation ${AZURE_DEVOPS_REPO_ANNOTATION} was not in the correct format: /`, @@ -89,10 +92,11 @@ function getProjectRepo(annotation: string): { return { project, repo }; } -function getHostOrg(annotation?: string): { +function getHostOrg(annotations?: Record): { host?: string; org?: string; } { + const annotation = annotations?.[AZURE_DEVOPS_HOST_ORG_ANNOTATION]; if (!annotation) { return { host: undefined, org: undefined }; } From 8ff165a2b5a4580d2a2f899db1e5768dc792ead0 Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Fri, 20 Oct 2023 14:58:51 -0400 Subject: [PATCH 287/348] Add path to dependency array to fix FireFox issue. Signed-off-by: Sydney Achinger --- .../TechDocsReaderPageContent.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx index 8508c59142..f4c5ad8745 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx @@ -81,19 +81,22 @@ export const TechDocsReaderPageContent = withTechDocsReaderProvider( setShadowRoot, } = useTechDocsReaderPage(); const dom = useTechDocsReaderDom(entityRef); + const path = window.location.pathname; const hash = window.location.hash; const isStyleLoading = useShadowDomStylesLoading(dom); const [hashElement] = useShadowRootElements([`[id="${hash.slice(1)}"]`]); useEffect(() => { + if (isStyleLoading) return; + if (hash) { - if (hashElement && !isStyleLoading) { + if (hashElement) { hashElement.scrollIntoView(); } } else { document?.querySelector('header')?.scrollIntoView(); } - }, [hash, hashElement, isStyleLoading]); + }, [path, hash, hashElement, isStyleLoading]); const handleAppend = useCallback( (newShadowRoot: ShadowRoot) => { From 9bc4d2b4497095da1a0142949339548c07679b8f Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Fri, 20 Oct 2023 16:05:46 -0500 Subject: [PATCH 288/348] Added EntityAzureReadmeCard to help with testing Signed-off-by: Andre Wanlin --- packages/app/src/components/catalog/EntityPage.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 81af3b91e7..ecc1f008b5 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -41,6 +41,7 @@ import { EntityAzurePullRequestsContent, isAzureDevOpsAvailable, isAzurePipelinesAvailable, + EntityAzureReadmeCard, } from '@backstage/plugin-azure-devops'; import { isOctopusDeployAvailable, @@ -415,6 +416,14 @@ const overviewContent = ( + + + + + + + + From 36123575ad64d91181e91eb712d152b0b971c577 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 25 May 2023 11:53:34 +0200 Subject: [PATCH 289/348] catalog-react: add reduceBackendCatalogFilters Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/src/utils/filters.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/plugins/catalog-react/src/utils/filters.ts b/plugins/catalog-react/src/utils/filters.ts index 109e864c52..5ab6e43593 100644 --- a/plugins/catalog-react/src/utils/filters.ts +++ b/plugins/catalog-react/src/utils/filters.ts @@ -16,6 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { EntityFilter } from '../types'; +import { EntityKindFilter, EntityTypeFilter } from '../filters'; export function reduceCatalogFilters( filters: EntityFilter[], @@ -28,6 +29,24 @@ export function reduceCatalogFilters( }, {} as Record); } +export function reduceBackendCatalogFilters(filters: EntityFilter[]) { + const backendCatalogFilters: Record< + string, + string | symbol | (string | symbol)[] + > = {}; + + filters.forEach(filter => { + if ( + filter instanceof EntityKindFilter || + filter instanceof EntityTypeFilter + ) { + Object.assign(backendCatalogFilters, filter.getCatalogFilters()); + } + }); + + return backendCatalogFilters; +} + export function reduceEntityFilters( filters: EntityFilter[], ): (entity: Entity) => boolean { From c9f2a54d71411a253fe2b4a665ed1d427d3defc2 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 25 May 2023 11:57:14 +0200 Subject: [PATCH 290/348] catalog-react: pick kind and type filters as backend filters Signed-off-by: Vincenzo Scamporlino --- .../catalog-react/src/hooks/useEntityListProvider.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index b4c464a26c..b7ee8a94ed 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -41,16 +41,17 @@ import { EntityTypeFilter, UserListFilter, EntityNamespaceFilter, + UserOwnersFilter, } from '../filters'; import { EntityFilter } from '../types'; -import { reduceCatalogFilters, reduceEntityFilters } from '../utils'; +import { reduceBackendCatalogFilters, reduceEntityFilters } from '../utils'; import { useApi } from '@backstage/core-plugin-api'; /** @public */ export type DefaultEntityFilters = { kind?: EntityKindFilter; type?: EntityTypeFilter; - user?: UserListFilter; + user?: UserListFilter | UserOwnersFilter; owners?: EntityOwnerFilter; lifecycles?: EntityLifecycleFilter; tags?: EntityTagFilter; @@ -156,8 +157,8 @@ export const EntityListProvider = ( async () => { const compacted = compact(Object.values(requestedFilters)); const entityFilter = reduceEntityFilters(compacted); - const backendFilter = reduceCatalogFilters(compacted); - const previousBackendFilter = reduceCatalogFilters( + const backendFilter = reduceBackendCatalogFilters(compacted); + const previousBackendFilter = reduceBackendCatalogFilters( compact(Object.values(outputState.appliedFilters)), ); From ae2f2dd18d99c1b23ed25db769d9470e3c617b54 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 25 May 2023 11:59:47 +0200 Subject: [PATCH 291/348] catalog-react: add getCatalogFilters methods for backend filtering Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/src/filters.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index c717a35202..1213ab9b7e 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -72,6 +72,10 @@ export class EntityTagFilter implements EntityFilter { return this.values.every(v => (entity.metadata.tags ?? []).includes(v)); } + getCatalogFilters(): Record { + return { 'metadata.tags': this.values }; + } + toQueryValue(): string[] { return this.values; } @@ -136,6 +140,10 @@ export class EntityOwnerFilter implements EntityFilter { }, [] as string[]); } + getCatalogFilters(): Record { + return { 'relations.ownedBy': this.values }; + } + filterEntity(entity: Entity): boolean { return this.values.some(v => getEntityRelations(entity, RELATION_OWNED_BY).some( @@ -160,6 +168,10 @@ export class EntityOwnerFilter implements EntityFilter { export class EntityLifecycleFilter implements EntityFilter { constructor(readonly values: string[]) {} + getCatalogFilters(): Record { + return { 'spec.lifecycle': this.values }; + } + filterEntity(entity: Entity): boolean { return this.values.some(v => entity.spec?.lifecycle === v); } @@ -176,6 +188,9 @@ export class EntityLifecycleFilter implements EntityFilter { export class EntityNamespaceFilter implements EntityFilter { constructor(readonly values: string[]) {} + getCatalogFilters(): Record { + return { 'spec.lifecycle': this.values }; + } filterEntity(entity: Entity): boolean { return this.values.some(v => entity.metadata.namespace === v); } @@ -218,6 +233,11 @@ export class UserListFilter implements EntityFilter { */ export class EntityOrphanFilter implements EntityFilter { constructor(readonly value: boolean) {} + + getCatalogFilters(): Record { + return { 'metadata.annotations.backstage.io/orphan': String(this.value) }; + } + filterEntity(entity: Entity): boolean { const orphan = entity.metadata.annotations?.['backstage.io/orphan']; return orphan !== undefined && this.value.toString() === orphan; @@ -230,6 +250,10 @@ export class EntityOrphanFilter implements EntityFilter { */ export class EntityErrorFilter implements EntityFilter { constructor(readonly value: boolean) {} + + // TODO(vinzscam): is it possible to implement + // getCatalogFilters? ask mammals + filterEntity(entity: Entity): boolean { const error = ((entity as AlphaEntity)?.status?.items?.length as number) > 0; From 8bae84e5f47597a1ebcb1c783b00aa91aa6afb19 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 25 May 2023 12:00:07 +0200 Subject: [PATCH 292/348] catalog-react: introduce UserOwnersFilter Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/src/filters.ts | 46 ++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index 1213ab9b7e..a5a39f9b02 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -200,8 +200,54 @@ export class EntityNamespaceFilter implements EntityFilter { } } +/** + * @public + */ +export class UserOwnersFilter implements EntityFilter { + private constructor( + readonly value: UserListFilterKind, + readonly refs?: string[], + ) {} + + static owned(ownershipEntityRefs: string[]) { + return new UserOwnersFilter('owned', ownershipEntityRefs); + } + + static all() { + return new UserOwnersFilter('all'); + } + + static starred(starredEntityRefs: string[]) { + return new UserOwnersFilter('starred', starredEntityRefs); + } + + getCatalogFilters(): Record { + if (this.value === 'owned') { + return { 'relations.ownedBy': this.refs ?? [] }; + } + if (this.value === 'starred') { + return { + 'metadata.name': this.refs?.map(e => parseEntityRef(e).name) ?? [], + }; + } + return {}; + } + + filterEntity(entity: Entity) { + if (this.value === 'starred') { + return this.refs?.includes(stringifyEntityRef(entity)) ?? true; + } + return true; + } + + toQueryValue(): string { + return this.value; + } +} + /** * Filters entities based on whatever the user has starred or owns them. + * @deprecated use UserOwnersFilter * @public */ export class UserListFilter implements EntityFilter { From 58b6d860d34653be8b968c3f60825d520e28f659 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 25 May 2023 12:00:59 +0200 Subject: [PATCH 293/348] catalog-react: add useIsOwnedEntity hook Signed-off-by: Vincenzo Scamporlino --- .../catalog-react/src/hooks/useEntityOwnership.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-react/src/hooks/useEntityOwnership.ts b/plugins/catalog-react/src/hooks/useEntityOwnership.ts index f8a37a2c83..1f1e200634 100644 --- a/plugins/catalog-react/src/hooks/useEntityOwnership.ts +++ b/plugins/catalog-react/src/hooks/useEntityOwnership.ts @@ -46,9 +46,15 @@ export function useEntityOwnership(): { return ownershipEntityRefs; }, []); - const isOwnedEntity = useMemo(() => { + const isOwnedEntity = useIsOwnedEntity(refs); + + return useMemo(() => ({ loading, isOwnedEntity }), [loading, isOwnedEntity]); +} + +export function useIsOwnedEntity(refs?: string[]) { + return useMemo(() => { const myOwnerRefs = new Set(refs ?? []); - return (entity: Entity) => { + const isOwnedEntity = (entity: Entity) => { const entityOwnerRefs = getEntityRelations(entity, RELATION_OWNED_BY).map( stringifyEntityRef, ); @@ -59,7 +65,6 @@ export function useEntityOwnership(): { } return false; }; + return isOwnedEntity; }, [refs]); - - return useMemo(() => ({ loading, isOwnedEntity }), [loading, isOwnedEntity]); } From 1b31deed8f7d136993e180b86e27fee03183b4c1 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 25 May 2023 12:03:32 +0200 Subject: [PATCH 294/348] catalog-react: decouple UserListPicker from backendEntities Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/api-report.md | 35 +- .../UserListPicker/UserListPicker.test.tsx | 695 +++++++++++++----- .../UserListPicker/UserListPicker.tsx | 132 ++-- .../UserListPicker/useAllEntitiesCount.ts | 61 ++ .../UserListPicker/useOwnedEntitiesCount.ts | 107 +++ .../UserListPicker/useStarredEntitiesCount.ts | 80 ++ 6 files changed, 879 insertions(+), 231 deletions(-) create mode 100644 plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts create mode 100644 plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts create mode 100644 plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index a72df6bb3d..3faa5524c9 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -142,7 +142,7 @@ export const columnFactories: Readonly<{ export type DefaultEntityFilters = { kind?: EntityKindFilter; type?: EntityTypeFilter; - user?: UserListFilter; + user?: UserListFilter | UserOwnersFilter; owners?: EntityOwnerFilter; lifecycles?: EntityLifecycleFilter; tags?: EntityTagFilter; @@ -224,6 +224,8 @@ export class EntityLifecycleFilter implements EntityFilter { // (undocumented) filterEntity(entity: Entity): boolean; // (undocumented) + getCatalogFilters(): Record; + // (undocumented) toQueryValue(): string[]; // (undocumented) readonly values: string[]; @@ -275,6 +277,8 @@ export class EntityNamespaceFilter implements EntityFilter { // (undocumented) filterEntity(entity: Entity): boolean; // (undocumented) + getCatalogFilters(): Record; + // (undocumented) toQueryValue(): string[]; // (undocumented) readonly values: string[]; @@ -289,6 +293,8 @@ export class EntityOrphanFilter implements EntityFilter { // (undocumented) filterEntity(entity: Entity): boolean; // (undocumented) + getCatalogFilters(): Record; + // (undocumented) readonly value: boolean; } @@ -297,6 +303,8 @@ export class EntityOwnerFilter implements EntityFilter { constructor(values: string[]); // (undocumented) filterEntity(entity: Entity): boolean; + // (undocumented) + getCatalogFilters(): Record; toQueryValue(): string[]; // (undocumented) readonly values: string[]; @@ -447,6 +455,8 @@ export class EntityTagFilter implements EntityFilter { // (undocumented) filterEntity(entity: Entity): boolean; // (undocumented) + getCatalogFilters(): Record; + // (undocumented) toQueryValue(): string[]; // (undocumented) readonly values: string[]; @@ -620,7 +630,7 @@ export function useRelatedEntities( error: Error | undefined; }; -// @public +// @public @deprecated export class UserListFilter implements EntityFilter { constructor( value: UserListFilterKind, @@ -651,8 +661,29 @@ export const UserListPicker: ( export type UserListPickerProps = { initialFilter?: UserListFilterKind; availableFilters?: UserListFilterKind[]; + useServerSideFilters?: boolean; }; +// @public (undocumented) +export class UserOwnersFilter implements EntityFilter { + // (undocumented) + static all(): UserOwnersFilter; + // (undocumented) + filterEntity(entity: Entity): boolean; + // (undocumented) + getCatalogFilters(): Record; + // (undocumented) + static owned(ownershipEntityRefs: string[]): UserOwnersFilter; + // (undocumented) + readonly refs?: string[] | undefined; + // (undocumented) + static starred(starredEntityRefs: string[]): UserOwnersFilter; + // (undocumented) + toQueryValue(): string; + // (undocumented) + readonly value: UserListFilterKind; +} + // @public (undocumented) export function useStarredEntities(): { starredEntities: Set; diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index c31381df20..1315c95061 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -16,15 +16,18 @@ import React from 'react'; import { fireEvent, render, waitFor, screen } from '@testing-library/react'; -import { - Entity, - RELATION_OWNED_BY, - UserEntity, -} from '@backstage/catalog-model'; -import { UserListPicker } from './UserListPicker'; +import { Entity, UserEntity } from '@backstage/catalog-model'; +import { UserListPicker, UserListPickerProps } from './UserListPicker'; import { MockEntityListContextProvider } from '../../testUtils/providers'; -import { EntityTagFilter, UserListFilter } from '../../filters'; -import { CatalogApi } from '@backstage/catalog-client'; +import { + EntityTagFilter, + UserListFilter, + UserOwnersFilter, +} from '../../filters'; +import { + CatalogApi, + QueryEntitiesInitialRequest, +} from '@backstage/catalog-client'; import { catalogApiRef } from '../../api'; import { MockStorageApi, TestApiRegistry } from '@backstage/test-utils'; import { ApiProvider } from '@backstage/core-app-api'; @@ -35,7 +38,7 @@ import { identityApiRef, storageApiRef, } from '@backstage/core-plugin-api'; -import { useEntityOwnership } from '../../hooks'; +import { MockStarredEntitiesApi, starredEntitiesApiRef } from '../../apis'; const mockUser: UserEntity = { apiVersion: 'backstage.io/v1alpha1', @@ -54,19 +57,22 @@ const mockConfigApi = { } as Partial; const mockCatalogApi = { - getEntityByRef: () => Promise.resolve(mockUser), -} as Partial; + getEntityByRef: jest.fn(), + queryEntities: jest.fn(), +} as Partial>; const mockIdentityApi = { - getUserId: () => 'testUser', - getIdToken: async () => undefined, -} as Partial; + getBackstageIdentity: jest.fn(), +} as Partial>; + +const mockStarredEntitiesApi = new MockStarredEntitiesApi(); const apis = TestApiRegistry.from( [configApiRef, mockConfigApi], [catalogApiRef, mockCatalogApi], [identityApiRef, mockIdentityApi], [storageApiRef, MockStorageApi.create()], + [starredEntitiesApiRef, mockStarredEntitiesApi], ); const mockIsOwnedEntity = jest.fn( @@ -77,113 +83,117 @@ const mockIsStarredEntity = jest.fn( (entity: Entity) => entity.metadata.name === 'component-3', ); -jest.mock('../../hooks', () => { - const actual = jest.requireActual('../../hooks'); - return { - ...actual, - useEntityOwnership: jest.fn(() => ({ - isOwnedEntity: mockIsOwnedEntity, - })), - useStarredEntities: () => ({ - isStarredEntity: mockIsStarredEntity, - }), - }; -}); - -const backendEntities: Entity[] = [ - { - apiVersion: '1', - kind: 'Component', - metadata: { - namespace: 'namespace-1', - name: 'component-1', - tags: ['tag1'], - }, - relations: [ - { - type: RELATION_OWNED_BY, - targetRef: 'user:default/testuser', - }, - ], - }, - { - apiVersion: '1', - kind: 'Component', - metadata: { - namespace: 'namespace-2', - name: 'component-2', - tags: ['tag1'], - }, - }, - { - apiVersion: '1', - kind: 'Component', - metadata: { - namespace: 'namespace-2', - name: 'component-3', - tags: [], - }, - }, - { - apiVersion: '1', - kind: 'Component', - metadata: { - namespace: 'namespace-2', - name: 'component-4', - tags: [], - }, - relations: [ - { - type: RELATION_OWNED_BY, - targetRef: 'user:default/testuser', - }, - ], - }, -]; - +const ownershipEntityRefs = ['user:default/testuser']; describe('', () => { - it('renders filter groups', () => { + const mockQueryEntitiesImplementation: CatalogApi['queryEntities'] = + async request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['relations.ownedBy'] + ) { + // owned entities + return { items: [], totalItems: 3, pageInfo: {} }; + } + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['metadata.name'] + ) { + // starred entities + return { + items: [ + { + apiVersion: '1', + kind: 'component', + metadata: { name: 'e-1', namespace: 'default' }, + }, + { + apiVersion: '1', + kind: 'component', + metadata: { name: 'e-2', namespace: 'default' }, + }, + ], + totalItems: 2, + pageInfo: {}, + }; + } + // all items + return { items: [], totalItems: 10, pageInfo: {} }; + }; + + beforeAll(() => { + mockStarredEntitiesApi.toggleStarred('component:default/e-1'); + mockStarredEntitiesApi.toggleStarred('component:default/e-2'); + }); + + beforeEach(() => { + mockCatalogApi.getEntityByRef?.mockResolvedValue(mockUser); + mockIdentityApi.getBackstageIdentity?.mockResolvedValue({ + ownershipEntityRefs, + type: 'user', + userEntityRef: 'user:default/testuser', + }); + + mockCatalogApi.queryEntities?.mockImplementation( + mockQueryEntitiesImplementation, + ); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + it('renders filter groups', async () => { render( - + , ); + await waitFor(() => + expect(mockIdentityApi.getBackstageIdentity).toHaveBeenCalled(), + ); + await waitFor(() => + expect(mockCatalogApi.queryEntities).toHaveBeenCalled(), + ); expect(screen.getByText('Personal')).toBeInTheDocument(); expect(screen.getByText('Test Company')).toBeInTheDocument(); }); - it('renders filters', () => { + it('renders filters', async () => { render( - + , ); - expect( - screen.getAllByRole('menuitem').map(({ textContent }) => textContent), - ).toEqual(['Owned 1', 'Starred 1', 'All 4']); - }); - - it('includes counts alongside each filter', async () => { - render( - - - - - , - ); - - // Material UI renders ListItemSecondaryActions outside the - // menuitem itself, so we pick off the next sibling. - await waitFor(() => { + await waitFor(() => expect( screen.getAllByRole('menuitem').map(({ textContent }) => textContent), - ).toEqual(['Owned 1', 'Starred 1', 'All 4']); + ).toEqual(['Owned 3', 'Starred 2', 'All 10']), + ); + + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: {}, + limit: 0, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { 'metadata.name': ['e-1', 'e-2'] }, + limit: 1000, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { 'relations.ownedBy': ['user:default/testuser'] }, + limit: 0, }); }); @@ -192,7 +202,6 @@ describe('', () => { @@ -204,35 +213,104 @@ describe('', () => { await waitFor(() => { expect( screen.getAllByRole('menuitem').map(({ textContent }) => textContent), - ).toEqual(['Owned 1', 'Starred 0', 'All 2']); + ).toEqual(['Owned 3', 'Starred 2', 'All 10']); + }); + + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { 'metadata.tags': ['tag1'] }, + limit: 0, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { 'metadata.name': ['e-1', 'e-2'], 'metadata.tags': ['tag1'] }, + limit: 1000, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { + 'relations.ownedBy': ['user:default/testuser'], + 'metadata.tags': ['tag1'], + }, + limit: 0, }); }); - it('respects the query parameter filter value', () => { + it('respects the query parameter filter value, legacy', async () => { const updateFilters = jest.fn(); const queryParameters = { user: 'owned' }; render( , ); - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter('owned', mockIsOwnedEntity, mockIsStarredEntity), + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: new UserListFilter( + 'owned', + expect.any(Function), + expect.any(Function), + ), + }), + ); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: {}, + limit: 0, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { 'metadata.name': ['e-1', 'e-2'] }, + limit: 1000, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { + 'relations.ownedBy': ['user:default/testuser'], + }, + limit: 0, }); }); - it('updates user filter when a menuitem is selected', () => { + it('respects the query parameter filter value', async () => { const updateFilters = jest.fn(); + const queryParameters = { user: 'owned' }; render( + + + , + ); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: UserOwnersFilter.owned(ownershipEntityRefs), + }), + ); + + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: {}, + limit: 0, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { 'metadata.name': ['e-1', 'e-2'] }, + limit: 1000, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { + 'relations.ownedBy': ['user:default/testuser'], + }, + limit: 0, + }); + }); + + it('updates user filter when a menuitem is selected, legacy', async () => { + const updateFilters = jest.fn(); + render( + + , @@ -240,22 +318,45 @@ describe('', () => { fireEvent.click(screen.getByText('Starred')); - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'starred', - mockIsOwnedEntity, - mockIsStarredEntity, - ), - }); + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: new UserListFilter( + 'starred', + expect.any(Function), + expect.any(Function), + ), + }), + ); }); - it('responds to external queryParameters changes', () => { + it('updates user filter when a menuitem is selected', async () => { + const updateFilters = jest.fn(); + render( + + + + + , + ); + + fireEvent.click(screen.getByText('Starred')); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: UserOwnersFilter.starred([ + 'component:default/e-1', + 'component:default/e-2', + ]), + }), + ); + }); + + it('responds to external queryParameters changes, legacy', async () => { const updateFilters = jest.fn(); const rendered = render( ', () => { , ); - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter('all', mockIsOwnedEntity, mockIsStarredEntity), - }); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: new UserListFilter( + 'all', + expect.any(Function), + expect.any(Function), + ), + }), + ); + rendered.rerender( ', () => { , ); expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter('owned', mockIsOwnedEntity, mockIsStarredEntity), + user: new UserListFilter( + 'owned', + expect.any(Function), + expect.any(Function), + ), }); }); - describe.each` - type | filterFn - ${'owned'} | ${mockIsOwnedEntity} - ${'starred'} | ${mockIsStarredEntity} - `('filter resetting for $type entities', ({ type, filterFn }) => { - let updateFilters: jest.Mock; - - const picker = (props: { loading: boolean }) => ( + it('responds to external queryParameters changes', async () => { + const updateFilters = jest.fn(); + const rendered = render( - + + + , + ); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: UserOwnersFilter.all(), + }), + ); + + rendered.rerender( + + + + + , + ); + expect(updateFilters).toHaveBeenLastCalledWith({ + user: UserOwnersFilter.owned(ownershipEntityRefs), + }); + }); + + describe('filter resetting', () => { + let updateFilters: jest.Mock; + + const Picker = (props: UserListPickerProps) => ( + + + ); @@ -306,57 +450,213 @@ describe('', () => { updateFilters = jest.fn(); }); - describe(`when there are no ${type} entities match the filter`, () => { - beforeEach(() => { - filterFn.mockReturnValue(false); + describe(`when there are no owned entities match the filter`, () => { + it('does not reset the filter while entities are loading', async () => { + mockCatalogApi.queryEntities?.mockImplementation( + () => new Promise(() => {}), + ); + + render(); + + await waitFor(() => + expect(mockCatalogApi.queryEntities).toHaveBeenCalled(), + ); + expect(updateFilters).not.toHaveBeenCalled(); }); - it('does not reset the filter while entities are loading', () => { - render(picker({ loading: true })); + it('does not reset the filter while owned entities are loading', async () => { + mockCatalogApi.queryEntities?.mockImplementation(request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['relations.ownedBy'] + ) { + return new Promise(() => {}); + } + return mockQueryEntitiesImplementation(request); + }); + render(); + + await waitFor(() => + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), + ); expect(updateFilters).not.toHaveBeenCalledWith({ - user: new UserListFilter( - 'all', - mockIsOwnedEntity, - mockIsStarredEntity, - ), + user: expect.any(Object), }); }); - it('does not reset the filter while owned entities are loading', () => { - const isOwnedEntity = jest.fn(() => false); - (useEntityOwnership as jest.Mock).mockReturnValueOnce({ - loading: true, - isOwnedEntity, + it('resets the filter to "all" when entities are loaded, legacy', async () => { + mockCatalogApi.queryEntities?.mockImplementation(async request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['relations.ownedBy'] + ) { + return { items: [], totalItems: 0, pageInfo: {} }; + } + return mockQueryEntitiesImplementation(request); }); - render(picker({ loading: false })); - expect(updateFilters).not.toHaveBeenCalledWith({ - user: new UserListFilter('all', isOwnedEntity, mockIsStarredEntity), - }); + render(); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: new UserListFilter( + 'all', + expect.any(Function), + expect.any(Function), + ), + }), + ); }); - it('resets the filter to "all" when entities are loaded', () => { - render(picker({ loading: false })); - - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'all', - mockIsOwnedEntity, - mockIsStarredEntity, - ), + it('resets the filter to "all" when entities are loaded', async () => { + mockCatalogApi.queryEntities?.mockImplementation(async request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['relations.ownedBy'] + ) { + return { items: [], totalItems: 0, pageInfo: {} }; + } + return mockQueryEntitiesImplementation(request); }); + + render(); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: UserOwnersFilter.all(), + }), + ); }); }); - describe(`when there are some ${type} entities present`, () => { - beforeEach(() => { - filterFn.mockReturnValue(true); + describe(`when there are no starred entities match the filter`, () => { + it('does not reset the filter while entities are loading', async () => { + mockCatalogApi.queryEntities?.mockImplementation( + () => new Promise(() => {}), + ); + + render(); + + await waitFor(() => + expect(mockCatalogApi.queryEntities).toHaveBeenCalled(), + ); + expect(updateFilters).not.toHaveBeenCalled(); }); - it('does not reset the filter while entities are loading', () => { - render(picker({ loading: true })); + it('does not reset the filter while starred entities are loading', async () => { + mockCatalogApi.queryEntities?.mockImplementation(request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['metadata.name'] + ) { + return new Promise(() => {}); + } + return mockQueryEntitiesImplementation(request); + }); + render(); + + await waitFor(() => + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), + ); + expect(updateFilters).not.toHaveBeenCalledWith({ + user: expect.any(Object), + }); + }); + + it('resets the filter to "all" when entities are loaded, legacy', async () => { + mockCatalogApi.queryEntities?.mockImplementation(async request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['metadata.name'] + ) { + return { items: [], totalItems: 0, pageInfo: {} }; + } + return mockQueryEntitiesImplementation(request); + }); + + render(); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: new UserListFilter( + 'all', + expect.any(Function), + expect.any(Function), + ), + }), + ); + }); + + it('resets the filter to "all" when entities are loaded', async () => { + mockCatalogApi.queryEntities?.mockImplementation(async request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['metadata.name'] + ) { + return { items: [], totalItems: 0, pageInfo: {} }; + } + return mockQueryEntitiesImplementation(request); + }); + + render(); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: UserOwnersFilter.all(), + }), + ); + }); + }); + + describe(`when there are some owned entities present`, () => { + it('does not reset the filter while entities are loading', async () => { + mockCatalogApi.queryEntities?.mockImplementation(request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['relations.ownedBy'] + ) { + return new Promise(() => {}); + } + return mockQueryEntitiesImplementation(request); + }); + + render( + , + ); /* picker({ loading: true })*/ + + await waitFor(() => + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), + ); expect(updateFilters).not.toHaveBeenCalledWith({ user: new UserListFilter( 'all', @@ -366,17 +666,74 @@ describe('', () => { }); }); - it('does not reset the filter when entities are loaded', () => { - render(picker({ loading: false })); + it('does not reset the filter when entities are loaded', async () => { + render(); - expect(updateFilters).toHaveBeenLastCalledWith({ + await waitFor(() => + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), + ); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: new UserListFilter( + 'owned', + expect.any(Function), + expect.any(Function), + ), + }), + ); + }); + }); + + describe(`when there are some starred entities present`, () => { + it('does not reset the filter while entities are loading', async () => { + mockCatalogApi.queryEntities?.mockImplementation(request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['metadata.name'] + ) { + return new Promise(() => {}); + } + return mockQueryEntitiesImplementation(request); + }); + + render( + , + ); /* picker({ loading: true })*/ + + await waitFor(() => + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), + ); + expect(updateFilters).not.toHaveBeenCalledWith({ user: new UserListFilter( - type, + 'all', mockIsOwnedEntity, mockIsStarredEntity, ), }); }); + + it('does not reset the filter when entities are loaded', async () => { + render(); + + await waitFor(() => + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), + ); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + user: new UserListFilter( + 'starred', + expect.any(Function), + expect.any(Function), + ), + }), + ); + }); }); }); }); diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index e7c306e0d0..153cdfdb9e 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -32,16 +32,14 @@ import { } from '@material-ui/core'; import SettingsIcon from '@material-ui/icons/Settings'; import StarIcon from '@material-ui/icons/Star'; -import { compact } from 'lodash'; import React, { Fragment, useEffect, useMemo, useState } from 'react'; -import { UserListFilter } from '../../filters'; -import { - useEntityList, - useStarredEntities, - useEntityOwnership, -} from '../../hooks'; +import { UserListFilter, UserOwnersFilter } from '../../filters'; +import { useEntityList, useStarredEntities } from '../../hooks'; import { UserListFilterKind } from '../../types'; -import { reduceEntityFilters } from '../../utils'; +import { useOwnedEntitiesCount } from './useOwnedEntitiesCount'; +import { useAllEntitiesCount } from './useAllEntitiesCount'; +import { useStarredEntitiesCount } from './useStarredEntitiesCount'; +import { useIsOwnedEntity } from '../../hooks/useEntityOwnership'; /** @public */ export type CatalogReactUserListPickerClassKey = @@ -122,20 +120,19 @@ function getFilterGroups(orgName: string | undefined): ButtonGroup[] { export type UserListPickerProps = { initialFilter?: UserListFilterKind; availableFilters?: UserListFilterKind[]; + useServerSideFilters?: boolean; }; /** @public */ export const UserListPicker = (props: UserListPickerProps) => { - const { initialFilter, availableFilters } = props; + const { initialFilter, availableFilters, useServerSideFilters } = props; const classes = useStyles(); const configApi = useApi(configApiRef); const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; const { filters, updateFilters, - backendEntities, queryParameters: { kind: kindParameter, user: userParameter }, - loading: loadingBackendEntities, } = useEntityList(); // Remove group items that aren't in availableFilters and exclude @@ -153,21 +150,18 @@ export const UserListPicker = (props: UserListPickerProps) => { })) .filter(({ items }) => !!items.length); - const { isStarredEntity } = useStarredEntities(); - const { isOwnedEntity, loading: loadingEntityOwnership } = - useEntityOwnership(); - - const loading = loadingBackendEntities || loadingEntityOwnership; - - // Static filters; used for generating counts of potentially unselected kinds - const ownedFilter = useMemo( - () => new UserListFilter('owned', isOwnedEntity, isStarredEntity), - [isOwnedEntity, isStarredEntity], - ); - const starredFilter = useMemo( - () => new UserListFilter('starred', isOwnedEntity, isStarredEntity), - [isOwnedEntity, isStarredEntity], - ); + const { + count: ownedEntitiesCount, + loading: loadingOwnedEntities, + filter: ownedEntitiesFilter, + ownershipEntityRefs, + } = useOwnedEntitiesCount(); + const { count: allCount } = useAllEntitiesCount(); + const { + count: starredEntitiesCount, + filter: starredEntitiesFilter, + loading: loadingStarredEntities, + } = useStarredEntitiesCount(); const queryParamUserFilter = useMemo( () => [userParameter].flat()[0], @@ -175,33 +169,19 @@ export const UserListPicker = (props: UserListPickerProps) => { ); const [selectedUserFilter, setSelectedUserFilter] = useState( - queryParamUserFilter ?? initialFilter, + (queryParamUserFilter as UserListFilterKind) ?? initialFilter, ); - // To show proper counts for each section, apply all other frontend filters _except_ the user - // filter that's controlled by this picker. - const entitiesWithoutUserFilter = useMemo( - () => - backendEntities.filter( - reduceEntityFilters( - compact(Object.values({ ...filters, user: undefined })), - ), - ), - [filters, backendEntities], - ); + const filterCounts = useMemo(() => { + return { + all: allCount, + starred: starredEntitiesCount, + owned: ownedEntitiesCount, + }; + }, [starredEntitiesCount, ownedEntitiesCount, allCount]); - const filterCounts = useMemo>( - () => ({ - all: entitiesWithoutUserFilter.length, - starred: entitiesWithoutUserFilter.filter(entity => - starredFilter.filterEntity(entity), - ).length, - owned: entitiesWithoutUserFilter.filter(entity => - ownedFilter.filterEntity(entity), - ).length, - }), - [entitiesWithoutUserFilter, starredFilter, ownedFilter], - ); + const { isStarredEntity } = useStarredEntities(); + const isOwnedEntity = useIsOwnedEntity(ownershipEntityRefs); // Set selected user filter on query parameter updates; this happens at initial page load and from // external updates to the page location. @@ -211,6 +191,8 @@ export const UserListPicker = (props: UserListPickerProps) => { } }, [queryParamUserFilter]); + const loading = loadingOwnedEntities || loadingStarredEntities; + useEffect(() => { if ( !loading && @@ -223,16 +205,46 @@ export const UserListPicker = (props: UserListPickerProps) => { }, [loading, filterCounts, selectedUserFilter, setSelectedUserFilter]); useEffect(() => { - updateFilters({ - user: selectedUserFilter - ? new UserListFilter( - selectedUserFilter as UserListFilterKind, - isOwnedEntity, - isStarredEntity, - ) - : undefined, - }); - }, [selectedUserFilter, isOwnedEntity, isStarredEntity, updateFilters]); + if (!selectedUserFilter) { + return; + } + if (loading) { + return; + } + if (useServerSideFilters) { + const getFilter = () => { + if (selectedUserFilter === 'owned') { + return ownedEntitiesFilter; + } + if (selectedUserFilter === 'starred') { + return starredEntitiesFilter; + } + return UserOwnersFilter.all(); + }; + + updateFilters({ user: getFilter() }); + } else { + // legacy + updateFilters({ + user: selectedUserFilter + ? new UserListFilter( + selectedUserFilter as UserListFilterKind, + isOwnedEntity, + isStarredEntity, + ) + : undefined, + }); + } + }, [ + selectedUserFilter, + starredEntitiesFilter, + ownedEntitiesFilter, + updateFilters, + useServerSideFilters, + isOwnedEntity, + isStarredEntity, + loading, + ]); return ( diff --git a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts new file mode 100644 index 0000000000..499762ff87 --- /dev/null +++ b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts @@ -0,0 +1,61 @@ +/* + * Copyright 2023 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 { QueryEntitiesInitialRequest } from '@backstage/catalog-client'; +import { useApi } from '@backstage/core-plugin-api'; +import { compact, isEqual } from 'lodash'; +import { useMemo, useRef } from 'react'; +import useAsync from 'react-use/lib/useAsync'; +import { catalogApiRef } from '../../api'; +import { useEntityList } from '../../hooks'; +import { reduceCatalogFilters } from '../../utils'; + +/** + * TODO(vinzscam): we need to find a better way + * for retrieving this value. One possible way, could be to use + * the /entities endpoint: since this method is paginated, + * it should also return how many items matching the provided filters + * are in the catalog + */ +export function useAllEntitiesCount() { + const catalogApi = useApi(catalogApiRef); + const { filters } = useEntityList(); + + const refRequest = useRef(); + useMemo(() => { + const { user, ...allFilters } = filters; + const compacted = compact(Object.values(allFilters)); + const filter = reduceCatalogFilters(compacted); + const request: QueryEntitiesInitialRequest = { + filter, + limit: 0, + }; + + if (isEqual(request, refRequest.current)) { + return refRequest.current; + } + refRequest.current = request; + + return request; + }, [filters]); + + const { value: count, loading } = useAsync(async () => { + const { totalItems } = await catalogApi.queryEntities(refRequest.current); + + return totalItems; + }, [refRequest.current]); + + return { count, loading }; +} diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts new file mode 100644 index 0000000000..32e367cc07 --- /dev/null +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts @@ -0,0 +1,107 @@ +/* + * Copyright 2023 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 { QueryEntitiesInitialRequest } from '@backstage/catalog-client'; +import { identityApiRef, useApi } from '@backstage/core-plugin-api'; +import { compact, intersection, isEqual } from 'lodash'; +import { useMemo, useRef } from 'react'; +import useAsync from 'react-use/lib/useAsync'; +import { catalogApiRef } from '../../api'; +import { UserOwnersFilter } from '../../filters'; +import { useEntityList } from '../../hooks'; +import { reduceCatalogFilters } from '../../utils'; + +export function useOwnedEntitiesCount() { + const identityApi = useApi(identityApiRef); + const catalogApi = useApi(catalogApiRef); + + const { filters } = useEntityList(); + // Trigger load only on mount + const { value: ownershipEntityRefs, loading: loadingEntityRefs } = useAsync( + async () => (await identityApi.getBackstageIdentity()).ownershipEntityRefs, + + [], + ); + + const refRequest = useRef(); + + useMemo(async () => { + const compacted = compact(Object.values(filters)); + const allFilter = reduceCatalogFilters(compacted); + const { ['metadata.name']: metadata, ...filter } = allFilter; + + const facet = 'relations.ownedBy'; + + const ownedByFilter = Array.isArray(filter[facet]) + ? (filter[facet] as string[]) + : []; + + const commonOwnedBy = intersection(ownedByFilter, ownershipEntityRefs); + + const ownedBy = + ownedByFilter.length > 0 ? ownedByFilter : ownershipEntityRefs; + if (ownedByFilter.length > 0 && commonOwnedBy.length === 0) { + // don't send any request if another filter sets + // totally different values for relations.ownedBy filter. + // TODO(vinzscam): check conflicts between UserOwnersFilter and EntityOwnerFilter. + // both set filters on the same relations.ownedBy key, so the conflicts need + // to be addressed properly. + refRequest.current = undefined; + return null; + } + const request: QueryEntitiesInitialRequest = { + filter: { + ...filter, + 'relations.ownedBy': ownedBy ?? [], + }, + limit: 0, + }; + + if (isEqual(request, refRequest.current)) { + return refRequest.current; + } + + refRequest.current = request; + + return request; + }, [filters, ownershipEntityRefs]); + + const { value: count, loading: loadingEntityOwnership } = + useAsync(async () => { + if (!ownershipEntityRefs?.length) { + return 0; + } + if (!refRequest.current) { + return 0; + } + const { totalItems } = await catalogApi.queryEntities(refRequest.current); + + return totalItems; + }, [refRequest.current]); + + const loading = loadingEntityRefs || loadingEntityOwnership; + const filter = useMemo( + () => UserOwnersFilter.owned(ownershipEntityRefs ?? []), + [ownershipEntityRefs], + ); + + return { + count, + loading, + filter, + ownershipEntityRefs, + }; +} diff --git a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts new file mode 100644 index 0000000000..ea7423efe8 --- /dev/null +++ b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts @@ -0,0 +1,80 @@ +/* + * Copyright 2023 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 { QueryEntitiesInitialRequest } from '@backstage/catalog-client'; +import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; +import { useApi } from '@backstage/core-plugin-api'; +import { compact, isEqual } from 'lodash'; +import { useMemo, useRef } from 'react'; +import useAsync from 'react-use/lib/useAsync'; +import { catalogApiRef } from '../../api'; +import { UserOwnersFilter } from '../../filters'; +import { useEntityList, useStarredEntities } from '../../hooks'; +import { reduceCatalogFilters } from '../../utils'; + +export function useStarredEntitiesCount() { + const catalogApi = useApi(catalogApiRef); + const { filters } = useEntityList(); + const { starredEntities } = useStarredEntities(); + + const refRequest = useRef(); + useMemo(async () => { + const { user, ...allFilters } = filters; + const compacted = compact(Object.values(allFilters)); + const filter = reduceCatalogFilters(compacted); + + const facet = 'metadata.name'; + + const request: QueryEntitiesInitialRequest = { + filter: { + ...filter, + [facet]: Array.from(starredEntities).map(e => parseEntityRef(e).name), + }, + limit: 1000, + }; + if (isEqual(request, refRequest.current)) { + return refRequest.current; + } + refRequest.current = request; + + return request; + }, [filters, starredEntities]); + + const { value: count, loading } = useAsync(async () => { + if (!starredEntities.size) { + return 0; + } + + const response = await catalogApi.queryEntities(refRequest.current); + + return response.items + .map(e => + stringifyEntityRef({ + kind: e.kind, + namespace: e.metadata.namespace, + name: e.metadata.name, + }), + ) + .filter(e => starredEntities.has(e)).length; + }, [refRequest.current, starredEntities]); + + const filter = useMemo( + () => UserOwnersFilter.starred(Array.from(starredEntities)), + [starredEntities], + ); + + return { count, loading, filter }; +} From eb81d1673d35f9de06d60ae0cb57cbf422bbb140 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 26 May 2023 14:04:07 +0200 Subject: [PATCH 295/348] catalog-react: rename filter to EntityUserListFilter Signed-off-by: Vincenzo Scamporlino --- .../UserListPicker/UserListPicker.test.tsx | 14 +++++++------- .../components/UserListPicker/UserListPicker.tsx | 4 ++-- .../UserListPicker/useOwnedEntitiesCount.ts | 4 ++-- .../UserListPicker/useStarredEntitiesCount.ts | 4 ++-- plugins/catalog-react/src/filters.ts | 10 +++++----- .../src/hooks/useEntityListProvider.tsx | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index 1315c95061..20dedf23a6 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -22,7 +22,7 @@ import { MockEntityListContextProvider } from '../../testUtils/providers'; import { EntityTagFilter, UserListFilter, - UserOwnersFilter, + EntityUserListFilter, } from '../../filters'; import { CatalogApi, @@ -286,7 +286,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: UserOwnersFilter.owned(ownershipEntityRefs), + user: EntityUserListFilter.owned(ownershipEntityRefs), }), ); @@ -343,7 +343,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: UserOwnersFilter.starred([ + user: EntityUserListFilter.starred([ 'component:default/e-1', 'component:default/e-2', ]), @@ -414,7 +414,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: UserOwnersFilter.all(), + user: EntityUserListFilter.all(), }), ); @@ -431,7 +431,7 @@ describe('', () => { , ); expect(updateFilters).toHaveBeenLastCalledWith({ - user: UserOwnersFilter.owned(ownershipEntityRefs), + user: EntityUserListFilter.owned(ownershipEntityRefs), }); }); @@ -536,7 +536,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: UserOwnersFilter.all(), + user: EntityUserListFilter.all(), }), ); }); @@ -628,7 +628,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: UserOwnersFilter.all(), + user: EntityUserListFilter.all(), }), ); }); diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index 153cdfdb9e..dff4f995ae 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -33,7 +33,7 @@ import { import SettingsIcon from '@material-ui/icons/Settings'; import StarIcon from '@material-ui/icons/Star'; import React, { Fragment, useEffect, useMemo, useState } from 'react'; -import { UserListFilter, UserOwnersFilter } from '../../filters'; +import { UserListFilter, EntityUserListFilter } from '../../filters'; import { useEntityList, useStarredEntities } from '../../hooks'; import { UserListFilterKind } from '../../types'; import { useOwnedEntitiesCount } from './useOwnedEntitiesCount'; @@ -219,7 +219,7 @@ export const UserListPicker = (props: UserListPickerProps) => { if (selectedUserFilter === 'starred') { return starredEntitiesFilter; } - return UserOwnersFilter.all(); + return EntityUserListFilter.all(); }; updateFilters({ user: getFilter() }); diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts index 32e367cc07..f7fb9d4516 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts @@ -20,7 +20,7 @@ import { compact, intersection, isEqual } from 'lodash'; import { useMemo, useRef } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; -import { UserOwnersFilter } from '../../filters'; +import { EntityUserListFilter } from '../../filters'; import { useEntityList } from '../../hooks'; import { reduceCatalogFilters } from '../../utils'; @@ -94,7 +94,7 @@ export function useOwnedEntitiesCount() { const loading = loadingEntityRefs || loadingEntityOwnership; const filter = useMemo( - () => UserOwnersFilter.owned(ownershipEntityRefs ?? []), + () => EntityUserListFilter.owned(ownershipEntityRefs ?? []), [ownershipEntityRefs], ); diff --git a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts index ea7423efe8..aff5066a74 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts @@ -21,7 +21,7 @@ import { compact, isEqual } from 'lodash'; import { useMemo, useRef } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; -import { UserOwnersFilter } from '../../filters'; +import { EntityUserListFilter } from '../../filters'; import { useEntityList, useStarredEntities } from '../../hooks'; import { reduceCatalogFilters } from '../../utils'; @@ -72,7 +72,7 @@ export function useStarredEntitiesCount() { }, [refRequest.current, starredEntities]); const filter = useMemo( - () => UserOwnersFilter.starred(Array.from(starredEntities)), + () => EntityUserListFilter.starred(Array.from(starredEntities)), [starredEntities], ); diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index a5a39f9b02..d0ab093e3c 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -203,22 +203,22 @@ export class EntityNamespaceFilter implements EntityFilter { /** * @public */ -export class UserOwnersFilter implements EntityFilter { +export class EntityUserListFilter implements EntityFilter { private constructor( readonly value: UserListFilterKind, readonly refs?: string[], ) {} static owned(ownershipEntityRefs: string[]) { - return new UserOwnersFilter('owned', ownershipEntityRefs); + return new EntityUserListFilter('owned', ownershipEntityRefs); } static all() { - return new UserOwnersFilter('all'); + return new EntityUserListFilter('all'); } static starred(starredEntityRefs: string[]) { - return new UserOwnersFilter('starred', starredEntityRefs); + return new EntityUserListFilter('starred', starredEntityRefs); } getCatalogFilters(): Record { @@ -247,7 +247,7 @@ export class UserOwnersFilter implements EntityFilter { /** * Filters entities based on whatever the user has starred or owns them. - * @deprecated use UserOwnersFilter + * @deprecated use EntityUserListFilter * @public */ export class UserListFilter implements EntityFilter { diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index b7ee8a94ed..e2a8cfc657 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -41,7 +41,7 @@ import { EntityTypeFilter, UserListFilter, EntityNamespaceFilter, - UserOwnersFilter, + EntityUserListFilter, } from '../filters'; import { EntityFilter } from '../types'; import { reduceBackendCatalogFilters, reduceEntityFilters } from '../utils'; @@ -51,7 +51,7 @@ import { useApi } from '@backstage/core-plugin-api'; export type DefaultEntityFilters = { kind?: EntityKindFilter; type?: EntityTypeFilter; - user?: UserListFilter | UserOwnersFilter; + user?: UserListFilter | EntityUserListFilter; owners?: EntityOwnerFilter; lifecycles?: EntityLifecycleFilter; tags?: EntityTagFilter; From 78b2610717546e406def7f2a55c3c385b7f0b656 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 26 May 2023 14:14:48 +0200 Subject: [PATCH 296/348] catalog-react: remove UserListFilter usage Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/api-report.md | 43 ++-- .../UserListPicker/UserListPicker.test.tsx | 215 +----------------- .../UserListPicker/UserListPicker.tsx | 50 ++-- plugins/catalog-react/src/filters.ts | 9 + .../src/hooks/useEntityListProvider.test.tsx | 23 +- .../src/hooks/useEntityOwnership.ts | 14 +- 6 files changed, 73 insertions(+), 281 deletions(-) diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 3faa5524c9..e73441f7dc 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -142,7 +142,7 @@ export const columnFactories: Readonly<{ export type DefaultEntityFilters = { kind?: EntityKindFilter; type?: EntityTypeFilter; - user?: UserListFilter | UserOwnersFilter; + user?: UserListFilter | EntityUserListFilter; owners?: EntityOwnerFilter; lifecycles?: EntityLifecycleFilter; tags?: EntityTagFilter; @@ -507,6 +507,26 @@ export interface EntityTypePickerProps { initialFilter?: string; } +// @public (undocumented) +export class EntityUserListFilter implements EntityFilter { + // (undocumented) + static all(): EntityUserListFilter; + // (undocumented) + filterEntity(entity: Entity): boolean; + // (undocumented) + getCatalogFilters(): Record; + // (undocumented) + static owned(ownershipEntityRefs: string[]): EntityUserListFilter; + // (undocumented) + readonly refs?: string[] | undefined; + // (undocumented) + static starred(starredEntityRefs: string[]): EntityUserListFilter; + // (undocumented) + toQueryValue(): string; + // (undocumented) + readonly value: UserListFilterKind; +} + // @public export const FavoriteEntity: ( props: FavoriteEntityProps, @@ -661,29 +681,8 @@ export const UserListPicker: ( export type UserListPickerProps = { initialFilter?: UserListFilterKind; availableFilters?: UserListFilterKind[]; - useServerSideFilters?: boolean; }; -// @public (undocumented) -export class UserOwnersFilter implements EntityFilter { - // (undocumented) - static all(): UserOwnersFilter; - // (undocumented) - filterEntity(entity: Entity): boolean; - // (undocumented) - getCatalogFilters(): Record; - // (undocumented) - static owned(ownershipEntityRefs: string[]): UserOwnersFilter; - // (undocumented) - readonly refs?: string[] | undefined; - // (undocumented) - static starred(starredEntityRefs: string[]): UserOwnersFilter; - // (undocumented) - toQueryValue(): string; - // (undocumented) - readonly value: UserListFilterKind; -} - // @public (undocumented) export function useStarredEntities(): { starredEntities: Set; diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index 20dedf23a6..ed6c43d12e 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -16,14 +16,10 @@ import React from 'react'; import { fireEvent, render, waitFor, screen } from '@testing-library/react'; -import { Entity, UserEntity } from '@backstage/catalog-model'; +import { UserEntity } from '@backstage/catalog-model'; import { UserListPicker, UserListPickerProps } from './UserListPicker'; import { MockEntityListContextProvider } from '../../testUtils/providers'; -import { - EntityTagFilter, - UserListFilter, - EntityUserListFilter, -} from '../../filters'; +import { EntityTagFilter, EntityUserListFilter } from '../../filters'; import { CatalogApi, QueryEntitiesInitialRequest, @@ -75,14 +71,6 @@ const apis = TestApiRegistry.from( [starredEntitiesApiRef, mockStarredEntitiesApi], ); -const mockIsOwnedEntity = jest.fn( - (entity: Entity) => entity.metadata.name === 'component-1', -); - -const mockIsStarredEntity = jest.fn( - (entity: Entity) => entity.metadata.name === 'component-3', -); - const ownershipEntityRefs = ['user:default/testuser']; describe('', () => { const mockQueryEntitiesImplementation: CatalogApi['queryEntities'] = @@ -233,44 +221,6 @@ describe('', () => { }); }); - it('respects the query parameter filter value, legacy', async () => { - const updateFilters = jest.fn(); - const queryParameters = { user: 'owned' }; - render( - - - - - , - ); - - await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'owned', - expect.any(Function), - expect.any(Function), - ), - }), - ); - expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ - filter: {}, - limit: 0, - }); - expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ - filter: { 'metadata.name': ['e-1', 'e-2'] }, - limit: 1000, - }); - expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ - filter: { - 'relations.ownedBy': ['user:default/testuser'], - }, - limit: 0, - }); - }); - it('respects the query parameter filter value', async () => { const updateFilters = jest.fn(); const queryParameters = { user: 'owned' }; @@ -279,7 +229,7 @@ describe('', () => { - + , ); @@ -306,35 +256,12 @@ describe('', () => { }); }); - it('updates user filter when a menuitem is selected, legacy', async () => { - const updateFilters = jest.fn(); - render( - - - - - , - ); - - fireEvent.click(screen.getByText('Starred')); - - await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'starred', - expect.any(Function), - expect.any(Function), - ), - }), - ); - }); - it('updates user filter when a menuitem is selected', async () => { const updateFilters = jest.fn(); render( - + , ); @@ -351,52 +278,6 @@ describe('', () => { ); }); - it('responds to external queryParameters changes, legacy', async () => { - const updateFilters = jest.fn(); - const rendered = render( - - - - - , - ); - - await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'all', - expect.any(Function), - expect.any(Function), - ), - }), - ); - - rendered.rerender( - - - - - , - ); - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'owned', - expect.any(Function), - expect.any(Function), - ), - }); - }); - it('responds to external queryParameters changes', async () => { const updateFilters = jest.fn(); const rendered = render( @@ -407,7 +288,7 @@ describe('', () => { queryParameters: { user: ['all'] }, }} > - + , ); @@ -426,7 +307,7 @@ describe('', () => { queryParameters: { user: ['owned'] }, }} > - + , ); @@ -489,34 +370,6 @@ describe('', () => { }); }); - it('resets the filter to "all" when entities are loaded, legacy', async () => { - mockCatalogApi.queryEntities?.mockImplementation(async request => { - if ( - ( - (request as QueryEntitiesInitialRequest).filter as Record< - string, - string - > - )['relations.ownedBy'] - ) { - return { items: [], totalItems: 0, pageInfo: {} }; - } - return mockQueryEntitiesImplementation(request); - }); - - render(); - - await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'all', - expect.any(Function), - expect.any(Function), - ), - }), - ); - }); - it('resets the filter to "all" when entities are loaded', async () => { mockCatalogApi.queryEntities?.mockImplementation(async request => { if ( @@ -532,7 +385,7 @@ describe('', () => { return mockQueryEntitiesImplementation(request); }); - render(); + render(); await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ @@ -581,34 +434,6 @@ describe('', () => { }); }); - it('resets the filter to "all" when entities are loaded, legacy', async () => { - mockCatalogApi.queryEntities?.mockImplementation(async request => { - if ( - ( - (request as QueryEntitiesInitialRequest).filter as Record< - string, - string - > - )['metadata.name'] - ) { - return { items: [], totalItems: 0, pageInfo: {} }; - } - return mockQueryEntitiesImplementation(request); - }); - - render(); - - await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'all', - expect.any(Function), - expect.any(Function), - ), - }), - ); - }); - it('resets the filter to "all" when entities are loaded', async () => { mockCatalogApi.queryEntities?.mockImplementation(async request => { if ( @@ -624,7 +449,7 @@ describe('', () => { return mockQueryEntitiesImplementation(request); }); - render(); + render(); await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ @@ -658,11 +483,7 @@ describe('', () => { expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), ); expect(updateFilters).not.toHaveBeenCalledWith({ - user: new UserListFilter( - 'all', - mockIsOwnedEntity, - mockIsStarredEntity, - ), + user: EntityUserListFilter.all(), }); }); @@ -675,11 +496,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'owned', - expect.any(Function), - expect.any(Function), - ), + user: EntityUserListFilter.owned(expect.any(Array)), }), ); }); @@ -709,11 +526,7 @@ describe('', () => { expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), ); expect(updateFilters).not.toHaveBeenCalledWith({ - user: new UserListFilter( - 'all', - mockIsOwnedEntity, - mockIsStarredEntity, - ), + user: EntityUserListFilter.all(), }); }); @@ -726,11 +539,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: new UserListFilter( - 'starred', - expect.any(Function), - expect.any(Function), - ), + user: EntityUserListFilter.starred(expect.any(Array)), }), ); }); diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index dff4f995ae..b0a86b1322 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -33,13 +33,12 @@ import { import SettingsIcon from '@material-ui/icons/Settings'; import StarIcon from '@material-ui/icons/Star'; import React, { Fragment, useEffect, useMemo, useState } from 'react'; -import { UserListFilter, EntityUserListFilter } from '../../filters'; -import { useEntityList, useStarredEntities } from '../../hooks'; +import { EntityUserListFilter } from '../../filters'; +import { useEntityList } from '../../hooks'; import { UserListFilterKind } from '../../types'; import { useOwnedEntitiesCount } from './useOwnedEntitiesCount'; import { useAllEntitiesCount } from './useAllEntitiesCount'; import { useStarredEntitiesCount } from './useStarredEntitiesCount'; -import { useIsOwnedEntity } from '../../hooks/useEntityOwnership'; /** @public */ export type CatalogReactUserListPickerClassKey = @@ -120,12 +119,11 @@ function getFilterGroups(orgName: string | undefined): ButtonGroup[] { export type UserListPickerProps = { initialFilter?: UserListFilterKind; availableFilters?: UserListFilterKind[]; - useServerSideFilters?: boolean; }; /** @public */ export const UserListPicker = (props: UserListPickerProps) => { - const { initialFilter, availableFilters, useServerSideFilters } = props; + const { initialFilter, availableFilters } = props; const classes = useStyles(); const configApi = useApi(configApiRef); const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; @@ -154,7 +152,6 @@ export const UserListPicker = (props: UserListPickerProps) => { count: ownedEntitiesCount, loading: loadingOwnedEntities, filter: ownedEntitiesFilter, - ownershipEntityRefs, } = useOwnedEntitiesCount(); const { count: allCount } = useAllEntitiesCount(); const { @@ -180,9 +177,6 @@ export const UserListPicker = (props: UserListPickerProps) => { }; }, [starredEntitiesCount, ownedEntitiesCount, allCount]); - const { isStarredEntity } = useStarredEntities(); - const isOwnedEntity = useIsOwnedEntity(ownershipEntityRefs); - // Set selected user filter on query parameter updates; this happens at initial page load and from // external updates to the page location. useEffect(() => { @@ -211,38 +205,24 @@ export const UserListPicker = (props: UserListPickerProps) => { if (loading) { return; } - if (useServerSideFilters) { - const getFilter = () => { - if (selectedUserFilter === 'owned') { - return ownedEntitiesFilter; - } - if (selectedUserFilter === 'starred') { - return starredEntitiesFilter; - } - return EntityUserListFilter.all(); - }; - updateFilters({ user: getFilter() }); - } else { - // legacy - updateFilters({ - user: selectedUserFilter - ? new UserListFilter( - selectedUserFilter as UserListFilterKind, - isOwnedEntity, - isStarredEntity, - ) - : undefined, - }); - } + const getFilter = () => { + if (selectedUserFilter === 'owned') { + return ownedEntitiesFilter; + } + if (selectedUserFilter === 'starred') { + return starredEntitiesFilter; + } + return EntityUserListFilter.all(); + }; + + updateFilters({ user: getFilter() }); }, [ selectedUserFilter, starredEntitiesFilter, ownedEntitiesFilter, updateFilters, - useServerSideFilters, - isOwnedEntity, - isStarredEntity, + loading, ]); diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index d0ab093e3c..bafaae4fb2 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -237,6 +237,15 @@ export class EntityUserListFilter implements EntityFilter { if (this.value === 'starred') { return this.refs?.includes(stringifyEntityRef(entity)) ?? true; } + if (this.value === 'owned') { + return ( + this.refs?.some(v => + getEntityRelations(entity, RELATION_OWNED_BY).some( + o => stringifyEntityRef(o) === v, + ), + ) ?? false + ); + } return true; } diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index d77655ebcc..a4401e3441 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -32,7 +32,11 @@ import { MemoryRouter } from 'react-router-dom'; import { catalogApiRef } from '../api'; import { starredEntitiesApiRef, MockStarredEntitiesApi } from '../apis'; import { EntityKindPicker, UserListPicker } from '../components'; -import { EntityKindFilter, EntityTypeFilter, UserListFilter } from '../filters'; +import { + EntityKindFilter, + EntityTypeFilter, + EntityUserListFilter, +} from '../filters'; import { UserListFilterKind } from '../types'; import { EntityListProvider, useEntityList } from './useEntityListProvider'; @@ -62,11 +66,14 @@ const entities: Entity[] = [ const mockConfigApi = { getOptionalString: () => '', } as Partial; + +const ownershipEntityRefs = ['user:default/guest']; + const mockIdentityApi: Partial = { getBackstageIdentity: async () => ({ type: 'user', userEntityRef: 'user:default/guest', - ownershipEntityRefs: [], + ownershipEntityRefs, }), getCredentials: async () => ({ token: undefined }), }; @@ -148,11 +155,7 @@ describe('', () => { act(() => result.current.updateFilters({ - user: new UserListFilter( - 'owned', - entity => entity.metadata.name === 'component-1', - () => true, - ), + user: EntityUserListFilter.owned(ownershipEntityRefs), }), ); @@ -193,11 +196,7 @@ describe('', () => { act(() => result.current.updateFilters({ - user: new UserListFilter( - 'owned', - entity => entity.metadata.name === 'component-1', - () => true, - ), + user: EntityUserListFilter.owned(ownershipEntityRefs), }), ); diff --git a/plugins/catalog-react/src/hooks/useEntityOwnership.ts b/plugins/catalog-react/src/hooks/useEntityOwnership.ts index 1f1e200634..9c86d6e01a 100644 --- a/plugins/catalog-react/src/hooks/useEntityOwnership.ts +++ b/plugins/catalog-react/src/hooks/useEntityOwnership.ts @@ -46,15 +46,10 @@ export function useEntityOwnership(): { return ownershipEntityRefs; }, []); - const isOwnedEntity = useIsOwnedEntity(refs); - - return useMemo(() => ({ loading, isOwnedEntity }), [loading, isOwnedEntity]); -} - -export function useIsOwnedEntity(refs?: string[]) { - return useMemo(() => { + const isOwnedEntity = useMemo(() => { const myOwnerRefs = new Set(refs ?? []); - const isOwnedEntity = (entity: Entity) => { + + return (entity: Entity) => { const entityOwnerRefs = getEntityRelations(entity, RELATION_OWNED_BY).map( stringifyEntityRef, ); @@ -65,6 +60,7 @@ export function useIsOwnedEntity(refs?: string[]) { } return false; }; - return isOwnedEntity; }, [refs]); + + return { loading, isOwnedEntity }; } From 971a108ab168be535f27aab121603b7d7beea2f3 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 26 May 2023 14:19:25 +0200 Subject: [PATCH 297/348] catalog-react: add clarifying comment to EntityUserListFilter Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/src/filters.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index bafaae4fb2..5879d91591 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -237,6 +237,10 @@ export class EntityUserListFilter implements EntityFilter { if (this.value === 'starred') { return this.refs?.includes(stringifyEntityRef(entity)) ?? true; } + // used only for retro-compatibility with the old + // non paginated table. This is supposed to return always true + // for paginated owned entities, since the filters are applied + // server side. if (this.value === 'owned') { return ( this.refs?.some(v => From d46acd694893c2291ebbe932efc1e0afcda69a04 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 26 May 2023 23:29:13 +0200 Subject: [PATCH 298/348] catalog-react: improve memo readability Signed-off-by: Vincenzo Scamporlino --- .../UserListPicker/useAllEntitiesCount.ts | 26 ++++++--------- .../UserListPicker/useOwnedEntitiesCount.ts | 32 ++++++++----------- .../UserListPicker/useStarredEntitiesCount.ts | 18 +++++------ 3 files changed, 32 insertions(+), 44 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts index 499762ff87..13217c6800 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts @@ -22,40 +22,32 @@ import { catalogApiRef } from '../../api'; import { useEntityList } from '../../hooks'; import { reduceCatalogFilters } from '../../utils'; -/** - * TODO(vinzscam): we need to find a better way - * for retrieving this value. One possible way, could be to use - * the /entities endpoint: since this method is paginated, - * it should also return how many items matching the provided filters - * are in the catalog - */ export function useAllEntitiesCount() { const catalogApi = useApi(catalogApiRef); const { filters } = useEntityList(); - const refRequest = useRef(); - useMemo(() => { + const prevRequest = useRef(); + const request = useMemo(() => { const { user, ...allFilters } = filters; const compacted = compact(Object.values(allFilters)); const filter = reduceCatalogFilters(compacted); - const request: QueryEntitiesInitialRequest = { + const newRequest: QueryEntitiesInitialRequest = { filter, limit: 0, }; - if (isEqual(request, refRequest.current)) { - return refRequest.current; + if (isEqual(newRequest, prevRequest.current)) { + return prevRequest.current; } - refRequest.current = request; - - return request; + prevRequest.current = newRequest; + return newRequest; }, [filters]); const { value: count, loading } = useAsync(async () => { - const { totalItems } = await catalogApi.queryEntities(refRequest.current); + const { totalItems } = await catalogApi.queryEntities(request); return totalItems; - }, [refRequest.current]); + }, [request]); return { count, loading }; } diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts index f7fb9d4516..f2ff985c09 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts @@ -32,13 +32,12 @@ export function useOwnedEntitiesCount() { // Trigger load only on mount const { value: ownershipEntityRefs, loading: loadingEntityRefs } = useAsync( async () => (await identityApi.getBackstageIdentity()).ownershipEntityRefs, - [], ); - const refRequest = useRef(); + const prevRequest = useRef(); - useMemo(async () => { + const request = useMemo(() => { const compacted = compact(Object.values(filters)); const allFilter = reduceCatalogFilters(compacted); const { ['metadata.name']: metadata, ...filter } = allFilter; @@ -54,15 +53,12 @@ export function useOwnedEntitiesCount() { const ownedBy = ownedByFilter.length > 0 ? ownedByFilter : ownershipEntityRefs; if (ownedByFilter.length > 0 && commonOwnedBy.length === 0) { - // don't send any request if another filter sets - // totally different values for relations.ownedBy filter. - // TODO(vinzscam): check conflicts between UserOwnersFilter and EntityOwnerFilter. - // both set filters on the same relations.ownedBy key, so the conflicts need - // to be addressed properly. - refRequest.current = undefined; - return null; + // detect whether another filter sets values that will produce + // empty results in order to avoid sending an additional request. + prevRequest.current = undefined; + return undefined; } - const request: QueryEntitiesInitialRequest = { + const newRequest: QueryEntitiesInitialRequest = { filter: { ...filter, 'relations.ownedBy': ownedBy ?? [], @@ -70,13 +66,13 @@ export function useOwnedEntitiesCount() { limit: 0, }; - if (isEqual(request, refRequest.current)) { - return refRequest.current; + if (isEqual(newRequest, prevRequest.current)) { + return prevRequest.current; } - refRequest.current = request; + prevRequest.current = newRequest; - return request; + return newRequest; }, [filters, ownershipEntityRefs]); const { value: count, loading: loadingEntityOwnership } = @@ -84,13 +80,13 @@ export function useOwnedEntitiesCount() { if (!ownershipEntityRefs?.length) { return 0; } - if (!refRequest.current) { + if (!request) { return 0; } - const { totalItems } = await catalogApi.queryEntities(refRequest.current); + const { totalItems } = await catalogApi.queryEntities(request); return totalItems; - }, [refRequest.current]); + }, [request]); const loading = loadingEntityRefs || loadingEntityOwnership; const filter = useMemo( diff --git a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts index aff5066a74..93adad0489 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts @@ -30,27 +30,27 @@ export function useStarredEntitiesCount() { const { filters } = useEntityList(); const { starredEntities } = useStarredEntities(); - const refRequest = useRef(); - useMemo(async () => { + const prevRequest = useRef(); + const request = useMemo(() => { const { user, ...allFilters } = filters; const compacted = compact(Object.values(allFilters)); const filter = reduceCatalogFilters(compacted); const facet = 'metadata.name'; - const request: QueryEntitiesInitialRequest = { + const newRequest: QueryEntitiesInitialRequest = { filter: { ...filter, [facet]: Array.from(starredEntities).map(e => parseEntityRef(e).name), }, limit: 1000, }; - if (isEqual(request, refRequest.current)) { - return refRequest.current; + if (isEqual(newRequest, prevRequest.current)) { + return prevRequest.current; } - refRequest.current = request; + prevRequest.current = newRequest; - return request; + return newRequest; }, [filters, starredEntities]); const { value: count, loading } = useAsync(async () => { @@ -58,7 +58,7 @@ export function useStarredEntitiesCount() { return 0; } - const response = await catalogApi.queryEntities(refRequest.current); + const response = await catalogApi.queryEntities(request); return response.items .map(e => @@ -69,7 +69,7 @@ export function useStarredEntitiesCount() { }), ) .filter(e => starredEntities.has(e)).length; - }, [refRequest.current, starredEntities]); + }, [request, starredEntities]); const filter = useMemo( () => EntityUserListFilter.starred(Array.from(starredEntities)), From 167d08dca03e6387b8585bae8682a910f167540f Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 26 May 2023 23:41:36 +0200 Subject: [PATCH 299/348] catalog-react: clarify comment Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/src/filters.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index 5879d91591..d6bd8eee3f 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -237,10 +237,9 @@ export class EntityUserListFilter implements EntityFilter { if (this.value === 'starred') { return this.refs?.includes(stringifyEntityRef(entity)) ?? true; } - // used only for retro-compatibility with the old - // non paginated table. This is supposed to return always true - // for paginated owned entities, since the filters are applied - // server side. + // used only for retro-compatibility with non paginated data. + // This is supposed to return always true for paginated + // owned entities, since the filters are applied server side. if (this.value === 'owned') { return ( this.refs?.some(v => From a996c54f68968712e95b08f09c177c73f1af5ec2 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 15 Jun 2023 19:33:44 +0200 Subject: [PATCH 300/348] catalog-react: fix EntityNamespaceFilter Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/src/filters.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index d6bd8eee3f..b94b538802 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -189,7 +189,7 @@ export class EntityNamespaceFilter implements EntityFilter { constructor(readonly values: string[]) {} getCatalogFilters(): Record { - return { 'spec.lifecycle': this.values }; + return { 'metadata.namespace': this.values }; } filterEntity(entity: Entity): boolean { return this.values.some(v => entity.metadata.namespace === v); From 633358a05bef97141564407fe10fe732998456fb Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 15 Jun 2023 19:34:51 +0200 Subject: [PATCH 301/348] catalog-react: improve comment Signed-off-by: Vincenzo Scamporlino --- .../UserListPicker/useOwnedEntitiesCount.ts | 3 ++- .../catalog-react/src/hooks/useEntityOwnership.ts | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts index f2ff985c09..5eac3ced60 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts @@ -29,9 +29,10 @@ export function useOwnedEntitiesCount() { const catalogApi = useApi(catalogApiRef); const { filters } = useEntityList(); - // Trigger load only on mount + const { value: ownershipEntityRefs, loading: loadingEntityRefs } = useAsync( async () => (await identityApi.getBackstageIdentity()).ownershipEntityRefs, + // load only on mount [], ); diff --git a/plugins/catalog-react/src/hooks/useEntityOwnership.ts b/plugins/catalog-react/src/hooks/useEntityOwnership.ts index 9c86d6e01a..fdd73434ec 100644 --- a/plugins/catalog-react/src/hooks/useEntityOwnership.ts +++ b/plugins/catalog-react/src/hooks/useEntityOwnership.ts @@ -41,10 +41,14 @@ export function useEntityOwnership(): { const identityApi = useApi(identityApiRef); // Trigger load only on mount - const { loading, value: refs } = useAsync(async () => { - const { ownershipEntityRefs } = await identityApi.getBackstageIdentity(); - return ownershipEntityRefs; - }, []); + const { loading, value: refs } = useAsync( + async () => { + const { ownershipEntityRefs } = await identityApi.getBackstageIdentity(); + return ownershipEntityRefs; + }, + // load only on mount + [], + ); const isOwnedEntity = useMemo(() => { const myOwnerRefs = new Set(refs ?? []); From ead3cb82f64ef1601bf14e57c8af41e669c96643 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 20 Jun 2023 13:57:23 +0200 Subject: [PATCH 302/348] catalog-react: do not send request when filters are loading Signed-off-by: Vincenzo Scamporlino --- .../src/components/UserListPicker/useAllEntitiesCount.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts index 13217c6800..ba971b088d 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts @@ -36,6 +36,11 @@ export function useAllEntitiesCount() { limit: 0, }; + if (Object.keys(filter).length === 0) { + prevRequest.current = undefined; + return prevRequest.current; + } + if (isEqual(newRequest, prevRequest.current)) { return prevRequest.current; } @@ -44,6 +49,9 @@ export function useAllEntitiesCount() { }, [filters]); const { value: count, loading } = useAsync(async () => { + if (request === undefined) { + return 0; + } const { totalItems } = await catalogApi.queryEntities(request); return totalItems; From ecf4b77d50bedc1724678447f2c10a712590eb89 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 20 Jun 2023 13:58:05 +0200 Subject: [PATCH 303/348] catalog-react: add useAllEntitiesCount tests Signed-off-by: Vincenzo Scamporlino --- .../useAllEntitiesCount.test.tsx | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx diff --git a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx new file mode 100644 index 0000000000..61c2c6eb0a --- /dev/null +++ b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx @@ -0,0 +1,106 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { PropsWithChildren } from 'react'; +import { CatalogApi } from '@backstage/catalog-client'; +import { useAllEntitiesCount } from './useAllEntitiesCount'; +import { waitFor } from '@testing-library/react'; +import { renderHook } from '@testing-library/react-hooks'; +import { EntityListProvider, useEntityList } from '../../hooks'; +import { catalogApiRef } from '../../api'; +import { ApiRef } from '@backstage/core-plugin-api'; +import { MemoryRouter } from 'react-router-dom'; +import { EntityOwnerFilter } from '../../filters'; +import { useMountEffect } from '@react-hookz/web'; + +const mockQueryEntities: jest.MockedFn = jest.fn(); +const mockCatalogApi: jest.Mocked> = { + queryEntities: mockQueryEntities, +}; + +jest.mock('@backstage/core-plugin-api', () => { + const actual = jest.requireActual('@backstage/core-plugin-api'); + return { + ...actual, + useApi: (ref: ApiRef) => + ref === catalogApiRef ? mockCatalogApi : actual.useApi(ref), + }; +}); + +describe('useAllEntitiesCount', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return the count', async () => { + mockQueryEntities.mockResolvedValue({ + items: [], + totalItems: 10, + pageInfo: {}, + }); + + function WrapFilters(props: PropsWithChildren<{}>) { + const { updateFilters } = useEntityList(); + + useMountEffect(() => { + updateFilters({ + owners: new EntityOwnerFilter(['user:default/owner']), + }); + }); + return <>{props.children}; + } + + const { result } = renderHook(() => useAllEntitiesCount(), { + wrapper: ({ children }) => ( + + + {children} + + + ), + }); + + await waitFor(() => + expect(mockQueryEntities).toHaveBeenCalledWith({ + filter: { + 'relations.ownedBy': ['user:default/owner'], + }, + limit: 0, + }), + ); + expect(result.current).toEqual({ count: 10, loading: false }); + }); + + it(`shouldn't invoke the endpoint at startup, when filters are missing`, async () => { + mockQueryEntities.mockResolvedValue({ + items: [], + totalItems: 10, + pageInfo: {}, + }); + + const { result } = renderHook(() => useAllEntitiesCount(), { + wrapper: ({ children }) => ( + + {children} + + ), + }); + + await expect( + waitFor(() => expect(mockQueryEntities).toHaveBeenCalled()), + ).rejects.toThrow(); + expect(result.current).toEqual({ count: 0, loading: false }); + }); +}); From 84822daea6914e82967a03c05ae7b8ab5c339630 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 20 Jun 2023 13:59:41 +0200 Subject: [PATCH 304/348] catalog-react: send proper filters Signed-off-by: Vincenzo Scamporlino --- .../UserListPicker/useOwnedEntitiesCount.ts | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts index 5eac3ced60..605c006f44 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts @@ -20,7 +20,7 @@ import { compact, intersection, isEqual } from 'lodash'; import { useMemo, useRef } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; -import { EntityUserListFilter } from '../../filters'; +import { EntityOwnerFilter, EntityUserListFilter } from '../../filters'; import { useEntityList } from '../../hooks'; import { reduceCatalogFilters } from '../../utils'; @@ -39,30 +39,25 @@ export function useOwnedEntitiesCount() { const prevRequest = useRef(); const request = useMemo(() => { - const compacted = compact(Object.values(filters)); + const { user, owners, ...allFilters } = filters; + const compacted = compact(Object.values(allFilters)); const allFilter = reduceCatalogFilters(compacted); const { ['metadata.name']: metadata, ...filter } = allFilter; - const facet = 'relations.ownedBy'; + const countFilter = getOwnedCountClaims(owners, ownershipEntityRefs); - const ownedByFilter = Array.isArray(filter[facet]) - ? (filter[facet] as string[]) - : []; - - const commonOwnedBy = intersection(ownedByFilter, ownershipEntityRefs); - - const ownedBy = - ownedByFilter.length > 0 ? ownedByFilter : ownershipEntityRefs; - if (ownedByFilter.length > 0 && commonOwnedBy.length === 0) { - // detect whether another filter sets values that will produce - // empty results in order to avoid sending an additional request. + if ( + ownershipEntityRefs?.length === 0 || + countFilter === undefined || + Object.keys(filter).length === 0 + ) { prevRequest.current = undefined; return undefined; } const newRequest: QueryEntitiesInitialRequest = { filter: { ...filter, - 'relations.ownedBy': ownedBy ?? [], + 'relations.ownedBy': countFilter, }, limit: 0, }; @@ -78,14 +73,10 @@ export function useOwnedEntitiesCount() { const { value: count, loading: loadingEntityOwnership } = useAsync(async () => { - if (!ownershipEntityRefs?.length) { - return 0; - } if (!request) { return 0; } const { totalItems } = await catalogApi.queryEntities(request); - return totalItems; }, [request]); @@ -102,3 +93,21 @@ export function useOwnedEntitiesCount() { ownershipEntityRefs, }; } + +function getOwnedCountClaims( + owners: EntityOwnerFilter | undefined, + ownershipEntityRefs: string[] | undefined, +) { + if (ownershipEntityRefs === undefined) { + return undefined; + } + const ownersRefs = owners?.values ?? []; + if (ownersRefs.length) { + const commonOwnedBy = intersection(ownersRefs, ownershipEntityRefs); + if (commonOwnedBy.length === 0) { + return undefined; + } + return commonOwnedBy; + } + return ownershipEntityRefs; +} From 7709c264cabc4c2fc8b0c9d609c02c4cc8abeacf Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 20 Jun 2023 15:22:50 +0200 Subject: [PATCH 305/348] catalog-react: add useOwnedEntitiesCount tests Signed-off-by: Vincenzo Scamporlino --- .../useOwnedEntitiesCount.test.tsx | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx new file mode 100644 index 0000000000..6a79e63c8f --- /dev/null +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx @@ -0,0 +1,235 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { PropsWithChildren } from 'react'; +import { CatalogApi } from '@backstage/catalog-client'; +import { renderHook } from '@testing-library/react-hooks'; +import { + DefaultEntityFilters, + EntityListProvider, + useEntityList, +} from '../../hooks'; +import { catalogApiRef } from '../../api'; +import { + ApiRef, + IdentityApi, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { MemoryRouter } from 'react-router-dom'; +import { useOwnedEntitiesCount } from './useOwnedEntitiesCount'; +import { + EntityNamespaceFilter, + EntityOwnerFilter, + EntityUserListFilter, +} from '../../filters'; +import { useMountEffect } from '@react-hookz/web'; + +const mockQueryEntities: jest.MockedFn = jest.fn(); +const mockCatalogApi: jest.Mocked> = { + queryEntities: mockQueryEntities, +}; + +const mockGetBackstageIdentity: jest.MockedFn< + IdentityApi['getBackstageIdentity'] +> = jest.fn(); + +jest.mock('@backstage/core-plugin-api', () => { + const actual = jest.requireActual('@backstage/core-plugin-api'); + return { + ...actual, + useApi: (ref: ApiRef) => { + if (ref === catalogApiRef) { + return mockCatalogApi; + } + if (ref === identityApiRef) { + return { + getBackstageIdentity: mockGetBackstageIdentity, + }; + } + + return actual.useApi(ref); + }, + }; +}); + +describe('useOwnedEntitiesCount', () => { + beforeEach(() => { + jest.clearAllMocks(); + + mockGetBackstageIdentity.mockResolvedValue({ + ownershipEntityRefs: ['user:default/spiderman', 'user:group/a-group'], + userEntityRef: 'user:default/spiderman', + type: 'user', + }); + }); + + it(`shouldn't invoke queryEntities when filters are loading`, async () => { + mockQueryEntities.mockResolvedValue({ + items: [], + totalItems: 10, + pageInfo: {}, + }); + + const { result, waitFor } = renderHook(() => useOwnedEntitiesCount(), { + wrapper: createWrapperWithInitialFilters({}), + }); + + await waitFor(() => expect(mockGetBackstageIdentity).toHaveBeenCalled()); + + await expect( + waitFor(() => expect(mockQueryEntities).toHaveBeenCalled()), + ).rejects.toThrow(); + + expect(result.current).toEqual({ + count: 0, + loading: false, + filter: EntityUserListFilter.owned([ + 'user:default/spiderman', + 'user:group/a-group', + ]), + ownershipEntityRefs: ['user:default/spiderman', 'user:group/a-group'], + }); + }); + + it(`should properly apply the filters`, async () => { + mockQueryEntities.mockResolvedValue({ + items: [], + totalItems: 10, + pageInfo: {}, + }); + + const { result, waitFor } = renderHook(() => useOwnedEntitiesCount(), { + wrapper: createWrapperWithInitialFilters({ + namespace: new EntityNamespaceFilter(['a-namespace']), + }), + }); + + await waitFor(() => expect(mockGetBackstageIdentity).toHaveBeenCalled()); + + await waitFor(() => + expect(mockQueryEntities).toHaveBeenCalledWith({ + filter: { + 'metadata.namespace': ['a-namespace'], + 'relations.ownedBy': ['user:default/spiderman', 'user:group/a-group'], + }, + limit: 0, + }), + ); + + expect(result.current).toEqual({ + count: 10, + loading: false, + filter: EntityUserListFilter.owned([ + 'user:default/spiderman', + 'user:group/a-group', + ]), + ownershipEntityRefs: ['user:default/spiderman', 'user:group/a-group'], + }); + }); + + it(`should return count 0 without invoking queryEntities if owners filter doesn't have claims on common with logged in user`, async () => { + mockQueryEntities.mockResolvedValue({ + items: [], + totalItems: 10, + pageInfo: {}, + }); + + const { result, waitFor } = renderHook(() => useOwnedEntitiesCount(), { + wrapper: createWrapperWithInitialFilters({ + namespace: new EntityNamespaceFilter(['a-namespace']), + owners: new EntityOwnerFilter(['group:default/monsters']), + }), + }); + + await waitFor(() => expect(mockGetBackstageIdentity).toHaveBeenCalled()); + + await expect( + waitFor(() => expect(mockQueryEntities).toHaveBeenCalled()), + ).rejects.toThrow(); + + expect(result.current).toEqual({ + count: 0, + loading: false, + filter: EntityUserListFilter.owned([ + 'user:default/spiderman', + 'user:group/a-group', + ]), + ownershipEntityRefs: ['user:default/spiderman', 'user:group/a-group'], + }); + }); + + it(`should send claims in common between owners filter and logged in user`, async () => { + mockQueryEntities.mockResolvedValue({ + items: [], + totalItems: 10, + pageInfo: {}, + }); + + const { result, waitFor } = renderHook(() => useOwnedEntitiesCount(), { + wrapper: createWrapperWithInitialFilters({ + namespace: new EntityNamespaceFilter(['a-namespace']), + owners: new EntityOwnerFilter([ + 'group:default/monsters', + 'user:group/a-group', + ]), + }), + }); + + await waitFor(() => expect(mockGetBackstageIdentity).toHaveBeenCalled()); + + await waitFor(() => + expect(mockQueryEntities).toHaveBeenCalledWith({ + filter: { + 'metadata.namespace': ['a-namespace'], + 'relations.ownedBy': ['user:group/a-group'], + }, + limit: 0, + }), + ); + + expect(result.current).toEqual({ + count: 10, + loading: false, + filter: EntityUserListFilter.owned([ + 'user:default/spiderman', + 'user:group/a-group', + ]), + ownershipEntityRefs: ['user:default/spiderman', 'user:group/a-group'], + }); + }); +}); + +function createWrapperWithInitialFilters( + filters: Partial, +) { + function WrapFilters(props: PropsWithChildren<{}>) { + const { updateFilters } = useEntityList(); + + useMountEffect(() => { + updateFilters(filters); + }); + return <>{props.children}; + } + + return function Wrapper(props: PropsWithChildren<{}>) { + return ( + + + {props.children} + + + ); + }; +} From bd4c4cec5d52fc3104159f276c062896fd07ad3f Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 21 Jun 2023 10:42:04 +0200 Subject: [PATCH 306/348] catalog-react: fix UserListPicker tests Signed-off-by: Vincenzo Scamporlino --- .../UserListPicker/UserListPicker.test.tsx | 84 +++++++++++++++---- 1 file changed, 66 insertions(+), 18 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index ed6c43d12e..f0b82b550e 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -19,7 +19,12 @@ import { fireEvent, render, waitFor, screen } from '@testing-library/react'; import { UserEntity } from '@backstage/catalog-model'; import { UserListPicker, UserListPickerProps } from './UserListPicker'; import { MockEntityListContextProvider } from '../../testUtils/providers'; -import { EntityTagFilter, EntityUserListFilter } from '../../filters'; +import { + EntityKindFilter, + EntityNamespaceFilter, + EntityTagFilter, + EntityUserListFilter, +} from '../../filters'; import { CatalogApi, QueryEntitiesInitialRequest, @@ -159,12 +164,19 @@ describe('', () => { it('renders filters', async () => { render( - + , ); + await waitFor(() => + expect(mockIdentityApi.getBackstageIdentity).toHaveBeenCalled(), + ); await waitFor(() => expect( screen.getAllByRole('menuitem').map(({ textContent }) => textContent), @@ -172,17 +184,25 @@ describe('', () => { ); expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ - filter: {}, + filter: { + 'metadata.namespace': ['default'], + }, limit: 0, }); expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ - filter: { 'metadata.name': ['e-1', 'e-2'] }, + filter: { + 'metadata.namespace': ['default'], + 'relations.ownedBy': ['user:default/testuser'], + }, + limit: 0, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { + 'metadata.namespace': ['default'], + 'metadata.name': ['e-1', 'e-2'], + }, limit: 1000, }); - expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ - filter: { 'relations.ownedBy': ['user:default/testuser'] }, - limit: 0, - }); }); it('respects other frontend filters in counts', async () => { @@ -223,16 +243,23 @@ describe('', () => { it('respects the query parameter filter value', async () => { const updateFilters = jest.fn(); - const queryParameters = { user: 'owned' }; + const queryParameters = { user: 'owned', kind: 'component' }; render( , ); + await waitFor(() => + expect(mockIdentityApi.getBackstageIdentity).toHaveBeenCalled(), + ); await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ @@ -241,15 +268,16 @@ describe('', () => { ); expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ - filter: {}, + filter: { kind: 'component' }, limit: 0, }); expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ - filter: { 'metadata.name': ['e-1', 'e-2'] }, + filter: { kind: 'component', 'metadata.name': ['e-1', 'e-2'] }, limit: 1000, }); expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ filter: { + kind: 'component', 'relations.ownedBy': ['user:default/testuser'], }, limit: 0, @@ -285,7 +313,11 @@ describe('', () => { @@ -293,6 +325,10 @@ describe('', () => { , ); + await waitFor(() => + expect(mockIdentityApi.getBackstageIdentity).toHaveBeenCalled(), + ); + await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ user: EntityUserListFilter.all(), @@ -304,7 +340,11 @@ describe('', () => { @@ -319,9 +359,14 @@ describe('', () => { describe('filter resetting', () => { let updateFilters: jest.Mock; - const Picker = (props: UserListPickerProps) => ( + const Picker = ({ ...props }: UserListPickerProps) => ( - + @@ -331,7 +376,7 @@ describe('', () => { updateFilters = jest.fn(); }); - describe(`when there are no owned entities match the filter`, () => { + describe(`when there are no owned entities matching the filter`, () => { it('does not reset the filter while entities are loading', async () => { mockCatalogApi.queryEntities?.mockImplementation( () => new Promise(() => {}), @@ -342,7 +387,10 @@ describe('', () => { await waitFor(() => expect(mockCatalogApi.queryEntities).toHaveBeenCalled(), ); - expect(updateFilters).not.toHaveBeenCalled(); + + await expect( + waitFor(() => expect(updateFilters).toHaveBeenCalled()), + ).rejects.toThrow(); }); it('does not reset the filter while owned entities are loading', async () => { From 083d556ef6774c8ab3bf52fa886b34ea153f0b7e Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 22 Jun 2023 23:55:33 +0200 Subject: [PATCH 307/348] catalog: mock queryEntities Signed-off-by: Vincenzo Scamporlino --- .../CatalogPage/DefaultCatalogPage.test.tsx | 70 +++++++++++++++++-- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx index b7d3ca3ed8..f16eaf4e93 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx @@ -14,7 +14,10 @@ * limitations under the License. */ -import { CatalogApi } from '@backstage/catalog-client'; +import { + CatalogApi, + QueryEntitiesInitialRequest, +} from '@backstage/catalog-client'; import { RELATION_OWNED_BY } from '@backstage/catalog-model'; import { TableColumn, TableProps } from '@backstage/core-components'; import { @@ -36,7 +39,7 @@ import { renderInTestApp, } from '@backstage/test-utils'; import DashboardIcon from '@material-ui/icons/Dashboard'; -import { fireEvent, screen } from '@testing-library/react'; +import { fireEvent, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { createComponentRouteRef } from '../../routes'; import { CatalogTableRow } from '../CatalogTable'; @@ -49,10 +52,12 @@ describe('DefaultCatalogPage', () => { }); afterEach(() => { window.history.replaceState = origReplaceState; + + jest.clearAllMocks(); }); - const catalogApi: Partial = { - getEntities: () => + const catalogApi: jest.Mocked> = { + getEntities: jest.fn().mockImplementation(() => Promise.resolve({ items: [ { @@ -97,17 +102,59 @@ describe('DefaultCatalogPage', () => { }, ], }), - getLocationByRef: () => - Promise.resolve({ id: 'id', type: 'url', target: 'url' }), - getEntityFacets: async () => ({ + ), + getLocationByRef: jest + .fn() + .mockImplementation(() => + Promise.resolve({ id: 'id', type: 'url', target: 'url' }), + ), + getEntityFacets: jest.fn().mockImplementation(async () => ({ facets: { 'relations.ownedBy': [ { count: 1, value: 'group:default/not-tools' }, { count: 1, value: 'group:default/tools' }, ], }, + })), + queryEntities: jest.fn().mockImplementation(async request => { + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['relations.ownedBy'] + ) { + // owned entities + return { items: [], totalItems: 3, pageInfo: {} }; + } + + if ( + ( + (request as QueryEntitiesInitialRequest).filter as Record< + string, + string + > + )['metadata.name'] + ) { + // starred entities + return { + items: [ + { + apiVersion: '1', + kind: 'component', + metadata: { name: 'Entity1', namespace: 'default' }, + }, + ], + totalItems: 1, + pageInfo: {}, + }; + } + // all items + return { items: [], totalItems: 2, pageInfo: {} }; }), }; + const testProfile: Partial = { displayName: 'Display Name', }; @@ -183,6 +230,8 @@ describe('DefaultCatalogPage', () => { it('should render the default actions of an item in the grid', async () => { await renderWrapped(); + await waitFor(() => expect(catalogApi.queryEntities).toHaveBeenCalled()); + fireEvent.click(screen.getByTestId('user-picker-owned')); await expect( screen.findByText(/Owned components \(1\)/), @@ -215,6 +264,8 @@ describe('DefaultCatalogPage', () => { ]; await renderWrapped(); + await waitFor(() => expect(catalogApi.queryEntities).toHaveBeenCalled()); + fireEvent.click(screen.getByTestId('user-picker-owned')); await expect( screen.findByText(/Owned components \(1\)/), @@ -231,7 +282,10 @@ describe('DefaultCatalogPage', () => { // https://github.com/mbrn/material-table/issues/1293 it('should render', async () => { await renderWrapped(); + await waitFor(() => expect(catalogApi.queryEntities).toHaveBeenCalled()); + fireEvent.click(screen.getByTestId('user-picker-owned')); + await expect( screen.findByText(/Owned components \(1\)/), ).resolves.toBeInTheDocument(); @@ -252,6 +306,8 @@ describe('DefaultCatalogPage', () => { // entities defaulting to "owned" filter and not based on the selected filter it('should render the correct entities filtered on the selected filter', async () => { await renderWrapped(); + await waitFor(() => expect(catalogApi.queryEntities).toHaveBeenCalled()); + fireEvent.click(screen.getByTestId('user-picker-owned')); await expect( screen.findByText(/Owned components \(1\)/), From f858e6ee26b16e81a740e6ee77c59ddf0a5b6f14 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 23 Jun 2023 00:21:47 +0200 Subject: [PATCH 308/348] catalog: fix flaky namespace column test Signed-off-by: Vincenzo Scamporlino --- .../src/components/CatalogPage/DefaultCatalogPage.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx index f16eaf4e93..b331c0e477 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx @@ -83,6 +83,7 @@ describe('DefaultCatalogPage', () => { kind: 'Component', metadata: { name: 'Entity2', + namespace: 'default', }, spec: { owner: 'not-tools', From 5447358dc9e7c817c0d8f470b185e8ba3a5bf93d Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 3 Oct 2023 17:13:04 +0200 Subject: [PATCH 309/348] catalog-react: use correct waitFor Signed-off-by: Vincenzo Scamporlino --- .../components/UserListPicker/useAllEntitiesCount.test.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx index 61c2c6eb0a..fc2c0e65bd 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx @@ -16,7 +16,6 @@ import React, { PropsWithChildren } from 'react'; import { CatalogApi } from '@backstage/catalog-client'; import { useAllEntitiesCount } from './useAllEntitiesCount'; -import { waitFor } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; import { EntityListProvider, useEntityList } from '../../hooks'; import { catalogApiRef } from '../../api'; @@ -62,7 +61,7 @@ describe('useAllEntitiesCount', () => { return <>{props.children}; } - const { result } = renderHook(() => useAllEntitiesCount(), { + const { result, waitFor } = renderHook(() => useAllEntitiesCount(), { wrapper: ({ children }) => ( @@ -90,7 +89,7 @@ describe('useAllEntitiesCount', () => { pageInfo: {}, }); - const { result } = renderHook(() => useAllEntitiesCount(), { + const { result, waitFor } = renderHook(() => useAllEntitiesCount(), { wrapper: ({ children }) => ( {children} From 62206785147963524c5995fbc2533631eb1c1647 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 3 Oct 2023 17:13:36 +0200 Subject: [PATCH 310/348] catalog-react: add useStarredEntitiesCount tests Signed-off-by: Vincenzo Scamporlino --- .../useStarredEntitiesCount.test.tsx | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.test.tsx diff --git a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.test.tsx new file mode 100644 index 0000000000..1a02f3996b --- /dev/null +++ b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.test.tsx @@ -0,0 +1,124 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { CatalogApi } from '@backstage/catalog-client'; +import { EntityListProvider, useStarredEntities } from '../../hooks'; +import { catalogApiRef } from '../../api'; +import { ApiRef } from '@backstage/core-plugin-api'; +import { MemoryRouter } from 'react-router-dom'; +import { useStarredEntitiesCount } from './useStarredEntitiesCount'; +import { renderHook } from '@testing-library/react-hooks'; + +const mockQueryEntities: jest.MockedFn = jest.fn(); +const mockCatalogApi: jest.Mocked> = { + queryEntities: mockQueryEntities, +}; + +const mockStarredEntities: jest.MockedFn<() => Set> = jest.fn(); + +const mockUseStarredEntities: ReturnType = { + get starredEntities() { + return mockStarredEntities(); + }, +} as ReturnType; + +jest.mock('../../hooks', () => { + const actual = jest.requireActual('../../hooks'); + return { ...actual, useStarredEntities: () => mockUseStarredEntities }; +}); + +jest.mock('@backstage/core-plugin-api', () => { + const actual = jest.requireActual('@backstage/core-plugin-api'); + return { + ...actual, + useApi: (ref: ApiRef) => + ref === catalogApiRef ? mockCatalogApi : actual.useApi(ref), + }; +}); + +describe('useStarredEntitiesCount', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return the count', async () => { + mockStarredEntities.mockReturnValue( + new Set(['component:default/favourite1', 'component:default/favourite2']), + ); + mockQueryEntities.mockResolvedValue({ + items: [ + { + apiVersion: '1', + kind: 'component', + metadata: { name: 'favourite1' }, + }, + { + apiVersion: '1', + kind: 'component', + metadata: { name: 'favourite2' }, + }, + ], + totalItems: 2, + pageInfo: {}, + }); + + const { result, waitFor } = renderHook(() => useStarredEntitiesCount(), { + wrapper: ({ children }) => ( + + {children} + + ), + }); + + await waitFor(() => + expect(mockQueryEntities).toHaveBeenCalledWith({ + filter: { + 'metadata.name': ['favourite1', 'favourite2'], + }, + limit: 1000, + }), + ); + expect(result.current).toEqual({ + count: 2, + loading: false, + filter: { + refs: ['component:default/favourite1', 'component:default/favourite2'], + value: 'starred', + }, + }); + }); + + it(`shouldn't invoke the endpoint if there are no starred entities`, async () => { + mockStarredEntities.mockReturnValue(new Set()); + + const { result, waitFor } = renderHook(() => useStarredEntitiesCount(), { + wrapper: ({ children }) => ( + + {children} + + ), + }); + + await expect( + waitFor(() => expect(mockQueryEntities).toHaveBeenCalled()), + ).rejects.toThrow(); + expect(result.current).toEqual({ + count: 0, + loading: false, + filter: { refs: [], value: 'starred' }, + }); + }); +}); From 1fd53fa0c6e667e0601c417616cf1982582463aa Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 3 Oct 2023 17:30:01 +0200 Subject: [PATCH 311/348] add UserListPicker changeset Signed-off-by: Vincenzo Scamporlino --- .changeset/shaggy-buses-beg.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/shaggy-buses-beg.md diff --git a/.changeset/shaggy-buses-beg.md b/.changeset/shaggy-buses-beg.md new file mode 100644 index 0000000000..d2c9351b5e --- /dev/null +++ b/.changeset/shaggy-buses-beg.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-catalog-react': minor +--- + +The `UserListPicker` component has undergone improvements to enhance its performance. + +The previous implementation inferred the number of owned and starred entities based on the entities available in the `EntityListContext`. The updated version no longer relies on the `EntityListContext` for inference, allowing for better decoupling. + +The component now loads the entities' count asynchronously, resulting in improved performance and responsiveness. For this purpose, some of the exported filters such as `EntityTagFilter`, `EntityOwnerFilter`, `EntityLifecycleFilter` and `EntityNamespaceFilter` have now the `getCatalogFilters` method implemented. From db647a72fe9b7f05c9ec6c3f400cedb17b7cb367 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 3 Oct 2023 19:26:14 +0200 Subject: [PATCH 312/348] api-docs: fix flaky tests Signed-off-by: Vincenzo Scamporlino --- .../DefaultApiExplorerPage.test.tsx | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx index fa698ded58..6d0b191d68 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx @@ -52,6 +52,10 @@ describe('DefaultApiExplorerPage', () => { kind: 'API', metadata: { name: 'Entity1', + annotations: { + 'backstage.io/view-url': 'viewurl', + 'backstage.io/edit-url': 'editurl', + }, }, spec: { type: 'openapi' }, }, @@ -63,6 +67,11 @@ describe('DefaultApiExplorerPage', () => { getEntityFacets: async () => ({ facets: { 'relations.ownedBy': [] }, }), + queryEntities: async () => ({ + items: [], + pageInfo: {}, + totalItems: 0, + }), }; const configApi: ConfigApi = new ConfigReader({ @@ -152,37 +161,39 @@ describe('DefaultApiExplorerPage', () => { it('should render the default actions of an item in the grid', async () => { await renderWrapped(); - expect(await screen.findByText(/All apis \(1\)/)).toBeInTheDocument(); - expect(await screen.findByTitle(/View/)).toBeInTheDocument(); - expect(await screen.findByTitle(/View/)).toBeInTheDocument(); - expect(await screen.findByTitle(/Edit/)).toBeInTheDocument(); - expect(await screen.findByTitle(/Add to favorites/)).toBeInTheDocument(); + await waitFor(() => { + expect(screen.getByText(/All apis \(1\)/)).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getByRole('button', { name: /view/i })).toBeInTheDocument(); + }); + expect(screen.getByRole('button', { name: /edit/i })).toBeInTheDocument(); + expect(screen.getByTitle(/Add to favorites/)).toBeInTheDocument(); }); it('should render the custom actions of an item passed as prop', async () => { const actions: TableProps['actions'] = [ - () => { - return { - icon: () => , - tooltip: 'Foo Action', - disabled: false, - onClick: () => jest.fn(), - }; + { + icon: () => , + tooltip: 'Foo Action', + disabled: false, + onClick: jest.fn(), }, - () => { - return { - icon: () => , - tooltip: 'Bar Action', - disabled: true, - onClick: () => jest.fn(), - }; + { + icon: () => , + tooltip: 'Bar Action', + disabled: true, + onClick: jest.fn(), }, ]; await renderWrapped(); - expect(await screen.findByText(/All apis \(1\)/)).toBeInTheDocument(); - expect(await screen.findByTitle(/Foo Action/)).toBeInTheDocument(); - expect(await screen.findByTitle(/Bar Action/)).toBeInTheDocument(); - expect((await screen.findByTitle(/Bar Action/)).firstChild).toBeDisabled(); + await waitFor(() => { + expect(screen.getByText(/All apis \(1\)/)).toBeInTheDocument(); + }); + expect(screen.getByTitle(/Foo Action/)).toBeInTheDocument(); + expect(screen.getByTitle(/Bar Action/)).toBeInTheDocument(); + expect(screen.getByTitle(/Bar Action/).firstChild).toBeDisabled(); }); }); From 4efc4c1cab820bf8176a425c1df8ec121975139e Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Mon, 9 Oct 2023 14:12:27 +0200 Subject: [PATCH 313/348] catalog-react: fix comments Signed-off-by: Vincenzo Scamporlino --- .../UserListPicker/UserListPicker.test.tsx | 13 ++++++------- plugins/catalog-react/src/filters.ts | 9 +++------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index f0b82b550e..63228717a5 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -523,9 +523,7 @@ describe('', () => { return mockQueryEntitiesImplementation(request); }); - render( - , - ); /* picker({ loading: true })*/ + render(); await waitFor(() => expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), @@ -566,9 +564,7 @@ describe('', () => { return mockQueryEntitiesImplementation(request); }); - render( - , - ); /* picker({ loading: true })*/ + render(); await waitFor(() => expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), @@ -587,7 +583,10 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: EntityUserListFilter.starred(expect.any(Array)), + user: EntityUserListFilter.starred([ + 'component:default/e-1', + 'component:default/e-2', + ]), }), ); }); diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index b94b538802..74ab771999 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -241,11 +241,11 @@ export class EntityUserListFilter implements EntityFilter { // This is supposed to return always true for paginated // owned entities, since the filters are applied server side. if (this.value === 'owned') { + const relations = getEntityRelations(entity, RELATION_OWNED_BY); + return ( this.refs?.some(v => - getEntityRelations(entity, RELATION_OWNED_BY).some( - o => stringifyEntityRef(o) === v, - ), + relations.some(o => stringifyEntityRef(o) === v), ) ?? false ); } @@ -309,9 +309,6 @@ export class EntityOrphanFilter implements EntityFilter { export class EntityErrorFilter implements EntityFilter { constructor(readonly value: boolean) {} - // TODO(vinzscam): is it possible to implement - // getCatalogFilters? ask mammals - filterEntity(entity: Entity): boolean { const error = ((entity as AlphaEntity)?.status?.items?.length as number) > 0; From 0aa3cecddfb201865d58811f0c3bb45026474509 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Mon, 9 Oct 2023 14:13:44 +0200 Subject: [PATCH 314/348] catalog: simplify typings Signed-off-by: Vincenzo Scamporlino --- .../CatalogPage/DefaultCatalogPage.test.tsx | 60 ++++++++----------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx index b331c0e477..53f031e263 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx @@ -117,43 +117,31 @@ describe('DefaultCatalogPage', () => { ], }, })), - queryEntities: jest.fn().mockImplementation(async request => { - if ( - ( - (request as QueryEntitiesInitialRequest).filter as Record< - string, - string - > - )['relations.ownedBy'] - ) { - // owned entities - return { items: [], totalItems: 3, pageInfo: {} }; - } + queryEntities: jest + .fn() + .mockImplementation(async (request: QueryEntitiesInitialRequest) => { + if ((request.filter as any)['relations.ownedBy']) { + // owned entities + return { items: [], totalItems: 3, pageInfo: {} }; + } - if ( - ( - (request as QueryEntitiesInitialRequest).filter as Record< - string, - string - > - )['metadata.name'] - ) { - // starred entities - return { - items: [ - { - apiVersion: '1', - kind: 'component', - metadata: { name: 'Entity1', namespace: 'default' }, - }, - ], - totalItems: 1, - pageInfo: {}, - }; - } - // all items - return { items: [], totalItems: 2, pageInfo: {} }; - }), + if ((request.filter as any)['metadata.name']) { + // starred entities + return { + items: [ + { + apiVersion: '1', + kind: 'component', + metadata: { name: 'Entity1', namespace: 'default' }, + }, + ], + totalItems: 1, + pageInfo: {}, + }; + } + // all items + return { items: [], totalItems: 2, pageInfo: {} }; + }), }; const testProfile: Partial = { From 2dd206a2fd596e80e2673918e4965fd1599e8461 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 12 Oct 2023 13:25:47 +0200 Subject: [PATCH 315/348] catalog-react: fix orphan query Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/src/filters.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index 74ab771999..3d871fe412 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -293,7 +293,10 @@ export class EntityOrphanFilter implements EntityFilter { constructor(readonly value: boolean) {} getCatalogFilters(): Record { - return { 'metadata.annotations.backstage.io/orphan': String(this.value) }; + if (this.value) { + return { 'metadata.annotations.backstage.io/orphan': String(this.value) }; + } + return {}; } filterEntity(entity: Entity): boolean { From 3ea09ae6ebfcc8b5d84ed7da8cc9068165b9053a Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 20 Oct 2023 08:08:03 +0200 Subject: [PATCH 316/348] catalog: flip the allowed backend filters logic Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-react/src/utils/filters.ts | 31 +++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-react/src/utils/filters.ts b/plugins/catalog-react/src/utils/filters.ts index 5ab6e43593..f2cfe64960 100644 --- a/plugins/catalog-react/src/utils/filters.ts +++ b/plugins/catalog-react/src/utils/filters.ts @@ -16,7 +16,16 @@ import { Entity } from '@backstage/catalog-model'; import { EntityFilter } from '../types'; -import { EntityKindFilter, EntityTypeFilter } from '../filters'; +import { + EntityLifecycleFilter, + EntityNamespaceFilter, + EntityOrphanFilter, + EntityOwnerFilter, + EntityTagFilter, + EntityTextFilter, + EntityUserListFilter, + UserListFilter, +} from '../filters'; export function reduceCatalogFilters( filters: EntityFilter[], @@ -29,6 +38,13 @@ export function reduceCatalogFilters( }, {} as Record); } +/** + * This function computes and returns an object containing the filters to be sent + * to the backend. Any filter coming from `EntityKindFilter` and `EntityTypeFilter`, together + * with custom filter set by the adopters is allowed. This function is used by `EntityListProvider` + * and it won't be needed anymore in the future once pagination is implemented, as all the filters + * will be applied backend-side. + */ export function reduceBackendCatalogFilters(filters: EntityFilter[]) { const backendCatalogFilters: Record< string, @@ -37,11 +53,18 @@ export function reduceBackendCatalogFilters(filters: EntityFilter[]) { filters.forEach(filter => { if ( - filter instanceof EntityKindFilter || - filter instanceof EntityTypeFilter + filter instanceof EntityTagFilter || + filter instanceof EntityOwnerFilter || + filter instanceof EntityLifecycleFilter || + filter instanceof EntityNamespaceFilter || + filter instanceof EntityUserListFilter || + filter instanceof EntityOrphanFilter || + filter instanceof EntityTextFilter || + filter instanceof UserListFilter ) { - Object.assign(backendCatalogFilters, filter.getCatalogFilters()); + return; } + Object.assign(backendCatalogFilters, filter.getCatalogFilters?.() || {}); }); return backendCatalogFilters; From 89e0babcb8c6fd7b930a70bc62fc7d69090f70e1 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 20 Oct 2023 08:10:11 +0200 Subject: [PATCH 317/348] catalog-react: rename EntityUserListFilter to EntityUserFilter Signed-off-by: Vincenzo Scamporlino --- .../UserListPicker/UserListPicker.test.tsx | 22 +++++++++---------- .../UserListPicker/UserListPicker.tsx | 4 ++-- .../useOwnedEntitiesCount.test.tsx | 10 ++++----- .../UserListPicker/useOwnedEntitiesCount.ts | 4 ++-- .../UserListPicker/useStarredEntitiesCount.ts | 4 ++-- plugins/catalog-react/src/filters.ts | 10 ++++----- .../src/hooks/useEntityListProvider.test.tsx | 6 ++--- .../src/hooks/useEntityListProvider.tsx | 4 ++-- plugins/catalog-react/src/utils/filters.ts | 4 ++-- 9 files changed, 34 insertions(+), 34 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index 63228717a5..d7572c2ac3 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -23,7 +23,7 @@ import { EntityKindFilter, EntityNamespaceFilter, EntityTagFilter, - EntityUserListFilter, + EntityUserFilter, } from '../../filters'; import { CatalogApi, @@ -263,7 +263,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: EntityUserListFilter.owned(ownershipEntityRefs), + user: EntityUserFilter.owned(ownershipEntityRefs), }), ); @@ -298,7 +298,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: EntityUserListFilter.starred([ + user: EntityUserFilter.starred([ 'component:default/e-1', 'component:default/e-2', ]), @@ -331,7 +331,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: EntityUserListFilter.all(), + user: EntityUserFilter.all(), }), ); @@ -352,7 +352,7 @@ describe('', () => { , ); expect(updateFilters).toHaveBeenLastCalledWith({ - user: EntityUserListFilter.owned(ownershipEntityRefs), + user: EntityUserFilter.owned(ownershipEntityRefs), }); }); @@ -437,7 +437,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: EntityUserListFilter.all(), + user: EntityUserFilter.all(), }), ); }); @@ -501,7 +501,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: EntityUserListFilter.all(), + user: EntityUserFilter.all(), }), ); }); @@ -529,7 +529,7 @@ describe('', () => { expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), ); expect(updateFilters).not.toHaveBeenCalledWith({ - user: EntityUserListFilter.all(), + user: EntityUserFilter.all(), }); }); @@ -542,7 +542,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: EntityUserListFilter.owned(expect.any(Array)), + user: EntityUserFilter.owned(expect.any(Array)), }), ); }); @@ -570,7 +570,7 @@ describe('', () => { expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(3), ); expect(updateFilters).not.toHaveBeenCalledWith({ - user: EntityUserListFilter.all(), + user: EntityUserFilter.all(), }); }); @@ -583,7 +583,7 @@ describe('', () => { await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ - user: EntityUserListFilter.starred([ + user: EntityUserFilter.starred([ 'component:default/e-1', 'component:default/e-2', ]), diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index b0a86b1322..854a1cb1b7 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -33,7 +33,7 @@ import { import SettingsIcon from '@material-ui/icons/Settings'; import StarIcon from '@material-ui/icons/Star'; import React, { Fragment, useEffect, useMemo, useState } from 'react'; -import { EntityUserListFilter } from '../../filters'; +import { EntityUserFilter } from '../../filters'; import { useEntityList } from '../../hooks'; import { UserListFilterKind } from '../../types'; import { useOwnedEntitiesCount } from './useOwnedEntitiesCount'; @@ -213,7 +213,7 @@ export const UserListPicker = (props: UserListPickerProps) => { if (selectedUserFilter === 'starred') { return starredEntitiesFilter; } - return EntityUserListFilter.all(); + return EntityUserFilter.all(); }; updateFilters({ user: getFilter() }); diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx index 6a79e63c8f..4ce3503394 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx @@ -32,7 +32,7 @@ import { useOwnedEntitiesCount } from './useOwnedEntitiesCount'; import { EntityNamespaceFilter, EntityOwnerFilter, - EntityUserListFilter, + EntityUserFilter, } from '../../filters'; import { useMountEffect } from '@react-hookz/web'; @@ -95,7 +95,7 @@ describe('useOwnedEntitiesCount', () => { expect(result.current).toEqual({ count: 0, loading: false, - filter: EntityUserListFilter.owned([ + filter: EntityUserFilter.owned([ 'user:default/spiderman', 'user:group/a-group', ]), @@ -131,7 +131,7 @@ describe('useOwnedEntitiesCount', () => { expect(result.current).toEqual({ count: 10, loading: false, - filter: EntityUserListFilter.owned([ + filter: EntityUserFilter.owned([ 'user:default/spiderman', 'user:group/a-group', ]), @@ -162,7 +162,7 @@ describe('useOwnedEntitiesCount', () => { expect(result.current).toEqual({ count: 0, loading: false, - filter: EntityUserListFilter.owned([ + filter: EntityUserFilter.owned([ 'user:default/spiderman', 'user:group/a-group', ]), @@ -202,7 +202,7 @@ describe('useOwnedEntitiesCount', () => { expect(result.current).toEqual({ count: 10, loading: false, - filter: EntityUserListFilter.owned([ + filter: EntityUserFilter.owned([ 'user:default/spiderman', 'user:group/a-group', ]), diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts index 605c006f44..d86610d9ae 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts @@ -20,7 +20,7 @@ import { compact, intersection, isEqual } from 'lodash'; import { useMemo, useRef } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; -import { EntityOwnerFilter, EntityUserListFilter } from '../../filters'; +import { EntityOwnerFilter, EntityUserFilter } from '../../filters'; import { useEntityList } from '../../hooks'; import { reduceCatalogFilters } from '../../utils'; @@ -82,7 +82,7 @@ export function useOwnedEntitiesCount() { const loading = loadingEntityRefs || loadingEntityOwnership; const filter = useMemo( - () => EntityUserListFilter.owned(ownershipEntityRefs ?? []), + () => EntityUserFilter.owned(ownershipEntityRefs ?? []), [ownershipEntityRefs], ); diff --git a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts index 93adad0489..6fa49d37a5 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts @@ -21,7 +21,7 @@ import { compact, isEqual } from 'lodash'; import { useMemo, useRef } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; -import { EntityUserListFilter } from '../../filters'; +import { EntityUserFilter } from '../../filters'; import { useEntityList, useStarredEntities } from '../../hooks'; import { reduceCatalogFilters } from '../../utils'; @@ -72,7 +72,7 @@ export function useStarredEntitiesCount() { }, [request, starredEntities]); const filter = useMemo( - () => EntityUserListFilter.starred(Array.from(starredEntities)), + () => EntityUserFilter.starred(Array.from(starredEntities)), [starredEntities], ); diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index 3d871fe412..55983d124b 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -203,22 +203,22 @@ export class EntityNamespaceFilter implements EntityFilter { /** * @public */ -export class EntityUserListFilter implements EntityFilter { +export class EntityUserFilter implements EntityFilter { private constructor( readonly value: UserListFilterKind, readonly refs?: string[], ) {} static owned(ownershipEntityRefs: string[]) { - return new EntityUserListFilter('owned', ownershipEntityRefs); + return new EntityUserFilter('owned', ownershipEntityRefs); } static all() { - return new EntityUserListFilter('all'); + return new EntityUserFilter('all'); } static starred(starredEntityRefs: string[]) { - return new EntityUserListFilter('starred', starredEntityRefs); + return new EntityUserFilter('starred', starredEntityRefs); } getCatalogFilters(): Record { @@ -259,7 +259,7 @@ export class EntityUserListFilter implements EntityFilter { /** * Filters entities based on whatever the user has starred or owns them. - * @deprecated use EntityUserListFilter + * @deprecated use EntityUserFilter * @public */ export class UserListFilter implements EntityFilter { diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index a4401e3441..edbfb65c0c 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -35,7 +35,7 @@ import { EntityKindPicker, UserListPicker } from '../components'; import { EntityKindFilter, EntityTypeFilter, - EntityUserListFilter, + EntityUserFilter, } from '../filters'; import { UserListFilterKind } from '../types'; import { EntityListProvider, useEntityList } from './useEntityListProvider'; @@ -155,7 +155,7 @@ describe('', () => { act(() => result.current.updateFilters({ - user: EntityUserListFilter.owned(ownershipEntityRefs), + user: EntityUserFilter.owned(ownershipEntityRefs), }), ); @@ -196,7 +196,7 @@ describe('', () => { act(() => result.current.updateFilters({ - user: EntityUserListFilter.owned(ownershipEntityRefs), + user: EntityUserFilter.owned(ownershipEntityRefs), }), ); diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index e2a8cfc657..948efc969f 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -41,7 +41,7 @@ import { EntityTypeFilter, UserListFilter, EntityNamespaceFilter, - EntityUserListFilter, + EntityUserFilter, } from '../filters'; import { EntityFilter } from '../types'; import { reduceBackendCatalogFilters, reduceEntityFilters } from '../utils'; @@ -51,7 +51,7 @@ import { useApi } from '@backstage/core-plugin-api'; export type DefaultEntityFilters = { kind?: EntityKindFilter; type?: EntityTypeFilter; - user?: UserListFilter | EntityUserListFilter; + user?: UserListFilter | EntityUserFilter; owners?: EntityOwnerFilter; lifecycles?: EntityLifecycleFilter; tags?: EntityTagFilter; diff --git a/plugins/catalog-react/src/utils/filters.ts b/plugins/catalog-react/src/utils/filters.ts index f2cfe64960..580d7b0b76 100644 --- a/plugins/catalog-react/src/utils/filters.ts +++ b/plugins/catalog-react/src/utils/filters.ts @@ -23,7 +23,7 @@ import { EntityOwnerFilter, EntityTagFilter, EntityTextFilter, - EntityUserListFilter, + EntityUserFilter, UserListFilter, } from '../filters'; @@ -57,7 +57,7 @@ export function reduceBackendCatalogFilters(filters: EntityFilter[]) { filter instanceof EntityOwnerFilter || filter instanceof EntityLifecycleFilter || filter instanceof EntityNamespaceFilter || - filter instanceof EntityUserListFilter || + filter instanceof EntityUserFilter || filter instanceof EntityOrphanFilter || filter instanceof EntityTextFilter || filter instanceof UserListFilter From 67ee8f155f74764e119856d2801702b48a59c9be Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 20 Oct 2023 08:19:36 +0200 Subject: [PATCH 318/348] catalog-react: add clarify comments Signed-off-by: Vincenzo Scamporlino --- .../UserListPicker/useStarredEntitiesCount.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts index 6fa49d37a5..f7b2b101f3 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts @@ -41,8 +41,17 @@ export function useStarredEntitiesCount() { const newRequest: QueryEntitiesInitialRequest = { filter: { ...filter, + /** + * here we are filtering entities by `name`. Given this filter, + * the response might contain more entities than expected, in case multiple entities + * of different kind or namespace share the same name. Those extra entities are filtered out + * client side by `EntityUserFilter`, so they won't be visible to the user. + */ [facet]: Array.from(starredEntities).map(e => parseEntityRef(e).name), }, + /** + * limit is set to a high value as we are not expecting many starred entities + */ limit: 1000, }; if (isEqual(newRequest, prevRequest.current)) { @@ -58,6 +67,12 @@ export function useStarredEntitiesCount() { return 0; } + /** + * given a list of starred entity refs and some filters coming from CatalogPage, + * it reduces the list of starred entities, to a list of entities that matches the + * provided filters. It won't be possible to getEntitiesByRefs + * as the method doesn't accept any filter. + */ const response = await catalogApi.queryEntities(request); return response.items From 4078bd73bbf7a9df06c8f3b5a6a169686dff9546 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 20 Oct 2023 13:16:46 +0200 Subject: [PATCH 319/348] catalog-react: fixes for react 18 Signed-off-by: Vincenzo Scamporlino --- .../UserListPicker/UserListPicker.test.tsx | 13 +++---- .../useAllEntitiesCount.test.tsx | 6 ++-- .../useOwnedEntitiesCount.test.tsx | 12 +++---- .../UserListPicker/useOwnedEntitiesCount.ts | 36 ++++++++++++++----- .../useStarredEntitiesCount.test.tsx | 29 ++++++++------- .../src/hooks/useStarredEntities.test.tsx | 3 +- .../src/hooks/useStarredEntity.test.tsx | 3 +- 7 files changed, 61 insertions(+), 41 deletions(-) diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index d7572c2ac3..ad56681d6c 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -142,6 +142,7 @@ describe('', () => { afterEach(() => { jest.resetAllMocks(); }); + it('renders filter groups', async () => { render( @@ -357,7 +358,7 @@ describe('', () => { }); describe('filter resetting', () => { - let updateFilters: jest.Mock; + const updateFilters = jest.fn(); const Picker = ({ ...props }: UserListPickerProps) => ( @@ -372,15 +373,9 @@ describe('', () => { ); - beforeEach(() => { - updateFilters = jest.fn(); - }); - describe(`when there are no owned entities matching the filter`, () => { it('does not reset the filter while entities are loading', async () => { - mockCatalogApi.queryEntities?.mockImplementation( - () => new Promise(() => {}), - ); + mockCatalogApi.queryEntities?.mockReturnValue(new Promise(() => {})); render(); @@ -388,7 +383,7 @@ describe('', () => { expect(mockCatalogApi.queryEntities).toHaveBeenCalled(), ); - await expect( + await expect(() => waitFor(() => expect(updateFilters).toHaveBeenCalled()), ).rejects.toThrow(); }); diff --git a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx index fc2c0e65bd..dc3bc5d2bd 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx @@ -16,7 +16,7 @@ import React, { PropsWithChildren } from 'react'; import { CatalogApi } from '@backstage/catalog-client'; import { useAllEntitiesCount } from './useAllEntitiesCount'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { EntityListProvider, useEntityList } from '../../hooks'; import { catalogApiRef } from '../../api'; import { ApiRef } from '@backstage/core-plugin-api'; @@ -61,7 +61,7 @@ describe('useAllEntitiesCount', () => { return <>{props.children}; } - const { result, waitFor } = renderHook(() => useAllEntitiesCount(), { + const { result } = renderHook(() => useAllEntitiesCount(), { wrapper: ({ children }) => ( @@ -89,7 +89,7 @@ describe('useAllEntitiesCount', () => { pageInfo: {}, }); - const { result, waitFor } = renderHook(() => useAllEntitiesCount(), { + const { result } = renderHook(() => useAllEntitiesCount(), { wrapper: ({ children }) => ( {children} diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx index 4ce3503394..1f6fbfd53d 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx @@ -15,7 +15,7 @@ */ import React, { PropsWithChildren } from 'react'; import { CatalogApi } from '@backstage/catalog-client'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { DefaultEntityFilters, EntityListProvider, @@ -82,7 +82,7 @@ describe('useOwnedEntitiesCount', () => { pageInfo: {}, }); - const { result, waitFor } = renderHook(() => useOwnedEntitiesCount(), { + const { result } = renderHook(() => useOwnedEntitiesCount(), { wrapper: createWrapperWithInitialFilters({}), }); @@ -110,7 +110,7 @@ describe('useOwnedEntitiesCount', () => { pageInfo: {}, }); - const { result, waitFor } = renderHook(() => useOwnedEntitiesCount(), { + const { result } = renderHook(() => useOwnedEntitiesCount(), { wrapper: createWrapperWithInitialFilters({ namespace: new EntityNamespaceFilter(['a-namespace']), }), @@ -139,14 +139,14 @@ describe('useOwnedEntitiesCount', () => { }); }); - it(`should return count 0 without invoking queryEntities if owners filter doesn't have claims on common with logged in user`, async () => { + it(`should return count 0 without invoking queryEntities if owners filter doesn't have claims in common with logged in user`, async () => { mockQueryEntities.mockResolvedValue({ items: [], totalItems: 10, pageInfo: {}, }); - const { result, waitFor } = renderHook(() => useOwnedEntitiesCount(), { + const { result } = renderHook(() => useOwnedEntitiesCount(), { wrapper: createWrapperWithInitialFilters({ namespace: new EntityNamespaceFilter(['a-namespace']), owners: new EntityOwnerFilter(['group:default/monsters']), @@ -177,7 +177,7 @@ describe('useOwnedEntitiesCount', () => { pageInfo: {}, }); - const { result, waitFor } = renderHook(() => useOwnedEntitiesCount(), { + const { result } = renderHook(() => useOwnedEntitiesCount(), { wrapper: createWrapperWithInitialFilters({ namespace: new EntityNamespaceFilter(['a-namespace']), owners: new EntityOwnerFilter([ diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts index d86610d9ae..1adab49361 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts @@ -17,12 +17,13 @@ import { QueryEntitiesInitialRequest } from '@backstage/catalog-client'; import { identityApiRef, useApi } from '@backstage/core-plugin-api'; import { compact, intersection, isEqual } from 'lodash'; -import { useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; import { EntityOwnerFilter, EntityUserFilter } from '../../filters'; import { useEntityList } from '../../hooks'; import { reduceCatalogFilters } from '../../utils'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; export function useOwnedEntitiesCount() { const identityApi = useApi(identityApiRef); @@ -71,14 +72,33 @@ export function useOwnedEntitiesCount() { return newRequest; }, [filters, ownershipEntityRefs]); - const { value: count, loading: loadingEntityOwnership } = - useAsync(async () => { - if (!request) { - return 0; + const [{ value: count, loading: loadingEntityOwnership }, fetchEntities] = + useAsyncFn( + async ( + req: QueryEntitiesInitialRequest | undefined, + ownershipEntityRefsParam: string[], + ) => { + if (ownershipEntityRefsParam && !req) { + // this implicitly means that there aren't claims in common with + // the logged in users, so avoid invoking the queryEntities endpoint + // which will implicitly returns 0 + return 0; + } + const { totalItems } = await catalogApi.queryEntities(req); + return totalItems; + }, + [], + { loading: true }, + ); + + useEffect(() => { + if (ownershipEntityRefs) { + if (request && Object.keys(request).length === 0) { + return; } - const { totalItems } = await catalogApi.queryEntities(request); - return totalItems; - }, [request]); + fetchEntities(request, ownershipEntityRefs); + } + }, [fetchEntities, request, ownershipEntityRefs]); const loading = loadingEntityRefs || loadingEntityOwnership; const filter = useMemo( diff --git a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.test.tsx index 1a02f3996b..5fe648e1bc 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.test.tsx @@ -20,7 +20,7 @@ import { catalogApiRef } from '../../api'; import { ApiRef } from '@backstage/core-plugin-api'; import { MemoryRouter } from 'react-router-dom'; import { useStarredEntitiesCount } from './useStarredEntitiesCount'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; const mockQueryEntities: jest.MockedFn = jest.fn(); const mockCatalogApi: jest.Mocked> = { @@ -75,7 +75,7 @@ describe('useStarredEntitiesCount', () => { pageInfo: {}, }); - const { result, waitFor } = renderHook(() => useStarredEntitiesCount(), { + const { result } = renderHook(() => useStarredEntitiesCount(), { wrapper: ({ children }) => ( {children} @@ -83,28 +83,31 @@ describe('useStarredEntitiesCount', () => { ), }); - await waitFor(() => + await waitFor(() => { expect(mockQueryEntities).toHaveBeenCalledWith({ filter: { 'metadata.name': ['favourite1', 'favourite2'], }, limit: 1000, - }), - ); - expect(result.current).toEqual({ - count: 2, - loading: false, - filter: { - refs: ['component:default/favourite1', 'component:default/favourite2'], - value: 'starred', - }, + }); + expect(result.current).toEqual({ + count: 2, + loading: false, + filter: { + refs: [ + 'component:default/favourite1', + 'component:default/favourite2', + ], + value: 'starred', + }, + }); }); }); it(`shouldn't invoke the endpoint if there are no starred entities`, async () => { mockStarredEntities.mockReturnValue(new Set()); - const { result, waitFor } = renderHook(() => useStarredEntitiesCount(), { + const { result } = renderHook(() => useStarredEntitiesCount(), { wrapper: ({ children }) => ( {children} diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx index e3010a0f4a..07738fd3d9 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx @@ -16,7 +16,8 @@ import { Entity } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook, waitFor } from '@testing-library/react'; +import { act, renderHook } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { starredEntitiesApiRef, diff --git a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx index e64a9bbdf8..44a4c7aaa3 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx @@ -16,7 +16,8 @@ import { Entity, CompoundEntityRef } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { renderHook, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; +import { renderHook } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import Observable from 'zen-observable'; import { StarredEntitiesApi, starredEntitiesApiRef } from '../apis'; From 89748e3c2dc5768cf9f1d6938d6a7acfbd8ee2c9 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 20 Oct 2023 15:53:34 +0200 Subject: [PATCH 320/348] catalog: wait for async operation Signed-off-by: Vincenzo Scamporlino --- .../src/components/CatalogPage/DefaultCatalogPage.test.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx index 53f031e263..0ced712344 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx @@ -320,10 +320,9 @@ describe('DefaultCatalogPage', () => { // Now that we've starred an entity, the "Starred" menu option should be // enabled. - expect(screen.getByTestId('user-picker-starred')).not.toHaveAttribute( - 'aria-disabled', - 'true', - ); + expect( + await screen.findByTestId('user-picker-starred'), + ).not.toHaveAttribute('aria-disabled', 'true'); fireEvent.click(screen.getByTestId('user-picker-starred')); await expect( screen.findByText(/Starred components \(1\)/), From ff2131abe3f39249a02f8e3f6bb17be2db2b3fe4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 20 Oct 2023 17:46:22 +0200 Subject: [PATCH 321/348] catalog-react: update API report Signed-off-by: Patrik Oldsberg --- plugins/catalog-react/api-report.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index e73441f7dc..7422440955 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -142,7 +142,7 @@ export const columnFactories: Readonly<{ export type DefaultEntityFilters = { kind?: EntityKindFilter; type?: EntityTypeFilter; - user?: UserListFilter | EntityUserListFilter; + user?: UserListFilter | EntityUserFilter; owners?: EntityOwnerFilter; lifecycles?: EntityLifecycleFilter; tags?: EntityTagFilter; @@ -508,19 +508,19 @@ export interface EntityTypePickerProps { } // @public (undocumented) -export class EntityUserListFilter implements EntityFilter { +export class EntityUserFilter implements EntityFilter { // (undocumented) - static all(): EntityUserListFilter; + static all(): EntityUserFilter; // (undocumented) filterEntity(entity: Entity): boolean; // (undocumented) getCatalogFilters(): Record; // (undocumented) - static owned(ownershipEntityRefs: string[]): EntityUserListFilter; + static owned(ownershipEntityRefs: string[]): EntityUserFilter; // (undocumented) readonly refs?: string[] | undefined; // (undocumented) - static starred(starredEntityRefs: string[]): EntityUserListFilter; + static starred(starredEntityRefs: string[]): EntityUserFilter; // (undocumented) toQueryValue(): string; // (undocumented) From bc9a18d5ecde14aea43cb2d75cc99f62de395090 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 21 Oct 2023 15:43:28 +0200 Subject: [PATCH 322/348] backend-app-api: double default wrapping workaround Signed-off-by: Patrik Oldsberg --- .changeset/strong-taxis-wait.md | 5 ++++ .../src/wiring/BackstageBackend.ts | 23 +++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 .changeset/strong-taxis-wait.md diff --git a/.changeset/strong-taxis-wait.md b/.changeset/strong-taxis-wait.md new file mode 100644 index 0000000000..13cfa9a1ba --- /dev/null +++ b/.changeset/strong-taxis-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Added a workaround for double `default` wrapping when dynamically importing CommonJS modules with default exports. diff --git a/packages/backend-app-api/src/wiring/BackstageBackend.ts b/packages/backend-app-api/src/wiring/BackstageBackend.ts index 2b916908de..d523481cf7 100644 --- a/packages/backend-app-api/src/wiring/BackstageBackend.ts +++ b/packages/backend-app-api/src/wiring/BackstageBackend.ts @@ -57,7 +57,26 @@ function isPromise(value: unknown | Promise): value is Promise { } function unwrapFeature( - feature: BackendFeature | (() => BackendFeature), + feature: + | BackendFeature + | (() => BackendFeature) + | { default: BackendFeature | (() => BackendFeature) }, ): BackendFeature { - return typeof feature === 'function' ? feature() : feature; + if (typeof feature === 'function') { + return feature(); + } + if ('$$type' in feature) { + return feature; + } + // This is a workaround where default exports get transpiled to `exports['default'] = ...` + // in CommonJS modules, which in turn results in a double `{ default: { default: ... } }` nesting + // when importing using a dynamic import. + // TODO: This is a broader issue than just this piece of code, and should move away from CommonJS. + if ('default' in feature) { + const defaultFeature = feature.default; + return typeof defaultFeature === 'function' + ? defaultFeature() + : defaultFeature; + } + return feature; } From 4ba4ac351f37ffec7e09059d12639dcd95497b19 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 21 Oct 2023 15:46:56 +0200 Subject: [PATCH 323/348] cli: switch to using tsx and module loader register API Signed-off-by: Patrik Oldsberg --- .changeset/dry-days-invite.md | 5 ++ packages/cli/package.json | 3 +- .../experimental/startBackendExperimental.ts | 9 ++- yarn.lock | 75 ++++++++++--------- 4 files changed, 52 insertions(+), 40 deletions(-) create mode 100644 .changeset/dry-days-invite.md diff --git a/.changeset/dry-days-invite.md b/.changeset/dry-days-invite.md new file mode 100644 index 0000000000..dcf052acd2 --- /dev/null +++ b/.changeset/dry-days-invite.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Switch from using deprecated `@esbuild-kit/*` packages to using `tsx`. This also switches to using the new module loader `register` API when available, avoiding the experimental warning when starting backends. diff --git a/packages/cli/package.json b/packages/cli/package.json index 419b02d929..9d8b8cfdaa 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -40,8 +40,6 @@ "@backstage/integration": "workspace:^", "@backstage/release-manifests": "workspace:^", "@backstage/types": "workspace:^", - "@esbuild-kit/cjs-loader": "^2.4.1", - "@esbuild-kit/esm-loader": "^2.5.5", "@manypkg/get-packages": "^1.1.3", "@octokit/graphql": "^5.0.0", "@octokit/graphql-schema": "^13.7.0", @@ -131,6 +129,7 @@ "swc-loader": "^0.2.3", "tar": "^6.1.12", "terser-webpack-plugin": "^5.1.3", + "tsx": "^3.14.0", "util": "^0.12.3", "webpack": "^5.70.0", "webpack-dev-server": "^4.7.3", diff --git a/packages/cli/src/lib/experimental/startBackendExperimental.ts b/packages/cli/src/lib/experimental/startBackendExperimental.ts index c4271deb3d..cc6d3a940e 100644 --- a/packages/cli/src/lib/experimental/startBackendExperimental.ts +++ b/packages/cli/src/lib/experimental/startBackendExperimental.ts @@ -27,11 +27,14 @@ import { isAbsolute as isAbsolutePath } from 'path'; import { paths } from '../paths'; import spawn from 'cross-spawn'; +const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(Number); +const supportsModuleLoaderRegister = nodeMajor >= 20 && nodeMinor >= 6; + const loaderArgs = [ '--require', - require.resolve('@esbuild-kit/cjs-loader'), - '--loader', - pathToFileURL(require.resolve('@esbuild-kit/esm-loader')).toString(), // Windows prefers a URL here + require.resolve('tsx/preflight'), + supportsModuleLoaderRegister ? '--import' : '--loader', + pathToFileURL(require.resolve('tsx')).toString(), // Windows prefers a URL here ]; export async function startBackendExperimental(options: BackendServeOptions) { diff --git a/yarn.lock b/yarn.lock index 3075745d85..0da2e78684 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3726,8 +3726,6 @@ __metadata: "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@backstage/types": "workspace:^" - "@esbuild-kit/cjs-loader": ^2.4.1 - "@esbuild-kit/esm-loader": ^2.5.5 "@manypkg/get-packages": ^1.1.3 "@octokit/graphql": ^5.0.0 "@octokit/graphql-schema": ^13.7.0 @@ -3837,6 +3835,7 @@ __metadata: tar: ^6.1.12 terser-webpack-plugin: ^5.1.3 ts-node: ^10.0.0 + tsx: ^3.14.0 type-fest: ^2.19.0 util: ^0.12.3 webpack: ^5.70.0 @@ -10641,36 +10640,6 @@ __metadata: languageName: node linkType: hard -"@esbuild-kit/cjs-loader@npm:^2.4.1": - version: 2.4.2 - resolution: "@esbuild-kit/cjs-loader@npm:2.4.2" - dependencies: - "@esbuild-kit/core-utils": ^3.0.0 - get-tsconfig: ^4.4.0 - checksum: e346e339bfc7eff5c52c270fd0ec06a7f2341b624adfb69f84b7d83f119c35070420906f2761a0b4604e0a0ec90e35eaf12544585476c428ed6d6ee3b250c0fe - languageName: node - linkType: hard - -"@esbuild-kit/core-utils@npm:^3.0.0, @esbuild-kit/core-utils@npm:^3.3.2": - version: 3.3.2 - resolution: "@esbuild-kit/core-utils@npm:3.3.2" - dependencies: - esbuild: ~0.18.20 - source-map-support: ^0.5.21 - checksum: 62f3b97457fa4ef39d752bd2ad1c8adac08929b50c411f5259f105cc74896f1fdb3429a540aa423e8eae37f32ef44656ca21ccb9a723cd9955d65a820960ab1f - languageName: node - linkType: hard - -"@esbuild-kit/esm-loader@npm:^2.5.5": - version: 2.6.5 - resolution: "@esbuild-kit/esm-loader@npm:2.6.5" - dependencies: - "@esbuild-kit/core-utils": ^3.3.2 - get-tsconfig: ^4.7.0 - checksum: 88a27203898f14bd69f03244ae2b3bae727e00243d7801292c4da8caba69813b0978fb8245a55b83bc9b907f475ed634f094a1f44cc590c0754993f4a924cc22 - languageName: node - linkType: hard - "@esbuild/android-arm64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/android-arm64@npm:0.16.17" @@ -26652,7 +26621,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:2.3.2, fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": +"fsevents@npm:2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" dependencies: @@ -26662,7 +26631,17 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@2.3.2#~builtin, fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin": +"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@2.3.2#~builtin": version: 2.3.2 resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7" dependencies: @@ -26671,6 +26650,15 @@ __metadata: languageName: node linkType: hard +"fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin, fsevents@patch:fsevents@~2.3.3#~builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=18f3a7" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + "function-bind@npm:^1.1.1": version: 1.1.1 resolution: "function-bind@npm:1.1.1" @@ -26861,7 +26849,7 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.4.0, get-tsconfig@npm:^4.7.0": +"get-tsconfig@npm:^4.7.2": version: 4.7.2 resolution: "get-tsconfig@npm:4.7.2" dependencies: @@ -40881,6 +40869,23 @@ __metadata: languageName: node linkType: hard +"tsx@npm:^3.14.0": + version: 3.14.0 + resolution: "tsx@npm:3.14.0" + dependencies: + esbuild: ~0.18.20 + fsevents: ~2.3.3 + get-tsconfig: ^4.7.2 + source-map-support: ^0.5.21 + dependenciesMeta: + fsevents: + optional: true + bin: + tsx: dist/cli.mjs + checksum: afcef5d9b90b5800cf1ffb749e943f63042d78a4c0d9eef6e13e43f4ecab465d45e2c9812a2c515cbdc2ee913ff1cd01bf5c606a48013dd3ce2214a631b45557 + languageName: node + linkType: hard + "tty-browserify@npm:0.0.0": version: 0.0.0 resolution: "tty-browserify@npm:0.0.0" From 26ca97ebaa6adc6e334b0682e61fc6ac3ff6e70d Mon Sep 17 00:00:00 2001 From: parmar-abhinav Date: Sat, 21 Oct 2023 19:51:47 +0530 Subject: [PATCH 324/348] Add examples for gitlab:projectAccessToken:create scaffolder action Signed-off-by: parmar-abhinav --- .changeset/wicked-ties-knock.md | 5 + .../package.json | 1 + ...bProjectAccessTokenAction.examples.test.ts | 303 ++++++++++++++++++ ...GitlabProjectAccessTokenAction.examples.ts | 104 ++++++ .../createGitlabProjectAccessTokenAction.ts | 2 + yarn.lock | 1 + 6 files changed, 416 insertions(+) create mode 100644 .changeset/wicked-ties-knock.md create mode 100644 plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.test.ts create mode 100644 plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.ts diff --git a/.changeset/wicked-ties-knock.md b/.changeset/wicked-ties-knock.md new file mode 100644 index 0000000000..582cb905d0 --- /dev/null +++ b/.changeset/wicked-ties-knock.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-gitlab': patch +--- + +Add examples for `gitlab:projectAccessToken:create` scaffolder action & improve related tests diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index 99c84ed4b9..deecc3b333 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -36,6 +36,7 @@ "@backstage/integration": "workspace:^", "@backstage/plugin-scaffolder-node": "workspace:^", "@gitbeaker/node": "^35.8.0", + "yaml": "^2.0.0", "zod": "^3.21.4" }, "devDependencies": { diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.test.ts new file mode 100644 index 0000000000..6a809fc386 --- /dev/null +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.test.ts @@ -0,0 +1,303 @@ +/* + * Copyright 2023 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 yaml from 'yaml'; +import { createGitlabProjectAccessTokenAction } from './createGitlabProjectAccessTokenAction'; // Adjust the import based on your project structure +import { ScmIntegrations } from '@backstage/integration'; +import { ConfigReader } from '@backstage/config'; +import { getVoidLogger } from '@backstage/backend-common'; +import { PassThrough } from 'stream'; +import { examples } from './createGitlabProjectAccessTokenAction.examples'; + +jest.mock('node-fetch'); + +const mockGitlabClient = { + ProjectDeployTokens: { + create: jest.fn(), + }, +}; + +jest.mock('@gitbeaker/node', () => ({ + Gitlab: class { + constructor() { + return mockGitlabClient; + } + }, +})); + +describe('gitlab:projectAccessToken:create examples', () => { + const config = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'tokenlols', + apiBaseUrl: 'https://api.gitlab.com', + }, + { + host: 'hosted.gitlab.com', + apiBaseUrl: 'https://api.hosted.gitlab.com', + }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + const action = createGitlabProjectAccessTokenAction({ integrations }); + + const mockContext = { + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + }, + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('Create a GitLab project access token with minimal options.', async () => { + const fetchMock = jest.spyOn(global, 'fetch'); + const mockResponse = { + token: 'mock-access-token', + }; + + fetchMock.mockResolvedValue({ + json: async () => mockResponse, + } as Response); + + jest.mock('../util', () => ({ + getToken: jest.fn().mockReturnValue({ + token: 'mock-api-token', + integrationConfig: { config: { baseUrl: 'https://api.gitlab.com' } }, + }), + })); + + const input = yaml.parse(examples[0].example).steps[0].input; + + await action.handler({ + ...mockContext, + input, + }); + + expect(fetchMock).toHaveBeenCalledWith( + 'https://gitlab.com/api/v4/projects/456/access_tokens', + { + method: 'POST', + headers: { + 'PRIVATE-TOKEN': 'tokenlols', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: undefined, + scopes: undefined, + access_level: undefined, + }), + }, + ); + expect(mockContext.output).toHaveBeenCalledWith( + 'access_token', + 'mock-access-token', + ); + }); + + it('Create a GitLab project access token with custom scopes.', async () => { + const input = yaml.parse(examples[1].example).steps[0].input; + + const mockResponse = { + token: 'mock-access-token', + }; + + const fetchMock = jest.spyOn(global, 'fetch'); + fetchMock.mockResolvedValue({ + json: async () => mockResponse, + } as Response); + + jest.mock('../util', () => ({ + getToken: jest.fn().mockReturnValue({ + token: 'mock-api-token', + integrationConfig: { config: { baseUrl: 'https://api.gitlab.com' } }, + }), + })); + + await action.handler({ + ...mockContext, + input, + }); + + expect(fetchMock).toHaveBeenCalledWith( + 'https://gitlab.com/api/v4/projects/789/access_tokens', + { + method: 'POST', + headers: { + 'PRIVATE-TOKEN': 'tokenlols', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: undefined, + scopes: ['read_registry', 'write_repository'], + access_level: undefined, + }), + }, + ); + + expect(mockContext.output).toHaveBeenCalledWith( + 'access_token', + 'mock-access-token', + ); + }); + + it('Create a GitLab project access token with a specified name.', async () => { + const input = yaml.parse(examples[2].example).steps[0].input; + + const mockResponse = { + token: 'mock-access-token', + }; + + const fetchMock = jest.spyOn(global, 'fetch'); + fetchMock.mockResolvedValue({ + json: async () => mockResponse, + } as Response); + + jest.mock('../util', () => ({ + getToken: jest.fn().mockReturnValue({ + token: 'mock-api-token', + integrationConfig: { config: { baseUrl: 'https://api.gitlab.com' } }, + }), + })); + + await action.handler({ + ...mockContext, + input, + }); + + expect(fetchMock).toHaveBeenCalledWith( + 'https://gitlab.com/api/v4/projects/101112/access_tokens', + { + method: 'POST', + headers: { + 'PRIVATE-TOKEN': 'tokenlols', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: 'my-custom-token', + scopes: undefined, + access_level: undefined, + }), + }, + ); + + expect(mockContext.output).toHaveBeenCalledWith( + 'access_token', + 'mock-access-token', + ); + }); + + it('Create a GitLab project access token with a numeric project ID.', async () => { + const input = yaml.parse(examples[3].example).steps[0].input; + + const mockResponse = { + token: 'mock-access-token', + }; + + const fetchMock = jest.spyOn(global, 'fetch'); + fetchMock.mockResolvedValue({ + json: async () => mockResponse, + } as Response); + + jest.mock('../util', () => ({ + getToken: jest.fn().mockReturnValue({ + token: 'mock-api-token', + integrationConfig: { config: { baseUrl: 'https://api.gitlab.com' } }, + }), + })); + + await action.handler({ + ...mockContext, + input, + }); + + expect(fetchMock).toHaveBeenCalledWith( + 'https://gitlab.com/api/v4/projects/42/access_tokens', + { + method: 'POST', + headers: { + 'PRIVATE-TOKEN': 'tokenlols', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: undefined, + scopes: undefined, + access_level: undefined, + }), + }, + ); + + expect(mockContext.output).toHaveBeenCalledWith( + 'access_token', + 'mock-access-token', + ); + }); + + it('Create a GitLab project access token using specific GitLab integrations.', async () => { + const input = yaml.parse(examples[4].example).steps[0].input; + + const mockResponse = { + token: 'mock-access-token', + }; + + const fetchMock = jest.spyOn(global, 'fetch'); + fetchMock.mockResolvedValue({ + json: async () => mockResponse, + } as Response); + + jest.mock('../util', () => ({ + getToken: jest.fn().mockReturnValue({ + token: 'mock-api-token', + integrationConfig: { config: { baseUrl: 'https://api.gitlab.com' } }, + }), + })); + + await action.handler({ + ...mockContext, + input, + }); + + expect(fetchMock).toHaveBeenCalledWith( + 'https://gitlab.com/api/v4/projects/123/access_tokens', + { + method: 'POST', + headers: { + 'PRIVATE-TOKEN': 'tokenlols', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: undefined, + scopes: undefined, + access_level: undefined, + }), + }, + ); + + expect(mockContext.output).toHaveBeenCalledWith( + 'access_token', + 'mock-access-token', + ); + }); +}); diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.ts new file mode 100644 index 0000000000..5fe157badf --- /dev/null +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.ts @@ -0,0 +1,104 @@ +/* + * Copyright 2023 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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: 'Create a GitLab project access token with minimal options.', + example: yaml.stringify({ + steps: [ + { + id: 'createAccessToken', + action: 'gitlab:projectAccessToken:create', + name: 'Create GitLab Project Access Token', + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + projectId: '456', + }, + }, + ], + }), + }, + { + description: 'Create a GitLab project access token with custom scopes.', + example: yaml.stringify({ + steps: [ + { + id: 'createAccessToken', + action: 'gitlab:projectAccessToken:create', + name: 'Create GitLab Project Access Token', + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + projectId: '789', + scopes: ['read_registry', 'write_repository'], + }, + }, + ], + }), + }, + { + description: 'Create a GitLab project access token with a specified name.', + example: yaml.stringify({ + steps: [ + { + id: 'createAccessToken', + action: 'gitlab:projectAccessToken:create', + name: 'Create GitLab Project Access Token', + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + projectId: '101112', + name: 'my-custom-token', + }, + }, + ], + }), + }, + { + description: + 'Create a GitLab project access token with a numeric project ID.', + example: yaml.stringify({ + steps: [ + { + id: 'createAccessToken', + action: 'gitlab:projectAccessToken:create', + name: 'Create GitLab Project Access Token', + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + projectId: 42, + }, + }, + ], + }), + }, + { + description: + 'Create a GitLab project access token using specific GitLab integrations.', + example: yaml.stringify({ + steps: [ + { + id: 'createAccessToken', + action: 'gitlab:projectAccessToken:create', + name: 'Create GitLab Project Access Token', + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + projectId: '123', + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.ts index 614de0e221..a050b3c1b4 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.ts @@ -19,6 +19,7 @@ import { ScmIntegrationRegistry } from '@backstage/integration'; import commonGitlabConfig from '../commonGitlabConfig'; import { getToken } from '../util'; import { z } from 'zod'; +import { examples } from './createGitlabProjectAccessTokenAction.examples'; /** * Creates a `gitlab:projectAccessToken:create` Scaffolder action. @@ -32,6 +33,7 @@ export const createGitlabProjectAccessTokenAction = (options: { const { integrations } = options; return createTemplateAction({ id: 'gitlab:projectAccessToken:create', + examples, schema: { input: commonGitlabConfig.merge( z.object({ diff --git a/yarn.lock b/yarn.lock index 059c18d859..2ad8f4458e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8487,6 +8487,7 @@ __metadata: "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" "@gitbeaker/node": ^35.8.0 + yaml: ^2.0.0 zod: ^3.21.4 languageName: unknown linkType: soft From 0a7c9ede2e7203bde1168a994972c9e57e342af4 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 21 Oct 2023 10:41:32 -0500 Subject: [PATCH 325/348] Refactored to use positive return Signed-off-by: Andre Wanlin --- .../getAnnotationValuesFromEntity.test.ts | 12 ++--- .../utils/getAnnotationValuesFromEntity.ts | 54 ++++++------------- 2 files changed, 22 insertions(+), 44 deletions(-) diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts index 0d7a11f48b..a5d3725716 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts @@ -61,7 +61,7 @@ describe('getAnnotationValuesFromEntity', () => { }; expect(test).toThrow( - 'Value for annotation dev.azure.com/project-repo was not in the correct format: /', + 'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: /, found: "project"', ); }); }); @@ -85,7 +85,7 @@ describe('getAnnotationValuesFromEntity', () => { }; expect(test).toThrow( - 'Project Name for annotation dev.azure.com/project-repo was not found; expected format is: /', + 'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: /, found: "/repo"', ); }); }); @@ -109,7 +109,7 @@ describe('getAnnotationValuesFromEntity', () => { }; expect(test).toThrow( - 'Repo Name for annotation dev.azure.com/project-repo was not found; expected format is: /', + 'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: /, found: "project/"', ); }); }); @@ -255,7 +255,7 @@ describe('getAnnotationValuesFromEntity', () => { }; expect(test).toThrow( - 'Value for annotation dev.azure.com/host-org was not in the correct format: /', + 'Invalid value for annotation "dev.azure.com/host-org"; expected format is: /, found: "host"', ); }); }); @@ -279,7 +279,7 @@ describe('getAnnotationValuesFromEntity', () => { }; expect(test).toThrow( - 'Host for annotation dev.azure.com/host-org was not found; expected format is: /', + 'Invalid value for annotation "dev.azure.com/host-org"; expected format is: /, found: "/org"', ); }); }); @@ -303,7 +303,7 @@ describe('getAnnotationValuesFromEntity', () => { }; expect(test).toThrow( - 'Organization for annotation dev.azure.com/host-org was not found; expected format is: /', + 'Invalid value for annotation "dev.azure.com/host-org"; expected format is: /, found: "host/"', ); }); }); diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts index 7099352524..99b194a834 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts @@ -69,27 +69,16 @@ function getProjectRepo(annotations?: Record): { return { project: undefined, repo: undefined }; } - if (!annotation.includes('/')) { - throw new Error( - `Value for annotation ${AZURE_DEVOPS_REPO_ANNOTATION} was not in the correct format: /`, - ); + if (annotation.includes('/')) { + const [project, repo] = annotation.split('/'); + if (project && repo) { + return { project, repo }; + } } - const [project, repo] = annotation.split('/'); - - if (!project) { - throw new Error( - `Project Name for annotation ${AZURE_DEVOPS_REPO_ANNOTATION} was not found; expected format is: /`, - ); - } - - if (!repo) { - throw new Error( - `Repo Name for annotation ${AZURE_DEVOPS_REPO_ANNOTATION} was not found; expected format is: /`, - ); - } - - return { project, repo }; + throw new Error( + `Invalid value for annotation "${AZURE_DEVOPS_REPO_ANNOTATION}"; expected format is: /, found: "${annotation}"`, + ); } function getHostOrg(annotations?: Record): { @@ -101,25 +90,14 @@ function getHostOrg(annotations?: Record): { return { host: undefined, org: undefined }; } - if (!annotation.includes('/')) { - throw new Error( - `Value for annotation ${AZURE_DEVOPS_HOST_ORG_ANNOTATION} was not in the correct format: /`, - ); + if (annotation.includes('/')) { + const [host, org] = annotation.split('/'); + if (host && org) { + return { host, org }; + } } - const [host, org] = annotation.split('/'); - - if (!host) { - throw new Error( - `Host for annotation ${AZURE_DEVOPS_HOST_ORG_ANNOTATION} was not found; expected format is: /`, - ); - } - - if (!org) { - throw new Error( - `Organization for annotation ${AZURE_DEVOPS_HOST_ORG_ANNOTATION} was not found; expected format is: /`, - ); - } - - return { host, org }; + throw new Error( + `Invalid value for annotation "${AZURE_DEVOPS_HOST_ORG_ANNOTATION}"; expected format is: /, found: "${annotation}"`, + ); } From 5578328e57908f4e0b4a809234b311688ad41fe3 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 21 Oct 2023 12:14:10 -0500 Subject: [PATCH 326/348] Added tests for changed hooks Signed-off-by: Andre Wanlin --- .../src/hooks/useGitTags.test.tsx | 130 ++++++++++++++++++ plugins/azure-devops/src/hooks/useGitTags.ts | 5 +- .../src/hooks/usePullRequests.test.tsx | 129 +++++++++++++++++ .../azure-devops/src/hooks/usePullRequests.ts | 5 +- .../src/hooks/useRepoBuilds.test.tsx | 126 +++++++++++++++++ .../azure-devops/src/hooks/useRepoBuilds.ts | 5 +- .../getAnnotationValuesFromEntity.test.ts | 4 +- .../utils/getAnnotationValuesFromEntity.ts | 4 +- 8 files changed, 392 insertions(+), 16 deletions(-) create mode 100644 plugins/azure-devops/src/hooks/useGitTags.test.tsx create mode 100644 plugins/azure-devops/src/hooks/usePullRequests.test.tsx create mode 100644 plugins/azure-devops/src/hooks/useRepoBuilds.test.tsx diff --git a/plugins/azure-devops/src/hooks/useGitTags.test.tsx b/plugins/azure-devops/src/hooks/useGitTags.test.tsx new file mode 100644 index 0000000000..1a5620e16e --- /dev/null +++ b/plugins/azure-devops/src/hooks/useGitTags.test.tsx @@ -0,0 +1,130 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { renderHook, waitFor } from '@testing-library/react'; +import { useGitTags } from './useGitTags'; +import { Entity } from '@backstage/catalog-model'; +import { GitTag } from '@backstage/plugin-azure-devops-common'; +import { TestApiProvider } from '@backstage/test-utils'; +import { AzureDevOpsApi, azureDevOpsApiRef } from '../api'; + +describe('useGitTags', () => { + const azureDevOpsApiMock = { + getGitTags: jest.fn(), + }; + const azureDevOpsApi = + azureDevOpsApiMock as Partial as AzureDevOpsApi; + + const Wrapper = (props: { children?: React.ReactNode }) => ( + + {props.children} + + ); + + it('should provide an array of GitTag', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'projectName/repoName', + }, + }, + }; + const tags: GitTag[] = [ + { + objectId: 'tag-1', + peeledObjectId: 'tag-1', + name: 'tag-1', + createdBy: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + commitLink: 'https://dev.azure.com/org/project/repo/commit-sha-1', + }, + { + objectId: 'tag-2', + peeledObjectId: 'tag-2', + name: 'tag-2', + createdBy: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + commitLink: 'https://dev.azure.com/org/project/repo/commit-sha-2', + }, + { + objectId: 'tag-3', + peeledObjectId: 'tag-3', + name: 'tag-3', + createdBy: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + commitLink: 'https://dev.azure.com/org/project/repo/commit-sha-3', + }, + ]; + azureDevOpsApiMock.getGitTags.mockResolvedValue({ items: tags }); + const { result } = renderHook(() => useGitTags(entity), { + wrapper: Wrapper, + }); + + expect(result.current.loading).toEqual(true); + + await waitFor(() => { + expect(result.current).toEqual({ + error: undefined, + items: tags, + loading: false, + }); + }); + }); + + it('should return throw when annotation missing', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + }, + }; + + expect(() => + renderHook(() => useGitTags(entity), { + wrapper: Wrapper, + }), + ).toThrow('Value for annotation "dev.azure.com/project" was not found'); + }); + + it('should return throw when annotation invalid', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'fake', + }, + }, + }; + + expect(() => + renderHook(() => useGitTags(entity), { + wrapper: Wrapper, + }), + ).toThrow( + 'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: /, found: "fake"', + ); + }); +}); diff --git a/plugins/azure-devops/src/hooks/useGitTags.ts b/plugins/azure-devops/src/hooks/useGitTags.ts index f36f9224aa..13c7118934 100644 --- a/plugins/azure-devops/src/hooks/useGitTags.ts +++ b/plugins/azure-devops/src/hooks/useGitTags.ts @@ -31,10 +31,7 @@ export function useGitTags(entity: Entity): { const { project, repo } = getAnnotationValuesFromEntity(entity); const { value, loading, error } = useAsync(async () => { - if (repo) { - return await api.getGitTags(project, repo); - } - return undefined; + return await api.getGitTags(project, repo as string); }, [api, project, repo]); return { diff --git a/plugins/azure-devops/src/hooks/usePullRequests.test.tsx b/plugins/azure-devops/src/hooks/usePullRequests.test.tsx new file mode 100644 index 0000000000..3e51c003e6 --- /dev/null +++ b/plugins/azure-devops/src/hooks/usePullRequests.test.tsx @@ -0,0 +1,129 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { renderHook, waitFor } from '@testing-library/react'; +import { Entity } from '@backstage/catalog-model'; +import { PullRequest } from '@backstage/plugin-azure-devops-common'; +import { TestApiProvider } from '@backstage/test-utils'; +import { AzureDevOpsApi, azureDevOpsApiRef } from '../api'; +import { usePullRequests } from './usePullRequests'; + +describe('usePullRequests', () => { + const azureDevOpsApiMock = { + getPullRequests: jest.fn(), + }; + const azureDevOpsApi = + azureDevOpsApiMock as Partial as AzureDevOpsApi; + + const Wrapper = (props: { children?: React.ReactNode }) => ( + + {props.children} + + ); + + it('should provide an array of PullRequest', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'projectName/repoName', + }, + }, + }; + const pullRequests: PullRequest[] = [ + { + pullRequestId: 1, + repoName: 'repo', + title: 'title-1', + createdBy: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + }, + { + pullRequestId: 2, + repoName: 'repo', + title: 'title-2', + createdBy: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + }, + { + pullRequestId: 3, + repoName: 'repo', + title: 'title-3', + createdBy: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + }, + ]; + azureDevOpsApiMock.getPullRequests.mockResolvedValue({ + items: pullRequests, + }); + const { result } = renderHook(() => usePullRequests(entity), { + wrapper: Wrapper, + }); + + expect(result.current.loading).toEqual(true); + + await waitFor(() => { + expect(result.current).toEqual({ + error: undefined, + items: pullRequests, + loading: false, + }); + }); + }); + + it('should return throw when annotation missing', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + }, + }; + + expect(() => + renderHook(() => usePullRequests(entity), { + wrapper: Wrapper, + }), + ).toThrow('Value for annotation "dev.azure.com/project" was not found'); + }); + + it('should return throw when annotation invalid', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'fake', + }, + }, + }; + + expect(() => + renderHook(() => usePullRequests(entity), { + wrapper: Wrapper, + }), + ).toThrow( + 'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: /, found: "fake"', + ); + }); +}); diff --git a/plugins/azure-devops/src/hooks/usePullRequests.ts b/plugins/azure-devops/src/hooks/usePullRequests.ts index c412836ae5..c4223871f2 100644 --- a/plugins/azure-devops/src/hooks/usePullRequests.ts +++ b/plugins/azure-devops/src/hooks/usePullRequests.ts @@ -47,10 +47,7 @@ export function usePullRequests( const { project, repo } = getAnnotationValuesFromEntity(entity); const { value, loading, error } = useAsync(async () => { - if (repo) { - return await api.getPullRequests(project, repo, options); - } - return undefined; + return await api.getPullRequests(project, repo as string, options); }, [api, project, repo, top, status]); return { diff --git a/plugins/azure-devops/src/hooks/useRepoBuilds.test.tsx b/plugins/azure-devops/src/hooks/useRepoBuilds.test.tsx new file mode 100644 index 0000000000..99eaeb1ce3 --- /dev/null +++ b/plugins/azure-devops/src/hooks/useRepoBuilds.test.tsx @@ -0,0 +1,126 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { renderHook, waitFor } from '@testing-library/react'; +import { Entity } from '@backstage/catalog-model'; +import { RepoBuild } from '@backstage/plugin-azure-devops-common'; +import { TestApiProvider } from '@backstage/test-utils'; +import { AzureDevOpsApi, azureDevOpsApiRef } from '../api'; +import { useRepoBuilds } from './useRepoBuilds'; + +describe('useRepoBuilds', () => { + const azureDevOpsApiMock = { + getRepoBuilds: jest.fn(), + }; + const azureDevOpsApi = + azureDevOpsApiMock as Partial as AzureDevOpsApi; + + const Wrapper = (props: { children?: React.ReactNode }) => ( + + {props.children} + + ); + + it('should provide an array of RepoBuild', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'projectName/repoName', + }, + }, + }; + const repoBuilds: RepoBuild[] = [ + { + id: 1, + title: 'title-1', + source: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + }, + { + id: 2, + title: 'title-2', + source: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + }, + { + id: 3, + title: 'title-3', + source: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + }, + ]; + azureDevOpsApiMock.getRepoBuilds.mockResolvedValue({ + items: repoBuilds, + }); + const { result } = renderHook(() => useRepoBuilds(entity), { + wrapper: Wrapper, + }); + + expect(result.current.loading).toEqual(true); + + await waitFor(() => { + expect(result.current).toEqual({ + error: undefined, + items: repoBuilds, + loading: false, + }); + }); + }); + + it('should return throw when annotation missing', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + }, + }; + + expect(() => + renderHook(() => useRepoBuilds(entity), { + wrapper: Wrapper, + }), + ).toThrow('Value for annotation "dev.azure.com/project" was not found'); + }); + + it('should return throw when annotation invalid', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'fake', + }, + }, + }; + + expect(() => + renderHook(() => useRepoBuilds(entity), { + wrapper: Wrapper, + }), + ).toThrow( + 'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: /, found: "fake"', + ); + }); +}); diff --git a/plugins/azure-devops/src/hooks/useRepoBuilds.ts b/plugins/azure-devops/src/hooks/useRepoBuilds.ts index 4ba88bd5fb..9292a6e035 100644 --- a/plugins/azure-devops/src/hooks/useRepoBuilds.ts +++ b/plugins/azure-devops/src/hooks/useRepoBuilds.ts @@ -43,10 +43,7 @@ export function useRepoBuilds( const { project, repo } = getAnnotationValuesFromEntity(entity); const { value, loading, error } = useAsync(async () => { - if (repo) { - return await api.getRepoBuilds(project, repo, options); - } - return undefined; + return await api.getRepoBuilds(project, repo as string, options); }, [api, project, repo, entity]); return { diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts index a5d3725716..67e46cee7b 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.test.ts @@ -157,7 +157,7 @@ describe('getAnnotationValuesFromEntity', () => { }; expect(test).toThrow( - 'Value for annotation dev.azure.com/build-definition was not found', + 'Value for annotation "dev.azure.com/build-definition" was not found', ); }); }); @@ -180,7 +180,7 @@ describe('getAnnotationValuesFromEntity', () => { }; expect(test).toThrow( - 'Value for annotation dev.azure.com/project was not found', + 'Value for annotation "dev.azure.com/project" was not found', ); }); }); diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts index 99b194a834..9feec8bf95 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts @@ -46,7 +46,7 @@ export function getAnnotationValuesFromEntity(entity: Entity): { entity.metadata.annotations?.[AZURE_DEVOPS_PROJECT_ANNOTATION]; if (!project) { throw new Error( - `Value for annotation ${AZURE_DEVOPS_PROJECT_ANNOTATION} was not found`, + `Value for annotation "${AZURE_DEVOPS_PROJECT_ANNOTATION}" was not found`, ); } @@ -54,7 +54,7 @@ export function getAnnotationValuesFromEntity(entity: Entity): { entity.metadata.annotations?.[AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION]; if (!definition) { throw new Error( - `Value for annotation ${AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION} was not found`, + `Value for annotation "${AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION}" was not found`, ); } return { project, definition, host, org }; From c0bb5117955f0f203d5be00e31462042c5bfb75b Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 21 Oct 2023 15:18:30 -0500 Subject: [PATCH 327/348] Refactor Readme into hook Signed-off-by: Andre Wanlin --- .../src/components/ReadmeCard/ReadmeCard.tsx | 15 +-- plugins/azure-devops/src/hooks/index.ts | 1 + .../azure-devops/src/hooks/useReadme.test.tsx | 108 ++++++++++++++++++ plugins/azure-devops/src/hooks/useReadme.ts | 42 +++++++ 4 files changed, 154 insertions(+), 12 deletions(-) create mode 100644 plugins/azure-devops/src/hooks/useReadme.test.tsx create mode 100644 plugins/azure-devops/src/hooks/useReadme.ts diff --git a/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx b/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx index d9afe8db5a..420fe6ecf4 100644 --- a/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx +++ b/plugins/azure-devops/src/components/ReadmeCard/ReadmeCard.tsx @@ -23,11 +23,9 @@ import { ErrorPanel, } from '@backstage/core-components'; import { useEntity } from '@backstage/plugin-catalog-react'; -import { useApi } from '@backstage/core-plugin-api'; import React from 'react'; -import { azureDevOpsApiRef } from '../../api'; -import useAsync from 'react-use/lib/useAsync'; -import { getAnnotationValuesFromEntity } from '../../utils'; + +import { useReadme } from '../../hooks'; const useStyles = makeStyles(theme => ({ readMe: { @@ -85,16 +83,9 @@ const ReadmeCardError = ({ error }: ErrorProps) => { export const ReadmeCard = (props: Props) => { const classes = useStyles(); - const api = useApi(azureDevOpsApiRef); const { entity } = useEntity(); - const { project, repo } = getAnnotationValuesFromEntity(entity); - const { loading, error, value } = useAsync(async () => { - if (repo) { - return await api.getReadme({ project, repo }); - } - return undefined; - }, [api, project, repo, entity]); + const { loading, error, item: value } = useReadme(entity); if (loading) { return ; diff --git a/plugins/azure-devops/src/hooks/index.ts b/plugins/azure-devops/src/hooks/index.ts index 0b745ba586..ab1a3c9998 100644 --- a/plugins/azure-devops/src/hooks/index.ts +++ b/plugins/azure-devops/src/hooks/index.ts @@ -20,3 +20,4 @@ export * from './usePullRequests'; export * from './useRepoBuilds'; export * from './useUserEmail'; export * from './useUserTeamIds'; +export * from './useReadme'; diff --git a/plugins/azure-devops/src/hooks/useReadme.test.tsx b/plugins/azure-devops/src/hooks/useReadme.test.tsx new file mode 100644 index 0000000000..ffc33c136b --- /dev/null +++ b/plugins/azure-devops/src/hooks/useReadme.test.tsx @@ -0,0 +1,108 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { renderHook, waitFor } from '@testing-library/react'; +import { Entity } from '@backstage/catalog-model'; +import { Readme } from '@backstage/plugin-azure-devops-common'; +import { TestApiProvider } from '@backstage/test-utils'; +import { AzureDevOpsApi, azureDevOpsApiRef } from '../api'; +import { useReadme } from './useReadme'; + +describe('useReadme', () => { + const azureDevOpsApiMock = { + getReadme: jest.fn(), + }; + const azureDevOpsApi = + azureDevOpsApiMock as Partial as AzureDevOpsApi; + + const Wrapper = (props: { children?: React.ReactNode }) => ( + + {props.children} + + ); + + it('should provide a Readme', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'projectName/repoName', + }, + }, + }; + const readme: Readme = { + url: 'https://dev.azure.com/org/project/repo', + content: 'This is some fake README content', + }; + azureDevOpsApiMock.getReadme.mockResolvedValue({ + item: readme, + }); + const { result } = renderHook(() => useReadme(entity), { + wrapper: Wrapper, + }); + + expect(result.current.loading).toEqual(true); + + await waitFor(() => { + expect(result.current.item).toEqual({ + item: readme, + }); + }); + }); + + it('should return throw when annotation missing', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + }, + }; + + expect(() => + renderHook(() => useReadme(entity), { + wrapper: Wrapper, + }), + ).toThrow('Value for annotation "dev.azure.com/project" was not found'); + }); + + it('should return throw when annotation invalid', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'fake', + }, + }, + }; + + expect(() => + renderHook(() => useReadme(entity), { + wrapper: Wrapper, + }), + ).toThrow( + 'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: /, found: "fake"', + ); + }); +}); diff --git a/plugins/azure-devops/src/hooks/useReadme.ts b/plugins/azure-devops/src/hooks/useReadme.ts new file mode 100644 index 0000000000..60b2e21990 --- /dev/null +++ b/plugins/azure-devops/src/hooks/useReadme.ts @@ -0,0 +1,42 @@ +/* + * 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 { Readme } from '@backstage/plugin-azure-devops-common'; + +import { Entity } from '@backstage/catalog-model'; +import { azureDevOpsApiRef } from '../api'; +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; +import { getAnnotationValuesFromEntity } from '../utils'; + +export function useReadme(entity: Entity): { + item?: Readme; + loading: boolean; + error?: Error; +} { + const api = useApi(azureDevOpsApiRef); + const { project, repo } = getAnnotationValuesFromEntity(entity); + + const { value, loading, error } = useAsync(async () => { + return await api.getReadme({ project, repo: repo as string }); + }, [api, project, repo]); + + return { + item: value, + loading, + error, + }; +} From 8613ba3928e09d167511f84208afe51cc12d9edc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 21 Oct 2023 15:28:00 +0200 Subject: [PATCH 328/348] plugins: remove usages of --experimental-type-build Signed-off-by: Patrik Oldsberg --- .changeset/sour-toes-joke.md | 13 ++++++ .../02-adding-a-basic-permission-check.md | 2 +- packages/backend-next/src/index.ts | 2 +- plugins/bazaar-backend/alpha-api-report.md | 13 ++++++ plugins/bazaar-backend/api-report.md | 5 --- plugins/bazaar-backend/package.json | 22 +++++++--- .../src/{plugin.ts => alpha.ts} | 2 +- plugins/bazaar-backend/src/index.ts | 1 - .../example-todo-list-backend/api-report.md | 2 +- .../example-todo-list-backend/package.json | 5 +-- .../example-todo-list-backend/src/plugin.ts | 2 +- plugins/kafka-backend/alpha-api-report.md | 13 ++++++ plugins/kafka-backend/api-report.md | 5 --- plugins/kafka-backend/package.json | 22 +++++++--- .../kafka-backend/src/{plugin.ts => alpha.ts} | 2 +- plugins/kafka-backend/src/index.ts | 1 - plugins/periskop-backend/alpha-api-report.md | 13 ++++++ plugins/periskop-backend/api-report.md | 5 --- plugins/periskop-backend/package.json | 22 +++++++--- .../src/{plugin.ts => alpha.ts} | 2 +- plugins/periskop-backend/src/index.ts | 1 - plugins/proxy-backend/alpha-api-report.md | 13 ++++++ plugins/proxy-backend/api-report.md | 5 --- plugins/proxy-backend/package.json | 22 +++++++--- .../proxy-backend/src/{plugin.ts => alpha.ts} | 2 +- plugins/proxy-backend/src/index.ts | 1 - .../src/ScaffolderPlugin.ts | 8 ++-- plugins/scaffolder-node/alpha-api-report.md | 42 +++++++++++++++++++ plugins/scaffolder-node/api-report.md | 34 --------------- plugins/scaffolder-node/package.json | 22 +++++++--- .../src/{extensions.ts => alpha.ts} | 0 plugins/scaffolder-node/src/index.ts | 8 ---- plugins/sonarqube/package.json | 5 +-- plugins/todo/package.json | 5 +-- .../user-settings-backend/alpha-api-report.md | 13 ++++++ plugins/user-settings-backend/api-report.md | 5 --- plugins/user-settings-backend/package.json | 22 +++++++--- .../src/{plugin.ts => alpha.ts} | 2 +- plugins/user-settings-backend/src/index.ts | 1 - 39 files changed, 242 insertions(+), 123 deletions(-) create mode 100644 .changeset/sour-toes-joke.md create mode 100644 plugins/bazaar-backend/alpha-api-report.md rename plugins/bazaar-backend/src/{plugin.ts => alpha.ts} (96%) create mode 100644 plugins/kafka-backend/alpha-api-report.md rename plugins/kafka-backend/src/{plugin.ts => alpha.ts} (96%) create mode 100644 plugins/periskop-backend/alpha-api-report.md rename plugins/periskop-backend/src/{plugin.ts => alpha.ts} (96%) create mode 100644 plugins/proxy-backend/alpha-api-report.md rename plugins/proxy-backend/src/{plugin.ts => alpha.ts} (96%) create mode 100644 plugins/scaffolder-node/alpha-api-report.md rename plugins/scaffolder-node/src/{extensions.ts => alpha.ts} (100%) create mode 100644 plugins/user-settings-backend/alpha-api-report.md rename plugins/user-settings-backend/src/{plugin.ts => alpha.ts} (95%) diff --git a/.changeset/sour-toes-joke.md b/.changeset/sour-toes-joke.md new file mode 100644 index 0000000000..4e380f4ded --- /dev/null +++ b/.changeset/sour-toes-joke.md @@ -0,0 +1,13 @@ +--- +'@backstage/plugin-user-settings-backend': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-periskop-backend': patch +'@backstage/plugin-scaffolder-node': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-kafka-backend': patch +'@backstage/plugin-proxy-backend': patch +'@backstage/plugin-sonarqube': patch +'@backstage/plugin-todo': patch +--- + +Switched to using `"exports"` field for `/alpha` subpath export. diff --git a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md index 839441e733..23bc4e84f1 100644 --- a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md +++ b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md @@ -349,7 +349,7 @@ import { createRouter } from './service/router'; /** * The example TODO list backend plugin. * -* @alpha +* @public */ export const exampleTodoListPlugin = createBackendPlugin({ pluginId: 'exampleTodoList', diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index bdfbc2c26b..dd2c6994f9 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -39,7 +39,7 @@ backend.add( import('@backstage/plugin-permission-backend-module-allow-all-policy'), ); backend.add(import('@backstage/plugin-permission-backend/alpha')); -backend.add(import('@backstage/plugin-proxy-backend')); +backend.add(import('@backstage/plugin-proxy-backend/alpha')); backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); backend.add(import('@backstage/plugin-search-backend-module-catalog/alpha')); backend.add(import('@backstage/plugin-search-backend-module-explore/alpha')); diff --git a/plugins/bazaar-backend/alpha-api-report.md b/plugins/bazaar-backend/alpha-api-report.md new file mode 100644 index 0000000000..7ef46f20ab --- /dev/null +++ b/plugins/bazaar-backend/alpha-api-report.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/plugin-bazaar-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +const _default: () => BackendFeature; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/bazaar-backend/api-report.md b/plugins/bazaar-backend/api-report.md index d9243fd3af..1ee889c04a 100644 --- a/plugins/bazaar-backend/api-report.md +++ b/plugins/bazaar-backend/api-report.md @@ -3,17 +3,12 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; -// @alpha -const bazaarPlugin: () => BackendFeature; -export default bazaarPlugin; - // @public (undocumented) export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 3fdfa32a7f..2a0c2c8f28 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -5,10 +5,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "backend-plugin" @@ -21,7 +33,7 @@ }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/plugins/bazaar-backend/src/plugin.ts b/plugins/bazaar-backend/src/alpha.ts similarity index 96% rename from plugins/bazaar-backend/src/plugin.ts rename to plugins/bazaar-backend/src/alpha.ts index 1c06bda705..466181e073 100644 --- a/plugins/bazaar-backend/src/plugin.ts +++ b/plugins/bazaar-backend/src/alpha.ts @@ -26,7 +26,7 @@ import { createRouter } from './service/router'; * * @alpha */ -export const bazaarPlugin = createBackendPlugin({ +export default createBackendPlugin({ pluginId: 'bazaar', register(env) { env.registerInit({ diff --git a/plugins/bazaar-backend/src/index.ts b/plugins/bazaar-backend/src/index.ts index d6f3df2d04..ca73cb27ba 100644 --- a/plugins/bazaar-backend/src/index.ts +++ b/plugins/bazaar-backend/src/index.ts @@ -15,4 +15,3 @@ */ export * from './service/router'; -export { bazaarPlugin as default } from './plugin'; diff --git a/plugins/example-todo-list-backend/api-report.md b/plugins/example-todo-list-backend/api-report.md index d78f5e0796..4c27733124 100644 --- a/plugins/example-todo-list-backend/api-report.md +++ b/plugins/example-todo-list-backend/api-report.md @@ -11,7 +11,7 @@ import { Logger } from 'winston'; // @public export function createRouter(options: RouterOptions): Promise; -// @alpha +// @public const exampleTodoListPlugin: () => BackendFeature; export default exampleTodoListPlugin; diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index c13bb571e2..21759dffa2 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -17,12 +17,11 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "types": "dist/index.d.ts" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/plugins/example-todo-list-backend/src/plugin.ts b/plugins/example-todo-list-backend/src/plugin.ts index 42985f6e88..6bdae201f1 100644 --- a/plugins/example-todo-list-backend/src/plugin.ts +++ b/plugins/example-todo-list-backend/src/plugin.ts @@ -24,7 +24,7 @@ import { createRouter } from './service/router'; /** * The example TODO list backend plugin. * - * @alpha + * @public */ export const exampleTodoListPlugin = createBackendPlugin({ pluginId: 'exampleTodoList', diff --git a/plugins/kafka-backend/alpha-api-report.md b/plugins/kafka-backend/alpha-api-report.md new file mode 100644 index 0000000000..01c035aa0d --- /dev/null +++ b/plugins/kafka-backend/alpha-api-report.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/plugin-kafka-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +const _default: () => BackendFeature; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/kafka-backend/api-report.md b/plugins/kafka-backend/api-report.md index b03bad12e5..20c8260b52 100644 --- a/plugins/kafka-backend/api-report.md +++ b/plugins/kafka-backend/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; @@ -11,10 +10,6 @@ import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; -// @alpha -const kafkaPlugin: () => BackendFeature; -export default kafkaPlugin; - // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 68060f254c..8533f54b35 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -6,10 +6,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "backend-plugin" @@ -27,7 +39,7 @@ "configSchema": "config.d.ts", "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/plugins/kafka-backend/src/plugin.ts b/plugins/kafka-backend/src/alpha.ts similarity index 96% rename from plugins/kafka-backend/src/plugin.ts rename to plugins/kafka-backend/src/alpha.ts index 0548a5f128..bc627eb9d3 100644 --- a/plugins/kafka-backend/src/plugin.ts +++ b/plugins/kafka-backend/src/alpha.ts @@ -26,7 +26,7 @@ import { createRouter } from './service/router'; * * @alpha */ -export const kafkaPlugin = createBackendPlugin({ +export default createBackendPlugin({ pluginId: 'kafka', register(env) { env.registerInit({ diff --git a/plugins/kafka-backend/src/index.ts b/plugins/kafka-backend/src/index.ts index d87d313941..70b7fb45a4 100644 --- a/plugins/kafka-backend/src/index.ts +++ b/plugins/kafka-backend/src/index.ts @@ -22,4 +22,3 @@ export type { RouterOptions } from './service/router'; export { createRouter } from './service/router'; -export { kafkaPlugin as default } from './plugin'; diff --git a/plugins/periskop-backend/alpha-api-report.md b/plugins/periskop-backend/alpha-api-report.md new file mode 100644 index 0000000000..d6ace05993 --- /dev/null +++ b/plugins/periskop-backend/alpha-api-report.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/plugin-periskop-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +const _default: () => BackendFeature; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/periskop-backend/api-report.md b/plugins/periskop-backend/api-report.md index 46d5de8d93..caaed109f9 100644 --- a/plugins/periskop-backend/api-report.md +++ b/plugins/periskop-backend/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; @@ -11,10 +10,6 @@ import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; -// @alpha -const periskopPlugin: () => BackendFeature; -export default periskopPlugin; - // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index 1ef6c62431..73977e626d 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -14,14 +14,26 @@ "directory": "plugins/periskop-backend" }, "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/plugins/periskop-backend/src/plugin.ts b/plugins/periskop-backend/src/alpha.ts similarity index 96% rename from plugins/periskop-backend/src/plugin.ts rename to plugins/periskop-backend/src/alpha.ts index 2123dcbece..59271e02fc 100644 --- a/plugins/periskop-backend/src/plugin.ts +++ b/plugins/periskop-backend/src/alpha.ts @@ -26,7 +26,7 @@ import { createRouter } from './service/router'; * * @alpha */ -export const periskopPlugin = createBackendPlugin({ +export default createBackendPlugin({ pluginId: 'periskop', register(env) { env.registerInit({ diff --git a/plugins/periskop-backend/src/index.ts b/plugins/periskop-backend/src/index.ts index 17a6d0d054..ca73cb27ba 100644 --- a/plugins/periskop-backend/src/index.ts +++ b/plugins/periskop-backend/src/index.ts @@ -15,4 +15,3 @@ */ export * from './service/router'; -export { periskopPlugin as default } from './plugin'; diff --git a/plugins/proxy-backend/alpha-api-report.md b/plugins/proxy-backend/alpha-api-report.md new file mode 100644 index 0000000000..73c3052acb --- /dev/null +++ b/plugins/proxy-backend/alpha-api-report.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/plugin-proxy-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +const _default: () => BackendFeature; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/proxy-backend/api-report.md b/plugins/proxy-backend/api-report.md index ae327d485a..12e6bfa1c9 100644 --- a/plugins/proxy-backend/api-report.md +++ b/plugins/proxy-backend/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; @@ -12,10 +11,6 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; // @public export function createRouter(options: RouterOptions): Promise; -// @alpha -const proxyPlugin: () => BackendFeature; -export default proxyPlugin; - // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index adbfe9fce9..4506f62107 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -6,10 +6,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "backend-plugin" @@ -25,7 +37,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/plugins/proxy-backend/src/plugin.ts b/plugins/proxy-backend/src/alpha.ts similarity index 96% rename from plugins/proxy-backend/src/plugin.ts rename to plugins/proxy-backend/src/alpha.ts index e4c14b0037..9f6bad4832 100644 --- a/plugins/proxy-backend/src/plugin.ts +++ b/plugins/proxy-backend/src/alpha.ts @@ -26,7 +26,7 @@ import { createRouter } from './service/router'; * * @alpha */ -export const proxyPlugin = createBackendPlugin({ +export default createBackendPlugin({ pluginId: 'proxy', register(env) { env.registerInit({ diff --git a/plugins/proxy-backend/src/index.ts b/plugins/proxy-backend/src/index.ts index 3163abd381..8f5d5c79dc 100644 --- a/plugins/proxy-backend/src/index.ts +++ b/plugins/proxy-backend/src/index.ts @@ -21,4 +21,3 @@ */ export * from './service'; -export { proxyPlugin as default } from './plugin'; diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index 98bd4a1d66..beabaa50aa 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -22,14 +22,16 @@ import { loggerToWinstonLogger } from '@backstage/backend-common'; import { ScmIntegrations } from '@backstage/integration'; import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha'; import { - scaffolderActionsExtensionPoint, - scaffolderTaskBrokerExtensionPoint, - scaffolderTemplatingExtensionPoint, TaskBroker, TemplateAction, TemplateFilter, TemplateGlobal, } from '@backstage/plugin-scaffolder-node'; +import { + scaffolderActionsExtensionPoint, + scaffolderTaskBrokerExtensionPoint, + scaffolderTemplatingExtensionPoint, +} from '@backstage/plugin-scaffolder-node/alpha'; import { createBuiltinActions } from './scaffolder'; import { createRouter } from './service/router'; diff --git a/plugins/scaffolder-node/alpha-api-report.md b/plugins/scaffolder-node/alpha-api-report.md new file mode 100644 index 0000000000..c2a2a1597e --- /dev/null +++ b/plugins/scaffolder-node/alpha-api-report.md @@ -0,0 +1,42 @@ +## API Report File for "@backstage/plugin-scaffolder-node" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ExtensionPoint } from '@backstage/backend-plugin-api'; +import { TaskBroker } from '@backstage/plugin-scaffolder-node'; +import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { TemplateFilter } from '@backstage/plugin-scaffolder-node'; +import { TemplateGlobal } from '@backstage/plugin-scaffolder-node'; + +// @alpha +export interface ScaffolderActionsExtensionPoint { + // (undocumented) + addActions(...actions: TemplateAction[]): void; +} + +// @alpha +export const scaffolderActionsExtensionPoint: ExtensionPoint; + +// @alpha +export interface ScaffolderTaskBrokerExtensionPoint { + // (undocumented) + setTaskBroker(taskBroker: TaskBroker): void; +} + +// @alpha +export const scaffolderTaskBrokerExtensionPoint: ExtensionPoint; + +// @alpha +export interface ScaffolderTemplatingExtensionPoint { + // (undocumented) + addTemplateFilters(filters: Record): void; + // (undocumented) + addTemplateGlobals(filters: Record): void; +} + +// @alpha +export const scaffolderTemplatingExtensionPoint: ExtensionPoint; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/scaffolder-node/api-report.md b/plugins/scaffolder-node/api-report.md index 52ce3c8d13..08caf36812 100644 --- a/plugins/scaffolder-node/api-report.md +++ b/plugins/scaffolder-node/api-report.md @@ -5,7 +5,6 @@ ```ts /// -import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { Logger } from 'winston'; @@ -13,11 +12,7 @@ import { Observable } from '@backstage/types'; import { Schema } from 'jsonschema'; import { ScmIntegrations } from '@backstage/integration'; import { SpawnOptionsWithoutStdio } from 'child_process'; -import { TaskBroker as TaskBroker_2 } from '@backstage/plugin-scaffolder-node'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; -import { TemplateAction as TemplateAction_2 } from '@backstage/plugin-scaffolder-node'; -import { TemplateFilter as TemplateFilter_2 } from '@backstage/plugin-scaffolder-node'; -import { TemplateGlobal as TemplateGlobal_2 } from '@backstage/plugin-scaffolder-node'; import { TemplateInfo } from '@backstage/plugin-scaffolder-common'; import { UrlReader } from '@backstage/backend-common'; import { UserEntity } from '@backstage/catalog-model'; @@ -109,35 +104,6 @@ export function fetchFile(options: { outputPath: string; }): Promise; -// @alpha -export interface ScaffolderActionsExtensionPoint { - // (undocumented) - addActions(...actions: TemplateAction_2[]): void; -} - -// @alpha -export const scaffolderActionsExtensionPoint: ExtensionPoint; - -// @alpha -export interface ScaffolderTaskBrokerExtensionPoint { - // (undocumented) - setTaskBroker(taskBroker: TaskBroker_2): void; -} - -// @alpha -export const scaffolderTaskBrokerExtensionPoint: ExtensionPoint; - -// @alpha -export interface ScaffolderTemplatingExtensionPoint { - // (undocumented) - addTemplateFilters(filters: Record): void; - // (undocumented) - addTemplateGlobals(filters: Record): void; -} - -// @alpha -export const scaffolderTemplatingExtensionPoint: ExtensionPoint; - // @public export type SerializedTask = { id: string; diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index 3194f0c0d6..8e887b480b 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -6,10 +6,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "node-library" @@ -22,7 +34,7 @@ }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", diff --git a/plugins/scaffolder-node/src/extensions.ts b/plugins/scaffolder-node/src/alpha.ts similarity index 100% rename from plugins/scaffolder-node/src/extensions.ts rename to plugins/scaffolder-node/src/alpha.ts diff --git a/plugins/scaffolder-node/src/index.ts b/plugins/scaffolder-node/src/index.ts index dcce065108..98691c2afa 100644 --- a/plugins/scaffolder-node/src/index.ts +++ b/plugins/scaffolder-node/src/index.ts @@ -23,11 +23,3 @@ export * from './actions'; export * from './tasks'; export type { TemplateFilter, TemplateGlobal } from './types'; -export { - scaffolderActionsExtensionPoint, - type ScaffolderActionsExtensionPoint, - scaffolderTaskBrokerExtensionPoint, - type ScaffolderTaskBrokerExtensionPoint, - scaffolderTemplatingExtensionPoint, - type ScaffolderTemplatingExtensionPoint, -} from './extensions'; diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 00d6c494db..4244c74759 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -8,8 +8,7 @@ "publishConfig": { "access": "public", "main": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "types": "dist/index.d.ts" }, "backstage": { "role": "frontend-plugin" @@ -27,7 +26,7 @@ ], "sideEffects": false, "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "start": "backstage-cli package start", "lint": "backstage-cli package lint", "test": "backstage-cli package test", diff --git a/plugins/todo/package.json b/plugins/todo/package.json index ec27528d72..6c230d7a4b 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -8,8 +8,7 @@ "publishConfig": { "access": "public", "main": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "types": "dist/index.d.ts" }, "backstage": { "role": "frontend-plugin" @@ -22,7 +21,7 @@ }, "sideEffects": false, "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "start": "backstage-cli package start", "lint": "backstage-cli package lint", "test": "backstage-cli package test", diff --git a/plugins/user-settings-backend/alpha-api-report.md b/plugins/user-settings-backend/alpha-api-report.md new file mode 100644 index 0000000000..aa6b246616 --- /dev/null +++ b/plugins/user-settings-backend/alpha-api-report.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/plugin-user-settings-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +const _default: () => BackendFeature; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/user-settings-backend/api-report.md b/plugins/user-settings-backend/api-report.md index 808bd0f29b..1bc37bbec7 100644 --- a/plugins/user-settings-backend/api-report.md +++ b/plugins/user-settings-backend/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import express from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { PluginDatabaseManager } from '@backstage/backend-common'; @@ -19,9 +18,5 @@ export interface RouterOptions { identity: IdentityApi; } -// @alpha -const userSettingsPlugin: () => BackendFeature; -export default userSettingsPlugin; - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index c72f349301..cf68c43c3b 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -9,10 +9,22 @@ "role": "backend-plugin" }, "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } }, "homepage": "https://backstage.io", "repository": { @@ -22,7 +34,7 @@ }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/plugins/user-settings-backend/src/plugin.ts b/plugins/user-settings-backend/src/alpha.ts similarity index 95% rename from plugins/user-settings-backend/src/plugin.ts rename to plugins/user-settings-backend/src/alpha.ts index e200d22ffe..8404c4ae94 100644 --- a/plugins/user-settings-backend/src/plugin.ts +++ b/plugins/user-settings-backend/src/alpha.ts @@ -25,7 +25,7 @@ import { createRouter } from './service/router'; * * @alpha */ -export const userSettingsPlugin = createBackendPlugin({ +export default createBackendPlugin({ pluginId: 'userSettings', register(env) { env.registerInit({ diff --git a/plugins/user-settings-backend/src/index.ts b/plugins/user-settings-backend/src/index.ts index 14a9704e53..04d8accdaf 100644 --- a/plugins/user-settings-backend/src/index.ts +++ b/plugins/user-settings-backend/src/index.ts @@ -16,4 +16,3 @@ export * from './service'; export * from './database'; -export { userSettingsPlugin as default } from './plugin'; From 4e36abef145b41c2273b2aea0d5fcad7ff0e2acd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 21 Oct 2023 15:31:16 +0200 Subject: [PATCH 329/348] cli: remove support for --experimental-type-build Signed-off-by: Patrik Oldsberg --- .changeset/many-masks-smoke.md | 6 + REVIEWING.md | 8 +- docs/local-dev/cli-build-system.md | 35 ----- packages/cli/cli-report.md | 1 - packages/cli/package.json | 4 - packages/cli/src/commands/build/command.ts | 1 - packages/cli/src/commands/index.ts | 4 - .../src/commands/migrate/packageScripts.ts | 3 - packages/cli/src/commands/repo/build.ts | 1 - .../src/lib/builder/buildTypeDefinitions.ts | 129 ------------------ .../lib/builder/buildTypeDefinitionsWorker.ts | 97 ------------- packages/cli/src/lib/builder/config.ts | 2 +- packages/cli/src/lib/builder/packager.ts | 17 --- packages/cli/src/lib/builder/types.ts | 1 - .../src/lib/packager/createDistWorkspace.ts | 1 - .../src/commands/api-reports/api-extractor.ts | 11 +- yarn.lock | 3 - 17 files changed, 9 insertions(+), 315 deletions(-) create mode 100644 .changeset/many-masks-smoke.md delete mode 100644 packages/cli/src/lib/builder/buildTypeDefinitions.ts delete mode 100644 packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts diff --git a/.changeset/many-masks-smoke.md b/.changeset/many-masks-smoke.md new file mode 100644 index 0000000000..6d249eeb15 --- /dev/null +++ b/.changeset/many-masks-smoke.md @@ -0,0 +1,6 @@ +--- +'@backstage/repo-tools': minor +'@backstage/cli': minor +--- + +Remove support for the deprecated `--experimental-type-build` option for `package build`. diff --git a/REVIEWING.md b/REVIEWING.md index 43085090a8..7ed3fcda57 100644 --- a/REVIEWING.md +++ b/REVIEWING.md @@ -172,13 +172,7 @@ We generate API Reports using the [API Extractor](https://api-extractor.com/) to Each API report contains a list of all the exported types of each package. As long as the API report does not have any warnings it will contain the full publicly facing API of the package, meaning you do not need to consider any other changes to the package from the point of view of TypeScript API stability. -Exported types can be marked with either `@public`, `@alpha` or `@beta` release tags. It is only the `@public` exports that we consider to be part of the stable API. The `@alpha` and `@beta` exports are considered unstable and can be changed at any time without needing a breaking package versions bump. However, this **ONLY** applies if the package has been configured to use experimental type builds, which looks like this in `package.json`: - -```json - "build": "backstage-cli package build --experimental-type-build" -``` - -If a package does not have this configuration, then all exported types are considered stable, even if they are marked as `@alpha` or `@beta`. +Exported types can be marked with either `@public`, `@alpha` or `@beta` release tags. It is only the `@public` exports that we consider to be part of the stable API. The `@alpha` and `@beta` exports are considered unstable and can be changed at any time without needing a breaking package versions bump. #### Changes that are Not Considered Breaking diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index 61e24863fe..7bb4918d47 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -674,38 +674,3 @@ To add subpath exports to an existing package, simply add the desired `"exports" ```bash yarn backstage-cli migrate package-exports ``` - -## Experimental Type Build - -> Note: Experimental type builds are deprecated and will be removed in the future. They have been replaced by [subpath exports](#subpath-exports). - -The Backstage CLI has an experimental feature where multiple different type definition files can be generated for different release stages. The release stages are marked in the [TSDoc](https://tsdoc.org/) for each individual export, using either `@public`, `@alpha`, or `@beta`. Rather than just building a single `index.d.ts` file, the build process will instead output `index.d.ts`, `index.beta.d.ts`, and `index.alpha.d.ts`. Each of these files will have exports from more unstable release stages stripped, meaning that `index.d.ts` will omit all exports marked with `@alpha` or `@beta`, while `index.beta.d.ts` will omit all exports marked with `@alpha`. - -This feature is aimed at projects that publish to package registries and wish to maintain different levels of API stability within each package. There is no need to use this within a single monorepo, as it has no effect due to only applying to built and published packages. - -In order for the experimental type build to work, `@microsoft/api-extractor` must be installed in your project, as it is an optional peer dependency of the Backstage CLI. There are then three steps that need to be taken for each package where you want to enable this feature: - -- Add the `--experimental-type-build` flag to the `"build"` script of the package. -- Add either one or both of `"alphaTypes"` and `"betaTypes"` to the `"publishConfig"` of the package: - ```json - "publishConfig": { - ... - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts", - "betaTypes": "dist/index.beta.d.ts" - }, - ``` -- Add either one or both of `"alpha"` and `"beta"` to the `"files"` of the package: - ```json - "files": [ - "dist", - "alpha", - "beta" - ] - ``` - -Once this setup is complete, users of the published packages will only be able to access the stable API via the main package entry point, for example `@acme/my-plugin`. Exports marked with `@alpha` or `@beta` will only be available via the `/alpha` entry point, for example `@acme/my-plugin/alpha`, and exports marked with `@beta` will only be available via `/beta`. This does not apply within the monorepo that contains the package. There all exports still have to be imported via the main entry point. - -Note that these different entry points are only separated during type checking. At runtime they all share the same code which contains the exports from all releases stages. - -An example of this setup can be seen in the [`@backstage/catalog-model`](https://github.com/backstage/backstage/blob/da0675bf9f28ed1460f03635a22d3c26abd14707/packages/catalog-model/package.json#L14) package, which has enabled `alpha` type exports. With this setup, exports marked as `@alpha` are only available for import via `@backstage/catalog-model/alpha`. The `@backstage/catalog-model` package currently does not have any exports marked as `@beta`, or a `/beta` entry point. diff --git a/packages/cli/cli-report.md b/packages/cli/cli-report.md index 9d6ffd3f69..9292f2ea37 100644 --- a/packages/cli/cli-report.md +++ b/packages/cli/cli-report.md @@ -224,7 +224,6 @@ Usage: backstage-cli package build [options] Options: --role --minify - --experimental-type-build --skip-build-dependencies --stats --config diff --git a/packages/cli/package.json b/packages/cli/package.json index 4f08231f7e..5fb892952f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -175,16 +175,12 @@ "type-fest": "^2.19.0" }, "peerDependencies": { - "@microsoft/api-extractor": "^7.21.2", "@vitejs/plugin-react": "^4.0.4", "vite": "^4.4.9", "vite-plugin-html": "^3.2.0", "vite-plugin-node-polyfills": "^0.14.1" }, "peerDependenciesMeta": { - "@microsoft/api-extractor": { - "optional": true - }, "@vitejs/plugin-react": { "optional": true }, diff --git a/packages/cli/src/commands/build/command.ts b/packages/cli/src/commands/build/command.ts index 507085e0a0..1b3aeff2f9 100644 --- a/packages/cli/src/commands/build/command.ts +++ b/packages/cli/src/commands/build/command.ts @@ -65,6 +65,5 @@ export async function command(opts: OptionValues): Promise { return buildPackage({ outputs, minify: Boolean(opts.minify), - useApiExtractor: Boolean(opts.experimentalTypeBuild), }); } diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index ce4a4d2bae..fb0a55f37e 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -130,10 +130,6 @@ export function registerScriptCommand(program: Command) { '--minify', 'Minify the generated code. Does not apply to app or backend packages.', ) - .option( - '--experimental-type-build', - 'Enable experimental type build. Does not apply to app or backend packages. [DEPRECATED]', - ) .option( '--skip-build-dependencies', 'Skip the automatic building of local dependencies. Applies to backend packages only.', diff --git a/packages/cli/src/commands/migrate/packageScripts.ts b/packages/cli/src/commands/migrate/packageScripts.ts index 1552208a5f..e9ff20aed3 100644 --- a/packages/cli/src/commands/migrate/packageScripts.ts +++ b/packages/cli/src/commands/migrate/packageScripts.ts @@ -49,9 +49,6 @@ export async function command() { if (scripts.build?.includes('--minify')) { buildCmd.push('--minify'); } - if (scripts.build?.includes('--experimental-type-build')) { - buildCmd.push('--experimental-type-build'); - } if (scripts.build?.includes('--config')) { buildCmd.push(...(scripts.build.match(configArgPattern) ?? [])); } diff --git a/packages/cli/src/commands/repo/build.ts b/packages/cli/src/commands/repo/build.ts index 71e58c6201..32f227c208 100644 --- a/packages/cli/src/commands/repo/build.ts +++ b/packages/cli/src/commands/repo/build.ts @@ -137,7 +137,6 @@ export async function command(opts: OptionValues, cmd: Command): Promise { outputs, logPrefix: `${chalk.cyan(relativePath(paths.targetRoot, pkg.dir))}: `, minify: buildOptions.minify, - useApiExtractor: buildOptions.experimentalTypeBuild, }; }); diff --git a/packages/cli/src/lib/builder/buildTypeDefinitions.ts b/packages/cli/src/lib/builder/buildTypeDefinitions.ts deleted file mode 100644 index 3bf3a4495f..0000000000 --- a/packages/cli/src/lib/builder/buildTypeDefinitions.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2020 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 fs from 'fs-extra'; -import chalk from 'chalk'; -import { relative as relativePath, resolve as resolvePath } from 'path'; -import { paths } from '../paths'; -import { buildTypeDefinitionsWorker } from './buildTypeDefinitionsWorker'; -import { runWorkerThreads } from '../parallel'; - -// These message types are ignored since we want to avoid duplicating the logic of -// handling them correctly, and we already have the API Reports warning about them. -const ignoredMessages = new Set(['tsdoc-undefined-tag', 'ae-forgotten-export']); - -export async function buildTypeDefinitions( - targetDirs: string[] = [paths.targetDir], -) { - const packageDirs = targetDirs.map(dir => - relativePath(paths.targetRoot, dir), - ); - const entryPoints = await Promise.all( - packageDirs.map(async dir => { - const entryPoint = paths.resolveTargetRoot( - 'dist-types', - dir, - 'src/index.d.ts', - ); - - const declarationsExist = await fs.pathExists(entryPoint); - if (!declarationsExist) { - throw new Error( - `No declaration files found at ${entryPoint}, be sure to run ${chalk.bgRed.white( - 'yarn tsc', - )} to generate .d.ts files before packaging`, - ); - } - return entryPoint; - }), - ); - - const workerConfigs = packageDirs.map(packageDir => { - const targetDir = paths.resolveTargetRoot(packageDir); - const targetTypesDir = paths.resolveTargetRoot('dist-types', packageDir); - const extractorOptions = { - configObject: { - mainEntryPointFilePath: resolvePath(targetTypesDir, 'src/index.d.ts'), - bundledPackages: [], - - compiler: { - skipLibCheck: true, - tsconfigFilePath: paths.resolveTargetRoot('tsconfig.json'), - }, - - dtsRollup: { - enabled: true, - untrimmedFilePath: resolvePath(targetDir, 'dist/index.alpha.d.ts'), - betaTrimmedFilePath: resolvePath(targetDir, 'dist/index.beta.d.ts'), - publicTrimmedFilePath: resolvePath(targetDir, 'dist/index.d.ts'), - }, - - newlineKind: 'lf', - - projectFolder: targetDir, - }, - configObjectFullPath: targetDir, - packageJsonFullPath: resolvePath(targetDir, 'package.json'), - }; - return { extractorOptions, targetTypesDir }; - }); - - const typescriptDir = paths.resolveTargetRoot('node_modules/typescript'); - const hasTypescript = await fs.pathExists(typescriptDir); - const typescriptCompilerFolder = hasTypescript ? typescriptDir : undefined; - await runWorkerThreads({ - threadCount: 1, - workerData: { - entryPoints, - workerConfigs, - typescriptCompilerFolder, - }, - worker: buildTypeDefinitionsWorker, - onMessage: ({ - message, - targetTypesDir, - }: { - message: any; - targetTypesDir: string; - }) => { - if (ignoredMessages.has(message.messageId)) { - return; - } - - let text = `${message.text} (${message.messageId})`; - if (message.sourceFilePath) { - text += ' at '; - text += relativePath(targetTypesDir, message.sourceFilePath); - if (message.sourceFileLine) { - text += `:${message.sourceFileLine}`; - if (message.sourceFileColumn) { - text += `:${message.sourceFileColumn}`; - } - } - } - if (message.logLevel === 'error') { - console.error(chalk.red(`Error: ${text}`)); - } else if ( - message.logLevel === 'warning' || - message.category === 'Extractor' - ) { - console.warn(`Warning: ${text}`); - } else { - console.log(text); - } - }, - }); -} diff --git a/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts b/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts deleted file mode 100644 index c3c37d91cf..0000000000 --- a/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * NOTE: This is a worker thread function that is stringified and executed - * within a `worker_threads.Worker`. Everything in this function must - * be self-contained. - * Using TypeScript is fine as it is transpiled before being stringified. - */ -export async function buildTypeDefinitionsWorker( - workerData: any, - sendMessage: (message: any) => void, -) { - try { - require('@microsoft/api-extractor'); - } catch (error) { - throw new Error( - 'Failed to resolve @microsoft/api-extractor, it must best installed ' + - 'as a dependency of your project in order to use experimental type builds', - ); - } - - const { dirname } = require('path'); - const { entryPoints, workerConfigs, typescriptCompilerFolder } = workerData; - - const apiExtractor = require('@microsoft/api-extractor'); - const { Extractor, ExtractorConfig, CompilerState } = apiExtractor; - - /** - * All of this monkey patching below is because Material UI has these bare package.json file as a method - * for making TypeScript accept imports like `@material-ui/core/Button`, and improve tree-shaking - * by declaring them side effect free. - * - * The package.json lookup logic in api-extractor really doesn't like that though, as it enforces - * that the 'name' field exists in all package.json files that it discovers. This below is just - * making sure that we ignore those file package.json files instead of crashing. - */ - const { - PackageJsonLookup, - // eslint-disable-next-line @backstage/no-undeclared-imports - } = require('@rushstack/node-core-library/lib/PackageJsonLookup'); - - const old = PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor; - PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor = - function tryGetPackageJsonFilePathForPatch(path: string) { - if ( - path.includes('@material-ui') && - !dirname(path).endsWith('@material-ui') - ) { - return undefined; - } - return old.call(this, path); - }; - - let compilerState; - for (const { extractorOptions, targetTypesDir } of workerConfigs) { - const extractorConfig = ExtractorConfig.prepare(extractorOptions); - - if (!compilerState) { - compilerState = CompilerState.create(extractorConfig, { - additionalEntryPoints: entryPoints, - }); - } - - const extractorResult = Extractor.invoke(extractorConfig, { - compilerState, - localBuild: false, - typescriptCompilerFolder, - showVerboseMessages: false, - showDiagnostics: false, - messageCallback: (message: any) => { - message.handled = true; - sendMessage({ message, targetTypesDir }); - }, - }); - - if (!extractorResult.succeeded) { - throw new Error( - `Type definition build completed with ${extractorResult.errorCount} errors` + - ` and ${extractorResult.warningCount} warnings`, - ); - } - } -} diff --git a/packages/cli/src/lib/builder/config.ts b/packages/cli/src/lib/builder/config.ts index f614581320..41e9dd6906 100644 --- a/packages/cli/src/lib/builder/config.ts +++ b/packages/cli/src/lib/builder/config.ts @@ -151,7 +151,7 @@ export async function makeRollupConfigs( }); } - if (options.outputs.has(Output.types) && !options.useApiExtractor) { + if (options.outputs.has(Output.types)) { const input = Object.fromEntries( scriptEntryPoints.map(e => [ e.name, diff --git a/packages/cli/src/lib/builder/packager.ts b/packages/cli/src/lib/builder/packager.ts index 780f9c2cfe..be9bc9a6ea 100644 --- a/packages/cli/src/lib/builder/packager.ts +++ b/packages/cli/src/lib/builder/packager.ts @@ -21,7 +21,6 @@ import { relative as relativePath, resolve as resolvePath } from 'path'; import { paths } from '../paths'; import { makeRollupConfigs } from './config'; import { BuildOptions, Output } from './types'; -import { buildTypeDefinitions } from './buildTypeDefinitions'; import { PackageRoles } from '@backstage/cli-node'; import { runParallelWorkers } from '../parallel'; @@ -112,10 +111,6 @@ export const buildPackage = async (options: BuildOptions) => { const buildTasks = rollupConfigs.map(rollupBuild); - if (options.outputs.has(Output.types) && options.useApiExtractor) { - buildTasks.push(buildTypeDefinitions()); - } - await Promise.all(buildTasks); }; @@ -131,18 +126,6 @@ export const buildPackages = async (options: BuildOptions[]) => { const buildTasks = rollupConfigs.flat().map(opts => () => rollupBuild(opts)); - const typeDefinitionTargetDirs = options - .filter( - ({ outputs, useApiExtractor }) => - outputs.has(Output.types) && useApiExtractor, - ) - .map(_ => _.targetDir!); - - if (typeDefinitionTargetDirs.length > 0) { - // Make sure this one is started first - buildTasks.unshift(() => buildTypeDefinitions(typeDefinitionTargetDirs)); - } - await runParallelWorkers({ items: buildTasks, worker: async task => task(), diff --git a/packages/cli/src/lib/builder/types.ts b/packages/cli/src/lib/builder/types.ts index 330419235f..7d9c34fe29 100644 --- a/packages/cli/src/lib/builder/types.ts +++ b/packages/cli/src/lib/builder/types.ts @@ -28,5 +28,4 @@ export type BuildOptions = { packageJson?: BackstagePackageJson; outputs: Set; minify?: boolean; - useApiExtractor?: boolean; }; diff --git a/packages/cli/src/lib/packager/createDistWorkspace.ts b/packages/cli/src/lib/packager/createDistWorkspace.ts index e91924dd37..00b8784d6d 100644 --- a/packages/cli/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli/src/lib/packager/createDistWorkspace.ts @@ -206,7 +206,6 @@ export async function createDistWorkspace( logPrefix: `${chalk.cyan(relativePath(paths.targetRoot, pkg.dir))}: `, // No need to detect these for the backend builds, we assume no minification or types minify: false, - useApiExtractor: false, }); } } diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index 13b6acb8fd..ce3e6f5b20 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -304,7 +304,6 @@ async function findPackageEntryPoints(packageDirs: string[]): Promise< Array<{ packageDir: string; name: string; - usesExperimentalTypeBuild?: boolean; }> > { return Promise.all( @@ -317,9 +316,6 @@ async function findPackageEntryPoints(packageDirs: string[]): Promise< getPackageExportNames(pkg)?.map(name => ({ packageDir, name })) ?? { packageDir, name: 'index', - usesExperimentalTypeBuild: pkg.scripts?.build?.includes( - '--experimental-type-build', - ), } ); }), @@ -367,11 +363,7 @@ export async function runApiExtraction({ } const warnings = new Array(); - for (const { - packageDir, - name, - usesExperimentalTypeBuild, - } of packageEntryPoints) { + for (const { packageDir, name } of packageEntryPoints) { console.log(`## Processing ${packageDir}`); const noBail = Array.isArray(allowWarnings) ? allowWarnings.some(aw => aw === packageDir || minimatch(packageDir, aw)) @@ -511,7 +503,6 @@ export async function runApiExtraction({ // The root index entrypoint is only allowed @public exports, while /alpha and /beta only allow @alpha and @beta. if ( validateReleaseTags && - !usesExperimentalTypeBuild && fs.pathExistsSync(extractorConfig.reportFilePath) ) { if (['index', 'alpha', 'beta'].includes(name)) { diff --git a/yarn.lock b/yarn.lock index 0242c61e33..13934f039a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3870,14 +3870,11 @@ __metadata: yn: ^4.0.0 zod: ^3.21.4 peerDependencies: - "@microsoft/api-extractor": ^7.21.2 "@vitejs/plugin-react": ^4.0.4 vite: ^4.4.9 vite-plugin-html: ^3.2.0 vite-plugin-node-polyfills: ^0.14.1 peerDependenciesMeta: - "@microsoft/api-extractor": - optional: true "@vitejs/plugin-react": optional: true vite: From 8db5c3cd7a6cdf66cea2707c2b29336fb5036287 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 22 Oct 2023 11:01:13 +0200 Subject: [PATCH 330/348] cli,cli-node: remove support for alphaTypes/betaTypes Signed-off-by: Patrik Oldsberg --- .changeset/chilly-books-sneeze.md | 6 +++ packages/cli-node/api-report.md | 2 - .../cli-node/src/monorepo/PackageGraph.ts | 2 - .../cli/src/lib/packager/productionPack.ts | 48 +------------------ 4 files changed, 7 insertions(+), 51 deletions(-) create mode 100644 .changeset/chilly-books-sneeze.md diff --git a/.changeset/chilly-books-sneeze.md b/.changeset/chilly-books-sneeze.md new file mode 100644 index 0000000000..a2d3ca1e04 --- /dev/null +++ b/.changeset/chilly-books-sneeze.md @@ -0,0 +1,6 @@ +--- +'@backstage/cli-node': minor +'@backstage/cli': minor +--- + +Removed support for the `publishConfig.alphaTypes` and `.betaTypes` fields that were used together with `--experimental-type-build` to generate `/alpha` and `/beta` entry points. Use the `exports` field to achieve this instead. diff --git a/packages/cli-node/api-report.md b/packages/cli-node/api-report.md index 91148596b3..71be6c4bd4 100644 --- a/packages/cli-node/api-report.md +++ b/packages/cli-node/api-report.md @@ -53,8 +53,6 @@ export interface BackstagePackageJson { access?: 'public' | 'restricted'; directory?: string; registry?: string; - alphaTypes?: string; - betaTypes?: string; }; // (undocumented) scripts?: { diff --git a/packages/cli-node/src/monorepo/PackageGraph.ts b/packages/cli-node/src/monorepo/PackageGraph.ts index 421c49f9b9..fb46dbde26 100644 --- a/packages/cli-node/src/monorepo/PackageGraph.ts +++ b/packages/cli-node/src/monorepo/PackageGraph.ts @@ -56,8 +56,6 @@ export interface BackstagePackageJson { access?: 'public' | 'restricted'; directory?: string; registry?: string; - alphaTypes?: string; - betaTypes?: string; }; dependencies?: { diff --git a/packages/cli/src/lib/packager/productionPack.ts b/packages/cli/src/lib/packager/productionPack.ts index aea5df649a..6a59924a30 100644 --- a/packages/cli/src/lib/packager/productionPack.ts +++ b/packages/cli/src/lib/packager/productionPack.ts @@ -23,7 +23,7 @@ import { readEntryPoints } from '../entryPoints'; const PKG_PATH = 'package.json'; const PKG_BACKUP_PATH = 'package.json-prepack'; -const SKIPPED_KEYS = ['access', 'registry', 'tag', 'alphaTypes', 'betaTypes']; +const SKIPPED_KEYS = ['access', 'registry', 'tag']; const SCRIPT_EXTS = ['.js', '.jsx', '.ts', '.tsx']; interface ProductionPackOptions { @@ -42,14 +42,6 @@ export async function productionPack(options: ProductionPackOptions) { await fs.writeFile(PKG_BACKUP_PATH, pkgContent); } - const hasStageEntry = - !!pkg.publishConfig?.alphaTypes || !!pkg.publishConfig?.betaTypes; - if (pkg.exports && hasStageEntry) { - throw new Error( - 'Combining both exports and alpha/beta types is not supported', - ); - } - // This mutates pkg to fill in index exports, so call it before applying publishConfig const writeCompatibilityEntryPoints = await prepareExportsEntryPoints( pkg, @@ -99,12 +91,6 @@ export async function productionPack(options: ProductionPackOptions) { await fs.writeJson(pkgPath, pkg, { encoding: 'utf8', spaces: 2 }); } - if (publishConfig.alphaTypes) { - await writeReleaseStageEntrypoint(pkg, 'alpha', targetDir ?? packageDir); - } - if (publishConfig.betaTypes) { - await writeReleaseStageEntrypoint(pkg, 'beta', targetDir ?? packageDir); - } if (writeCompatibilityEntryPoints) { await writeCompatibilityEntryPoints(targetDir ?? packageDir); } @@ -118,12 +104,6 @@ export async function revertProductionPack(packageDir: string) { // Check if we're shipping types for other release stages, clean up in that case const pkg = await fs.readJson(PKG_PATH); - if (pkg.publishConfig?.alphaTypes) { - await fs.remove(resolvePath(packageDir, 'alpha')); - } - if (pkg.publishConfig?.betaTypes) { - await fs.remove(resolvePath(packageDir, 'beta')); - } // Remove any extra entrypoint backwards compatibility directories const entryPoints = readEntryPoints(pkg); @@ -140,32 +120,6 @@ export async function revertProductionPack(packageDir: string) { } } -function resolveEntrypoint(pkg: any, name: string) { - const targetEntry = pkg.publishConfig[name] || pkg[name]; - return targetEntry && posixPath.join('..', targetEntry); -} - -// Writes e.g. alpha/package.json -async function writeReleaseStageEntrypoint( - pkg: BackstagePackageJson, - stage: 'alpha' | 'beta', - targetDir: string, -) { - await fs.ensureDir(resolvePath(targetDir, stage)); - await fs.writeJson( - resolvePath(targetDir, stage, PKG_PATH), - { - name: pkg.name, - version: pkg.version, - main: resolveEntrypoint(pkg, 'main'), - module: resolveEntrypoint(pkg, 'module'), - browser: resolveEntrypoint(pkg, 'browser'), - types: posixPath.join('..', pkg.publishConfig![`${stage}Types`]!), - }, - { encoding: 'utf8', spaces: 2 }, - ); -} - const EXPORT_MAP = { import: '.esm.js', require: '.cjs.js', From ff8ab4316e86e310c402c431b58ca08ffaf056da Mon Sep 17 00:00:00 2001 From: Hannes Jetter Date: Mon, 23 Oct 2023 09:19:25 +0200 Subject: [PATCH 331/348] added api report Signed-off-by: Hannes Jetter --- .../alpha-api-report.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/search-backend-module-techdocs/alpha-api-report.md b/plugins/search-backend-module-techdocs/alpha-api-report.md index 997d4a68db..df98623631 100644 --- a/plugins/search-backend-module-techdocs/alpha-api-report.md +++ b/plugins/search-backend-module-techdocs/alpha-api-report.md @@ -4,10 +4,21 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; +import { ExtensionPoint } from '@backstage/backend-plugin-api'; +import { TechDocsCollatorEntityTransformer } from '@backstage/plugin-search-backend-module-techdocs'; // @alpha const _default: () => BackendFeature; export default _default; +// @alpha (undocumented) +export interface TechDocsCollatorEntityTransformerExtensionPoint { + // (undocumented) + setTransformer(transformer: TechDocsCollatorEntityTransformer): void; +} + +// @alpha +export const techdocsCollatorEntityTransformerExtensionPoint: ExtensionPoint; + // (No @packageDocumentation comment for this package) ``` From d1c549ea9d090b751f9a56b3c7b96dd0bd722d46 Mon Sep 17 00:00:00 2001 From: Alex Eftimie Date: Mon, 23 Oct 2023 09:40:15 +0000 Subject: [PATCH 332/348] Pass update input to createPullRequest (fixes: #17911) Signed-off-by: Alex Eftimie --- .../actions/builtin/publish/githubPullRequest.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts index a02f21cfc2..3b6e7c3ced 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts @@ -142,6 +142,7 @@ export const createPublishGithubPullRequestAction = ( reviewers?: string[]; teamReviewers?: string[]; commitMessage?: string; + update?: boolean; }>({ id: 'publish:github:pull-request', examples, @@ -219,6 +220,11 @@ export const createPublishGithubPullRequestAction = ( title: 'Commit Message', description: 'The commit message for the pull request commit', }, + update: { + type: 'boolean', + title: 'Update', + description: 'Update pull request if already exists', + }, }, }, output: { @@ -256,6 +262,7 @@ export const createPublishGithubPullRequestAction = ( reviewers, teamReviewers, commitMessage, + update, } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl, integrations); @@ -327,6 +334,7 @@ export const createPublishGithubPullRequestAction = ( body: description, head: branchName, draft, + update, }; if (targetBranchName) { createOptions.base = targetBranchName; From 5e4127c18ee24b96995aa5dd1aad9ee74a733f23 Mon Sep 17 00:00:00 2001 From: Alex Eftimie Date: Mon, 23 Oct 2023 10:11:53 +0000 Subject: [PATCH 333/348] Add changeset Signed-off-by: Alex Eftimie --- .changeset/tall-colts-roll.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tall-colts-roll.md diff --git a/.changeset/tall-colts-roll.md b/.changeset/tall-colts-roll.md new file mode 100644 index 0000000000..914a09cdac --- /dev/null +++ b/.changeset/tall-colts-roll.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Allow setting `update: true` in `publish:github:pull-request` scaffolder action From 96c4f54bf6070db12676e9af0bf75d0d479c3d72 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 23 Oct 2023 11:23:43 +0200 Subject: [PATCH 334/348] auth-backend: revert microsoft auth implementation Signed-off-by: Patrik Oldsberg --- .changeset/strange-queens-deliver.md | 5 + plugins/auth-backend/api-report.md | 6 +- plugins/auth-backend/config.d.ts | 12 + plugins/auth-backend/package.json | 1 - .../microsoft/__testUtils__/fake.test.ts | 90 ++++ .../providers/microsoft/__testUtils__/fake.ts | 126 +++++ .../src/providers/microsoft/provider.test.ts | 450 ++++++++++++++++++ .../src/providers/microsoft/provider.ts | 303 ++++++++++-- yarn.lock | 3 +- 9 files changed, 962 insertions(+), 34 deletions(-) create mode 100644 .changeset/strange-queens-deliver.md create mode 100644 plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.test.ts create mode 100644 plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.ts create mode 100644 plugins/auth-backend/src/providers/microsoft/provider.test.ts diff --git a/.changeset/strange-queens-deliver.md b/.changeset/strange-queens-deliver.md new file mode 100644 index 0000000000..ed1d4d0b5b --- /dev/null +++ b/.changeset/strange-queens-deliver.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Reverted the Microsoft auth provider to the previous implementation. diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 41536f2a3f..6372c2ee60 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -538,9 +538,9 @@ export const providers: Readonly<{ | undefined, ) => AuthProviderFactory_2; resolvers: Readonly<{ - emailMatchingUserEntityProfileEmail: () => SignInResolver_2; - emailLocalPartMatchingUserEntityName: () => SignInResolver_2; - emailMatchingUserEntityAnnotation: () => SignInResolver_2; + emailLocalPartMatchingUserEntityName: () => SignInResolver; + emailMatchingUserEntityProfileEmail: () => SignInResolver; + emailMatchingUserEntityAnnotation(): SignInResolver; }>; }>; oauth2: Readonly<{ diff --git a/plugins/auth-backend/config.d.ts b/plugins/auth-backend/config.d.ts index f8953e1588..e719468ac1 100644 --- a/plugins/auth-backend/config.d.ts +++ b/plugins/auth-backend/config.d.ts @@ -179,6 +179,18 @@ export interface Config { }; }; /** @visibility frontend */ + microsoft?: { + [authEnv: string]: { + clientId: string; + /** + * @visibility secret + */ + clientSecret: string; + tenantId: string; + callbackUrl?: string; + }; + }; + /** @visibility frontend */ onelogin?: { [authEnv: string]: { clientId: string; diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 61e7993ab3..6de6fddd58 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -42,7 +42,6 @@ "@backstage/plugin-auth-backend-module-github-provider": "workspace:^", "@backstage/plugin-auth-backend-module-gitlab-provider": "workspace:^", "@backstage/plugin-auth-backend-module-google-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-microsoft-provider": "workspace:^", "@backstage/plugin-auth-backend-module-oauth2-provider": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", diff --git a/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.test.ts b/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.test.ts new file mode 100644 index 0000000000..dee37f0f6b --- /dev/null +++ b/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.test.ts @@ -0,0 +1,90 @@ +/* + * Copyright 2023 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 { FakeMicrosoftAPI } from './fake'; + +describe('FakeMicrosoftAPI', () => { + const api = new FakeMicrosoftAPI(); + + describe('#token', () => { + it('exchanges auth codes', () => { + const { access_token } = api.token( + new URLSearchParams({ + grant_type: 'authorization_code', + code: api.generateAuthCode('User.Read'), + }), + ); + + expect(api.tokenHasScope(access_token, 'User.Read')).toBe(true); + }); + + it('supports scopes for the first requested audience only', () => { + const { access_token } = api.token( + new URLSearchParams({ + grant_type: 'authorization_code', + code: api.generateAuthCode('someaudience/somescope User.Read'), + }), + ); + + expect(api.tokenHasScope(access_token, 'User.Read')).toBe(false); + }); + + it('special openid scopes do not count towards the 1-audience limit', () => { + const { access_token } = api.token( + new URLSearchParams({ + grant_type: 'authorization_code', + code: api.generateAuthCode('openid offline_access User.Read'), + }), + ); + + expect(api.tokenHasScope(access_token, 'User.Read')).toBe(true); + }); + + it('refreshes tokens', () => { + const { access_token } = api.token( + new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: api.generateRefreshToken( + 'email openid profile User.Read', + ), + }), + ); + + expect( + api.tokenHasScope(access_token, 'email openid profile User.Read'), + ).toBe(true); + }); + it('requires `openid` scope for ID token', () => { + const { id_token } = api.token( + new URLSearchParams({ + grant_type: 'authorization_code', + code: api.generateAuthCode('User.Read'), + }), + ); + + expect(id_token).toBeUndefined(); + }); + it('requires `offline_access` scope for refresh token', () => { + const { refresh_token } = api.token( + new URLSearchParams({ + grant_type: 'authorization_code', + code: api.generateAuthCode('User.Read'), + }), + ); + + expect(refresh_token).toBeUndefined(); + }); + }); +}); diff --git a/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.ts b/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.ts new file mode 100644 index 0000000000..9b3ca09c57 --- /dev/null +++ b/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.ts @@ -0,0 +1,126 @@ +/* + * Copyright 2023 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 { decodeJwt } from 'jose'; + +type Claims = { aud: string; scp: string }; + +export class FakeMicrosoftAPI { + generateAccessToken(scope: string): string { + return this.tokenWithClaims(this.allClaimsForScope(scope)).access_token; + } + generateAuthCode(scope: string): string { + return this.encodeClaims(this.allClaimsForScope(scope)); + } + generateRefreshToken(scope: string): string { + return this.encodeClaims(this.allClaimsForScope(scope)); + } + token(formData: URLSearchParams): { + access_token: string; + scope: string; + refresh_token?: string; + id_token?: string; + } { + const scopeParameter = formData.get('scope'); + const claims = + (scopeParameter && this.allClaimsForScope(scopeParameter)) ?? + formData.get('grant_type') === 'refresh_token' + ? this.decodeClaims(formData.get('refresh_token')!) + : this.decodeClaims(formData.get('code')!); + return { + ...this.tokenWithClaims(claims), + ...(this.hasScope(claims, 'offline_access') && { + refresh_token: this.encodeClaims(claims), + }), + ...(this.hasScope(claims, 'openid') && { + id_token: 'header.e30K.microsoft', + }), + }; + } + tokenHasScope(token: string, scope: string): boolean { + const { aud, scp } = decodeJwt(token); + return this.hasScope({ aud: aud as string, scp: scp as string }, scope); + } + private tokenWithClaims(claims: Claims): { + access_token: string; + scope: string; + } { + const filteredClaims = { + ...claims, + scp: claims.scp + .split(' ') + .filter(s => s !== 'offline_access') + .join(' '), + }; + return { + access_token: `header.${Buffer.from( + JSON.stringify(filteredClaims), + ).toString('base64')}.signature`, + scope: this.scopeFromClaims(filteredClaims), + }; + } + private allClaimsForScope(scope: string): Claims { + const scopes = scope.split(' ').map(this.parseScope); + const firstAudience = scopes + .map(({ aud }) => aud) + .find(aud => aud !== 'openid'); + return { + aud: firstAudience ?? '00000003-0000-0000-c000-000000000000', + scp: scopes + .filter(({ aud }) => aud === 'openid' || aud === firstAudience) + .map(({ scp }) => scp) + .join(' '), + }; + } + // auth codes and refresh tokens in this fake system are base64-encoded JSON + // strings of claims + private encodeClaims(claims: Claims): string { + return Buffer.from(JSON.stringify(claims)).toString('base64'); + } + private decodeClaims(encoded: string): Claims { + return JSON.parse(Buffer.from(encoded, 'base64').toString()); + } + private hasScope(claims: Claims, scope: string): boolean { + return this.scopeFromClaims(claims).includes(scope); + } + private parseScope(s: string): Claims { + if (s.includes('/')) { + const [aud, scp] = s.split('/'); + return { aud, scp }; + } + switch (s) { + case 'email': + case 'openid': + case 'offline_access': + case 'profile': { + return { aud: 'openid', scp: s }; + } + default: + return { aud: '00000003-0000-0000-c000-000000000000', scp: s }; + } + } + private scopeFromClaims(claims: Claims): string { + return claims.scp + .split(' ') + .map(this.parseScope) + .map(({ aud, scp }) => + aud === 'openid' || + claims.aud === '00000003-0000-0000-c000-000000000000' + ? scp + : `${claims.aud}/${scp}`, + ) + .join(' '); + } +} diff --git a/plugins/auth-backend/src/providers/microsoft/provider.test.ts b/plugins/auth-backend/src/providers/microsoft/provider.test.ts new file mode 100644 index 0000000000..7bbfd085d6 --- /dev/null +++ b/plugins/auth-backend/src/providers/microsoft/provider.test.ts @@ -0,0 +1,450 @@ +/* + * Copyright 2020 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 { microsoft } from './provider'; +import { getVoidLogger } from '@backstage/backend-common'; +import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { ConfigReader } from '@backstage/config'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { AuthProviderRouteHandlers, AuthResolverContext } from '../types'; +import express from 'express'; +import crypto from 'crypto'; +import { FakeMicrosoftAPI } from './__testUtils__/fake'; + +describe('MicrosoftAuthProvider', () => { + const nonce = 'AAAAAAAAAAAAAAAAAAAAAA=='; // 16 bytes of zeros in base64 + const state = Buffer.from( + `nonce=${encodeURIComponent(nonce)}&env=development`, + ).toString('hex'); + const mockBackstageToken = `header.${Buffer.from( + JSON.stringify({ sub: 'user:default/mock' }), + 'utf8', + ).toString('base64')}.backstage`; + + const server = setupServer(); + const microsoftApi = new FakeMicrosoftAPI(); + let provider: AuthProviderRouteHandlers; + let response: jest.Mocked; + + setupRequestMockHandlers(server); + + beforeEach(() => { + provider = microsoft.create({ + signIn: { + resolver: microsoft.resolvers.emailMatchingUserEntityAnnotation(), + }, + })({ + providerId: 'microsoft', + baseUrl: 'http://backstage.test/api/auth', + appUrl: 'http://backstage.test', + isOriginAllowed: _ => true, + globalConfig: { + baseUrl: 'http://backstage.test/api/auth', + appUrl: 'http://backstage.test', + isOriginAllowed: _ => true, + }, + config: new ConfigReader({ + development: { + tenantId: 'tenantId', + clientId: 'clientId', + clientSecret: 'clientSecret', + }, + }), + logger: getVoidLogger(), + resolverContext: { + issueToken: jest.fn(), + findCatalogUser: jest.fn(), + signInWithCatalogUser: async _ => ({ + token: mockBackstageToken, + }), + } as AuthResolverContext, + }) as AuthProviderRouteHandlers; + + server.use( + rest.post( + 'https://login.microsoftonline.com/tenantId/oauth2/v2.0/token', + async (req, res, ctx) => { + return res( + ctx.json({ + ...microsoftApi.token(new URLSearchParams(await req.text())), + token_type: 'Bearer', + expires_in: 123, + ext_expires_in: 123, + }), + ); + }, + ), + rest.get('https://graph.microsoft.com/v1.0/me/', (req, res, ctx) => { + if ( + !microsoftApi.tokenHasScope( + req.headers.get('authorization')!.replace(/^Bearer /, ''), + 'User.Read', + ) + ) { + return res(ctx.status(403)); + } + return res( + ctx.json({ + id: 'conrad', + displayName: 'Conrad', + surname: 'Ribas', + givenName: 'Francisco', + mail: 'conrad@example.com', + }), + ); + }), + rest.get( + 'https://graph.microsoft.com/v1.0/me/photos/*', + async (req, res, ctx) => { + if ( + !microsoftApi.tokenHasScope( + req.headers.get('authorization')!.replace(/^Bearer /, ''), + 'User.Read', + ) + ) { + return res(ctx.status(403)); + } + const imageBuffer = new Uint8Array([104, 111, 119, 100, 121]).buffer; + return res( + ctx.set('Content-Length', imageBuffer.byteLength.toString()), + ctx.set('Content-Type', 'image/jpeg'), + ctx.body(imageBuffer), + ); + }, + ), + ); + response = { + cookie: jest.fn(), + end: jest.fn(), + json: jest.fn(), + setHeader: jest.fn(), + status: jest.fn(), + } as unknown as jest.Mocked; + response.status.mockReturnValue(response); + }); + + describe('#start', () => { + const randomBytes = jest.spyOn( + crypto, + 'randomBytes', + ) as unknown as jest.MockedFunction<(size: number) => Buffer>; + + afterEach(() => { + randomBytes.mockRestore(); + }); + + it('redirects to authorize URL', async () => { + randomBytes.mockReturnValue(Buffer.from(nonce, 'base64')); + + await provider.start( + { + query: { + env: 'development', + scope: 'email openid profile User.Read', + }, + } as unknown as express.Request, + response, + ); + + expect(response.setHeader).toHaveBeenCalledWith( + 'Location', + 'https://login.microsoftonline.com/tenantId/oauth2/v2.0/authorize' + + '?response_type=code' + + `&redirect_uri=${encodeURIComponent( + 'http://backstage.test/api/auth/microsoft/handler/frame', + )}` + + `&scope=${encodeURIComponent('email openid profile User.Read')}` + + `&state=${state}` + + '&client_id=clientId', + ); + }); + }); + + describe('#handle', () => { + it('returns provider info and profile with photo data', async () => { + await provider.frameHandler( + { + query: { + env: 'development', + code: microsoftApi.generateAuthCode( + 'email openid profile User.Read', + ), + state, + }, + cookies: { + 'microsoft-nonce': nonce, + }, + } as unknown as express.Request, + response, + ); + + expect(response.end).toHaveBeenCalledWith( + expect.stringContaining( + encodeURIComponent( + JSON.stringify({ + type: 'authorization_response', + response: { + providerInfo: { + accessToken: microsoftApi.generateAccessToken( + 'email openid profile User.Read', + ), + scope: 'email openid profile User.Read', + expiresInSeconds: 123, + idToken: 'header.e30K.microsoft', + }, + profile: { + email: 'conrad@example.com', + picture: 'data:image/jpeg;base64,aG93ZHk=', + displayName: 'Conrad', + }, + backstageIdentity: { + token: mockBackstageToken, + identity: { + type: 'user', + userEntityRef: 'user:default/mock', + ownershipEntityRefs: [], + }, + }, + }, + }), + ), + ), + ); + }); + + it('returns access token for non-microsoft graph scope', async () => { + await provider.frameHandler( + { + query: { + env: 'development', + code: microsoftApi.generateAuthCode('aks-audience/user.read'), + state, + }, + cookies: { + 'microsoft-nonce': nonce, + }, + } as unknown as express.Request, + response, + ); + + expect(response.end).toHaveBeenCalledWith( + expect.stringContaining( + encodeURIComponent( + JSON.stringify({ + type: 'authorization_response', + response: { + providerInfo: { + accessToken: microsoftApi.generateAccessToken( + 'aks-audience/user.read', + ), + scope: 'aks-audience/user.read', + expiresInSeconds: 123, + }, + profile: {}, + }, + }), + ), + ), + ); + }); + + it('sets refresh token', async () => { + await provider.frameHandler( + { + query: { + env: 'development', + code: microsoftApi.generateAuthCode( + 'email offline_access openid profile User.Read', + ), + state, + }, + cookies: { + 'microsoft-nonce': nonce, + }, + } as unknown as express.Request, + response, + ); + + expect(response.cookie).toHaveBeenCalledWith( + 'microsoft-refresh-token', + microsoftApi.generateRefreshToken( + 'email offline_access openid profile User.Read', + ), + { + domain: 'backstage.test', + httpOnly: true, + maxAge: 86400000000, + path: '/api/auth/microsoft', + sameSite: 'lax', + secure: false, + }, + ); + }); + + it('omits photo data when fetching it fails', async () => { + server.use( + rest.get('https://graph.microsoft.com/v1.0/me/photos/*', (_, res) => + res.networkError('remote hung up'), + ), + ); + + await provider.frameHandler( + { + query: { + env: 'development', + code: microsoftApi.generateAuthCode( + 'email openid profile User.Read', + ), + state, + }, + cookies: { + 'microsoft-nonce': nonce, + }, + } as unknown as express.Request, + response, + ); + + expect(response.end).toHaveBeenCalledWith( + expect.stringContaining( + encodeURIComponent( + JSON.stringify({ + type: 'authorization_response', + response: { + providerInfo: { + accessToken: microsoftApi.generateAccessToken( + 'email openid profile User.Read', + ), + scope: 'email openid profile User.Read', + expiresInSeconds: 123, + idToken: 'header.e30K.microsoft', + }, + profile: { + email: 'conrad@example.com', + displayName: 'Conrad', + }, + backstageIdentity: { + token: mockBackstageToken, + identity: { + type: 'user', + userEntityRef: 'user:default/mock', + ownershipEntityRefs: [], + }, + }, + }, + }), + ), + ), + ); + }); + }); + + describe('#refresh', () => { + it('returns provider info and profile with photo data', async () => { + await provider.refresh!( + { + query: { + env: 'development', + scope: 'email openid profile User.Read', + }, + header: jest.fn(_ => 'XMLHttpRequest'), + cookies: { + 'microsoft-refresh-token': microsoftApi.generateRefreshToken( + 'email openid profile User.Read', + ), + }, + get: jest.fn(), + } as unknown as express.Request, + response, + ); + + expect(response.json).toHaveBeenCalledWith( + expect.objectContaining({ + providerInfo: { + accessToken: microsoftApi.generateAccessToken( + 'email openid profile User.Read', + ), + scope: 'email openid profile User.Read', + expiresInSeconds: 123, + idToken: 'header.e30K.microsoft', + }, + profile: { + email: 'conrad@example.com', + picture: 'data:image/jpeg;base64,aG93ZHk=', + displayName: 'Conrad', + }, + }), + ); + }); + + it('returns access token for non-microsoft graph scope', async () => { + await provider.refresh!( + { + query: { + env: 'development', + scope: 'aks-audience/user.read', + }, + header: jest.fn(_ => 'XMLHttpRequest'), + cookies: { + 'microsoft-refresh-token': microsoftApi.generateRefreshToken( + 'aks-audience/user.read', + ), + }, + get: jest.fn(), + } as unknown as express.Request, + response, + ); + + expect(response.json).toHaveBeenCalledWith({ + providerInfo: { + accessToken: microsoftApi.generateAccessToken( + 'aks-audience/user.read', + ), + expiresInSeconds: 123, + scope: 'aks-audience/user.read', + }, + profile: {}, + }); + }); + + it('returns backstage identity', async () => { + await provider.refresh!( + { + query: { + env: 'development', + scope: 'email openid profile User.Read', + }, + header: jest.fn(_ => 'XMLHttpRequest'), + cookies: { + 'microsoft-refresh-token': microsoftApi.generateRefreshToken( + 'email openid profile User.Read', + ), + }, + get: jest.fn(), + } as unknown as express.Request, + response, + ); + + expect(response.json).toHaveBeenCalledWith( + expect.objectContaining({ + backstageIdentity: expect.objectContaining({ + token: mockBackstageToken, + }), + }), + ); + }); + }); +}); diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index 8947c7432b..8fc8459f10 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -14,25 +14,218 @@ * limitations under the License. */ -import { SignInResolver, AuthHandler } from '../types'; -import { OAuthResult } from '../../lib/oauth'; +import express from 'express'; +import passport from 'passport'; +import { Strategy as MicrosoftStrategy } from 'passport-microsoft'; +import { + encodeState, + OAuthAdapter, + OAuthEnvironmentHandler, + OAuthHandlers, + OAuthProviderOptions, + OAuthRefreshRequest, + OAuthResponse, + OAuthResult, + OAuthStartRequest, +} from '../../lib/oauth'; +import { + executeFetchUserProfileStrategy, + executeFrameHandlerStrategy, + executeRedirectStrategy, + executeRefreshTokenStrategy, + makeProfileInfo, + PassportDoneCallback, +} from '../../lib/passport'; +import { + AuthHandler, + OAuthStartResponse, + SignInResolver, + AuthResolverContext, +} from '../types'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; import { - commonSignInResolvers, - createOAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, - adaptOAuthSignInResolverToLegacy, -} from '../../lib/legacy'; -import { - microsoftAuthenticator, - microsoftSignInResolvers, -} from '@backstage/plugin-auth-backend-module-microsoft-provider'; + commonByEmailLocalPartResolver, + commonByEmailResolver, +} from '../resolvers'; +import { LoggerService } from '@backstage/backend-plugin-api'; +import fetch from 'node-fetch'; +import { decodeJwt } from 'jose'; +import { Profile as PassportProfile } from 'passport'; +import { BACKSTAGE_SESSION_EXPIRATION } from '../../lib/session'; + +type PrivateInfo = { + refreshToken: string; +}; + +type Options = OAuthProviderOptions & { + signInResolver?: SignInResolver; + authHandler: AuthHandler; + logger: LoggerService; + resolverContext: AuthResolverContext; + authorizationUrl?: string; + tokenUrl?: string; +}; + +export class MicrosoftAuthProvider implements OAuthHandlers { + private readonly _strategy: MicrosoftStrategy; + private readonly signInResolver?: SignInResolver; + private readonly authHandler: AuthHandler; + private readonly logger: LoggerService; + private readonly resolverContext: AuthResolverContext; + + constructor(options: Options) { + this.signInResolver = options.signInResolver; + this.authHandler = options.authHandler; + this.logger = options.logger; + this.resolverContext = options.resolverContext; + + this._strategy = new MicrosoftStrategy( + { + clientID: options.clientId, + clientSecret: options.clientSecret, + callbackURL: options.callbackUrl, + authorizationURL: options.authorizationUrl, + tokenURL: options.tokenUrl, + passReqToCallback: false, + skipUserProfile: ( + accessToken: string, + done: (err: unknown, skip: boolean) => void, + ) => { + done(null, this.skipUserProfile(accessToken)); + }, + }, + ( + accessToken: any, + refreshToken: any, + params: any, + fullProfile: passport.Profile, + done: PassportDoneCallback, + ) => { + done(undefined, { fullProfile, accessToken, params }, { refreshToken }); + }, + ); + } + + private skipUserProfile = (accessToken: string): boolean => { + const { aud, scp } = decodeJwt(accessToken); + const hasGraphReadScope = + aud === '00000003-0000-0000-c000-000000000000' && + (scp as string) + .split(' ') + .map(s => s.toLowerCase()) + .includes('user.read'); + return !hasGraphReadScope; + }; + + async start(req: OAuthStartRequest): Promise { + return await executeRedirectStrategy(req, this._strategy, { + scope: req.scope, + state: encodeState(req.state), + }); + } + + async handler(req: express.Request) { + const { result, privateInfo } = await executeFrameHandlerStrategy< + OAuthResult, + PrivateInfo + >(req, this._strategy); + + return { + response: await this.handleResult(result), + refreshToken: privateInfo.refreshToken, + }; + } + + async refresh(req: OAuthRefreshRequest) { + const { accessToken, refreshToken, params } = + await executeRefreshTokenStrategy( + this._strategy, + req.refreshToken, + req.scope, + ); + + return { + response: await this.handleResult({ + params, + accessToken, + ...(!this.skipUserProfile(accessToken) && { + fullProfile: await executeFetchUserProfileStrategy( + this._strategy, + accessToken, + ), + }), + }), + refreshToken, + }; + } + + private async handleResult(result: { + fullProfile?: PassportProfile; + params: { + id_token?: string; + scope: string; + expires_in: number; + }; + accessToken: string; + refreshToken?: string; + }): Promise { + let profile = {}; + if (result.fullProfile) { + const photo = await this.getUserPhoto(result.accessToken); + result.fullProfile.photos = photo ? [{ value: photo }] : undefined; + ({ profile } = await this.authHandler( + result as OAuthResult, + this.resolverContext, + )); + } + + const expiresInSeconds = + result.params.expires_in === undefined + ? BACKSTAGE_SESSION_EXPIRATION + : Math.min(result.params.expires_in, BACKSTAGE_SESSION_EXPIRATION); + + return { + providerInfo: { + accessToken: result.accessToken, + scope: result.params.scope, + expiresInSeconds, + ...{ idToken: result.params.id_token }, + }, + profile, + ...(result.fullProfile && + this.signInResolver && { + backstageIdentity: await this.signInResolver( + { result: result as OAuthResult, profile }, + this.resolverContext, + ), + }), + }; + } + + private async getUserPhoto(accessToken: string): Promise { + try { + const res = await fetch( + 'https://graph.microsoft.com/v1.0/me/photos/48x48/$value', + { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }, + ); + const data = await res.buffer(); + + return `data:image/jpeg;base64,${data.toString('base64')}`; + } catch (error) { + this.logger.warn( + `Could not retrieve user profile photo from Microsoft Graph API: ${error}`, + ); + return undefined; + } + } +} /** - * Auth provider integration for GitLab auth + * Auth provider integration for Microsoft auth * * @public */ @@ -48,21 +241,75 @@ export const microsoft = createAuthProviderIntegration({ * Configure sign-in for this provider, without it the provider can not be used to sign users in. */ signIn?: { + /** + * Maps an auth result to a Backstage identity for the user. + */ resolver: SignInResolver; }; }) { - return createOAuthProviderFactory({ - authenticator: microsoftAuthenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); + return ({ providerId, globalConfig, config, logger, resolverContext }) => + OAuthEnvironmentHandler.mapConfig(config, envConfig => { + const clientId = envConfig.getString('clientId'); + const clientSecret = envConfig.getString('clientSecret'); + const tenantId = envConfig.getString('tenantId'); + + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const authorizationUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize`; + const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`; + + const authHandler: AuthHandler = options?.authHandler + ? options.authHandler + : async ({ fullProfile, params }) => ({ + profile: makeProfileInfo(fullProfile ?? {}, params.id_token), + }); + + const provider = new MicrosoftAuthProvider({ + clientId, + clientSecret, + callbackUrl, + authorizationUrl, + tokenUrl, + authHandler, + signInResolver: options?.signIn?.resolver, + logger, + resolverContext, + }); + + return OAuthAdapter.fromConfig(globalConfig, provider, { + providerId, + callbackUrl, + }); + }); + }, + resolvers: { + /** + * Looks up the user by matching their email local part to the entity name. + */ + emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver, + /** + * Looks up the user by matching their email to the entity email. + */ + emailMatchingUserEntityProfileEmail: () => commonByEmailResolver, + /** + * Looks up the user by matching their email to the `microsoft.com/email` annotation. + */ + emailMatchingUserEntityAnnotation(): SignInResolver { + return async (info, ctx) => { + const { profile } = info; + + if (!profile.email) { + throw new Error('Microsoft profile contained no email'); + } + + return ctx.signInWithCatalogUser({ + annotations: { + 'microsoft.com/email': profile.email, + }, + }); + }; + }, }, - resolvers: adaptOAuthSignInResolverToLegacy({ - emailLocalPartMatchingUserEntityName: - commonSignInResolvers.emailLocalPartMatchingUserEntityName(), - emailMatchingUserEntityProfileEmail: - commonSignInResolvers.emailMatchingUserEntityProfileEmail(), - emailMatchingUserEntityAnnotation: - microsoftSignInResolvers.emailMatchingUserEntityAnnotation(), - }), }); diff --git a/yarn.lock b/yarn.lock index deb4f1a532..fddf4643ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4827,7 +4827,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-microsoft-provider@workspace:^, @backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-provider": +"@backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-provider" dependencies: @@ -4904,7 +4904,6 @@ __metadata: "@backstage/plugin-auth-backend-module-github-provider": "workspace:^" "@backstage/plugin-auth-backend-module-gitlab-provider": "workspace:^" "@backstage/plugin-auth-backend-module-google-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-microsoft-provider": "workspace:^" "@backstage/plugin-auth-backend-module-oauth2-provider": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" From 11aa8d4ee86b868150483b912502fb83fc4b40f4 Mon Sep 17 00:00:00 2001 From: Alex Eftimie Date: Mon, 23 Oct 2023 10:51:16 +0000 Subject: [PATCH 335/348] Update api-reports Signed-off-by: Alex Eftimie --- plugins/scaffolder-backend/api-report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index ba7576b1bb..1f8615b477 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -659,6 +659,7 @@ export const createPublishGithubPullRequestAction: ( reviewers?: string[] | undefined; teamReviewers?: string[] | undefined; commitMessage?: string | undefined; + update?: boolean | undefined; }, JsonObject >; From c5aa242ce3ce66fde76abd7916ea863bbccaa507 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 23 Oct 2023 14:28:27 +0200 Subject: [PATCH 336/348] Update plugins/code-coverage-backend/README.md Signed-off-by: Patrik Oldsberg --- plugins/code-coverage-backend/README.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md index 4d5c473c56..2b22b0ad1d 100644 --- a/plugins/code-coverage-backend/README.md +++ b/plugins/code-coverage-backend/README.md @@ -74,20 +74,7 @@ The code coverage backend plugin has support for the [new backend system](https: In your `packages/backend/src/index.ts` make the following changes: ```diff - import { createBackend } from '@backstage/backend-defaults'; -+ import { codeCoveragePlugin } from '@backstage/plugin-code-coverage-backend'; - const backend = createBackend(); - // ... other feature additions -+ backend.add(codeCoveragePlugin()); - backend.start(); -``` - -Alternatively, you can actually remove the import line above, and do this instead. - -```diff - backend.add(explorePlugin()); + backend.add(import('@backstage/plugin-explore-backend')); - ``` ## Configuring your entity From 2b91568fa3c4ddeee8e982621c06a57ee1cd5544 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 21 Oct 2023 13:07:53 +0200 Subject: [PATCH 337/348] refactor(catalog): rename filters extensions file Signed-off-by: Camila Belo --- ...uiltInFilterExtensions.tsx => filters.tsx} | 2 +- plugins/catalog/src/alpha/plugin.tsx | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) rename plugins/catalog/src/alpha/{builtInFilterExtensions.tsx => filters.tsx} (98%) diff --git a/plugins/catalog/src/alpha/builtInFilterExtensions.tsx b/plugins/catalog/src/alpha/filters.tsx similarity index 98% rename from plugins/catalog/src/alpha/builtInFilterExtensions.tsx rename to plugins/catalog/src/alpha/filters.tsx index 5a7575c4f5..7b73c2d14b 100644 --- a/plugins/catalog/src/alpha/builtInFilterExtensions.tsx +++ b/plugins/catalog/src/alpha/filters.tsx @@ -109,7 +109,7 @@ const CatalogUserListFilter = createCatalogFilterExtension({ }, }); -export const builtInFilterExtensions = [ +export default [ CatalogEntityTagFilter, CatalogEntityKindFilter, CatalogEntityTypeFilter, diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index d9d2878213..9f6094d288 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -15,7 +15,9 @@ */ import React from 'react'; +import Grid from '@material-ui/core/Grid'; import HomeIcon from '@material-ui/icons/Home'; + import { createApiFactory, discoveryApiRef, @@ -23,7 +25,6 @@ import { storageApiRef, } from '@backstage/core-plugin-api'; import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; -import { CatalogClient } from '@backstage/catalog-client'; import { createApiExtension, createPageExtension, @@ -32,6 +33,8 @@ import { coreExtensionData, createExtensionInput, } from '@backstage/frontend-plugin-api'; + +import { CatalogClient } from '@backstage/catalog-client'; import { AsyncEntityProvider, catalogApiRef, @@ -44,6 +47,7 @@ import { entityContentTitleExtensionDataRef, } from '@backstage/plugin-catalog-react/alpha'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; + import { DefaultStarredEntitiesApi } from '../apis'; import { createComponentRouteRef, @@ -51,9 +55,9 @@ import { rootRouteRef, viewTechDocRouteRef, } from '../routes'; -import { builtInFilterExtensions } from './builtInFilterExtensions'; import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; -import Grid from '@material-ui/core/Grid'; + +import filters from './filters'; /** @alpha */ export const CatalogApi = createApiExtension({ @@ -99,8 +103,11 @@ const CatalogIndexPage = createPageExtension({ }, loader: async ({ inputs }) => { const { BaseCatalogPage } = await import('../components/CatalogPage'); - const filters = inputs.filters.map(filter => filter.element); - return {filters}} />; + return ( + {inputs.filters.map(filter => filter.element)}} + /> + ); }, }); @@ -188,6 +195,7 @@ export default createPlugin({ createFromTemplate: convertLegacyRouteRef(createFromTemplateRouteRef), }, extensions: [ + ...filters, CatalogApi, StarredEntitiesApi, CatalogSearchResultListItemExtension, @@ -196,6 +204,5 @@ export default createPlugin({ CatalogNavItem, OverviewEntityContent, EntityAboutCard, - ...builtInFilterExtensions, ], }); From 12e562f379e4fecf145aba298750d2d983e9d808 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 21 Oct 2023 13:10:22 +0200 Subject: [PATCH 338/348] refactor(catalog): extract apis extensions file Signed-off-by: Camila Belo --- plugins/catalog/src/alpha/apis.tsx | 51 ++++++++++++++++++++++++++++ plugins/catalog/src/alpha/plugin.tsx | 37 ++------------------ 2 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 plugins/catalog/src/alpha/apis.tsx diff --git a/plugins/catalog/src/alpha/apis.tsx b/plugins/catalog/src/alpha/apis.tsx new file mode 100644 index 0000000000..a887a33a04 --- /dev/null +++ b/plugins/catalog/src/alpha/apis.tsx @@ -0,0 +1,51 @@ +/* + * Copyright 2023 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 { + createApiFactory, + discoveryApiRef, + fetchApiRef, + storageApiRef, +} from '@backstage/core-plugin-api'; +import { CatalogClient } from '@backstage/catalog-client'; +import { createApiExtension } from '@backstage/frontend-plugin-api'; +import { + catalogApiRef, + starredEntitiesApiRef, +} from '@backstage/plugin-catalog-react'; +import { DefaultStarredEntitiesApi } from '../apis'; + +export const CatalogApi = createApiExtension({ + factory: createApiFactory({ + api: catalogApiRef, + deps: { + discoveryApi: discoveryApiRef, + fetchApi: fetchApiRef, + }, + factory: ({ discoveryApi, fetchApi }) => + new CatalogClient({ discoveryApi, fetchApi }), + }), +}); + +export const StarredEntitiesApi = createApiExtension({ + factory: createApiFactory({ + api: starredEntitiesApiRef, + deps: { storageApi: storageApiRef }, + factory: ({ storageApi }) => new DefaultStarredEntitiesApi({ storageApi }), + }), +}); + +export default [CatalogApi, StarredEntitiesApi]; diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index 9f6094d288..c40bb55aa5 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -18,15 +18,8 @@ import React from 'react'; import Grid from '@material-ui/core/Grid'; import HomeIcon from '@material-ui/icons/Home'; -import { - createApiFactory, - discoveryApiRef, - fetchApiRef, - storageApiRef, -} from '@backstage/core-plugin-api'; import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; import { - createApiExtension, createPageExtension, createPlugin, createNavItemExtension, @@ -34,12 +27,9 @@ import { createExtensionInput, } from '@backstage/frontend-plugin-api'; -import { CatalogClient } from '@backstage/catalog-client'; import { AsyncEntityProvider, - catalogApiRef, entityRouteRef, - starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; import { createEntityContentExtension, @@ -48,7 +38,6 @@ import { } from '@backstage/plugin-catalog-react/alpha'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; -import { DefaultStarredEntitiesApi } from '../apis'; import { createComponentRouteRef, createFromTemplateRouteRef, @@ -57,30 +46,9 @@ import { } from '../routes'; import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; +import apis from './apis'; import filters from './filters'; -/** @alpha */ -export const CatalogApi = createApiExtension({ - factory: createApiFactory({ - api: catalogApiRef, - deps: { - discoveryApi: discoveryApiRef, - fetchApi: fetchApiRef, - }, - factory: ({ discoveryApi, fetchApi }) => - new CatalogClient({ discoveryApi, fetchApi }), - }), -}); - -/** @alpha */ -export const StarredEntitiesApi = createApiExtension({ - factory: createApiFactory({ - api: starredEntitiesApiRef, - deps: { storageApi: storageApiRef }, - factory: ({ storageApi }) => new DefaultStarredEntitiesApi({ storageApi }), - }), -}); - /** @alpha */ export const CatalogSearchResultListItemExtension = createSearchResultListItemExtension({ @@ -195,9 +163,8 @@ export default createPlugin({ createFromTemplate: convertLegacyRouteRef(createFromTemplateRouteRef), }, extensions: [ + ...apis, ...filters, - CatalogApi, - StarredEntitiesApi, CatalogSearchResultListItemExtension, CatalogIndexPage, CatalogEntityPage, From 3f65bb7208b93cbbed295be3d8098989947e9ef9 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 21 Oct 2023 13:12:00 +0200 Subject: [PATCH 339/348] refactor(catalog): extract pages extensions file Signed-off-by: Camila Belo --- plugins/catalog/src/alpha/pages.tsx | 83 ++++++++++++++++++++++++++++ plugins/catalog/src/alpha/plugin.tsx | 66 +--------------------- 2 files changed, 86 insertions(+), 63 deletions(-) create mode 100644 plugins/catalog/src/alpha/pages.tsx diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx new file mode 100644 index 0000000000..6270ae777d --- /dev/null +++ b/plugins/catalog/src/alpha/pages.tsx @@ -0,0 +1,83 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { + createPageExtension, + coreExtensionData, + createExtensionInput, +} from '@backstage/frontend-plugin-api'; +import { + AsyncEntityProvider, + entityRouteRef, +} from '@backstage/plugin-catalog-react'; +import { entityContentTitleExtensionDataRef } from '@backstage/plugin-catalog-react/alpha'; +import { rootRouteRef } from '../routes'; +import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; + +export const CatalogIndexPage = createPageExtension({ + id: 'plugin.catalog.page.index', + defaultPath: '/catalog', + routeRef: convertLegacyRouteRef(rootRouteRef), + inputs: { + filters: createExtensionInput({ + element: coreExtensionData.reactElement, + }), + }, + loader: async ({ inputs }) => { + const { BaseCatalogPage } = await import('../components/CatalogPage'); + const filters = inputs.filters.map(filter => filter.element); + return {filters}} />; + }, +}); + +export const CatalogEntityPage = createPageExtension({ + id: 'plugin.catalog.page.entity', + defaultPath: '/catalog/:namespace/:kind/:name', + routeRef: convertLegacyRouteRef(entityRouteRef), + inputs: { + contents: createExtensionInput({ + element: coreExtensionData.reactElement, + path: coreExtensionData.routePath, + routeRef: coreExtensionData.routeRef.optional(), + title: entityContentTitleExtensionDataRef, + }), + }, + loader: async ({ inputs }) => { + const { EntityLayout } = await import('../components/EntityLayout'); + const Component = () => { + return ( + + + {inputs.contents.map(content => ( + + {content.element} + + ))} + + + ); + }; + return ; + }, +}); + +export default [CatalogIndexPage, CatalogEntityPage]; diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index c40bb55aa5..67d1f036ee 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -20,21 +20,16 @@ import HomeIcon from '@material-ui/icons/Home'; import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; import { - createPageExtension, createPlugin, createNavItemExtension, coreExtensionData, createExtensionInput, } from '@backstage/frontend-plugin-api'; -import { - AsyncEntityProvider, - entityRouteRef, -} from '@backstage/plugin-catalog-react'; +import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { createEntityContentExtension, createEntityCardExtension, - entityContentTitleExtensionDataRef, } from '@backstage/plugin-catalog-react/alpha'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; @@ -44,9 +39,9 @@ import { rootRouteRef, viewTechDocRouteRef, } from '../routes'; -import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; import apis from './apis'; +import pages from './pages'; import filters from './filters'; /** @alpha */ @@ -60,60 +55,6 @@ export const CatalogSearchResultListItemExtension = ), }); -const CatalogIndexPage = createPageExtension({ - id: 'plugin.catalog.page.index', - defaultPath: '/catalog', - routeRef: convertLegacyRouteRef(rootRouteRef), - inputs: { - filters: createExtensionInput({ - element: coreExtensionData.reactElement, - }), - }, - loader: async ({ inputs }) => { - const { BaseCatalogPage } = await import('../components/CatalogPage'); - return ( - {inputs.filters.map(filter => filter.element)}} - /> - ); - }, -}); - -const CatalogEntityPage = createPageExtension({ - id: 'plugin.catalog.page.entity', - defaultPath: '/catalog/:namespace/:kind/:name', - routeRef: convertLegacyRouteRef(entityRouteRef), - inputs: { - contents: createExtensionInput({ - element: coreExtensionData.reactElement, - path: coreExtensionData.routePath, - routeRef: coreExtensionData.routeRef.optional(), - title: entityContentTitleExtensionDataRef, - }), - }, - loader: async ({ inputs }) => { - const { EntityLayout } = await import('../components/EntityLayout'); - const Component = () => { - return ( - - - {inputs.contents.map(content => ( - - {content.element} - - ))} - - - ); - }; - return ; - }, -}); - const EntityAboutCard = createEntityCardExtension({ id: 'about', loader: async () => @@ -164,10 +105,9 @@ export default createPlugin({ }, extensions: [ ...apis, + ...pages, ...filters, CatalogSearchResultListItemExtension, - CatalogIndexPage, - CatalogEntityPage, CatalogNavItem, OverviewEntityContent, EntityAboutCard, From 870e4186eff059dabcb23117adc301f197997faa Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 21 Oct 2023 13:13:04 +0200 Subject: [PATCH 340/348] refactor(catalog): extract entity cards extensions file Signed-off-by: Camila Belo --- plugins/catalog/src/alpha/entityCards.tsx | 173 ++++++++++++++++++++++ plugins/catalog/src/alpha/plugin.tsx | 16 +- 2 files changed, 176 insertions(+), 13 deletions(-) create mode 100644 plugins/catalog/src/alpha/entityCards.tsx diff --git a/plugins/catalog/src/alpha/entityCards.tsx b/plugins/catalog/src/alpha/entityCards.tsx new file mode 100644 index 0000000000..9faf0b9517 --- /dev/null +++ b/plugins/catalog/src/alpha/entityCards.tsx @@ -0,0 +1,173 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; +import { createSchemaFromZod } from '@backstage/frontend-plugin-api'; + +export const EntityAboutCard = createEntityCardExtension({ + id: 'about', + configSchema: createSchemaFromZod(z => + z.object({ + variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), + }), + ), + loader: async ({ config }) => + import('../components/AboutCard').then(m => ( + + )), +}); + +export const EntityLinksCard = createEntityCardExtension({ + id: 'links', + configSchema: createSchemaFromZod(z => + z.object({ + variant: z.enum(['gridItem', 'flex', 'fullHeight']).optional(), + cols: z + .union([ + z.number(), + z.object({ + xs: z.number(), + sm: z.number(), + md: z.number(), + lg: z.number(), + xl: z.number(), + }), + ]) + .optional(), + }), + ), + loader: async ({ config }) => + import('../components/EntityLinksCard').then(m => { + return ; + }), +}); + +export const EntityLabelsCard = createEntityCardExtension({ + id: 'labels', + configSchema: createSchemaFromZod(z => + z.object({ + variant: z.enum(['gridItem', 'flex', 'fullHeight']).optional(), + title: z.string().optional(), + }), + ), + loader: async ({ config }) => + import('../components/EntityLabelsCard').then(m => ( + + )), +}); + +export const EntityDependsOnComponentsCard = createEntityCardExtension({ + id: 'dependsOn.components', + configSchema: createSchemaFromZod(z => + z.object({ + variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), + title: z.string().optional(), + // TODO: columns, tableOptions + }), + ), + loader: async ({ config }) => + import('../components/DependsOnComponentsCard').then(m => ( + + )), +}); + +export const EntityDependsOnResourcesCard = createEntityCardExtension({ + id: 'dependsOn.resources', + configSchema: createSchemaFromZod(z => + z.object({ + variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), + title: z.string().optional(), + // TODO: columns, tableOptions + }), + ), + loader: async ({ config }) => + import('../components/DependsOnResourcesCard').then(m => ( + + )), +}); + +export const EntityHasComponentsCard = createEntityCardExtension({ + id: 'has.components', + configSchema: createSchemaFromZod(z => + z.object({ + variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), + title: z.string().optional(), + }), + ), + loader: async ({ config }) => + import('../components/HasComponentsCard').then(m => ( + + )), +}); + +export const EntityHasResourcesCard = createEntityCardExtension({ + id: 'has.resources', + configSchema: createSchemaFromZod(z => + z.object({ + variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), + title: z.string().optional(), + }), + ), + loader: async ({ config }) => + import('../components/HasResourcesCard').then(m => ( + + )), +}); + +export const EntityHasSubcomponentsCard = createEntityCardExtension({ + id: 'has.subcomponents', + configSchema: createSchemaFromZod(z => + z.object({ + variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), + title: z.string().optional(), + // TODO: tableOptions + }), + ), + loader: async ({ config }) => + import('../components/HasSubcomponentsCard').then(m => ( + + )), +}); + +export const EntityHasSystemsCard = createEntityCardExtension({ + id: 'has.systems', + configSchema: createSchemaFromZod(z => + z.object({ + variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), + title: z.string().optional(), + }), + ), + loader: async ({ config }) => + import('../components/HasSystemsCard').then(m => ( + + )), +}); + +export default [ + EntityAboutCard, + EntityLinksCard, + EntityLabelsCard, + EntityDependsOnComponentsCard, + EntityDependsOnResourcesCard, + EntityHasComponentsCard, + EntityHasResourcesCard, + EntityHasSubcomponentsCard, + EntityHasSystemsCard, +]; diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index 67d1f036ee..761a00c29b 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -27,10 +27,7 @@ import { } from '@backstage/frontend-plugin-api'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; -import { - createEntityContentExtension, - createEntityCardExtension, -} from '@backstage/plugin-catalog-react/alpha'; +import { createEntityContentExtension } from '@backstage/plugin-catalog-react/alpha'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; import { @@ -43,6 +40,7 @@ import { import apis from './apis'; import pages from './pages'; import filters from './filters'; +import entityCards from './entityCards'; /** @alpha */ export const CatalogSearchResultListItemExtension = @@ -55,14 +53,6 @@ export const CatalogSearchResultListItemExtension = ), }); -const EntityAboutCard = createEntityCardExtension({ - id: 'about', - loader: async () => - import('../components/AboutCard').then(m => ( - - )), -}); - const OverviewEntityContent = createEntityContentExtension({ id: 'overview', defaultPath: '/', @@ -107,9 +97,9 @@ export default createPlugin({ ...apis, ...pages, ...filters, + ...entityCards, CatalogSearchResultListItemExtension, CatalogNavItem, OverviewEntityContent, - EntityAboutCard, ], }); From 81497c8a4125cf779d3f12d53c8d1f504d413d7d Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 21 Oct 2023 13:17:02 +0200 Subject: [PATCH 341/348] refactor(catalog): extract nav items extensions file Signed-off-by: Camila Belo --- plugins/catalog/src/alpha/navItems.tsx | 29 ++++++++++++++++++++++++++ plugins/catalog/src/alpha/plugin.tsx | 12 ++--------- 2 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 plugins/catalog/src/alpha/navItems.tsx diff --git a/plugins/catalog/src/alpha/navItems.tsx b/plugins/catalog/src/alpha/navItems.tsx new file mode 100644 index 0000000000..b6481fd764 --- /dev/null +++ b/plugins/catalog/src/alpha/navItems.tsx @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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 HomeIcon from '@material-ui/icons/Home'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { createNavItemExtension } from '@backstage/frontend-plugin-api'; +import { rootRouteRef } from '../routes'; + +export const CatalogIndexNavItem = createNavItemExtension({ + id: 'catalog.nav.index', + routeRef: convertLegacyRouteRef(rootRouteRef), + title: 'Catalog', + icon: HomeIcon, +}); + +export default [CatalogIndexNavItem]; diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index 761a00c29b..10e516874f 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -16,12 +16,10 @@ import React from 'react'; import Grid from '@material-ui/core/Grid'; -import HomeIcon from '@material-ui/icons/Home'; import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; import { createPlugin, - createNavItemExtension, coreExtensionData, createExtensionInput, } from '@backstage/frontend-plugin-api'; @@ -40,6 +38,7 @@ import { import apis from './apis'; import pages from './pages'; import filters from './filters'; +import navItems from './navItems'; import entityCards from './entityCards'; /** @alpha */ @@ -74,13 +73,6 @@ const OverviewEntityContent = createEntityContentExtension({ ), }); -const CatalogNavItem = createNavItemExtension({ - id: 'catalog.nav.index', - routeRef: convertLegacyRouteRef(rootRouteRef), - title: 'Catalog', - icon: HomeIcon, -}); - /** @alpha */ export default createPlugin({ id: 'catalog', @@ -97,9 +89,9 @@ export default createPlugin({ ...apis, ...pages, ...filters, + ...navItems, ...entityCards, CatalogSearchResultListItemExtension, - CatalogNavItem, OverviewEntityContent, ], }); From 29ccace57b72f2a44c576291456ae518b16bf67b Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 21 Oct 2023 13:19:47 +0200 Subject: [PATCH 342/348] refactor(catalog): extract search result items extensions file Signed-off-by: Camila Belo --- plugins/catalog/src/alpha/plugin.tsx | 15 ++-------- .../catalog/src/alpha/searchResultItems.tsx | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 plugins/catalog/src/alpha/searchResultItems.tsx diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index 10e516874f..2c85e2bc51 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -26,7 +26,6 @@ import { import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { createEntityContentExtension } from '@backstage/plugin-catalog-react/alpha'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; import { createComponentRouteRef, @@ -40,17 +39,7 @@ import pages from './pages'; import filters from './filters'; import navItems from './navItems'; import entityCards from './entityCards'; - -/** @alpha */ -export const CatalogSearchResultListItemExtension = - createSearchResultListItemExtension({ - id: 'catalog', - predicate: result => result.type === 'software-catalog', - component: () => - import('../components/CatalogSearchResultListItem').then( - m => m.CatalogSearchResultListItem, - ), - }); +import searchResultItems from './searchResultItems'; const OverviewEntityContent = createEntityContentExtension({ id: 'overview', @@ -91,7 +80,7 @@ export default createPlugin({ ...filters, ...navItems, ...entityCards, - CatalogSearchResultListItemExtension, + ...searchResultItems, OverviewEntityContent, ], }); diff --git a/plugins/catalog/src/alpha/searchResultItems.tsx b/plugins/catalog/src/alpha/searchResultItems.tsx new file mode 100644 index 0000000000..f677869136 --- /dev/null +++ b/plugins/catalog/src/alpha/searchResultItems.tsx @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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 { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; + +export const CatalogSearchResultListItemExtension = + createSearchResultListItemExtension({ + id: 'catalog', + predicate: result => result.type === 'software-catalog', + component: () => + import('../components/CatalogSearchResultListItem').then( + m => m.CatalogSearchResultListItem, + ), + }); + +export default [CatalogSearchResultListItemExtension]; From 24dced7352c44eb3f093bd7bd64a89206660226d Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 21 Oct 2023 17:37:22 +0200 Subject: [PATCH 343/348] refactor(catalog): extract entity contentes extensions file Signed-off-by: Camila Belo --- plugins/catalog/src/alpha/entityContents.tsx | 46 ++++++++++++++++++++ plugins/catalog/src/alpha/plugin.tsx | 34 ++------------- 2 files changed, 49 insertions(+), 31 deletions(-) create mode 100644 plugins/catalog/src/alpha/entityContents.tsx diff --git a/plugins/catalog/src/alpha/entityContents.tsx b/plugins/catalog/src/alpha/entityContents.tsx new file mode 100644 index 0000000000..0e26373b5e --- /dev/null +++ b/plugins/catalog/src/alpha/entityContents.tsx @@ -0,0 +1,46 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { Grid } from '@material-ui/core'; +import { + coreExtensionData, + createExtensionInput, +} from '@backstage/frontend-plugin-api'; +import { createEntityContentExtension } from '@backstage/plugin-catalog-react/alpha'; + +export const OverviewEntityContent = createEntityContentExtension({ + id: 'overview', + defaultPath: '/', + defaultTitle: 'Overview', + disabled: false, + inputs: { + cards: createExtensionInput({ + element: coreExtensionData.reactElement, + }), + }, + loader: async ({ inputs }) => ( + + {inputs.cards.map(card => ( + + {card.element} + + ))} + + ), +}); + +export default [OverviewEntityContent]; diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index 2c85e2bc51..2f019ca33e 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -14,18 +14,10 @@ * limitations under the License. */ -import React from 'react'; -import Grid from '@material-ui/core/Grid'; - import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; -import { - createPlugin, - coreExtensionData, - createExtensionInput, -} from '@backstage/frontend-plugin-api'; +import { createPlugin } from '@backstage/frontend-plugin-api'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; -import { createEntityContentExtension } from '@backstage/plugin-catalog-react/alpha'; import { createComponentRouteRef, @@ -39,29 +31,9 @@ import pages from './pages'; import filters from './filters'; import navItems from './navItems'; import entityCards from './entityCards'; +import entityContents from './entityContents'; import searchResultItems from './searchResultItems'; -const OverviewEntityContent = createEntityContentExtension({ - id: 'overview', - defaultPath: '/', - defaultTitle: 'Overview', - disabled: false, - inputs: { - cards: createExtensionInput({ - element: coreExtensionData.reactElement, - }), - }, - loader: async ({ inputs }) => ( - - {inputs.cards.map(card => ( - - {card.element} - - ))} - - ), -}); - /** @alpha */ export default createPlugin({ id: 'catalog', @@ -80,7 +52,7 @@ export default createPlugin({ ...filters, ...navItems, ...entityCards, + ...entityContents, ...searchResultItems, - OverviewEntityContent, ], }); From 8a8445663b49d22ebb8ad52b871400d192818b27 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 21 Oct 2023 13:33:31 +0200 Subject: [PATCH 344/348] chore: add changeset file Signed-off-by: Camila Belo --- .changeset/fast-bears-lick.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fast-bears-lick.md diff --git a/.changeset/fast-bears-lick.md b/.changeset/fast-bears-lick.md new file mode 100644 index 0000000000..8e0dc8e60b --- /dev/null +++ b/.changeset/fast-bears-lick.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Migrate catalog entity cards to new frontend system extension format. From 150f2a8797eb9414d13b809d269690ab58a86f7c Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 23 Oct 2023 14:28:24 +0200 Subject: [PATCH 345/348] refactor(catalog): remove cards config for now Signed-off-by: Camila Belo --- plugins/catalog/src/alpha/entityCards.tsx | 107 ++++------------------ 1 file changed, 18 insertions(+), 89 deletions(-) diff --git a/plugins/catalog/src/alpha/entityCards.tsx b/plugins/catalog/src/alpha/entityCards.tsx index 9faf0b9517..cc30928fcf 100644 --- a/plugins/catalog/src/alpha/entityCards.tsx +++ b/plugins/catalog/src/alpha/entityCards.tsx @@ -16,147 +16,76 @@ import React from 'react'; import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; -import { createSchemaFromZod } from '@backstage/frontend-plugin-api'; export const EntityAboutCard = createEntityCardExtension({ id: 'about', - configSchema: createSchemaFromZod(z => - z.object({ - variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), - }), - ), - loader: async ({ config }) => + loader: async () => import('../components/AboutCard').then(m => ( - + )), }); export const EntityLinksCard = createEntityCardExtension({ id: 'links', - configSchema: createSchemaFromZod(z => - z.object({ - variant: z.enum(['gridItem', 'flex', 'fullHeight']).optional(), - cols: z - .union([ - z.number(), - z.object({ - xs: z.number(), - sm: z.number(), - md: z.number(), - lg: z.number(), - xl: z.number(), - }), - ]) - .optional(), - }), - ), - loader: async ({ config }) => + loader: async () => import('../components/EntityLinksCard').then(m => { - return ; + return ; }), }); export const EntityLabelsCard = createEntityCardExtension({ id: 'labels', - configSchema: createSchemaFromZod(z => - z.object({ - variant: z.enum(['gridItem', 'flex', 'fullHeight']).optional(), - title: z.string().optional(), - }), - ), - loader: async ({ config }) => + loader: async () => import('../components/EntityLabelsCard').then(m => ( - + )), }); export const EntityDependsOnComponentsCard = createEntityCardExtension({ id: 'dependsOn.components', - configSchema: createSchemaFromZod(z => - z.object({ - variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), - title: z.string().optional(), - // TODO: columns, tableOptions - }), - ), - loader: async ({ config }) => + loader: async () => import('../components/DependsOnComponentsCard').then(m => ( - + )), }); export const EntityDependsOnResourcesCard = createEntityCardExtension({ id: 'dependsOn.resources', - configSchema: createSchemaFromZod(z => - z.object({ - variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), - title: z.string().optional(), - // TODO: columns, tableOptions - }), - ), - loader: async ({ config }) => + loader: async () => import('../components/DependsOnResourcesCard').then(m => ( - + )), }); export const EntityHasComponentsCard = createEntityCardExtension({ id: 'has.components', - configSchema: createSchemaFromZod(z => - z.object({ - variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), - title: z.string().optional(), - }), - ), - loader: async ({ config }) => + loader: async () => import('../components/HasComponentsCard').then(m => ( - + )), }); export const EntityHasResourcesCard = createEntityCardExtension({ id: 'has.resources', - configSchema: createSchemaFromZod(z => - z.object({ - variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), - title: z.string().optional(), - }), - ), - loader: async ({ config }) => + loader: async () => import('../components/HasResourcesCard').then(m => ( - + )), }); export const EntityHasSubcomponentsCard = createEntityCardExtension({ id: 'has.subcomponents', - configSchema: createSchemaFromZod(z => - z.object({ - variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), - title: z.string().optional(), - // TODO: tableOptions - }), - ), - loader: async ({ config }) => + loader: async () => import('../components/HasSubcomponentsCard').then(m => ( - + )), }); export const EntityHasSystemsCard = createEntityCardExtension({ id: 'has.systems', - configSchema: createSchemaFromZod(z => - z.object({ - variant: z.enum(['gridItem', 'flex', 'fullHeight']).default('gridItem'), - title: z.string().optional(), - }), - ), - loader: async ({ config }) => + loader: async () => import('../components/HasSystemsCard').then(m => ( - + )), }); From 5b46f06a4f1956a55e190308198045f6797febda Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 23 Oct 2023 16:32:55 +0200 Subject: [PATCH 346/348] chore: fix needless re-rendering Signed-off-by: blam --- .../src/next/components/Form/Form.tsx | 45 +++++++++++-------- .../src/next/components/Stepper/Stepper.tsx | 7 ++- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Form/Form.tsx b/plugins/scaffolder-react/src/next/components/Form/Form.tsx index 85e75e2c0d..8717c8b55a 100644 --- a/plugins/scaffolder-react/src/next/components/Form/Form.tsx +++ b/plugins/scaffolder-react/src/next/components/Form/Form.tsx @@ -32,27 +32,34 @@ const WrappedForm = withTheme(MuiTheme); export const Form = (props: PropsWithChildren) => { // This is where we unbreak the changes from RJSF, and make it work with our custom fields so we don't pass on this // breaking change to our users. We will look more into a better API for this in scaffolderv2. - const wrappedFields = Object.fromEntries( - Object.entries(props.fields ?? {}).map(([key, Component]) => [ - key, - (wrapperProps: FieldProps) => { - return ( - - ); - }, - ]), + const wrappedFields = React.useMemo( + () => + Object.fromEntries( + Object.entries(props.fields ?? {}).map(([key, Component]) => [ + key, + (wrapperProps: FieldProps) => { + return ( + + ); + }, + ]), + ), + [props.fields], ); - const templates = { - FieldTemplate, - DescriptionFieldTemplate, - ...props.templates, - }; + const templates = React.useMemo( + () => ({ + FieldTemplate, + DescriptionFieldTemplate, + ...props.templates, + }), + [props.templates], + ); return ( diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 1e43eba770..23e97c67e4 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -115,6 +115,11 @@ export const Stepper = (stepperProps: StepperProps) => { ); }, [props.extensions]); + const fields = useMemo( + () => ({ ...FieldOverrides, ...extensions }), + [extensions], + ); + const validators = useMemo(() => { return Object.fromEntries( props.extensions.map(({ name, validation }) => [name, validation]), @@ -197,7 +202,7 @@ export const Stepper = (stepperProps: StepperProps) => { schema={currentStep.schema} uiSchema={currentStep.uiSchema} onSubmit={handleNext} - fields={{ ...FieldOverrides, ...extensions }} + fields={fields} showErrorList={false} onChange={handleChange} {...(props.formProps ?? {})} From 120ec0965a2739ccf593ef6d5d683e58f145a5d2 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 23 Oct 2023 17:40:14 +0200 Subject: [PATCH 347/348] chore(home): pin react-grid-layout to 1.3.4 Signed-off-by: Camila Belo --- plugins/home/package.json | 2 +- yarn.lock | 25 ++++++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/plugins/home/package.json b/plugins/home/package.json index edb7e6542d..5db7347f7c 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -67,7 +67,7 @@ "@types/react": "^16.13.1 || ^17.0.0", "lodash": "^4.17.21", "luxon": "^3.4.3", - "react-grid-layout": "^1.3.4", + "react-grid-layout": "1.3.4", "react-resizable": "^3.0.4", "react-use": "^17.2.4", "zod": "^3.21.4" diff --git a/yarn.lock b/yarn.lock index 70667644f7..7f4d77db75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7275,7 +7275,7 @@ __metadata: lodash: ^4.17.21 luxon: ^3.4.3 msw: ^1.0.0 - react-grid-layout: ^1.3.4 + react-grid-layout: 1.3.4 react-resizable: ^3.0.4 react-use: ^17.2.4 zod: ^3.21.4 @@ -32278,7 +32278,7 @@ __metadata: languageName: node linkType: hard -"lodash.isequal@npm:^4.5.0": +"lodash.isequal@npm:^4.0.0, lodash.isequal@npm:^4.5.0": version: 4.5.0 resolution: "lodash.isequal@npm:4.5.0" checksum: da27515dc5230eb1140ba65ff8de3613649620e8656b19a6270afe4866b7bd461d9ba2ac8a48dcc57f7adac4ee80e1de9f965d89d4d81a0ad52bb3eec2609644 @@ -37555,7 +37555,7 @@ __metadata: languageName: node linkType: hard -"react-draggable@npm:^4.0.3, react-draggable@npm:^4.4.5": +"react-draggable@npm:^4.0.0, react-draggable@npm:^4.0.3": version: 4.4.6 resolution: "react-draggable@npm:4.4.6" dependencies: @@ -37623,20 +37623,19 @@ __metadata: languageName: node linkType: hard -"react-grid-layout@npm:^1.3.4": - version: 1.4.2 - resolution: "react-grid-layout@npm:1.4.2" +"react-grid-layout@npm:1.3.4": + version: 1.3.4 + resolution: "react-grid-layout@npm:1.3.4" dependencies: - clsx: ^2.0.0 - fast-equals: ^4.0.3 + clsx: ^1.1.1 + lodash.isequal: ^4.0.0 prop-types: ^15.8.1 - react-draggable: ^4.4.5 - react-resizable: ^3.0.5 - resize-observer-polyfill: ^1.5.1 + react-draggable: ^4.0.0 + react-resizable: ^3.0.4 peerDependencies: react: ">= 16.3.0" react-dom: ">= 16.3.0" - checksum: a052d38c290b18e1c513a3b939757c239887009b7f175814b472d007708962870960d3b20d4a15dbdeb955ac55434ce6c5e5e5f8c850cfbdcc90f75c318f1d58 + checksum: f56c8c452acd9588edf1dc6996a4ea14d9f669d77f6b2ebd50146eaeeb9325c83f5ca44b66bac2b8c24f9cb2ec7ed49396350435991255c3b31e21b8a2e3d243 languageName: node linkType: hard @@ -37868,7 +37867,7 @@ __metadata: languageName: node linkType: hard -"react-resizable@npm:^3.0.4, react-resizable@npm:^3.0.5": +"react-resizable@npm:^3.0.4": version: 3.0.5 resolution: "react-resizable@npm:3.0.5" dependencies: From cc0e8d0b51ae3008239b198168c664e45e5d0b06 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 23 Oct 2023 17:48:31 +0200 Subject: [PATCH 348/348] docs: add changeset file Signed-off-by: Camila Belo --- .changeset/small-buckets-roll.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/small-buckets-roll.md diff --git a/.changeset/small-buckets-roll.md b/.changeset/small-buckets-roll.md new file mode 100644 index 0000000000..5cd9b23678 --- /dev/null +++ b/.changeset/small-buckets-roll.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Temporarily pin the `react-grid-layout` sub-dependency to version `1.3.4` while the horizontal resizing of the latest version is not fixed. For more details, see [#20712](https://github.com/backstage/backstage/issues/20712).