From e8258d002a3a35de7585aeacc3fdd769f272ef60 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 3 Feb 2026 10:36:49 +0100 Subject: [PATCH 1/3] catalog: remove summary entity card type Removes the 'summary' type from EntityCardType while keeping runtime support for backward compatibility. Signed-off-by: Patrik Oldsberg Signed-off-by: Patrik Oldsberg --- .changeset/remove-summary-card-type.md | 7 ++++ .changeset/summary-card-backward-compat.md | 5 +++ plugins/api-docs/report-alpha.api.md | 24 +++++------ plugins/catalog-graph/report-alpha.api.md | 4 +- plugins/catalog-react/report-alpha.api.md | 6 +-- .../blueprints/EntityCardBlueprint.test.tsx | 1 - .../src/alpha/blueprints/extensionData.tsx | 3 +- plugins/catalog/report-alpha.api.md | 40 +++++++++---------- .../src/alpha/DefaultEntityContentLayout.tsx | 11 ++++- plugins/org/report-alpha.api.md | 16 ++++---- 10 files changed, 68 insertions(+), 49 deletions(-) create mode 100644 .changeset/remove-summary-card-type.md create mode 100644 .changeset/summary-card-backward-compat.md diff --git a/.changeset/remove-summary-card-type.md b/.changeset/remove-summary-card-type.md new file mode 100644 index 0000000000..8052445e69 --- /dev/null +++ b/.changeset/remove-summary-card-type.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog-react': minor +--- + +**BREAKING**: Removed the 'summary' entity card type from `EntityCardType`. Users should migrate to using 'content' or 'info' card types instead. + +TypeScript will now show errors if you try to use `type: 'summary'` when creating entity cards. diff --git a/.changeset/summary-card-backward-compat.md b/.changeset/summary-card-backward-compat.md new file mode 100644 index 0000000000..e76d1426b0 --- /dev/null +++ b/.changeset/summary-card-backward-compat.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +The default entity content layout still supports rendering summary cards at runtime for backward compatibility, but logs a console warning when they are detected to help identify where migration is needed. diff --git a/plugins/api-docs/report-alpha.api.md b/plugins/api-docs/report-alpha.api.md index 1a035bc706..2b42b528aa 100644 --- a/plugins/api-docs/report-alpha.api.md +++ b/plugins/api-docs/report-alpha.api.md @@ -86,11 +86,11 @@ const _default: OverridableFrontendPlugin< name: 'consumed-apis'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -127,11 +127,11 @@ const _default: OverridableFrontendPlugin< name: 'consuming-components'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -168,11 +168,11 @@ const _default: OverridableFrontendPlugin< name: 'definition'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -209,11 +209,11 @@ const _default: OverridableFrontendPlugin< name: 'has-apis'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -250,11 +250,11 @@ const _default: OverridableFrontendPlugin< name: 'provided-apis'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -291,11 +291,11 @@ const _default: OverridableFrontendPlugin< name: 'providing-components'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog-graph/report-alpha.api.md b/plugins/catalog-graph/report-alpha.api.md index 2ce85431e8..fce2dc1bec 100644 --- a/plugins/catalog-graph/report-alpha.api.md +++ b/plugins/catalog-graph/report-alpha.api.md @@ -92,7 +92,7 @@ const _default: OverridableFrontendPlugin< title: string | undefined; height: number | undefined; filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { height?: number | undefined; @@ -107,7 +107,7 @@ const _default: OverridableFrontendPlugin< relationPairs?: [string, string][] | undefined; unidirectional?: boolean | undefined; filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index 22ac105eeb..d4cdf44742 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -192,11 +192,11 @@ export const EntityCardBlueprint: ExtensionBlueprint<{ inputs: {}; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; dataRefs: { filterFunction: ConfigurableExtensionDataRef< @@ -218,7 +218,7 @@ export const EntityCardBlueprint: ExtensionBlueprint<{ }>; // @alpha (undocumented) -export type EntityCardType = 'summary' | 'info' | 'content'; +export type EntityCardType = 'info' | 'content'; // @alpha export const EntityContentBlueprint: ExtensionBlueprint<{ diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx index af04673ad1..ef823e7edf 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx @@ -177,7 +177,6 @@ describe('EntityCardBlueprint', () => { }, "type": { "enum": [ - "summary", "info", "content", ], diff --git a/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx b/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx index 0a52ce2c5c..c304ccf7eb 100644 --- a/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx @@ -56,13 +56,12 @@ export const entityContentGroupDataRef = createExtensionDataRef().with({ * Available entity card types */ export const entityCardTypes = [ - 'summary', 'info', 'content', ] as const satisfies readonly EntityCardType[]; /** @alpha */ -export type EntityCardType = 'summary' | 'info' | 'content'; +export type EntityCardType = 'info' | 'content'; /** @internal */ export const entityCardTypeDataRef = diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index 950b7a4383..7f68ba4c72 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -293,11 +293,11 @@ const _default: OverridableFrontendPlugin< 'entity-card:catalog/about': OverridableExtensionDefinition<{ config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -363,11 +363,11 @@ const _default: OverridableFrontendPlugin< name: 'depends-on-components'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -404,11 +404,11 @@ const _default: OverridableFrontendPlugin< name: 'depends-on-resources'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -445,11 +445,11 @@ const _default: OverridableFrontendPlugin< name: 'has-components'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -486,11 +486,11 @@ const _default: OverridableFrontendPlugin< name: 'has-resources'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -527,11 +527,11 @@ const _default: OverridableFrontendPlugin< name: 'has-subcomponents'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -568,11 +568,11 @@ const _default: OverridableFrontendPlugin< name: 'has-subdomains'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -609,11 +609,11 @@ const _default: OverridableFrontendPlugin< name: 'has-systems'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -650,11 +650,11 @@ const _default: OverridableFrontendPlugin< name: 'labels'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -691,11 +691,11 @@ const _default: OverridableFrontendPlugin< name: 'links'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx b/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx index d0bb4aeb8d..fa753e7e4a 100644 --- a/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx +++ b/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx @@ -137,11 +137,20 @@ export function DefaultEntityContentLayout(props: EntityContentLayoutProps) { const { cards } = props; const infoCards = cards.filter(card => card.type === 'info'); - const summaryCards = cards.filter(card => card.type === 'summary'); + // Keep support for 'summary' type at runtime for backward compatibility + // even though it's been removed from the type system + const summaryCards = cards.filter(card => card.type === ('summary' as any)); const contentCards = cards.filter( card => !card.type || card.type === 'content', ); + if (summaryCards.length > 0) { + // eslint-disable-next-line no-console + console.warn( + "The 'summary' entity card type has been removed. Please update your cards to use 'content' or 'info' types instead.", + ); + } + const classes = useStyles({ infoCards: !!infoCards.length, summaryCards: !!summaryCards.length, diff --git a/plugins/org/report-alpha.api.md b/plugins/org/report-alpha.api.md index cfd2290502..f6c3dcff2b 100644 --- a/plugins/org/report-alpha.api.md +++ b/plugins/org/report-alpha.api.md @@ -25,11 +25,11 @@ const _default: OverridableFrontendPlugin< name: 'group-profile'; config: { filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -66,13 +66,13 @@ const _default: OverridableFrontendPlugin< initialRelationAggregation: 'direct' | 'aggregated' | undefined; showAggregateMembersToggle: boolean | undefined; filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { showAggregateMembersToggle?: boolean | undefined; initialRelationAggregation?: 'direct' | 'aggregated' | undefined; filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -112,14 +112,14 @@ const _default: OverridableFrontendPlugin< showAggregateMembersToggle: boolean | undefined; ownedKinds: string[] | undefined; filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { showAggregateMembersToggle?: boolean | undefined; initialRelationAggregation?: 'direct' | 'aggregated' | undefined; ownedKinds?: string[] | undefined; filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -158,13 +158,13 @@ const _default: OverridableFrontendPlugin< maxRelations: number | undefined; hideIcons: boolean; filter: EntityPredicate | undefined; - type: 'content' | 'summary' | 'info' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { hideIcons?: boolean | undefined; maxRelations?: number | undefined; filter?: EntityPredicate | undefined; - type?: 'content' | 'summary' | 'info' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef From ba2f6ff647215ee0b8940efe4fa3637a57675ec9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Feb 2026 11:34:48 +0000 Subject: [PATCH 2/3] Initial plan From 5071208398c4ea14ce76ffba2f9d88dcf5c72b08 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Feb 2026 11:39:12 +0000 Subject: [PATCH 3/3] Prevent console warning spam by logging only once Co-authored-by: Rugvip <4984472+Rugvip@users.noreply.github.com> --- plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx b/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx index fa753e7e4a..f18ce1b193 100644 --- a/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx +++ b/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx @@ -32,6 +32,9 @@ import { } from '../components/EntityProcessingErrorsPanel'; import { HorizontalScrollGrid } from '@backstage/core-components'; +// Module-level flag to ensure deprecation warning is only logged once +let hasLoggedSummaryWarning = false; + const useStyles = makeStyles< Theme, { infoCards: boolean; summaryCards: boolean; contentCards: boolean } @@ -144,7 +147,8 @@ export function DefaultEntityContentLayout(props: EntityContentLayoutProps) { card => !card.type || card.type === 'content', ); - if (summaryCards.length > 0) { + if (summaryCards.length > 0 && !hasLoggedSummaryWarning) { + hasLoggedSummaryWarning = true; // eslint-disable-next-line no-console console.warn( "The 'summary' entity card type has been removed. Please update your cards to use 'content' or 'info' types instead.",