From 6a77ebee420d9772d544fee2baef35406e82ab68 Mon Sep 17 00:00:00 2001 From: Yi Cai Date: Fri, 24 Jul 2026 14:23:04 -0400 Subject: [PATCH 1/7] chore(scorecard): promote scorecard NFS plugin from /alpha to stable Signed-off-by: Yi Cai --- .../graduate-nfs-alpha-to-stable.md | 5 + .../scorecard/packages/app-legacy/src/App.tsx | 2 +- workspaces/scorecard/packages/app/src/App.tsx | 2 +- .../scorecard/plugins/scorecard/README.md | 11 +- .../scorecard/plugins/scorecard/dev/index.tsx | 2 +- .../scorecard/plugins/scorecard/package.json | 16 ++ .../plugins/scorecard/report-alpha.api.md | 129 ---------------- .../plugins/scorecard/report-legacy.api.md | 145 ++++++++++++++++++ .../report-scorecard-catalog-module.api.md | 13 ++ .../report-scorecard-home-module.api.md | 13 ++ ...eport-scorecard-translations-module.api.md | 13 ++ .../scorecard/plugins/scorecard/report.api.md | 137 ++++++++++++++++- .../plugins/scorecard/src/alpha/index.tsx | 86 +---------- .../scorecard/plugins/scorecard/src/index.ts | 90 +++++++++-- .../plugins/scorecard/src/legacyExports.ts | 36 +++++ .../plugins/scorecard/src/nfsExports.test.tsx | 39 +++++ .../src/scorecardCatalogModuleExport.ts | 17 ++ .../src/scorecardHomeModuleExport.ts | 17 ++ .../src/scorecardTranslationsModuleExport.ts | 17 ++ 19 files changed, 555 insertions(+), 235 deletions(-) create mode 100644 workspaces/scorecard/.changeset/graduate-nfs-alpha-to-stable.md create mode 100644 workspaces/scorecard/plugins/scorecard/report-legacy.api.md create mode 100644 workspaces/scorecard/plugins/scorecard/report-scorecard-catalog-module.api.md create mode 100644 workspaces/scorecard/plugins/scorecard/report-scorecard-home-module.api.md create mode 100644 workspaces/scorecard/plugins/scorecard/report-scorecard-translations-module.api.md create mode 100644 workspaces/scorecard/plugins/scorecard/src/legacyExports.ts create mode 100644 workspaces/scorecard/plugins/scorecard/src/nfsExports.test.tsx create mode 100644 workspaces/scorecard/plugins/scorecard/src/scorecardCatalogModuleExport.ts create mode 100644 workspaces/scorecard/plugins/scorecard/src/scorecardHomeModuleExport.ts create mode 100644 workspaces/scorecard/plugins/scorecard/src/scorecardTranslationsModuleExport.ts diff --git a/workspaces/scorecard/.changeset/graduate-nfs-alpha-to-stable.md b/workspaces/scorecard/.changeset/graduate-nfs-alpha-to-stable.md new file mode 100644 index 00000000000..0a6c3d037f2 --- /dev/null +++ b/workspaces/scorecard/.changeset/graduate-nfs-alpha-to-stable.md @@ -0,0 +1,5 @@ +--- +'@red-hat-developer-hub/backstage-plugin-scorecard': minor +--- + +Graduate the New Frontend System (NFS) plugin from the `./alpha` export to the primary `./` entry point. OFS (legacy) exports are now available at `./legacy`. Translations remain at `./alpha`. diff --git a/workspaces/scorecard/packages/app-legacy/src/App.tsx b/workspaces/scorecard/packages/app-legacy/src/App.tsx index 197695b3d59..849d79bf6de 100644 --- a/workspaces/scorecard/packages/app-legacy/src/App.tsx +++ b/workspaces/scorecard/packages/app-legacy/src/App.tsx @@ -51,7 +51,6 @@ import { AppRouter, FlatRoutes } from '@backstage/core-app-api'; import { CatalogGraphPage } from '@backstage/plugin-catalog-graph'; import { RequirePermission } from '@backstage/plugin-permission-react'; import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha'; -import { scorecardTranslations } from '@red-hat-developer-hub/backstage-plugin-scorecard/alpha'; import { githubAuthApiRef } from '@backstage/core-plugin-api'; import { getThemes } from '@red-hat-developer-hub/backstage-plugin-theme'; import { @@ -60,6 +59,7 @@ import { ScorecardErrorStatusIcon, ScorecardSuccessStatusIcon, ScorecardWarningStatusIcon, + scorecardTranslations, } from '@red-hat-developer-hub/backstage-plugin-scorecard'; import { ScalprumContext, ScalprumState } from '@scalprum/react-core'; diff --git a/workspaces/scorecard/packages/app/src/App.tsx b/workspaces/scorecard/packages/app/src/App.tsx index ae3442da72f..85338369b93 100644 --- a/workspaces/scorecard/packages/app/src/App.tsx +++ b/workspaces/scorecard/packages/app/src/App.tsx @@ -25,7 +25,7 @@ import scorecardPlugin, { scorecardHomeModule, scorecardTranslationsModule, scorecardCatalogModule, -} from '@red-hat-developer-hub/backstage-plugin-scorecard/alpha'; +} from '@red-hat-developer-hub/backstage-plugin-scorecard'; import { signInModule } from './modules/signIn'; import { navModule } from './modules/nav'; import { iconsModule } from './modules/icons'; diff --git a/workspaces/scorecard/plugins/scorecard/README.md b/workspaces/scorecard/plugins/scorecard/README.md index afe20c90a48..ed28e4b3ed3 100644 --- a/workspaces/scorecard/plugins/scorecard/README.md +++ b/workspaces/scorecard/plugins/scorecard/README.md @@ -2,7 +2,7 @@ The Scorecard plugin provides a configurable framework to visualize Key Performance Indicators (KPIs) in Backstage. This frontend plugin integrates with the Scorecard backend to deliver Scorecards. -The plugin supports both the **legacy** Backstage frontend and the **New Frontend System (NFS)**. Use the main package for legacy apps and the `/alpha` export for NFS apps. For NFS, the plugin currently provides three modules: a catalog module for the Scorecard entity tab, a home module for homepage widgets, and a translations module. +The plugin supports both the **legacy** Backstage frontend and the **New Frontend System (NFS)**. NFS is the primary package entry point. OFS (legacy) exports are available at `./legacy` (and are also re-exported from the main entry for compatibility). Translations remain available at `./alpha`. For NFS, the plugin provides three modules: a catalog module for the Scorecard entity tab, a home module for homepage widgets, and a translations module. **Features:** - **Entity scorecard tab** — View scorecard metrics on catalog entity pages (components, websites, etc.). @@ -44,19 +44,20 @@ yarn workspace app-legacy add @red-hat-developer-hub/backstage-plugin-scorecard yarn workspace app add @red-hat-developer-hub/backstage-plugin-scorecard ``` -2. Register the plugin in `packages/app/src/App.tsx` using the **alpha** export: +2. Register the plugin in `packages/app/src/App.tsx`: ```tsx // In packages/app/src/App.tsx import { createApp } from '@backstage/frontend-defaults'; - import { + import scorecardPlugin, { scorecardHomeModule, scorecardTranslationsModule, scorecardCatalogModule, - } from '@red-hat-developer-hub/backstage-plugin-scorecard/alpha'; + } from '@red-hat-developer-hub/backstage-plugin-scorecard'; const app = createApp({ features: [ + scorecardPlugin, scorecardHomeModule, scorecardCatalogModule, scorecardTranslationsModule, @@ -255,7 +256,7 @@ To align with the legacy EntityPage (Scorecard on component pages and default en ##### Modules and extensions (NFS) -The following modules and extensions are available from `@red-hat-developer-hub/backstage-plugin-scorecard/alpha` for NFS apps: +The following modules and extensions are available from `@red-hat-developer-hub/backstage-plugin-scorecard` for NFS apps: **Modules** diff --git a/workspaces/scorecard/plugins/scorecard/dev/index.tsx b/workspaces/scorecard/plugins/scorecard/dev/index.tsx index 1b3d9df76d6..8a7831e241f 100644 --- a/workspaces/scorecard/plugins/scorecard/dev/index.tsx +++ b/workspaces/scorecard/plugins/scorecard/dev/index.tsx @@ -52,7 +52,7 @@ import scorecardPlugin, { scorecardCatalogModule, scorecardHomeModule, scorecardTranslationsModule, -} from '../src/alpha'; +} from '../src'; import { scorecardApiRef } from '../src/api'; import { MockScorecardApi, mockCatalogApi } from './mocks'; diff --git a/workspaces/scorecard/plugins/scorecard/package.json b/workspaces/scorecard/plugins/scorecard/package.json index 65accbccbbe..aad6905d786 100644 --- a/workspaces/scorecard/plugins/scorecard/package.json +++ b/workspaces/scorecard/plugins/scorecard/package.json @@ -7,6 +7,10 @@ "exports": { ".": "./src/index.ts", "./alpha": "./src/alpha/index.tsx", + "./legacy": "./src/legacyExports.ts", + "./scorecard-catalog-module": "./src/scorecardCatalogModuleExport.ts", + "./scorecard-home-module": "./src/scorecardHomeModuleExport.ts", + "./scorecard-translations-module": "./src/scorecardTranslationsModuleExport.ts", "./package.json": "./package.json" }, "typesVersions": { @@ -14,6 +18,18 @@ "alpha": [ "src/alpha/index.tsx" ], + "legacy": [ + "src/legacyExports.ts" + ], + "scorecard-catalog-module": [ + "src/scorecardCatalogModuleExport.ts" + ], + "scorecard-home-module": [ + "src/scorecardHomeModuleExport.ts" + ], + "scorecard-translations-module": [ + "src/scorecardTranslationsModuleExport.ts" + ], "package.json": [ "package.json" ] diff --git a/workspaces/scorecard/plugins/scorecard/report-alpha.api.md b/workspaces/scorecard/plugins/scorecard/report-alpha.api.md index 91cfc1a13df..20f6e779701 100644 --- a/workspaces/scorecard/plugins/scorecard/report-alpha.api.md +++ b/workspaces/scorecard/plugins/scorecard/report-alpha.api.md @@ -3,135 +3,9 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AnyApiFactory } from '@backstage/frontend-plugin-api'; -import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { ApiFactory } from '@backstage/frontend-plugin-api'; -import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; -import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionInput } from '@backstage/frontend-plugin-api'; -import { FrontendModule } from '@backstage/frontend-plugin-api'; -import { IconElement } from '@backstage/frontend-plugin-api'; -import { JSX as JSX_2 } from 'react'; -import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; -import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; -import { RouteRef } from '@backstage/core-plugin-api'; -import { RouteRef as RouteRef_2 } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/frontend-plugin-api'; import { TranslationResource } from '@backstage/frontend-plugin-api'; -// @alpha -const _default: OverridableFrontendPlugin< - { - root: RouteRef; - drillDown: RouteRef<{ - aggregationId: string; - metricId: string; - }>; - }, - {}, - { - 'api:scorecard': OverridableExtensionDefinition<{ - kind: 'api'; - name: undefined; - config: {}; - configInput: {}; - output: ExtensionDataRef; - inputs: {}; - params: < - TApi, - TImpl extends TApi, - TDeps extends { [name in string]: unknown }, - >( - params: ApiFactory, - ) => ExtensionBlueprintParams; - }>; - 'page:scorecard': OverridableExtensionDefinition<{ - kind: 'page'; - name: undefined; - config: { - path: string | undefined; - title: string | undefined; - }; - configInput: { - path?: string | undefined; - title?: string | undefined; - }; - output: - | ExtensionDataRef - | ExtensionDataRef - | ExtensionDataRef< - RouteRef_2, - 'core.routing.ref', - { - optional: true; - } - > - | ExtensionDataRef< - string, - 'core.title', - { - optional: true; - } - > - | ExtensionDataRef< - IconElement, - 'core.icon', - { - optional: true; - } - >; - inputs: { - pages: ExtensionInput< - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - RouteRef_2, - 'core.routing.ref', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - string, - 'core.title', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - IconElement, - 'core.icon', - { - optional: true; - } - >, - { - singleton: false; - optional: false; - internal: false; - } - >; - }; - params: { - path: string; - title?: string; - icon?: IconElement; - loader?: () => Promise; - routeRef?: RouteRef_2; - noHeader?: boolean; - }; - }>; - } ->; -export default _default; - -// @alpha -export const scorecardCatalogModule: FrontendModule; - -// @alpha -export const scorecardHomeModule: FrontendModule; - // @public export const scorecardTranslationRef: TranslationRef< 'plugin.scorecard', @@ -250,8 +124,5 @@ export const scorecardTranslationRef: TranslationRef< // @public export const scorecardTranslations: TranslationResource<'plugin.scorecard'>; -// @alpha -export const scorecardTranslationsModule: FrontendModule; - // (No @packageDocumentation comment for this package) ``` diff --git a/workspaces/scorecard/plugins/scorecard/report-legacy.api.md b/workspaces/scorecard/plugins/scorecard/report-legacy.api.md new file mode 100644 index 00000000000..090d0032b8b --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard/report-legacy.api.md @@ -0,0 +1,145 @@ +## API Report File for "@red-hat-developer-hub/backstage-plugin-scorecard" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { JSX as JSX_2 } from 'react/jsx-runtime'; +import { default as ScorecardErrorStatusIcon } from '@mui/icons-material/DangerousOutlined'; +import { default as ScorecardSuccessStatusIcon } from '@mui/icons-material/CheckCircleOutline'; +import { default as ScorecardWarningStatusIcon } from '@mui/icons-material/WarningAmber'; +import { TranslationRef } from '@backstage/frontend-plugin-api'; +import { TranslationResource } from '@backstage/frontend-plugin-api'; + +// @public +export const EntityScorecardContent: () => JSX_2.Element; + +export { ScorecardErrorStatusIcon }; + +// @public +export const ScorecardHomepageCard: (props: { + metricId?: string; + aggregationId?: string; + showSubheader?: boolean; + showInfo?: boolean; +}) => JSX_2.Element; + +// @public +export const ScorecardPage: () => JSX_2.Element; + +// @public +export const scorecardPlugin: BackstagePlugin<{}, {}, {}>; + +export { ScorecardSuccessStatusIcon }; + +// @public +export const scorecardTranslationRef: TranslationRef< + 'plugin.scorecard', + { + readonly 'emptyState.title': string; + readonly 'emptyState.description': string; + readonly 'emptyState.button': string; + readonly 'emptyState.altText': string; + readonly 'notFound.title': string; + readonly 'notFound.description': string; + readonly 'notFound.altText': string; + readonly 'notFound.readMore': string; + readonly 'notFound.goBack': string; + readonly 'notFound.contactSupport': string; + readonly 'permissionRequired.title': string; + readonly 'permissionRequired.description': string; + readonly 'permissionRequired.button': string; + readonly 'permissionRequired.altText': string; + readonly 'common.loading': string; + readonly 'errors.entityMissingProperties': string; + readonly 'errors.missingAggregationId': string; + readonly 'errors.invalidApiResponse': string; + readonly 'errors.fetchError': string; + readonly 'errors.metricDataUnavailable': string; + readonly 'errors.invalidThresholds': string; + readonly 'errors.missingPermission': string; + readonly 'errors.noDataFound': string; + readonly 'errors.authenticationError': string; + readonly 'errors.missingPermissionMessage': string; + readonly 'errors.userNotFoundInCatalogMessage': string; + readonly 'errors.noDataFoundMessage': string; + readonly 'errors.unsupportedAggregationType': string; + readonly 'errors.authenticationErrorMessage': string; + readonly 'metric.github.openPRs.title': string; + readonly 'metric.github.openPRs.description': string; + readonly 'metric.jira.openIssues.title': string; + readonly 'metric.jira.openIssues.description': string; + readonly 'metric.sonarqube.qualityGate.title': string; + readonly 'metric.sonarqube.qualityGate.description': string; + readonly 'metric.sonarqube.openIssues.title': string; + readonly 'metric.sonarqube.openIssues.description': string; + readonly 'metric.sonarqube.securityRating.title': string; + readonly 'metric.sonarqube.securityRating.description': string; + readonly 'metric.sonarqube.securityIssues.title': string; + readonly 'metric.sonarqube.securityIssues.description': string; + readonly 'metric.sonarqube.securityReviewRating.title': string; + readonly 'metric.sonarqube.securityReviewRating.description': string; + readonly 'metric.sonarqube.securityHotspots.title': string; + readonly 'metric.sonarqube.securityHotspots.description': string; + readonly 'metric.sonarqube.reliabilityRating.title': string; + readonly 'metric.sonarqube.reliabilityRating.description': string; + readonly 'metric.sonarqube.reliabilityIssues.title': string; + readonly 'metric.sonarqube.reliabilityIssues.description': string; + readonly 'metric.sonarqube.maintainabilityRating.title': string; + readonly 'metric.sonarqube.maintainabilityRating.description': string; + readonly 'metric.sonarqube.maintainabilityIssues.title': string; + readonly 'metric.sonarqube.maintainabilityIssues.description': string; + readonly 'metric.sonarqube.codeCoverage.title': string; + readonly 'metric.sonarqube.codeCoverage.description': string; + readonly 'metric.sonarqube.codeDuplications.title': string; + readonly 'metric.sonarqube.codeDuplications.description': string; + readonly 'metric.filecheck.title': string; + readonly 'metric.filecheck.description': string; + readonly 'metric.lastUpdated': string; + readonly 'metric.lastUpdatedNotAvailable': string; + readonly 'metric.someEntitiesNotReportingValues': string; + readonly 'metric.weightedStatusScoreCenterTooltipTotalLabel': string; + readonly 'metric.weightedStatusScoreCenterTooltipMaxLabel': string; + readonly 'metric.weightedStatusScoreCenterTooltipBreakdownRow_one': string; + readonly 'metric.weightedStatusScoreCenterTooltipBreakdownRow_other': string; + readonly 'metric.weightedStatusScoreLegendTooltipEntitiesEach_one': string; + readonly 'metric.weightedStatusScoreLegendTooltipEntitiesEach_other': string; + readonly 'metric.weightedStatusScoreLegendTooltipRowTotal': string; + readonly 'metric.drillDownCalculationFailures': string; + readonly 'metric.homepageEntityHealthRatio': string; + readonly 'metric.homepageEntityCalculationHealth': string; + readonly 'thresholds.success': string; + readonly 'thresholds.warning': string; + readonly 'thresholds.error': string; + readonly 'thresholds.exist': string; + readonly 'thresholds.missing': string; + readonly 'thresholds.noEntities': string; + readonly 'thresholds.entities_one': string; + readonly 'thresholds.entities_other': string; + readonly 'entitiesPage.missingPermission': string; + readonly 'entitiesPage.noDataFound': string; + readonly 'entitiesPage.unknownMetric': string; + readonly 'entitiesPage.metricProviderNotRegistered': string; + readonly 'entitiesPage.entitiesTable.title': string; + readonly 'entitiesPage.entitiesTable.unavailable': string; + readonly 'entitiesPage.entitiesTable.titleWithCount': string; + readonly 'entitiesPage.entitiesTable.header.lastUpdated': string; + readonly 'entitiesPage.entitiesTable.header.status': string; + readonly 'entitiesPage.entitiesTable.header.value': string; + readonly 'entitiesPage.entitiesTable.header.entity': string; + readonly 'entitiesPage.entitiesTable.header.owner': string; + readonly 'entitiesPage.entitiesTable.header.kind': string; + readonly 'entitiesPage.entitiesTable.footer.of': string; + readonly 'entitiesPage.entitiesTable.footer.allRows': string; + readonly 'entitiesPage.entitiesTable.footer.rows_one': string; + readonly 'entitiesPage.entitiesTable.footer.rows_other': string; + } +>; + +// @public +export const scorecardTranslations: TranslationResource<'plugin.scorecard'>; + +export { ScorecardWarningStatusIcon }; + +// (No @packageDocumentation comment for this package) +``` diff --git a/workspaces/scorecard/plugins/scorecard/report-scorecard-catalog-module.api.md b/workspaces/scorecard/plugins/scorecard/report-scorecard-catalog-module.api.md new file mode 100644 index 00000000000..76ff0b4b5e4 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard/report-scorecard-catalog-module.api.md @@ -0,0 +1,13 @@ +## API Report File for "@red-hat-developer-hub/backstage-plugin-scorecard" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { FrontendModule } from '@backstage/frontend-plugin-api'; + +// @public +const scorecardCatalogModule: FrontendModule; +export default scorecardCatalogModule; + +// (No @packageDocumentation comment for this package) +``` diff --git a/workspaces/scorecard/plugins/scorecard/report-scorecard-home-module.api.md b/workspaces/scorecard/plugins/scorecard/report-scorecard-home-module.api.md new file mode 100644 index 00000000000..222477baf01 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard/report-scorecard-home-module.api.md @@ -0,0 +1,13 @@ +## API Report File for "@red-hat-developer-hub/backstage-plugin-scorecard" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { FrontendModule } from '@backstage/frontend-plugin-api'; + +// @public +const scorecardHomeModule: FrontendModule; +export default scorecardHomeModule; + +// (No @packageDocumentation comment for this package) +``` diff --git a/workspaces/scorecard/plugins/scorecard/report-scorecard-translations-module.api.md b/workspaces/scorecard/plugins/scorecard/report-scorecard-translations-module.api.md new file mode 100644 index 00000000000..2e61b84dcb5 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard/report-scorecard-translations-module.api.md @@ -0,0 +1,13 @@ +## API Report File for "@red-hat-developer-hub/backstage-plugin-scorecard" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { FrontendModule } from '@backstage/frontend-plugin-api'; + +// @public +const scorecardTranslationsModule: FrontendModule; +export default scorecardTranslationsModule; + +// (No @packageDocumentation comment for this package) +``` diff --git a/workspaces/scorecard/plugins/scorecard/report.api.md b/workspaces/scorecard/plugins/scorecard/report.api.md index e205c4e6c43..2ed172ff02a 100644 --- a/workspaces/scorecard/plugins/scorecard/report.api.md +++ b/workspaces/scorecard/plugins/scorecard/report.api.md @@ -3,8 +3,22 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AnyApiFactory } from '@backstage/frontend-plugin-api'; +import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; +import { ApiFactory } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { JSX as JSX_2 } from 'react/jsx-runtime'; +import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; +import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; +import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; +import { ExtensionInput } from '@backstage/frontend-plugin-api'; +import { FrontendModule } from '@backstage/frontend-plugin-api'; +import { IconElement } from '@backstage/frontend-plugin-api'; +import { JSX as JSX_2 } from 'react'; +import { JSX as JSX_3 } from 'react/jsx-runtime'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/core-plugin-api'; +import { RouteRef as RouteRef_2 } from '@backstage/frontend-plugin-api'; import { default as ScorecardErrorStatusIcon } from '@mui/icons-material/DangerousOutlined'; import { default as ScorecardSuccessStatusIcon } from '@mui/icons-material/CheckCircleOutline'; import { default as ScorecardWarningStatusIcon } from '@mui/icons-material/WarningAmber'; @@ -12,20 +26,132 @@ import { TranslationRef } from '@backstage/frontend-plugin-api'; import { TranslationResource } from '@backstage/frontend-plugin-api'; // @public -export const EntityScorecardContent: () => JSX_2.Element; +const _default: OverridableFrontendPlugin< + { + root: RouteRef; + drillDown: RouteRef<{ + aggregationId: string; + metricId: string; + }>; + }, + {}, + { + 'api:scorecard': OverridableExtensionDefinition<{ + kind: 'api'; + name: undefined; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: < + TApi, + TImpl extends TApi, + TDeps extends { [name in string]: unknown }, + >( + params: ApiFactory, + ) => ExtensionBlueprintParams; + }>; + 'page:scorecard': OverridableExtensionDefinition<{ + kind: 'page'; + name: undefined; + config: { + path: string | undefined; + title: string | undefined; + }; + configInput: { + path?: string | undefined; + title?: string | undefined; + }; + output: + | ExtensionDataRef + | ExtensionDataRef + | ExtensionDataRef< + RouteRef_2, + 'core.routing.ref', + { + optional: true; + } + > + | ExtensionDataRef< + string, + 'core.title', + { + optional: true; + } + > + | ExtensionDataRef< + IconElement, + 'core.icon', + { + optional: true; + } + >; + inputs: { + pages: ExtensionInput< + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef_2, + 'core.routing.ref', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'core.title', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + IconElement, + 'core.icon', + { + optional: true; + } + >, + { + singleton: false; + optional: false; + internal: false; + } + >; + }; + params: { + path: string; + title?: string; + icon?: IconElement; + loader?: () => Promise; + routeRef?: RouteRef_2; + noHeader?: boolean; + }; + }>; + } +>; +export default _default; + +// @public +export const EntityScorecardContent: () => JSX_3.Element; + +// @public +export const scorecardCatalogModule: FrontendModule; export { ScorecardErrorStatusIcon }; +// @public +export const scorecardHomeModule: FrontendModule; + // @public export const ScorecardHomepageCard: (props: { metricId?: string; aggregationId?: string; showSubheader?: boolean; showInfo?: boolean; -}) => JSX_2.Element; +}) => JSX_3.Element; // @public -export const ScorecardPage: () => JSX_2.Element; +export const ScorecardPage: () => JSX_3.Element; // @public export const scorecardPlugin: BackstagePlugin<{}, {}, {}>; @@ -150,6 +276,9 @@ export const scorecardTranslationRef: TranslationRef< // @public export const scorecardTranslations: TranslationResource<'plugin.scorecard'>; +// @public +export const scorecardTranslationsModule: FrontendModule; + export { ScorecardWarningStatusIcon }; // (No @packageDocumentation comment for this package) diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/index.tsx b/workspaces/scorecard/plugins/scorecard/src/alpha/index.tsx index ec837d1045f..311b89cd43c 100644 --- a/workspaces/scorecard/plugins/scorecard/src/alpha/index.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/alpha/index.tsx @@ -14,90 +14,8 @@ * limitations under the License. */ -import { - createFrontendModule, - createFrontendPlugin, -} from '@backstage/frontend-plugin-api'; -import { TranslationBlueprint } from '@backstage/plugin-app-react'; -import { rootRouteRef, scorecardDrillDownRouteRef } from '../routes'; -import { scorecardTranslations } from '../translations'; -import { scorecardApi } from './extensions/api'; -import { scorecardEntityContent } from './extensions/entityTab'; -import { - aggregatedCardWithDeprecatedMetricIdWidget, - aggregatedCardWithDefaultAggregationWidget, - aggregatedCardWithGithubOpenPrsWidget, - aggregatedCardWithJiraOpenIssuesWidget, - aggregatedCardWithGithubFilecheckLicenseWidget, - aggregatedCardWithGithubFilecheckCodeownersWidget, - aggregatedCardWithGithubOpenPrsWeightedWidget, -} from './extensions/homePageCards'; -import { scorecardPage } from './extensions/scorecardPage'; -import { scorecardEntityLayoutGrid } from './extensions/scorecardLayoutExtensions'; - -/** - * Extension for Scorecard translations. - */ -const scorecardTranslation = TranslationBlueprint.make({ - params: { - resource: scorecardTranslations, - }, -}); - -/** - * The primary Scorecard frontend plugin. - * @alpha - */ -export default createFrontendPlugin({ - pluginId: 'scorecard', - extensions: [scorecardApi, scorecardPage], - routes: { - root: rootRouteRef, - drillDown: scorecardDrillDownRouteRef, - }, -}); - -/** - * Catalog module that injects the Scorecard tab into Catalog entity pages. - * - * Also ships a grid layout extension (disabled by default). - * Enable it in app-config.yaml to get a layout toggle in the entity tab. - * - * @alpha - */ -export const scorecardCatalogModule = createFrontendModule({ - pluginId: 'catalog', - extensions: [scorecardEntityContent, scorecardEntityLayoutGrid], -}); - -/** - * App module that automatically registers Scorecard translations. - * @alpha - */ -export const scorecardTranslationsModule = createFrontendModule({ - pluginId: 'app', - extensions: [scorecardTranslation], -}); - -/** - * Home module that contributes scorecard homepage widget and layout. - * @alpha - */ -export const scorecardHomeModule = createFrontendModule({ - pluginId: 'home', - extensions: [ - aggregatedCardWithDeprecatedMetricIdWidget, - aggregatedCardWithDefaultAggregationWidget, - aggregatedCardWithJiraOpenIssuesWidget, - aggregatedCardWithGithubOpenPrsWidget, - aggregatedCardWithGithubFilecheckLicenseWidget, - aggregatedCardWithGithubFilecheckCodeownersWidget, - aggregatedCardWithGithubOpenPrsWeightedWidget, - ], -}); - /** - * Re-exporting translations for external usage. - * @alpha + * Translations remain available at the `/alpha` export. + * NFS plugin and modules have graduated to the primary package entry point. */ export * from '../translations'; diff --git a/workspaces/scorecard/plugins/scorecard/src/index.ts b/workspaces/scorecard/plugins/scorecard/src/index.ts index 6605a3dba91..5f2941dfbd3 100644 --- a/workspaces/scorecard/plugins/scorecard/src/index.ts +++ b/workspaces/scorecard/plugins/scorecard/src/index.ts @@ -19,18 +19,88 @@ * @packageDocumentation */ -import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className'; +import { + createFrontendModule, + createFrontendPlugin, +} from '@backstage/frontend-plugin-api'; +import { TranslationBlueprint } from '@backstage/plugin-app-react'; +import { rootRouteRef, scorecardDrillDownRouteRef } from './routes'; +import { scorecardTranslations } from './translations'; +import { scorecardApi } from './alpha/extensions/api'; +import { scorecardEntityContent } from './alpha/extensions/entityTab'; +import { + aggregatedCardWithDeprecatedMetricIdWidget, + aggregatedCardWithDefaultAggregationWidget, + aggregatedCardWithGithubOpenPrsWidget, + aggregatedCardWithJiraOpenIssuesWidget, + aggregatedCardWithGithubFilecheckLicenseWidget, + aggregatedCardWithGithubFilecheckCodeownersWidget, + aggregatedCardWithGithubOpenPrsWeightedWidget, +} from './alpha/extensions/homePageCards'; +import { scorecardPage } from './alpha/extensions/scorecardPage'; +import { scorecardEntityLayoutGrid } from './alpha/extensions/scorecardLayoutExtensions'; -ClassNameGenerator.configure(componentName => { - return componentName.startsWith('v5-') - ? componentName - : `v5-${componentName}`; +/** + * Extension for Scorecard translations. + */ +const scorecardTranslation = TranslationBlueprint.make({ + params: { + resource: scorecardTranslations, + }, +}); + +/** + * The primary Scorecard frontend plugin for the new Backstage frontend system. + * @public + */ +export default createFrontendPlugin({ + pluginId: 'scorecard', + extensions: [scorecardApi, scorecardPage], + routes: { + root: rootRouteRef, + drillDown: scorecardDrillDownRouteRef, + }, }); -export * from './plugin'; +/** + * Catalog module that injects the Scorecard tab into Catalog entity pages. + * + * Also ships a grid layout extension (disabled by default). + * Enable it in app-config.yaml to get a layout toggle in the entity tab. + * + * @public + */ +export const scorecardCatalogModule = createFrontendModule({ + pluginId: 'catalog', + extensions: [scorecardEntityContent, scorecardEntityLayoutGrid], +}); + +/** + * App module that automatically registers Scorecard translations. + * @public + */ +export const scorecardTranslationsModule = createFrontendModule({ + pluginId: 'app', + extensions: [scorecardTranslation], +}); + +/** + * Home module that contributes scorecard homepage widget and layout. + * @public + */ +export const scorecardHomeModule = createFrontendModule({ + pluginId: 'home', + extensions: [ + aggregatedCardWithDeprecatedMetricIdWidget, + aggregatedCardWithDefaultAggregationWidget, + aggregatedCardWithJiraOpenIssuesWidget, + aggregatedCardWithGithubOpenPrsWidget, + aggregatedCardWithGithubFilecheckLicenseWidget, + aggregatedCardWithGithubFilecheckCodeownersWidget, + aggregatedCardWithGithubOpenPrsWeightedWidget, + ], +}); -export { scorecardTranslations, scorecardTranslationRef } from './translations'; +export { scorecardTranslationRef, scorecardTranslations } from './translations'; -export { default as ScorecardSuccessStatusIcon } from '@mui/icons-material/CheckCircleOutline'; -export { default as ScorecardWarningStatusIcon } from '@mui/icons-material/WarningAmber'; -export { default as ScorecardErrorStatusIcon } from '@mui/icons-material/DangerousOutlined'; +export * from './legacyExports'; diff --git a/workspaces/scorecard/plugins/scorecard/src/legacyExports.ts b/workspaces/scorecard/plugins/scorecard/src/legacyExports.ts new file mode 100644 index 00000000000..6605a3dba91 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard/src/legacyExports.ts @@ -0,0 +1,36 @@ +/* + * Copyright Red Hat, Inc. + * + * 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. + */ + +/** + * Scorecard plugin for Backstage – entity scorecards, metrics, and entities page. + * @packageDocumentation + */ + +import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className'; + +ClassNameGenerator.configure(componentName => { + return componentName.startsWith('v5-') + ? componentName + : `v5-${componentName}`; +}); + +export * from './plugin'; + +export { scorecardTranslations, scorecardTranslationRef } from './translations'; + +export { default as ScorecardSuccessStatusIcon } from '@mui/icons-material/CheckCircleOutline'; +export { default as ScorecardWarningStatusIcon } from '@mui/icons-material/WarningAmber'; +export { default as ScorecardErrorStatusIcon } from '@mui/icons-material/DangerousOutlined'; diff --git a/workspaces/scorecard/plugins/scorecard/src/nfsExports.test.tsx b/workspaces/scorecard/plugins/scorecard/src/nfsExports.test.tsx new file mode 100644 index 00000000000..47b6662684d --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard/src/nfsExports.test.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Red Hat, Inc. + * + * 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 scorecardPlugin, { + scorecardCatalogModule, + scorecardHomeModule, + scorecardTranslationsModule, +} from './index'; + +describe('scorecard NFS exports', () => { + it('should export the scorecard plugin as default', () => { + expect(scorecardPlugin).toBeDefined(); + }); + + it('should export scorecardCatalogModule', () => { + expect(scorecardCatalogModule).toBeDefined(); + }); + + it('should export scorecardHomeModule', () => { + expect(scorecardHomeModule).toBeDefined(); + }); + + it('should export scorecardTranslationsModule', () => { + expect(scorecardTranslationsModule).toBeDefined(); + }); +}); diff --git a/workspaces/scorecard/plugins/scorecard/src/scorecardCatalogModuleExport.ts b/workspaces/scorecard/plugins/scorecard/src/scorecardCatalogModuleExport.ts new file mode 100644 index 00000000000..915a7704926 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard/src/scorecardCatalogModuleExport.ts @@ -0,0 +1,17 @@ +/* + * Copyright Red Hat, Inc. + * + * 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 { scorecardCatalogModule as default } from './index'; diff --git a/workspaces/scorecard/plugins/scorecard/src/scorecardHomeModuleExport.ts b/workspaces/scorecard/plugins/scorecard/src/scorecardHomeModuleExport.ts new file mode 100644 index 00000000000..8165556466a --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard/src/scorecardHomeModuleExport.ts @@ -0,0 +1,17 @@ +/* + * Copyright Red Hat, Inc. + * + * 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 { scorecardHomeModule as default } from './index'; diff --git a/workspaces/scorecard/plugins/scorecard/src/scorecardTranslationsModuleExport.ts b/workspaces/scorecard/plugins/scorecard/src/scorecardTranslationsModuleExport.ts new file mode 100644 index 00000000000..a3f225e256f --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard/src/scorecardTranslationsModuleExport.ts @@ -0,0 +1,17 @@ +/* + * Copyright Red Hat, Inc. + * + * 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 { scorecardTranslationsModule as default } from './index'; From 909f141eb3a23ca18b452263c9a5ada994dcd447 Mon Sep 17 00:00:00 2001 From: Yi Cai Date: Mon, 27 Jul 2026 15:21:00 -0400 Subject: [PATCH 2/7] updated report api Signed-off-by: Yi Cai --- .../plugins/scorecard/report-legacy.api.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/workspaces/scorecard/plugins/scorecard/report-legacy.api.md b/workspaces/scorecard/plugins/scorecard/report-legacy.api.md index 090d0032b8b..e205c4e6c43 100644 --- a/workspaces/scorecard/plugins/scorecard/report-legacy.api.md +++ b/workspaces/scorecard/plugins/scorecard/report-legacy.api.md @@ -116,6 +116,17 @@ export const scorecardTranslationRef: TranslationRef< readonly 'thresholds.noEntities': string; readonly 'thresholds.entities_one': string; readonly 'thresholds.entities_other': string; + readonly 'dataSourcesDialog.title': string; + readonly 'dataSourcesDialog.close': string; + readonly 'dataSourcesDialog.unknownPlugin': string; + readonly 'dataSourcesDialog.statusTooltip': string; + readonly 'dataSourcesDialog.columns.plugin': string; + readonly 'dataSourcesDialog.columns.check': string; + readonly 'dataSourcesDialog.columns.value': string; + readonly 'dataSourcesDialog.columns.status': string; + readonly 'dataSourcesDialog.columns.lastSynced': string; + readonly 'metricGroupCard.menuAriaLabel': string; + readonly 'metricGroupCard.viewDataSources': string; readonly 'entitiesPage.missingPermission': string; readonly 'entitiesPage.noDataFound': string; readonly 'entitiesPage.unknownMetric': string; @@ -124,8 +135,8 @@ export const scorecardTranslationRef: TranslationRef< readonly 'entitiesPage.entitiesTable.unavailable': string; readonly 'entitiesPage.entitiesTable.titleWithCount': string; readonly 'entitiesPage.entitiesTable.header.lastUpdated': string; - readonly 'entitiesPage.entitiesTable.header.status': string; readonly 'entitiesPage.entitiesTable.header.value': string; + readonly 'entitiesPage.entitiesTable.header.status': string; readonly 'entitiesPage.entitiesTable.header.entity': string; readonly 'entitiesPage.entitiesTable.header.owner': string; readonly 'entitiesPage.entitiesTable.header.kind': string; From 52013f45c4a28b4dafef425fc4cd2a657841ada2 Mon Sep 17 00:00:00 2001 From: Yi Cai Date: Mon, 27 Jul 2026 22:35:46 -0400 Subject: [PATCH 3/7] fix(scorecard): remove unused per-module package entry points Signed-off-by: Yi Cai --- .../scorecard/plugins/scorecard/package.json | 12 ------------ .../report-scorecard-catalog-module.api.md | 13 ------------- .../report-scorecard-home-module.api.md | 13 ------------- .../report-scorecard-translations-module.api.md | 13 ------------- .../plugins/scorecard/src/legacyExports.ts | 5 ----- .../src/scorecardCatalogModuleExport.ts | 17 ----------------- .../scorecard/src/scorecardHomeModuleExport.ts | 17 ----------------- .../src/scorecardTranslationsModuleExport.ts | 17 ----------------- 8 files changed, 107 deletions(-) delete mode 100644 workspaces/scorecard/plugins/scorecard/report-scorecard-catalog-module.api.md delete mode 100644 workspaces/scorecard/plugins/scorecard/report-scorecard-home-module.api.md delete mode 100644 workspaces/scorecard/plugins/scorecard/report-scorecard-translations-module.api.md delete mode 100644 workspaces/scorecard/plugins/scorecard/src/scorecardCatalogModuleExport.ts delete mode 100644 workspaces/scorecard/plugins/scorecard/src/scorecardHomeModuleExport.ts delete mode 100644 workspaces/scorecard/plugins/scorecard/src/scorecardTranslationsModuleExport.ts diff --git a/workspaces/scorecard/plugins/scorecard/package.json b/workspaces/scorecard/plugins/scorecard/package.json index aad6905d786..9d9318bb701 100644 --- a/workspaces/scorecard/plugins/scorecard/package.json +++ b/workspaces/scorecard/plugins/scorecard/package.json @@ -8,9 +8,6 @@ ".": "./src/index.ts", "./alpha": "./src/alpha/index.tsx", "./legacy": "./src/legacyExports.ts", - "./scorecard-catalog-module": "./src/scorecardCatalogModuleExport.ts", - "./scorecard-home-module": "./src/scorecardHomeModuleExport.ts", - "./scorecard-translations-module": "./src/scorecardTranslationsModuleExport.ts", "./package.json": "./package.json" }, "typesVersions": { @@ -21,15 +18,6 @@ "legacy": [ "src/legacyExports.ts" ], - "scorecard-catalog-module": [ - "src/scorecardCatalogModuleExport.ts" - ], - "scorecard-home-module": [ - "src/scorecardHomeModuleExport.ts" - ], - "scorecard-translations-module": [ - "src/scorecardTranslationsModuleExport.ts" - ], "package.json": [ "package.json" ] diff --git a/workspaces/scorecard/plugins/scorecard/report-scorecard-catalog-module.api.md b/workspaces/scorecard/plugins/scorecard/report-scorecard-catalog-module.api.md deleted file mode 100644 index 76ff0b4b5e4..00000000000 --- a/workspaces/scorecard/plugins/scorecard/report-scorecard-catalog-module.api.md +++ /dev/null @@ -1,13 +0,0 @@ -## API Report File for "@red-hat-developer-hub/backstage-plugin-scorecard" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { FrontendModule } from '@backstage/frontend-plugin-api'; - -// @public -const scorecardCatalogModule: FrontendModule; -export default scorecardCatalogModule; - -// (No @packageDocumentation comment for this package) -``` diff --git a/workspaces/scorecard/plugins/scorecard/report-scorecard-home-module.api.md b/workspaces/scorecard/plugins/scorecard/report-scorecard-home-module.api.md deleted file mode 100644 index 222477baf01..00000000000 --- a/workspaces/scorecard/plugins/scorecard/report-scorecard-home-module.api.md +++ /dev/null @@ -1,13 +0,0 @@ -## API Report File for "@red-hat-developer-hub/backstage-plugin-scorecard" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { FrontendModule } from '@backstage/frontend-plugin-api'; - -// @public -const scorecardHomeModule: FrontendModule; -export default scorecardHomeModule; - -// (No @packageDocumentation comment for this package) -``` diff --git a/workspaces/scorecard/plugins/scorecard/report-scorecard-translations-module.api.md b/workspaces/scorecard/plugins/scorecard/report-scorecard-translations-module.api.md deleted file mode 100644 index 2e61b84dcb5..00000000000 --- a/workspaces/scorecard/plugins/scorecard/report-scorecard-translations-module.api.md +++ /dev/null @@ -1,13 +0,0 @@ -## API Report File for "@red-hat-developer-hub/backstage-plugin-scorecard" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { FrontendModule } from '@backstage/frontend-plugin-api'; - -// @public -const scorecardTranslationsModule: FrontendModule; -export default scorecardTranslationsModule; - -// (No @packageDocumentation comment for this package) -``` diff --git a/workspaces/scorecard/plugins/scorecard/src/legacyExports.ts b/workspaces/scorecard/plugins/scorecard/src/legacyExports.ts index 6605a3dba91..91d552ba07f 100644 --- a/workspaces/scorecard/plugins/scorecard/src/legacyExports.ts +++ b/workspaces/scorecard/plugins/scorecard/src/legacyExports.ts @@ -14,11 +14,6 @@ * limitations under the License. */ -/** - * Scorecard plugin for Backstage – entity scorecards, metrics, and entities page. - * @packageDocumentation - */ - import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className'; ClassNameGenerator.configure(componentName => { diff --git a/workspaces/scorecard/plugins/scorecard/src/scorecardCatalogModuleExport.ts b/workspaces/scorecard/plugins/scorecard/src/scorecardCatalogModuleExport.ts deleted file mode 100644 index 915a7704926..00000000000 --- a/workspaces/scorecard/plugins/scorecard/src/scorecardCatalogModuleExport.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * 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 { scorecardCatalogModule as default } from './index'; diff --git a/workspaces/scorecard/plugins/scorecard/src/scorecardHomeModuleExport.ts b/workspaces/scorecard/plugins/scorecard/src/scorecardHomeModuleExport.ts deleted file mode 100644 index 8165556466a..00000000000 --- a/workspaces/scorecard/plugins/scorecard/src/scorecardHomeModuleExport.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * 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 { scorecardHomeModule as default } from './index'; diff --git a/workspaces/scorecard/plugins/scorecard/src/scorecardTranslationsModuleExport.ts b/workspaces/scorecard/plugins/scorecard/src/scorecardTranslationsModuleExport.ts deleted file mode 100644 index a3f225e256f..00000000000 --- a/workspaces/scorecard/plugins/scorecard/src/scorecardTranslationsModuleExport.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * 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 { scorecardTranslationsModule as default } from './index'; From a46105261c001ff9c447626485fa93fcdfb0e017 Mon Sep 17 00:00:00 2001 From: Yi Cai Date: Wed, 29 Jul 2026 12:46:52 -0400 Subject: [PATCH 4/7] fix(scorecard): fold NFS into plugin, drop legacy re-export, leave alpha for translations Signed-off-by: Yi Cai --- .../graduate-nfs-alpha-to-stable.md | 8 +- workspaces/scorecard/app-config.yaml | 2 +- workspaces/scorecard/package.json | 2 +- .../scorecard/packages/app-legacy/src/App.tsx | 2 +- .../src/components/catalog/EntityPage.tsx | 2 +- workspaces/scorecard/packages/app/src/App.tsx | 4 - .../packages/app/src/modules/icons/index.ts | 2 +- .../scorecard/plugins/scorecard/README.md | 127 ++++++--- .../scorecard/plugins/scorecard/dev/index.tsx | 8 +- .../scorecard/plugins/scorecard/package.json | 4 +- .../scorecard/plugins/scorecard/report.api.md | 245 +++++++++++++++--- .../src/{alpha/index.tsx => alpha.ts} | 2 +- .../ScorecardLayoutBlueprint.test.tsx | 2 +- .../blueprints/ScorecardLayoutBlueprint.ts | 8 +- .../src/{alpha => }/blueprints/index.ts | 0 .../ScorecardEntityContentGridView.tsx | 2 +- .../ScorecardIcon/ScorecardIcon.tsx | 8 +- .../src/{alpha => }/extensions/api.ts | 2 +- .../src/{alpha => }/extensions/entityTab.tsx | 8 +- .../{alpha => }/extensions/homePageCards.tsx | 9 +- .../extensions/scorecardLayoutExtensions.tsx | 9 +- .../{alpha => }/extensions/scorecardPage.tsx | 5 +- .../scorecard/plugins/scorecard/src/index.ts | 60 ++--- .../plugins/scorecard/src/nfsExports.test.tsx | 14 +- 24 files changed, 365 insertions(+), 170 deletions(-) rename workspaces/scorecard/plugins/scorecard/src/{alpha/index.tsx => alpha.ts} (95%) rename workspaces/scorecard/plugins/scorecard/src/{alpha => }/blueprints/ScorecardLayoutBlueprint.test.tsx (98%) rename workspaces/scorecard/plugins/scorecard/src/{alpha => }/blueprints/ScorecardLayoutBlueprint.ts (96%) rename workspaces/scorecard/plugins/scorecard/src/{alpha => }/blueprints/index.ts (100%) rename workspaces/scorecard/plugins/scorecard/src/{alpha => }/extensions/api.ts (94%) rename workspaces/scorecard/plugins/scorecard/src/{alpha => }/extensions/entityTab.tsx (94%) rename workspaces/scorecard/plugins/scorecard/src/{alpha => }/extensions/homePageCards.tsx (98%) rename workspaces/scorecard/plugins/scorecard/src/{alpha => }/extensions/scorecardLayoutExtensions.tsx (81%) rename workspaces/scorecard/plugins/scorecard/src/{alpha => }/extensions/scorecardPage.tsx (88%) diff --git a/workspaces/scorecard/.changeset/graduate-nfs-alpha-to-stable.md b/workspaces/scorecard/.changeset/graduate-nfs-alpha-to-stable.md index 0a6c3d037f2..143e1e95b8f 100644 --- a/workspaces/scorecard/.changeset/graduate-nfs-alpha-to-stable.md +++ b/workspaces/scorecard/.changeset/graduate-nfs-alpha-to-stable.md @@ -1,5 +1,9 @@ --- -'@red-hat-developer-hub/backstage-plugin-scorecard': minor +'@red-hat-developer-hub/backstage-plugin-scorecard': major --- -Graduate the New Frontend System (NFS) plugin from the `./alpha` export to the primary `./` entry point. OFS (legacy) exports are now available at `./legacy`. Translations remain at `./alpha`. +**BREAKING**: Graduated the New Frontend System (NFS) scorecard plugin to the stable entry point and simplified NFS feature registration. + +- NFS APIs move from `./alpha` to `.`; OFS APIs move to `./legacy` only (not re-exported from the main entry); translations remain at `./alpha`. +- `scorecardCatalogModule` and `scorecardHomeModule` are removed. Entity tab, layout, and homepage widgets are now provided by the default `scorecardPlugin`. Keep only `scorecardTranslationsModule` as a separate app module. +- Extension IDs move from the `catalog` / `home` namespaces to `scorecard` (for example `entity-content:catalog/entity-content-scorecard` → `entity-content:scorecard/entity-content-scorecard`). Update any `app.extensions` config accordingly. See the plugin README migration notes. diff --git a/workspaces/scorecard/app-config.yaml b/workspaces/scorecard/app-config.yaml index ac9ba4f569f..b2a7590992e 100644 --- a/workspaces/scorecard/app-config.yaml +++ b/workspaces/scorecard/app-config.yaml @@ -14,7 +14,7 @@ app: path: / # Scorecard tab: entity shows tab if it matches any filter below. - - entity-content:catalog/entity-content-scorecard: + - entity-content:scorecard/entity-content-scorecard: config: allowedFilters: - kind: component # e.g. Component with spec.type: website diff --git a/workspaces/scorecard/package.json b/workspaces/scorecard/package.json index 7c1862cdeba..76ce1abd974 100644 --- a/workspaces/scorecard/package.json +++ b/workspaces/scorecard/package.json @@ -14,7 +14,7 @@ "build:backend": "yarn workspace backend build", "build:all": "backstage-cli repo build --all", "build:api-reports": "yarn build:api-reports:only", - "build:api-reports:only": "backstage-repo-tools api-reports -o ae-wrong-input-file-type,ae-undocumented,ae-missing-release-tag --validate-release-tags", + "build:api-reports:only": "backstage-repo-tools api-reports -o ae-wrong-input-file-type,ae-undocumented,ae-missing-release-tag,ae-forgotten-export --validate-release-tags", "build-image": "yarn workspace backend build-image", "build:knip-reports": "backstage-repo-tools knip-reports", "clean": "backstage-cli repo clean", diff --git a/workspaces/scorecard/packages/app-legacy/src/App.tsx b/workspaces/scorecard/packages/app-legacy/src/App.tsx index 849d79bf6de..eb534262d1e 100644 --- a/workspaces/scorecard/packages/app-legacy/src/App.tsx +++ b/workspaces/scorecard/packages/app-legacy/src/App.tsx @@ -60,7 +60,7 @@ import { ScorecardSuccessStatusIcon, ScorecardWarningStatusIcon, scorecardTranslations, -} from '@red-hat-developer-hub/backstage-plugin-scorecard'; +} from '@red-hat-developer-hub/backstage-plugin-scorecard/legacy'; import { ScalprumContext, ScalprumState } from '@scalprum/react-core'; import { PluginStore } from '@openshift/dynamic-plugin-sdk'; diff --git a/workspaces/scorecard/packages/app-legacy/src/components/catalog/EntityPage.tsx b/workspaces/scorecard/packages/app-legacy/src/components/catalog/EntityPage.tsx index 8ee48f856a7..081c7e6f485 100644 --- a/workspaces/scorecard/packages/app-legacy/src/components/catalog/EntityPage.tsx +++ b/workspaces/scorecard/packages/app-legacy/src/components/catalog/EntityPage.tsx @@ -73,7 +73,7 @@ import { EntityKubernetesContent, isKubernetesAvailable, } from '@backstage/plugin-kubernetes'; -import { EntityScorecardContent } from '@red-hat-developer-hub/backstage-plugin-scorecard'; +import { EntityScorecardContent } from '@red-hat-developer-hub/backstage-plugin-scorecard/legacy'; import { GithubIssuesCard } from '@backstage-community/plugin-github-issues'; import { EntityGithubPullRequestsContent } from '@roadiehq/backstage-plugin-github-pull-requests'; diff --git a/workspaces/scorecard/packages/app/src/App.tsx b/workspaces/scorecard/packages/app/src/App.tsx index 85338369b93..0d3abec1327 100644 --- a/workspaces/scorecard/packages/app/src/App.tsx +++ b/workspaces/scorecard/packages/app/src/App.tsx @@ -22,9 +22,7 @@ import { homepageTranslationsModule, } from '@red-hat-developer-hub/backstage-plugin-dynamic-home-page/alpha'; import scorecardPlugin, { - scorecardHomeModule, scorecardTranslationsModule, - scorecardCatalogModule, } from '@red-hat-developer-hub/backstage-plugin-scorecard'; import { signInModule } from './modules/signIn'; import { navModule } from './modules/nav'; @@ -39,8 +37,6 @@ const app = createApp({ homePageModule, homepageTranslationsModule, scorecardPlugin, - scorecardHomeModule, - scorecardCatalogModule, scorecardTranslationsModule, iconsModule, signInModule, diff --git a/workspaces/scorecard/packages/app/src/modules/icons/index.ts b/workspaces/scorecard/packages/app/src/modules/icons/index.ts index 271499229ca..2735f7ed8db 100644 --- a/workspaces/scorecard/packages/app/src/modules/icons/index.ts +++ b/workspaces/scorecard/packages/app/src/modules/icons/index.ts @@ -21,7 +21,7 @@ import { ScorecardErrorStatusIcon, ScorecardSuccessStatusIcon, ScorecardWarningStatusIcon, -} from '@red-hat-developer-hub/backstage-plugin-scorecard'; +} from '@red-hat-developer-hub/backstage-plugin-scorecard/legacy'; export const iconsModule = createFrontendModule({ pluginId: 'app', diff --git a/workspaces/scorecard/plugins/scorecard/README.md b/workspaces/scorecard/plugins/scorecard/README.md index ed28e4b3ed3..dca668e547d 100644 --- a/workspaces/scorecard/plugins/scorecard/README.md +++ b/workspaces/scorecard/plugins/scorecard/README.md @@ -2,7 +2,10 @@ The Scorecard plugin provides a configurable framework to visualize Key Performance Indicators (KPIs) in Backstage. This frontend plugin integrates with the Scorecard backend to deliver Scorecards. -The plugin supports both the **legacy** Backstage frontend and the **New Frontend System (NFS)**. NFS is the primary package entry point. OFS (legacy) exports are available at `./legacy` (and are also re-exported from the main entry for compatibility). Translations remain available at `./alpha`. For NFS, the plugin provides three modules: a catalog module for the Scorecard entity tab, a home module for homepage widgets, and a translations module. +The plugin supports both the **legacy** Backstage frontend and the **New Frontend System (NFS)**. NFS is the primary package entry point. OFS (legacy) exports are available only at `./legacy`. Translations remain available at `./alpha`. + +For NFS, register the default `scorecardPlugin` plus `scorecardTranslationsModule`. The plugin itself contributes the Scorecard page, entity tab, layout, and homepage widgets (no separate catalog/home modules). + **Features:** - **Entity scorecard tab** — View scorecard metrics on catalog entity pages (components, websites, etc.). @@ -50,16 +53,12 @@ yarn workspace app-legacy add @red-hat-developer-hub/backstage-plugin-scorecard // In packages/app/src/App.tsx import { createApp } from '@backstage/frontend-defaults'; import scorecardPlugin, { - scorecardHomeModule, scorecardTranslationsModule, - scorecardCatalogModule, } from '@red-hat-developer-hub/backstage-plugin-scorecard'; const app = createApp({ features: [ scorecardPlugin, - scorecardHomeModule, - scorecardCatalogModule, scorecardTranslationsModule, // ... other plugins ], @@ -73,7 +72,7 @@ yarn workspace app-legacy add @red-hat-developer-hub/backstage-plugin-scorecard ```yaml app: extensions: - - entity-content:catalog/entity-content-scorecard: + - entity-content:scorecard/entity-content-scorecard: config: allowedFilters: - kind: component @@ -129,7 +128,7 @@ To align with the legacy EntityPage (Scorecard on component pages and default en ```yaml app: extensions: - - scorecard-layout:catalog/scorecard-entity-layout-grid: + - scorecard-layout:scorecard/scorecard-entity-layout-grid: config: groups: codeQuality: @@ -163,7 +162,7 @@ To align with the legacy EntityPage (Scorecard on component pages and default en - If `groups` is empty or omitted, the grid layout falls back to the default `EntityScorecardContent` view (individual cards for all metrics). - When multiple layout extensions are enabled, the Scorecard tab renders a toggle to switch between them. -7. (Optional) Enable homepage Scorecard widgets by adding `scorecardHomeModule` to app features (see step 2) and configuring home page extensions in `app-config.yaml`: +7. (Optional) Enable homepage Scorecard widgets by configuring home page extensions in `app-config.yaml` (widgets are registered by `scorecardPlugin`): ```yaml app: @@ -260,24 +259,92 @@ The following modules and extensions are available from `@red-hat-developer-hub/ **Modules** -| Module | Description | -| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `scorecardHomeModule` | Registers Scorecard homepage widgets for the home plugin (`AggregatedCardWithDeprecatedMetricId`, `AggregatedCardWithDefaultAggregation`, `AggregatedCardWithJiraOpenIssues`, `AggregatedCardWithGithubOpenPrs`, `AggregatedCardWithGithubFilecheckLicense`, `AggregatedCardWithGithubFilecheckCodeowners` and `AggregatedCardWithGithubOpenPrsWeighted`). | -| `scorecardCatalogModule` | Registers the Scorecard entity tab and the grid layout extension with the catalog plugin. Add to your app's `features`. Which entities show the tab is configured via `app.extensions` (see step 3). The grid layout is disabled by default; enable and configure it with `groups` (see step 6). | -| `scorecardTranslationsModule` | Registers Scorecard translations with the app. Add to your app's `features`. | - -**Extensions** - -- `api:scorecard` — Scorecard API (provided by the plugin; auto-discovered when the plugin is installed). -- `entity-content:catalog/entity-content-scorecard` — Scorecard tab on catalog entity pages. Configure with `allowedFilters` in `app.extensions` to limit by kind and optionally type. -- `scorecard-layout:catalog/scorecard-entity-layout-grid` — Grid layout with metric group cards (disabled by default). Enable via `app.extensions` and define `groups` to organize metrics into themed cards (see step 6). -- `home-page-widget:home/scorecard-deprecated-metric-id` — Homepage widget using deprecated metricId property (Jira open issues). -- `home-page-widget:home/scorecard-default-aggregation` — Homepage widget using default aggregation config (GitHub open PRs). -- `home-page-widget:home/scorecard-jira-open-issues` — Homepage widget showing Jira open blocking tickets. -- `home-page-widget:home/scorecard-github-open-prs` — Homepage widget showing GitHub open PRs. -- `home-page-widget:home/scorecard-github-filecheck-license` - Homepage widget showing file check "License". -- `home-page-widget:home/scorecard-github-filecheck-codeowners` - Homepage widget showing file check "Codeowners". -- `home-page-widget:home/scorecard-github-open-prs-weighted` - Homepage widget showing weighted status score for GitHub open PRs. +| Module | Description | +| ----------------------------- | ---------------------------------------------------------------------------- | +| `scorecardTranslationsModule` | Registers Scorecard translations with the app. Add to your app's `features`. | + +The default `scorecardPlugin` registers the Scorecard page, API, entity tab, layout, and homepage widgets. + +**Extension IDs** + +| Extension ID | Description | +| ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | +| `api:scorecard` | Scorecard API (auto-discovered when the plugin is installed). | +| `page:scorecard` | Scorecard entities / drill-down page. | +| `entity-content:scorecard/entity-content-scorecard` | Scorecard tab on catalog entity pages. Configure with `allowedFilters` in `app.extensions` to limit by kind and optionally type. | +| `scorecard-layout:scorecard/scorecard-entity-layout-grid` | Grid layout with metric group cards (disabled by default). Enable via `app.extensions` and define `groups` (see step 6). | +| `home-page-widget:scorecard/scorecard-deprecated-metric-id` | Homepage widget using deprecated `metricId` (Jira open issues). | +| `home-page-widget:scorecard/scorecard-default-aggregation` | Homepage widget using default aggregation (GitHub open PRs). | +| `home-page-widget:scorecard/scorecard-jira-open-issues` | Homepage widget for Jira open blocking tickets. | +| `home-page-widget:scorecard/scorecard-github-open-prs` | Homepage widget for GitHub open PRs. | +| `home-page-widget:scorecard/scorecard-github-filecheck-license` | Homepage widget for file check "License". | +| `home-page-widget:scorecard/scorecard-github-filecheck-codeowners` | Homepage widget for file check "Codeowners". | +| `home-page-widget:scorecard/scorecard-github-open-prs-weighted` | Homepage widget for weighted GitHub open PRs health. | + +##### Migration notes (NFS graduation) + +If you previously imported Scorecard NFS APIs from `/alpha` and registered separate catalog/home modules, update as follows. + +**1. Features registration** + +```diff +- import scorecardPlugin, { +- scorecardCatalogModule, +- scorecardHomeModule, +- scorecardTranslationsModule, +- } from '@red-hat-developer-hub/backstage-plugin-scorecard/alpha'; ++ import scorecardPlugin, { ++ scorecardTranslationsModule, ++ } from '@red-hat-developer-hub/backstage-plugin-scorecard'; + + features: [ + scorecardPlugin, +- scorecardCatalogModule, +- scorecardHomeModule, + scorecardTranslationsModule, + ] +``` + +`scorecardCatalogModule` and `scorecardHomeModule` are removed. Entity tab and homepage widgets are provided by `scorecardPlugin` directly. + +**2. `app.extensions` IDs** + +Extension IDs now use the `scorecard` plugin namespace (not `catalog` / `home`): + +| Old ID | New ID | +| ------------------------------------------------------------- | ------------------------------------------------------------------ | +| `entity-content:catalog/entity-content-scorecard` | `entity-content:scorecard/entity-content-scorecard` | +| `scorecard-layout:catalog/scorecard-entity-layout-grid` | `scorecard-layout:scorecard/scorecard-entity-layout-grid` | +| `home-page-widget:home/scorecard-deprecated-metric-id` | `home-page-widget:scorecard/scorecard-deprecated-metric-id` | +| `home-page-widget:home/scorecard-default-aggregation` | `home-page-widget:scorecard/scorecard-default-aggregation` | +| `home-page-widget:home/scorecard-jira-open-issues` | `home-page-widget:scorecard/scorecard-jira-open-issues` | +| `home-page-widget:home/scorecard-github-open-prs` | `home-page-widget:scorecard/scorecard-github-open-prs` | +| `home-page-widget:home/scorecard-github-filecheck-license` | `home-page-widget:scorecard/scorecard-github-filecheck-license` | +| `home-page-widget:home/scorecard-github-filecheck-codeowners` | `home-page-widget:scorecard/scorecard-github-filecheck-codeowners` | +| `home-page-widget:home/scorecard-github-open-prs-weighted` | `home-page-widget:scorecard/scorecard-github-open-prs-weighted` | + +Example: + +```diff + app: + extensions: +- - entity-content:catalog/entity-content-scorecard: ++ - entity-content:scorecard/entity-content-scorecard: + config: + allowedFilters: + - kind: component +``` + +Homepage widget **layout** config under `home-page-layout:home/dynamic-homepage-layout` (widget names like `AggregatedCardWithGithubOpenPrs`) is unchanged; only the extension IDs above move namespaces. + +**3. Legacy (OFS) imports** + +OFS components, the OFS plugin, and status icons are available only from `./legacy` (not re-exported from the main entry): + +```diff +- import { EntityScorecardContent } from '@red-hat-developer-hub/backstage-plugin-scorecard'; ++ import { EntityScorecardContent } from '@red-hat-developer-hub/backstage-plugin-scorecard/legacy'; +``` #### Legacy app @@ -290,7 +357,7 @@ The following modules and extensions are available from `@red-hat-developer-hub/ 2. Add the Scorecard tab to the entity overview in `packages/app-legacy/src/components/catalog/EntityPage.tsx` (or your legacy app's equivalent): ```tsx - import { EntityScorecardContent } from '@red-hat-developer-hub/backstage-plugin-scorecard'; + import { EntityScorecardContent } from '@red-hat-developer-hub/backstage-plugin-scorecard/legacy'; const scorecardRoute = ( @@ -335,7 +402,7 @@ The following modules and extensions are available from `@red-hat-developer-hub/ 3. (Optional) Add Scorecard homepage cards to your home page: ```tsx - import { ScorecardHomepageCard } from '@red-hat-developer-hub/backstage-plugin-scorecard'; + import { ScorecardHomepageCard } from '@red-hat-developer-hub/backstage-plugin-scorecard/legacy'; // GitHub open PRs @@ -379,7 +446,7 @@ permission: ### Homepage scorecard cards -The plugin exports **`ScorecardHomepageCard`** (see [`plugin.ts`](./src/plugin.ts)) for use on customizable home pages (for example **Dynamic Home Page** mount points such as `home.page/cards`). +The plugin exports **`ScorecardHomepageCard`** from `@red-hat-developer-hub/backstage-plugin-scorecard/legacy` (see [`plugin.ts`](./src/plugin.ts)) for use on customizable home pages (for example **Dynamic Home Page** mount points such as `home.page/cards`). #### Backend configuration @@ -410,7 +477,7 @@ The supported model is **a single `aggregationId` string** whose value is either Example (Dynamic Home Page–style mount point): register **`ScorecardHomepageCard`** and pass **`props.aggregationId`** (and **`metricId`** only if you still run an older card API): ```tsx -import { ScorecardHomepageCard } from '@red-hat-developer-hub/backstage-plugin-scorecard'; +import { ScorecardHomepageCard } from '@red-hat-developer-hub/backstage-plugin-scorecard/legacy'; import { ComponentType } from 'react'; // Inside your home page cards config: diff --git a/workspaces/scorecard/plugins/scorecard/dev/index.tsx b/workspaces/scorecard/plugins/scorecard/dev/index.tsx index 8a7831e241f..9c525482a40 100644 --- a/workspaces/scorecard/plugins/scorecard/dev/index.tsx +++ b/workspaces/scorecard/plugins/scorecard/dev/index.tsx @@ -48,11 +48,7 @@ import { import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { rhdhThemeModule } from '@red-hat-developer-hub/backstage-plugin-theme/alpha'; -import scorecardPlugin, { - scorecardCatalogModule, - scorecardHomeModule, - scorecardTranslationsModule, -} from '../src'; +import scorecardPlugin, { scorecardTranslationsModule } from '../src'; import { scorecardApiRef } from '../src/api'; import { MockScorecardApi, mockCatalogApi } from './mocks'; @@ -145,8 +141,6 @@ const app = createApp({ features: [ devNavModule, scorecardPlugin, - scorecardCatalogModule, - scorecardHomeModule, scorecardTranslationsModule, appDevModule, catalogDevModule, diff --git a/workspaces/scorecard/plugins/scorecard/package.json b/workspaces/scorecard/plugins/scorecard/package.json index 9d9318bb701..7d734b6e487 100644 --- a/workspaces/scorecard/plugins/scorecard/package.json +++ b/workspaces/scorecard/plugins/scorecard/package.json @@ -6,14 +6,14 @@ "types": "src/index.ts", "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha/index.tsx", + "./alpha": "./src/alpha.ts", "./legacy": "./src/legacyExports.ts", "./package.json": "./package.json" }, "typesVersions": { "*": { "alpha": [ - "src/alpha/index.tsx" + "src/alpha.ts" ], "legacy": [ "src/legacyExports.ts" diff --git a/workspaces/scorecard/plugins/scorecard/report.api.md b/workspaces/scorecard/plugins/scorecard/report.api.md index 2ed172ff02a..6eaae6752c6 100644 --- a/workspaces/scorecard/plugins/scorecard/report.api.md +++ b/workspaces/scorecard/plugins/scorecard/report.api.md @@ -6,22 +6,24 @@ import { AnyApiFactory } from '@backstage/frontend-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { ApiFactory } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { ComponentType } from 'react'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; +import { Entity } from '@backstage/catalog-model'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; +import { FilterPredicate } from '@backstage/filter-predicates'; import { FrontendModule } from '@backstage/frontend-plugin-api'; +import { HomePageWidgetBlueprintParams } from '@backstage/plugin-home-react/alpha'; +import { HomePageWidgetData } from '@backstage/plugin-home-react/alpha'; import { IconElement } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; -import { JSX as JSX_3 } from 'react/jsx-runtime'; +import { JSXElementConstructor } from 'react'; import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; +import { ReactElement } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { RouteRef as RouteRef_2 } from '@backstage/frontend-plugin-api'; -import { default as ScorecardErrorStatusIcon } from '@mui/icons-material/DangerousOutlined'; -import { default as ScorecardSuccessStatusIcon } from '@mui/icons-material/CheckCircleOutline'; -import { default as ScorecardWarningStatusIcon } from '@mui/icons-material/WarningAmber'; import { TranslationRef } from '@backstage/frontend-plugin-api'; import { TranslationResource } from '@backstage/frontend-plugin-api'; @@ -30,8 +32,8 @@ const _default: OverridableFrontendPlugin< { root: RouteRef; drillDown: RouteRef<{ - aggregationId: string; metricId: string; + aggregationId: string; }>; }, {}, @@ -51,6 +53,174 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; + 'entity-content:scorecard/entity-content-scorecard': OverridableExtensionDefinition<{ + config: { + allowedFilters: + | { + kind?: string | undefined; + type?: string | undefined; + }[] + | undefined; + path: string | undefined; + title: string | undefined; + filter: FilterPredicate | undefined; + group: string | false | undefined; + icon: string | undefined; + }; + configInput: { + allowedFilters?: + | { + kind?: string | undefined; + type?: string | undefined; + }[] + | undefined; + path?: string | undefined | undefined; + title?: string | undefined | undefined; + filter?: FilterPredicate | undefined; + group?: string | false | undefined | undefined; + icon?: string | undefined | undefined; + }; + output: + | ExtensionDataRef + | ExtensionDataRef + | ExtensionDataRef< + RouteRef_2, + 'core.routing.ref', + { + optional: true; + } + > + | ExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + > + | ExtensionDataRef + | ExtensionDataRef< + string, + 'catalog.entity-content-group', + { + optional: true; + } + > + | ExtensionDataRef< + string | ReactElement>, + 'catalog.entity-content-icon', + { + optional: true; + } + >; + inputs: { + layouts: ExtensionInput< + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >, + { + singleton: false; + optional: true; + internal: false; + } + >; + }; + kind: 'entity-content'; + name: 'entity-content-scorecard'; + params: { + defaultPath?: [Error: `Use the 'path' param instead`]; + path: string; + defaultTitle?: [Error: `Use the 'title' param instead`]; + title: string; + defaultGroup?: [Error: `Use the 'group' param instead`]; + group?: + | ( + | 'overview' + | 'documentation' + | 'development' + | 'deployment' + | 'operation' + | 'observability' + ) + | (string & {}); + icon?: string | ReactElement; + loader: () => Promise; + routeRef?: RouteRef_2; + filter?: string | FilterPredicate | ((entity: Entity) => boolean); + }; + }>; + 'home-page-widget:scorecard/scorecard-default-aggregation': OverridableExtensionDefinition<{ + kind: 'home-page-widget'; + name: 'scorecard-default-aggregation'; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: HomePageWidgetBlueprintParams; + }>; + 'home-page-widget:scorecard/scorecard-deprecated-metric-id': OverridableExtensionDefinition<{ + kind: 'home-page-widget'; + name: 'scorecard-deprecated-metric-id'; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: HomePageWidgetBlueprintParams; + }>; + 'home-page-widget:scorecard/scorecard-github-filecheck-codeowners': OverridableExtensionDefinition<{ + kind: 'home-page-widget'; + name: 'scorecard-github-filecheck-codeowners'; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: HomePageWidgetBlueprintParams; + }>; + 'home-page-widget:scorecard/scorecard-github-filecheck-license': OverridableExtensionDefinition<{ + kind: 'home-page-widget'; + name: 'scorecard-github-filecheck-license'; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: HomePageWidgetBlueprintParams; + }>; + 'home-page-widget:scorecard/scorecard-github-open-prs': OverridableExtensionDefinition<{ + kind: 'home-page-widget'; + name: 'scorecard-github-open-prs'; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: HomePageWidgetBlueprintParams; + }>; + 'home-page-widget:scorecard/scorecard-github-open-prs-weighted': OverridableExtensionDefinition<{ + kind: 'home-page-widget'; + name: 'scorecard-github-open-prs-weighted'; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: HomePageWidgetBlueprintParams; + }>; + 'home-page-widget:scorecard/scorecard-jira-open-issues': OverridableExtensionDefinition<{ + kind: 'home-page-widget'; + name: 'scorecard-jira-open-issues'; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: HomePageWidgetBlueprintParams; + }>; 'page:scorecard': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; @@ -127,37 +297,44 @@ const _default: OverridableFrontendPlugin< noHeader?: boolean; }; }>; + 'scorecard-layout:scorecard/scorecard-entity-layout-grid': OverridableExtensionDefinition<{ + kind: 'scorecard-layout'; + name: 'scorecard-entity-layout-grid'; + config: { + groups: Record< + string, + { + title: string; + metrics: string[]; + description?: string | undefined; + } + >; + }; + configInput: { + groups?: + | Record< + string, + { + title: string; + metrics: string[]; + description?: string | undefined; + } + > + | undefined; + }; + output: + | ExtensionDataRef + | ExtensionDataRef; + inputs: {}; + params: { + title: string; + loader: () => Promise>; + }; + }>; } >; export default _default; -// @public -export const EntityScorecardContent: () => JSX_3.Element; - -// @public -export const scorecardCatalogModule: FrontendModule; - -export { ScorecardErrorStatusIcon }; - -// @public -export const scorecardHomeModule: FrontendModule; - -// @public -export const ScorecardHomepageCard: (props: { - metricId?: string; - aggregationId?: string; - showSubheader?: boolean; - showInfo?: boolean; -}) => JSX_3.Element; - -// @public -export const ScorecardPage: () => JSX_3.Element; - -// @public -export const scorecardPlugin: BackstagePlugin<{}, {}, {}>; - -export { ScorecardSuccessStatusIcon }; - // @public export const scorecardTranslationRef: TranslationRef< 'plugin.scorecard', @@ -279,7 +456,5 @@ export const scorecardTranslations: TranslationResource<'plugin.scorecard'>; // @public export const scorecardTranslationsModule: FrontendModule; -export { ScorecardWarningStatusIcon }; - // (No @packageDocumentation comment for this package) ``` diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/index.tsx b/workspaces/scorecard/plugins/scorecard/src/alpha.ts similarity index 95% rename from workspaces/scorecard/plugins/scorecard/src/alpha/index.tsx rename to workspaces/scorecard/plugins/scorecard/src/alpha.ts index 311b89cd43c..9075f07271c 100644 --- a/workspaces/scorecard/plugins/scorecard/src/alpha/index.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/alpha.ts @@ -18,4 +18,4 @@ * Translations remain available at the `/alpha` export. * NFS plugin and modules have graduated to the primary package entry point. */ -export * from '../translations'; +export * from './translations'; diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/blueprints/ScorecardLayoutBlueprint.test.tsx b/workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.test.tsx similarity index 98% rename from workspaces/scorecard/plugins/scorecard/src/alpha/blueprints/ScorecardLayoutBlueprint.test.tsx rename to workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.test.tsx index 5f53805ecfc..ad985f8bd35 100644 --- a/workspaces/scorecard/plugins/scorecard/src/alpha/blueprints/ScorecardLayoutBlueprint.test.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.test.tsx @@ -40,7 +40,7 @@ describe('ScorecardEntityContentLayoutBlueprint', () => { expect(extensionData.kind).toBe('scorecard-layout'); expect(extensionData.name).toBe('scorecard-entity-layout-grid'); expect(extensionData.attachTo).toEqual({ - id: 'entity-content:catalog/entity-content-scorecard', + id: 'entity-content:scorecard/entity-content-scorecard', input: 'layouts', }); }); diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/blueprints/ScorecardLayoutBlueprint.ts b/workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.ts similarity index 96% rename from workspaces/scorecard/plugins/scorecard/src/alpha/blueprints/ScorecardLayoutBlueprint.ts rename to workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.ts index c1464c0edfc..dc863ddaee1 100644 --- a/workspaces/scorecard/plugins/scorecard/src/alpha/blueprints/ScorecardLayoutBlueprint.ts +++ b/workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.ts @@ -22,7 +22,7 @@ import { ExtensionBoundary, } from '@backstage/frontend-plugin-api'; -/** @alpha */ +/** @public */ export interface ScorecardLayoutProps { groups: Record< string, @@ -34,7 +34,7 @@ export interface ScorecardLayoutProps { * Extension data ref carrying the human-readable layout title * (e.g. "Grid", "List") so the entity tab can build a toggle. * - * @alpha + * @public */ export const scorecardLayoutTitleDataRef = createExtensionDataRef().with({ id: 'scorecard.layout-title' }); @@ -46,12 +46,12 @@ export const scorecardLayoutTitleDataRef = * Platform engineers enable/disable individual layouts via app-config.yaml; * when multiple layouts are enabled the tab renders a toggle to switch between them. * - * @alpha + * @public */ export const ScorecardEntityContentLayoutBlueprint = createExtensionBlueprint({ kind: 'scorecard-layout', attachTo: { - id: 'entity-content:catalog/entity-content-scorecard', + id: 'entity-content:scorecard/entity-content-scorecard', input: 'layouts', }, output: [coreExtensionData.reactElement, scorecardLayoutTitleDataRef], diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/blueprints/index.ts b/workspaces/scorecard/plugins/scorecard/src/blueprints/index.ts similarity index 100% rename from workspaces/scorecard/plugins/scorecard/src/alpha/blueprints/index.ts rename to workspaces/scorecard/plugins/scorecard/src/blueprints/index.ts diff --git a/workspaces/scorecard/plugins/scorecard/src/components/Scorecard/ScorecardEntityContentGridView.tsx b/workspaces/scorecard/plugins/scorecard/src/components/Scorecard/ScorecardEntityContentGridView.tsx index bd63393f305..2dec595c32c 100644 --- a/workspaces/scorecard/plugins/scorecard/src/components/Scorecard/ScorecardEntityContentGridView.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/components/Scorecard/ScorecardEntityContentGridView.tsx @@ -19,7 +19,7 @@ import { ResponseErrorPanel } from '@backstage/core-components'; import Box from '@mui/material/Box'; import Masonry from '@mui/lab/Masonry'; -import { ScorecardLayoutProps } from '../../alpha/blueprints/ScorecardLayoutBlueprint'; +import { ScorecardLayoutProps } from '../../blueprints/ScorecardLayoutBlueprint'; import { useScorecards } from '../../hooks/useScorecards'; import { useTranslation } from '../../hooks/useTranslation'; import NoScorecardsState from '../Common/NoScorecardsState'; diff --git a/workspaces/scorecard/plugins/scorecard/src/components/ScorecardIcon/ScorecardIcon.tsx b/workspaces/scorecard/plugins/scorecard/src/components/ScorecardIcon/ScorecardIcon.tsx index 59239a917a6..9274d72ffd5 100644 --- a/workspaces/scorecard/plugins/scorecard/src/components/ScorecardIcon/ScorecardIcon.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/components/ScorecardIcon/ScorecardIcon.tsx @@ -18,11 +18,9 @@ import Box from '@mui/material/Box'; import MuiIcon from '@mui/material/Icon'; import type { SvgIconComponent } from '@mui/icons-material'; import type { SxProps, Theme } from '@mui/material/styles'; -import { - ScorecardSuccessStatusIcon, - ScorecardWarningStatusIcon, - ScorecardErrorStatusIcon, -} from '../..'; +import ScorecardSuccessStatusIcon from '@mui/icons-material/CheckCircleOutline'; +import ScorecardWarningStatusIcon from '@mui/icons-material/WarningAmber'; +import ScorecardErrorStatusIcon from '@mui/icons-material/DangerousOutlined'; const builtInIcons: Record = { scorecardSuccessStatusIcon: ScorecardSuccessStatusIcon, diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/api.ts b/workspaces/scorecard/plugins/scorecard/src/extensions/api.ts similarity index 94% rename from workspaces/scorecard/plugins/scorecard/src/alpha/extensions/api.ts rename to workspaces/scorecard/plugins/scorecard/src/extensions/api.ts index 830c5540fbb..5b8f24229d5 100644 --- a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/api.ts +++ b/workspaces/scorecard/plugins/scorecard/src/extensions/api.ts @@ -20,7 +20,7 @@ import { discoveryApiRef, fetchApiRef, } from '@backstage/frontend-plugin-api'; -import { ScorecardApiClient, scorecardApiRef } from '../../api'; +import { ScorecardApiClient, scorecardApiRef } from '../api'; /** Scorecard API extension. */ export const scorecardApi = ApiBlueprint.make({ diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/entityTab.tsx b/workspaces/scorecard/plugins/scorecard/src/extensions/entityTab.tsx similarity index 94% rename from workspaces/scorecard/plugins/scorecard/src/alpha/extensions/entityTab.tsx rename to workspaces/scorecard/plugins/scorecard/src/extensions/entityTab.tsx index 8cfd1604dca..fc42ea18892 100644 --- a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/entityTab.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/extensions/entityTab.tsx @@ -21,7 +21,7 @@ import { coreExtensionData, } from '@backstage/frontend-plugin-api'; -import { rootRouteRef } from '../../routes'; +import { rootRouteRef } from '../routes'; import { scorecardLayoutTitleDataRef } from '../blueprints/ScorecardLayoutBlueprint'; /** @@ -30,8 +30,6 @@ import { scorecardLayoutTitleDataRef } from '../blueprints/ScorecardLayoutBluepr * When one or more layout blueprint extensions are attached, renders * a {@link ScorecardLayoutSwitcher} with a toggle (when 2+). * Otherwise falls back to the legacy flat {@link EntityScorecardContent}. - * - * @alpha */ export const scorecardEntityContent = EntityContentBlueprint.makeWithOverrides({ name: 'entity-content-scorecard', @@ -86,12 +84,12 @@ export const scorecardEntityContent = EntityContentBlueprint.makeWithOverrides({ })); const { ScorecardLayoutSwitcher } = await import( - '../../components/Scorecard/ScorecardLayoutSwitcher' + '../components/Scorecard/ScorecardLayoutSwitcher' ); return ; } const { EntityScorecardContent } = await import( - '../../components/Scorecard' + '../components/Scorecard' ); return ; }, diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/homePageCards.tsx b/workspaces/scorecard/plugins/scorecard/src/extensions/homePageCards.tsx similarity index 98% rename from workspaces/scorecard/plugins/scorecard/src/alpha/extensions/homePageCards.tsx rename to workspaces/scorecard/plugins/scorecard/src/extensions/homePageCards.tsx index 6ac56708486..96bd7838696 100644 --- a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/homePageCards.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/extensions/homePageCards.tsx @@ -41,7 +41,7 @@ function lazyScorecardWidget( ) { return async () => { const { ScorecardHomepageCardWithProvider } = await import( - '../../components/ScorecardHomepageSection' + '../components/ScorecardHomepageSection' ); return { Content: factory(ScorecardHomepageCardWithProvider) }; }; @@ -53,7 +53,6 @@ function BorderlessHomeWidgetRenderer({ Content }: RendererProps) { /** * NFS widget: AggregatedCardWithDeprecatedMetricId. - * @alpha */ export const aggregatedCardWithDeprecatedMetricIdWidget = HomePageWidgetBlueprint.make({ @@ -74,7 +73,6 @@ export const aggregatedCardWithDeprecatedMetricIdWidget = /** * NFS widget: AggregatedCardWithDefaultAggregation. - * @alpha */ export const aggregatedCardWithDefaultAggregationWidget = HomePageWidgetBlueprint.make({ @@ -95,7 +93,6 @@ export const aggregatedCardWithDefaultAggregationWidget = /** * NFS widget: AggregatedCardWithJiraOpenIssues. - * @alpha */ export const aggregatedCardWithJiraOpenIssuesWidget = HomePageWidgetBlueprint.make({ @@ -116,7 +113,6 @@ export const aggregatedCardWithJiraOpenIssuesWidget = /** * NFS widget: AggregatedCardWithGithubOpenPrs. - * @alpha */ export const aggregatedCardWithGithubOpenPrsWidget = HomePageWidgetBlueprint.make({ @@ -137,7 +133,6 @@ export const aggregatedCardWithGithubOpenPrsWidget = /** * NFS widget: AggregatedCardWithGithubFilecheckLicense. - * @alpha */ export const aggregatedCardWithGithubFilecheckLicenseWidget = HomePageWidgetBlueprint.make({ @@ -160,7 +155,6 @@ export const aggregatedCardWithGithubFilecheckLicenseWidget = /** * NFS widget: AggregatedCardWithGithubFilecheckCodeowners. - * @alpha */ export const aggregatedCardWithGithubFilecheckCodeownersWidget = HomePageWidgetBlueprint.make({ @@ -183,7 +177,6 @@ export const aggregatedCardWithGithubFilecheckCodeownersWidget = /** * NFS widget: AggregatedCardWithGithubOpenPrsWeighted. - * @alpha */ export const aggregatedCardWithGithubOpenPrsWeightedWidget = HomePageWidgetBlueprint.make({ diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/scorecardLayoutExtensions.tsx b/workspaces/scorecard/plugins/scorecard/src/extensions/scorecardLayoutExtensions.tsx similarity index 81% rename from workspaces/scorecard/plugins/scorecard/src/alpha/extensions/scorecardLayoutExtensions.tsx rename to workspaces/scorecard/plugins/scorecard/src/extensions/scorecardLayoutExtensions.tsx index 56135feb6e7..59c4a941dcc 100644 --- a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/scorecardLayoutExtensions.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/extensions/scorecardLayoutExtensions.tsx @@ -19,8 +19,7 @@ import { ScorecardEntityContentLayoutBlueprint } from '../blueprints'; /** * Grid view layout extension for the Scorecard entity tab. * - * Extension ID: scorecard-layout:catalog/scorecard-entity-layout-grid - * @alpha + * Extension ID: scorecard-layout:scorecard/scorecard-entity-layout-grid */ export const scorecardEntityLayoutGrid = ScorecardEntityContentLayoutBlueprint.make({ @@ -29,8 +28,8 @@ export const scorecardEntityLayoutGrid = params: { title: 'Grid', loader: () => - import( - '../../components/Scorecard/ScorecardEntityContentGridView' - ).then(m => m.ScorecardEntityContentGridView), + import('../components/Scorecard/ScorecardEntityContentGridView').then( + m => m.ScorecardEntityContentGridView, + ), }, }); diff --git a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/scorecardPage.tsx b/workspaces/scorecard/plugins/scorecard/src/extensions/scorecardPage.tsx similarity index 88% rename from workspaces/scorecard/plugins/scorecard/src/alpha/extensions/scorecardPage.tsx rename to workspaces/scorecard/plugins/scorecard/src/extensions/scorecardPage.tsx index 677626f667f..713b64dd348 100644 --- a/workspaces/scorecard/plugins/scorecard/src/alpha/extensions/scorecardPage.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/extensions/scorecardPage.tsx @@ -15,18 +15,17 @@ */ import { PageBlueprint } from '@backstage/frontend-plugin-api'; -import { scorecardDrillDownRouteRef } from '../../routes'; +import { scorecardDrillDownRouteRef } from '../routes'; /** * NFS page extension for the Scorecard drill-down page. - * @alpha */ export const scorecardPage = PageBlueprint.make({ params: { path: '/scorecard/aggregations/:aggregationId/metrics/:metricId', routeRef: scorecardDrillDownRouteRef, loader: () => - import('../../pages/ScorecardPage').then(m => ( + import('../pages/ScorecardPage').then(m => ( )), }, diff --git a/workspaces/scorecard/plugins/scorecard/src/index.ts b/workspaces/scorecard/plugins/scorecard/src/index.ts index 5f2941dfbd3..a1a16d51954 100644 --- a/workspaces/scorecard/plugins/scorecard/src/index.ts +++ b/workspaces/scorecard/plugins/scorecard/src/index.ts @@ -26,8 +26,8 @@ import { import { TranslationBlueprint } from '@backstage/plugin-app-react'; import { rootRouteRef, scorecardDrillDownRouteRef } from './routes'; import { scorecardTranslations } from './translations'; -import { scorecardApi } from './alpha/extensions/api'; -import { scorecardEntityContent } from './alpha/extensions/entityTab'; +import { scorecardApi } from './extensions/api'; +import { scorecardEntityContent } from './extensions/entityTab'; import { aggregatedCardWithDeprecatedMetricIdWidget, aggregatedCardWithDefaultAggregationWidget, @@ -36,9 +36,9 @@ import { aggregatedCardWithGithubFilecheckLicenseWidget, aggregatedCardWithGithubFilecheckCodeownersWidget, aggregatedCardWithGithubOpenPrsWeightedWidget, -} from './alpha/extensions/homePageCards'; -import { scorecardPage } from './alpha/extensions/scorecardPage'; -import { scorecardEntityLayoutGrid } from './alpha/extensions/scorecardLayoutExtensions'; +} from './extensions/homePageCards'; +import { scorecardPage } from './extensions/scorecardPage'; +import { scorecardEntityLayoutGrid } from './extensions/scorecardLayoutExtensions'; /** * Extension for Scorecard translations. @@ -51,30 +51,33 @@ const scorecardTranslation = TranslationBlueprint.make({ /** * The primary Scorecard frontend plugin for the new Backstage frontend system. + * + * Includes page, API, entity tab, layout, and homepage widget extensions. + * Translations remain a separate app module (NFS requirement). + * * @public */ export default createFrontendPlugin({ pluginId: 'scorecard', - extensions: [scorecardApi, scorecardPage], + extensions: [ + scorecardApi, + scorecardPage, + scorecardEntityContent, + scorecardEntityLayoutGrid, + aggregatedCardWithDeprecatedMetricIdWidget, + aggregatedCardWithDefaultAggregationWidget, + aggregatedCardWithJiraOpenIssuesWidget, + aggregatedCardWithGithubOpenPrsWidget, + aggregatedCardWithGithubFilecheckLicenseWidget, + aggregatedCardWithGithubFilecheckCodeownersWidget, + aggregatedCardWithGithubOpenPrsWeightedWidget, + ], routes: { root: rootRouteRef, drillDown: scorecardDrillDownRouteRef, }, }); -/** - * Catalog module that injects the Scorecard tab into Catalog entity pages. - * - * Also ships a grid layout extension (disabled by default). - * Enable it in app-config.yaml to get a layout toggle in the entity tab. - * - * @public - */ -export const scorecardCatalogModule = createFrontendModule({ - pluginId: 'catalog', - extensions: [scorecardEntityContent, scorecardEntityLayoutGrid], -}); - /** * App module that automatically registers Scorecard translations. * @public @@ -84,23 +87,4 @@ export const scorecardTranslationsModule = createFrontendModule({ extensions: [scorecardTranslation], }); -/** - * Home module that contributes scorecard homepage widget and layout. - * @public - */ -export const scorecardHomeModule = createFrontendModule({ - pluginId: 'home', - extensions: [ - aggregatedCardWithDeprecatedMetricIdWidget, - aggregatedCardWithDefaultAggregationWidget, - aggregatedCardWithJiraOpenIssuesWidget, - aggregatedCardWithGithubOpenPrsWidget, - aggregatedCardWithGithubFilecheckLicenseWidget, - aggregatedCardWithGithubFilecheckCodeownersWidget, - aggregatedCardWithGithubOpenPrsWeightedWidget, - ], -}); - export { scorecardTranslationRef, scorecardTranslations } from './translations'; - -export * from './legacyExports'; diff --git a/workspaces/scorecard/plugins/scorecard/src/nfsExports.test.tsx b/workspaces/scorecard/plugins/scorecard/src/nfsExports.test.tsx index 47b6662684d..78eba1809b5 100644 --- a/workspaces/scorecard/plugins/scorecard/src/nfsExports.test.tsx +++ b/workspaces/scorecard/plugins/scorecard/src/nfsExports.test.tsx @@ -14,25 +14,13 @@ * limitations under the License. */ -import scorecardPlugin, { - scorecardCatalogModule, - scorecardHomeModule, - scorecardTranslationsModule, -} from './index'; +import scorecardPlugin, { scorecardTranslationsModule } from './index'; describe('scorecard NFS exports', () => { it('should export the scorecard plugin as default', () => { expect(scorecardPlugin).toBeDefined(); }); - it('should export scorecardCatalogModule', () => { - expect(scorecardCatalogModule).toBeDefined(); - }); - - it('should export scorecardHomeModule', () => { - expect(scorecardHomeModule).toBeDefined(); - }); - it('should export scorecardTranslationsModule', () => { expect(scorecardTranslationsModule).toBeDefined(); }); From 00e2d340f86c994f8e7df87a015ceb51d4ac37c4 Mon Sep 17 00:00:00 2001 From: Yi Cai Date: Wed, 29 Jul 2026 12:51:57 -0400 Subject: [PATCH 5/7] updated report api Signed-off-by: Yi Cai --- workspaces/scorecard/plugins/scorecard/report.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspaces/scorecard/plugins/scorecard/report.api.md b/workspaces/scorecard/plugins/scorecard/report.api.md index 6eaae6752c6..7e3e2f3f259 100644 --- a/workspaces/scorecard/plugins/scorecard/report.api.md +++ b/workspaces/scorecard/plugins/scorecard/report.api.md @@ -32,8 +32,8 @@ const _default: OverridableFrontendPlugin< { root: RouteRef; drillDown: RouteRef<{ - metricId: string; aggregationId: string; + metricId: string; }>; }, {}, From 4d3059816207c77b97a4d6b7277461ef11a66990 Mon Sep 17 00:00:00 2001 From: Yi Cai Date: Wed, 29 Jul 2026 16:48:49 -0400 Subject: [PATCH 6/7] fix(scorecard): export ScorecardLayoutProps and stop omitting ae-forgotten-export Signed-off-by: Yi Cai --- workspaces/scorecard/package.json | 2 +- .../scorecard/plugins/scorecard/report.api.md | 25 +++++++++++++------ .../scorecard/plugins/scorecard/src/index.ts | 6 +++++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/workspaces/scorecard/package.json b/workspaces/scorecard/package.json index 76ce1abd974..7c1862cdeba 100644 --- a/workspaces/scorecard/package.json +++ b/workspaces/scorecard/package.json @@ -14,7 +14,7 @@ "build:backend": "yarn workspace backend build", "build:all": "backstage-cli repo build --all", "build:api-reports": "yarn build:api-reports:only", - "build:api-reports:only": "backstage-repo-tools api-reports -o ae-wrong-input-file-type,ae-undocumented,ae-missing-release-tag,ae-forgotten-export --validate-release-tags", + "build:api-reports:only": "backstage-repo-tools api-reports -o ae-wrong-input-file-type,ae-undocumented,ae-missing-release-tag --validate-release-tags", "build-image": "yarn workspace backend build-image", "build:knip-reports": "backstage-repo-tools knip-reports", "clean": "backstage-cli repo clean", diff --git a/workspaces/scorecard/plugins/scorecard/report.api.md b/workspaces/scorecard/plugins/scorecard/report.api.md index 7e3e2f3f259..3027ed054f6 100644 --- a/workspaces/scorecard/plugins/scorecard/report.api.md +++ b/workspaces/scorecard/plugins/scorecard/report.api.md @@ -57,8 +57,8 @@ const _default: OverridableFrontendPlugin< config: { allowedFilters: | { - kind?: string | undefined; type?: string | undefined; + kind?: string | undefined; }[] | undefined; path: string | undefined; @@ -70,8 +70,8 @@ const _default: OverridableFrontendPlugin< configInput: { allowedFilters?: | { - kind?: string | undefined; type?: string | undefined; + kind?: string | undefined; }[] | undefined; path?: string | undefined | undefined; @@ -121,12 +121,8 @@ const _default: OverridableFrontendPlugin< >; inputs: { layouts: ExtensionInput< - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - JSX_2.Element, - 'core.reactElement', - {} - >, + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef, { singleton: false; optional: true; @@ -335,6 +331,19 @@ const _default: OverridableFrontendPlugin< >; export default _default; +// @public (undocumented) +export interface ScorecardLayoutProps { + // (undocumented) + groups: Record< + string, + { + title: string; + description?: string; + metrics: string[]; + } + >; +} + // @public export const scorecardTranslationRef: TranslationRef< 'plugin.scorecard', diff --git a/workspaces/scorecard/plugins/scorecard/src/index.ts b/workspaces/scorecard/plugins/scorecard/src/index.ts index a1a16d51954..013897c36d1 100644 --- a/workspaces/scorecard/plugins/scorecard/src/index.ts +++ b/workspaces/scorecard/plugins/scorecard/src/index.ts @@ -88,3 +88,9 @@ export const scorecardTranslationsModule = createFrontendModule({ }); export { scorecardTranslationRef, scorecardTranslations } from './translations'; + +/** + * Props for Scorecard entity-tab layout components. + * @public + */ +export type { ScorecardLayoutProps } from './blueprints/ScorecardLayoutBlueprint'; From 0d0d172ca8380a63ace5d308932cae6d748c7658 Mon Sep 17 00:00:00 2001 From: Yi Cai Date: Wed, 29 Jul 2026 16:59:56 -0400 Subject: [PATCH 7/7] fix(scorecard): document ScorecardLayoutProps and sync API report with tsc:full Signed-off-by: Yi Cai --- .../scorecard/plugins/scorecard/report.api.md | 15 +++++++++------ .../src/blueprints/ScorecardLayoutBlueprint.ts | 9 ++++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/workspaces/scorecard/plugins/scorecard/report.api.md b/workspaces/scorecard/plugins/scorecard/report.api.md index 3027ed054f6..552da2a5092 100644 --- a/workspaces/scorecard/plugins/scorecard/report.api.md +++ b/workspaces/scorecard/plugins/scorecard/report.api.md @@ -57,8 +57,8 @@ const _default: OverridableFrontendPlugin< config: { allowedFilters: | { - type?: string | undefined; kind?: string | undefined; + type?: string | undefined; }[] | undefined; path: string | undefined; @@ -70,8 +70,8 @@ const _default: OverridableFrontendPlugin< configInput: { allowedFilters?: | { - type?: string | undefined; kind?: string | undefined; + type?: string | undefined; }[] | undefined; path?: string | undefined | undefined; @@ -121,8 +121,12 @@ const _default: OverridableFrontendPlugin< >; inputs: { layouts: ExtensionInput< - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef, + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >, { singleton: false; optional: true; @@ -331,9 +335,8 @@ const _default: OverridableFrontendPlugin< >; export default _default; -// @public (undocumented) +// @public export interface ScorecardLayoutProps { - // (undocumented) groups: Record< string, { diff --git a/workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.ts b/workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.ts index dc863ddaee1..f4728685b7e 100644 --- a/workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.ts +++ b/workspaces/scorecard/plugins/scorecard/src/blueprints/ScorecardLayoutBlueprint.ts @@ -22,8 +22,15 @@ import { ExtensionBoundary, } from '@backstage/frontend-plugin-api'; -/** @public */ +/** + * Props for custom Scorecard entity-tab layout components. + * + * @public + */ export interface ScorecardLayoutProps { + /** + * Metric groups to render, keyed by group id. + */ groups: Record< string, { title: string; description?: string; metrics: string[] }