Skip to content

RHIDP-14172 Refactor average aggregation type for Scorecard card#3417

Open
imykhno wants to merge 3 commits into
redhat-developer:mainfrom
imykhno:refactor/scorecard-aggregation-type
Open

RHIDP-14172 Refactor average aggregation type for Scorecard card#3417
imykhno wants to merge 3 commits into
redhat-developer:mainfrom
imykhno:refactor/scorecard-aggregation-type

Conversation

@imykhno

@imykhno imykhno commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Hey, I just made a Pull Request!

Based on our discussion regarding the new scorecard aggregation types, we decided that the currently implemented average is actually a weighted status score — not an average of raw values. Because of this, we have decided to refactor the name of the average type.

For:

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or Updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)

How to test:

Confirm that weightedStatusScore aggregation type works correctly:

  1. Add widget to the homepage
  2. Add config to app-config.yaml, for example:
scorecard:
  aggregationKPIs:
    openPrsWeightedKpi: # use this id for ScorecardHomepageCard cards mountpoint under 'config.props.aggregationId'
      title: GitHub Open PRs KPI (weighted health)
      type: weightedStatusScore
      description: Weighted health score for GitHub Open PRs by threshold status across your entities.
      metricId: github.open_prs
      options:
        statusScores:
          success: 100
          warning: 50
          error: 0
        thresholds:
          rules:
            - key: success
              expression: '>=80'
              color: '#6bb300' # green
            - key: warning
              expression: '51-80'
              color: 'rgb(224, 189, 108)' # light orange
            - key: error
              expression: '<51'
              color: '#be1ec7' # purple
            - key: critical
              expression: '<10'
              color: '#ff0000' # red
  1. Open homepage to confirmation

@rhdh-gh-app

rhdh-gh-app Bot commented Jun 16, 2026

Copy link
Copy Markdown

Important

This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior.

Changed Packages

Package Name Package Path Changeset Bump Current Version
app-legacy workspaces/scorecard/packages/app-legacy none v0.0.0
@red-hat-developer-hub/backstage-plugin-scorecard-backend workspaces/scorecard/plugins/scorecard-backend minor v2.7.9
@red-hat-developer-hub/backstage-plugin-scorecard-common workspaces/scorecard/plugins/scorecard-common minor v2.7.9
@red-hat-developer-hub/backstage-plugin-scorecard workspaces/scorecard/plugins/scorecard minor v2.7.9

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 16, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:19 PM UTC · Completed 2:35 PM UTC
Commit: e378636 · View workflow run →

@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 54.03%. Comparing base (efb4c4f) to head (60f1f11).
⚠️ Report is 12 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3417   +/-   ##
=======================================
  Coverage   54.02%   54.03%           
=======================================
  Files        2409     2409           
  Lines       87733    87740    +7     
  Branches    24306    24308    +2     
=======================================
+ Hits        47400    47407    +7     
  Misses      38812    38812           
  Partials     1521     1521           
Flag Coverage Δ *Carryforward flag
adoption-insights 83.58% <ø> (ø) Carriedforward from efb4c4f
ai-integrations 70.03% <ø> (ø) Carriedforward from efb4c4f
app-defaults 69.60% <ø> (ø) Carriedforward from efb4c4f
augment 46.39% <ø> (ø) Carriedforward from efb4c4f
bulk-import 72.69% <ø> (ø) Carriedforward from efb4c4f
cost-management 17.48% <ø> (ø) Carriedforward from efb4c4f
dcm 60.27% <ø> (ø) Carriedforward from efb4c4f
extensions 62.17% <ø> (ø) Carriedforward from efb4c4f
global-floating-action-button 74.30% <ø> (ø) Carriedforward from efb4c4f
global-header 61.63% <ø> (ø) Carriedforward from efb4c4f
homepage 52.60% <ø> (ø) Carriedforward from efb4c4f
install-dynamic-plugins 56.23% <ø> (ø) Carriedforward from efb4c4f
konflux 91.01% <ø> (ø) Carriedforward from efb4c4f
lightspeed 68.62% <ø> (ø) Carriedforward from efb4c4f
mcp-integrations 85.46% <ø> (ø) Carriedforward from efb4c4f
orchestrator 37.33% <ø> (ø) Carriedforward from efb4c4f
quickstart 62.09% <ø> (ø) Carriedforward from efb4c4f
sandbox 79.56% <ø> (ø) Carriedforward from efb4c4f
scorecard 83.97% <100.00%> (+0.03%) ⬆️
theme 64.44% <ø> (ø) Carriedforward from efb4c4f
translations 8.49% <ø> (ø) Carriedforward from efb4c4f
x2a 78.79% <ø> (ø) Carriedforward from efb4c4f

*This pull request uses carry forward flags. Click here to find out more.


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update efb4c4f...60f1f11. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review

Findings

Critical

  • [semver-violation] workspaces/scorecard/.changeset/stupid-knives-wonder.md — The changeset marks scorecard-common, scorecard-backend, and scorecard as minor bumps, but the PR introduces breaking changes to post-1.0 packages (currently v2.7.9): public exported types are renamed (AggregatedMetricAverageResultWeightedStatusScoreAggregationResult), public constant keys are renamed (aggregationTypes.averageaggregationTypes.weightedStatusScore), API response field names change, and the config type value changes. Per semver for packages ≥ 1.0.0, breaking changes require a major version bump. The changeset itself documents these as "Breaking changes" yet uses minor. The repo has precedent for major bumps (e.g., dcm workspace).
    Remediation: Change the changeset bump level from minor to major for all three affected packages. Alternatively, add deprecated aliases (see below) and keep the old keys alongside the new ones, deferring the removal to a future major.

  • [breaking-api-change] workspaces/scorecard/plugins/scorecard-common/src/types/aggregation.ts:73 — The public type AggregatedMetricAverageResult (listed as @public in report.api.md) is renamed to WeightedStatusScoreAggregationResult with no deprecated alias. External consumers importing this type will get compile-time errors. The fields averageScore, averageWeightedSum, and averageMaxPossible are also renamed, breaking runtime consumers that destructure or access these properties.
    Remediation: Either bump to major, or keep the old type as a deprecated alias: export type AggregatedMetricAverageResult = WeightedStatusScoreAggregationResult; with a @deprecated JSDoc tag.

  • [breaking-api-change] workspaces/scorecard/plugins/scorecard-common/src/constants/aggregations.ts:27 — The public constant aggregationTypes.average is renamed to aggregationTypes.weightedStatusScore. JavaScript consumers using aggregationTypes.average will get undefined at runtime (no compile error for JS consumers). This also changes the string literal value that appears in API responses (metadata.aggregationType) and config files (scorecard.aggregationKPIs.*.type).
    Remediation: Major bump, or add the new key while keeping the old key as deprecated: average: WEIGHTED_STATUS_SCORE, weightedStatusScore: WEIGHTED_STATUS_SCORE.

High

  • [breaking-config-change] workspaces/scorecard/plugins/scorecard-backend/config.d.ts — The config type value changes from average to weightedStatusScore. Any deployer with type: average in their app-config.yaml will get a config validation error or undefined behavior after upgrading.
    Remediation: Accept both average and weightedStatusScore as valid type values (with average logged as deprecated), or accompany with a major version bump.

Medium

  • [naming-consistency] workspaces/scorecard/plugins/scorecard-common/src/types/aggregation.ts:73 — The old type AggregatedMetricAverageResult followed the AggregatedMetric*Result naming pattern, while the new name WeightedStatusScoreAggregationResult follows the *AggregationResult pattern used by the sibling StatusGroupedAggregationResult. The rename moves toward consistency with the sibling type, but the two patterns now coexist in the type union AggregationResultByType.

  • [api-response-field-rename] workspaces/scorecard/plugins/scorecard-backend/src/service/aggregations/strategies/WeightedStatusScoreAggregationStrategy.ts:104 — This is a wire-protocol change, not just a TypeScript type rename. HTTP clients (including non-TypeScript consumers) that parse JSON fields averageScore, averageWeightedSum, averageMaxPossible by name will break.

Low

  • [missing-deprecation-path] workspaces/scorecard/plugins/scorecard-common/src/types/aggregation.ts — No deprecation path is provided for the renamed types and fields. The project previously demonstrated good deprecation practices (v2.5.0 deprecated the old catalog-aggregations URL with RFC 8594 headers rather than removing immediately).
Previous run

Review

Findings

High

  • [exported-constant-rename] workspaces/scorecard/plugins/scorecard-common/src/constants/aggregations.ts:24 — The @public exported aggregationTypes constant object loses its average key and gains weightedStatusScore. Any consumer referencing aggregationTypes.average will break at compile time and runtime. The value string also changes from 'average' to 'weightedStatusScore', breaking any code that persists or compares the string literal.
    Remediation: Major bump is correctly declared. For backward compatibility during a transition period, consider keeping average as a deprecated alias key on the frozen object so both values are accepted temporarily.

  • [api-response-contract] workspaces/scorecard/plugins/scorecard-backend/src/service/aggregations/strategies/WeightedStatusScoreAggregationStrategy.ts:104 — The GET /aggregations/:aggregationId REST API response body changes three field names on the result object (averageScoreweightedStatusScore, averageWeightedSumweightedStatusSum, averageMaxPossibleweightedStatusMaxPossible) and the metadata.aggregationType string value from 'average' to 'weightedStatusScore'. Any downstream HTTP client reading these fields will silently get undefined for the old field names.
    Remediation: Major version bump covers the semver contract. If rolling deployments are possible (frontend and backend updated independently), consider having the backend serve both old and new field names during a transition window, or document that frontend and backend must be upgraded in lockstep.

Medium

  • [exported-type-removal] workspaces/scorecard/plugins/scorecard-common/src/types/aggregation.ts:73 — The type AggregatedMetricAverageResult is removed and replaced by WeightedStatusScoreAggregationResult. While not annotated with @public JSDoc, it is used in the @public union AggregationResultByType and exported via barrel exports. External consumers importing it will get compile-time errors with no deprecation guidance.
    Remediation: Consider re-exporting WeightedStatusScoreAggregationResult under the old name as a deprecated alias for at least one release cycle.

  • [config-schema-change] workspaces/scorecard/plugins/scorecard-backend/config.d.ts:36 — The app-config schema for scorecard.aggregationKPIs.*.type no longer accepts the string 'average'. Existing deployed app-config.yaml files using type: average will fail backend startup validation via the Zod discriminated union with a generic parse error that does not mention the rename.
    Remediation: Add a validation check that detects type: 'average' and throws a targeted error message like: Aggregation type "average" has been renamed to "weightedStatusScore". Update your app-config.yaml.

  • [translation-key-rename] workspaces/scorecard/plugins/scorecard/src/translations/ref.ts:183 — Seven translation keys in the @public scorecardTranslationRef are renamed (e.g. metric.averageCenterTooltipTotalLabelmetric.weightedStatusScoreCenterTooltipTotalLabel). Any consumer that provides custom translation overrides for these keys will silently lose those overrides after upgrading.
    Remediation: Document the translation key renames in the migration/changelog so adopters with custom translations know to update them.

Low

  • [scope-creep] workspaces/scorecard/.changeset/rename-average-to-weighted-status-score.md:8 — The changeset declares major bumps for scorecard-backend-module-github, scorecard-backend-module-jira, and scorecard-node, but the diff contains zero code changes in those three packages and they do not re-export any renamed identifiers. A major bump signals breaking changes in a package's own API surface.
    Remediation: Remove those three packages from the changeset unless they re-export renamed types from scorecard-common.

  • [naming-coherence] workspaces/scorecard/plugins/scorecard-backend/src/service/aggregations/strategies/weightedStatusScoreAggregationStrategy.test.ts:119 — Several test fixtures still use avgKpi as the aggregation config id, referencing the old 'average' concept inconsistently with the otherwise thorough rename.
    Remediation: Rename test fixture ids from avgKpi to weightedKpi or weightedStatusScoreKpi.

Info

  • [traceability] The PR references RHIDP-14172 (a JIRA ticket) in the title but has no linked GitHub issue. The PR body is the default template with an empty checklist. There is no design rationale captured for why average is being renamed to weightedStatusScore.
    Remediation: Fill in the PR body with the motivation for the rename. Complete the PR checklist before removing the WIP label.

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

* Supported aggregation types
* @public
*/
export const aggregationTypes = Object.freeze({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[high] exported-constant-rename

The @public exported aggregationTypes constant object loses its average key and gains weightedStatusScore. Any consumer referencing aggregationTypes.average will break at compile time and runtime. The value string also changes from average to weightedStatusScore, breaking any code that persists or compares the string literal.

Suggested fix: Major bump is correctly declared. For backward compatibility during a transition period, consider keeping average as a deprecated alias key on the frozen object so both values are accepted temporarily.

@@ -101,11 +104,11 @@ export class AverageAggregationStrategy implements AggregationStrategy {
score: options.statusScores[rule.key] ?? 0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[high] api-response-contract

The GET /aggregations/:aggregationId REST API response body changes three field names on the result object (averageScore to weightedStatusScore, averageWeightedSum to weightedStatusSum, averageMaxPossible to weightedStatusMaxPossible) and the metadata.aggregationType string value. Any downstream HTTP client reading these fields will silently get undefined for the old field names.

Suggested fix: Major version bump covers the semver contract. If rolling deployments are possible, consider having the backend serve both old and new field names during a transition window, or document that frontend and backend must be upgraded in lockstep.

averageMaxPossible: number;
aggregationChartDisplayColor: string;
};
export type WeightedStatusScoreAggregationResult =

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] exported-type-removal

The type AggregatedMetricAverageResult is removed and replaced by WeightedStatusScoreAggregationResult. While not annotated with @public JSDoc, it is used in the @public union AggregationResultByType and exported via barrel exports. External consumers importing it will get compile-time errors with no deprecation guidance.

Suggested fix: Consider re-exporting WeightedStatusScoreAggregationResult under the old name as a deprecated alias for at least one release cycle.

'@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-jira': major
'@red-hat-developer-hub/backstage-plugin-scorecard-common': major
'@red-hat-developer-hub/backstage-plugin-scorecard-node': major
---

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] scope-creep

The changeset declares major bumps for scorecard-backend-module-github, scorecard-backend-module-jira, and scorecard-node, but the diff contains zero code changes in those three packages and they do not re-export any renamed identifiers.

Suggested fix: Remove those three packages from the changeset unless they re-export renamed types from scorecard-common.

@@ -119,7 +119,7 @@ describe('AverageAggregationStrategy', () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] naming-coherence

Several test fixtures still use avgKpi as the aggregation config id, referencing the old average concept inconsistently with the otherwise thorough rename.

Suggested fix: Rename test fixture ids from avgKpi to weightedKpi or weightedStatusScoreKpi.

imykhno added 3 commits June 16, 2026 16:37
…dStatusScore`

Signed-off-by: Ihor Mykhno <imykhno@redhat.com>
… safety and improved structure

Signed-off-by: Ihor Mykhno <imykhno@redhat.com>
…dKpi` across tests and configurations

Signed-off-by: Ihor Mykhno <imykhno@redhat.com>
@imykhno imykhno force-pushed the refactor/scorecard-aggregation-type branch from 4831a52 to 60f1f11 Compare June 17, 2026 08:33
@fullsend-ai-review

Copy link
Copy Markdown

🤖 Review · Started 8:35 AM UTC
Commit: bbcdc56 · View workflow run →

@sonarqubecloud

Copy link
Copy Markdown

@fullsend-ai-review

Copy link
Copy Markdown

🤖 Finished Review · ❌ Failure · Started 8:35 AM UTC · Completed 8:43 AM UTC
Commit: bbcdc56 · View workflow run →

@imykhno

imykhno commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

/fs-review

@imykhno imykhno marked this pull request as ready for review June 17, 2026 09:28
@fullsend-ai-review

Copy link
Copy Markdown

🤖 Review · Started 9:29 AM UTC
Commit: bbcdc56 · View workflow run →

@rhdh-qodo-merge

Copy link
Copy Markdown

PR Summary by Qodo

Refactor Scorecard aggregation type: average → weightedStatusScore
✨ Enhancement 📝 Documentation 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

Description

• Rename aggregation KPI type average to weightedStatusScore across backend, common, and UI.
• Update /aggregations/:aggregationId contract and config examples to new result fields.
• Refresh unit/e2e tests, fixtures, and i18n keys to match renamed aggregation.
Diagram

graph TD
  A["App config (aggregationKPIs)"] --> B(["Backend config validation"])
  B --> C(["Strategy registry"])
  C --> D{{"GET /aggregations/:id"}}
  D --> E["scorecard-common types"]
  D --> F(["Frontend AggregatedMetricCard"])
  F --> G(["WeightedStatusScore card"])
  G --> H["E2E/UI tests"]
  subgraph Legend
    direction LR
    _cfg["Config file"] ~~~ _svc(["Service/Module"]) ~~~ _api{{"API"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Backward-compatible alias (accept both types)
  • ➕ Avoids immediate breaking app-config changes (average continues working).
  • ➕ Allows a deprecation window with warnings and staged rollout.
  • ➖ More branching/complexity in validation and strategy registry.
  • ➖ Requires documenting deprecation policy and eventually removing alias.
2. API dual-field response during transition
  • ➕ Older clients can keep reading averageScore/averageWeightedSum/averageMaxPossible.
  • ➕ New clients can adopt weightedStatusScore* without coordination.
  • ➖ Bloats API payload and increases maintenance burden.
  • ➖ Ambiguity: which fields are canonical if both exist?
3. Keep name `average`, clarify semantics in docs only
  • ➕ Zero breaking changes to config and API.
  • ➕ Fastest migration path for users.
  • ➖ Terminology remains misleading; encourages incorrect mental model.
  • ➖ Increases long-term confusion and support load.

Recommendation: Current PR approach (explicit rename to weightedStatusScore across config + API + UI) is the cleanest long-term choice because it aligns the public contract with actual semantics. If consumers are sensitive to breakage, consider layering in an alias for average for one release with warnings, but keep weightedStatusScore as the canonical type/fields.

Files changed (53) +528 / -428

Refactor (25) +233 / -177
aggregationKPIs.tsRename default KPI result thresholds constant for weightedStatusScore +21/-20

Rename default KPI result thresholds constant for weightedStatusScore

• Renames the default thresholds constant from 'DEFAULT_AVERAGE_KPI_RESULT_THRESHOLDS' to 'DEFAULT_WEIGHTED_STATUS_SCORE_KPI_RESULT_THRESHOLDS', keeping the same rules.

workspaces/scorecard/plugins/scorecard-backend/src/constants/aggregationKPIs.ts

WeightedStatusScoreAggregationStrategy.tsRename strategy class and emit weightedStatusScore result fields +26/-23

Rename strategy class and emit weightedStatusScore result fields

• Renames the strategy from average to weightedStatusScore and updates log/error messages accordingly. Emits 'weightedStatusScore', 'weightedStatusSum', and 'weightedStatusMaxPossible', and applies the renamed default result thresholds constant when none are configured.

workspaces/scorecard/plugins/scorecard-backend/src/service/aggregations/strategies/WeightedStatusScoreAggregationStrategy.ts

registerStrategies.tsRegister weightedStatusScore aggregation strategy +5/-2

Register weightedStatusScore aggregation strategy

• Replaces the 'average' strategy registration with 'weightedStatusScore' in the aggregation strategy registry.

workspaces/scorecard/plugins/scorecard-backend/src/service/aggregations/strategies/registerStrategies.ts

buildAggregationConfig.tsAttach options only for weightedStatusScore aggregation type +1/-1

Attach options only for weightedStatusScore aggregation type

• Changes the type guard so options parsing is performed for 'aggregationTypes.weightedStatusScore' instead of 'average'.

workspaces/scorecard/plugins/scorecard-backend/src/utils/buildAggregationConfig.ts

aggregationConfigSchemas.tsRename Zod schema discriminator from average to weightedStatusScore +3/-3

Rename Zod schema discriminator from average to weightedStatusScore

• Replaces the 'average' aggregation schema with a 'weightedStatusScore' schema in the discriminated union used for validation.

workspaces/scorecard/plugins/scorecard-backend/src/validation/schemas/aggregationConfigSchemas.ts

validateAggregationConfig.tsValidate aggregation thresholds for weightedStatusScore type +1/-1

Validate aggregation thresholds for weightedStatusScore type

• Switches the conditional threshold validation trigger from 'average' to 'weightedStatusScore'.

workspaces/scorecard/plugins/scorecard-backend/src/validation/validateAggregationConfig.ts

aggregations.tsRename aggregationTypes constant from average to weightedStatusScore +2/-2

Rename aggregationTypes constant from average to weightedStatusScore

• Replaces the 'average' aggregation type constant with 'weightedStatusScore' in the exported 'aggregationTypes' object.

workspaces/scorecard/plugins/scorecard-common/src/constants/aggregations.ts

aggregation.tsRename aggregation result type and fields to weightedStatusScore +9/-8

Rename aggregation result type and fields to weightedStatusScore

• Replaces 'AggregatedMetricAverageResult' with 'WeightedStatusScoreAggregationResult' and updates unions and comments. Renames 'score' field documentation to match new aggregation naming.

workspaces/scorecard/plugins/scorecard-common/src/types/aggregation.ts

AggregatedMetricCard.tsxRefactor card dispatcher to type-guard scorecard results and route to new card +38/-25

Refactor card dispatcher to type-guard scorecard results and route to new card

• Replaces the 'switch' + casts with typed predicates based on 'metadata.aggregationType'. Routes weighted KPIs to 'WeightedStatusScoreCardComponent' and keeps the unsupported fallback panel.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/AggregatedMetricCard.tsx

types.tsTighten StatusGrouped card props typing and extract shared base props +8/-8

Tighten StatusGrouped card props typing and extract shared base props

• Introduces stronger typing for 'metadata.aggregationType === statusGrouped' and reuses a shared 'AggregatedMetricCardBaseProps' type.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/StatusGroupedCard/types.ts

DonutChartTooltipContent.tsxRename donut tooltip translation keys to weightedStatusScore +3/-3

Rename donut tooltip translation keys to weightedStatusScore

• Updates center tooltip labels and breakdown translation key usage to the new 'metric.weightedStatusScore*' namespace.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/WeightedStatusScoreCard/DonutChartTooltipContent.tsx

LegendTooltipContent.tsxRename legend tooltip translation keys to weightedStatusScore +2/-2

Rename legend tooltip translation keys to weightedStatusScore

• Updates legend tooltip translations to use the new weightedStatusScore translation keys while keeping the same content structure.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/WeightedStatusScoreCard/LegendTooltipContent.tsx

TooltipContent.tsxProvide shared tooltip value formatting and display component +0/-0

Provide shared tooltip value formatting and display component

• Defines a reusable 'TooltipContent' component plus 'formatAggregationScoreDetail' helper used by weightedStatusScore tooltip UIs.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/WeightedStatusScoreCard/TooltipContent.tsx

WeightedStatusScoreCardComponent.tsxRename average donut card component to weightedStatusScore and update field usage +22/-19

Rename average donut card component to weightedStatusScore and update field usage

• Renames constants/slice names/test IDs and switches the card to read 'weightedStatusScore', 'weightedStatusSum', and 'weightedStatusMaxPossible' from API results. Keeps the same donut gauge rendering behavior.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/WeightedStatusScoreCard/WeightedStatusScoreCardComponent.tsx

WeightedStatusScoreCardPieCenterLabel.tsxRename center label component and test IDs for weightedStatusScore donut +5/-5

Rename center label component and test IDs for weightedStatusScore donut

• Renames the center label component props/type and updates hover hit-area and percent label test IDs to the weightedStatusScore namespace.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/WeightedStatusScoreCard/WeightedStatusScoreCardPieCenterLabel.tsx

types.tsAdd typed props for WeightedStatusScore card and tooltip positioning +35/-0

Add typed props for WeightedStatusScore card and tooltip positioning

• Introduces a dedicated props type that narrows 'metadata.aggregationType' to 'weightedStatusScore' and binds the correct result type. Exports 'TooltipPosition' for shared tooltip components.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/WeightedStatusScoreCard/types.ts

CardLegendContent.tsxUpdate tooltip position type import for legend content +1/-1

Update tooltip position type import for legend content

• Switches the 'TooltipPosition' import to the new WeightedStatusScore card types module.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/components/CardLegendContent.tsx

CardTooltip.tsxUpdate tooltip position type import for tooltip portal component +1/-1

Update tooltip position type import for tooltip portal component

• Switches the 'TooltipPosition' import to the new WeightedStatusScore card types module.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/components/CardTooltip.tsx

types.tsExtract shared AggregatedMetricCard base props +1/-11

Extract shared AggregatedMetricCard base props

• Replaces the old average-card specific prop types with a shared 'AggregatedMetricCardBaseProps' used by all aggregation card variants.

workspaces/scorecard/plugins/scorecard/src/components/AggregatedMetricCards/types.ts

de.tsRename i18n keys for weightedStatusScore tooltip strings (DE) +9/-7

Rename i18n keys for weightedStatusScore tooltip strings (DE)

• Replaces 'metric.average*' keys with 'metric.weightedStatusScore*' equivalents for tooltip/legend labels.

workspaces/scorecard/plugins/scorecard/src/translations/de.ts

es.tsRename i18n keys for weightedStatusScore tooltip strings (ES) +9/-7

Rename i18n keys for weightedStatusScore tooltip strings (ES)

• Replaces 'metric.average*' keys with 'metric.weightedStatusScore*' equivalents for tooltip/legend labels.

workspaces/scorecard/plugins/scorecard/src/translations/es.ts

fr.tsRename i18n keys for weightedStatusScore tooltip strings (FR) +7/-7

Rename i18n keys for weightedStatusScore tooltip strings (FR)

• Replaces 'metric.average*' keys with 'metric.weightedStatusScore*' equivalents for tooltip/legend labels.

workspaces/scorecard/plugins/scorecard/src/translations/fr.ts

it.tsRename i18n keys for weightedStatusScore tooltip strings (IT) +9/-7

Rename i18n keys for weightedStatusScore tooltip strings (IT)

• Replaces 'metric.average*' keys with 'metric.weightedStatusScore*' equivalents for tooltip/legend labels.

workspaces/scorecard/plugins/scorecard/src/translations/it.ts

ja.tsRename i18n keys for weightedStatusScore tooltip strings (JA) +7/-7

Rename i18n keys for weightedStatusScore tooltip strings (JA)

• Replaces 'metric.average*' keys with 'metric.weightedStatusScore*' equivalents for tooltip/legend labels.

workspaces/scorecard/plugins/scorecard/src/translations/ja.ts

ref.tsRename reference i18n keys for weightedStatusScore tooltip strings +8/-7

Rename reference i18n keys for weightedStatusScore tooltip strings

• Updates the canonical 'ref' message bundle to use 'weightedStatusScore' key names for total/max and breakdown/legend tooltip strings.

workspaces/scorecard/plugins/scorecard/src/translations/ref.ts

Tests (15) +197 / -174
scorecard.test.tsUpdate legacy e2e tests to assert weightedStatusScore cards +14/-14

Update legacy e2e tests to assert weightedStatusScore cards

• Renames the aggregation KPI test suite from 'average' to 'weightedStatusScore'. Updates assertions, snapshot helpers, and expected API result field names.

workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts

apiUtils.tsWait for weightedStatusScore fields in aggregation API responses +2/-1

Wait for weightedStatusScore fields in aggregation API responses

• Adjusts the 'waitForAggregationResponse' readiness check to look for 'weightedStatusScore' instead of 'averageScore'.

workspaces/scorecard/packages/app-legacy/e2e-tests/utils/apiUtils.ts

scorecardResponseUtils.tsRename mock aggregation metadata/result fields to weightedStatusScore +11/-11

Rename mock aggregation metadata/result fields to weightedStatusScore

• Updates mock metadata ('aggregationType') and result payload fields ('weightedStatusScore*') used across e2e tests. Keeps the same numeric behavior while aligning field names.

workspaces/scorecard/packages/app-legacy/e2e-tests/utils/scorecardResponseUtils.ts

translationUtils.tsRename snapshot helper for weightedStatusScore homepage cards +6/-6

Rename snapshot helper for weightedStatusScore homepage cards

• Renames 'getAverageCardSnapshot' to 'getWeightedStatusScoreCardSnapshot' and updates parameter names to match the new headline label.

workspaces/scorecard/packages/app-legacy/e2e-tests/utils/translationUtils.ts

weightedStatusScoreCardAssertions.tsRename assertions + testids and i18n keys for weightedStatusScore card +32/-19

Rename assertions + testids and i18n keys for weightedStatusScore card

• Refactors assertion helpers to target the new 'weighted-status-score-*' test IDs and 'metric.weightedStatusScore*' translation keys. Updates pluralization key selection and expected tooltip content.

workspaces/scorecard/packages/app-legacy/e2e-tests/utils/weightedStatusScoreCardAssertions.ts

AggregationsService.test.tsUpdate AggregationsService tests for weightedStatusScore strategy and fields +18/-15

Update AggregationsService tests for weightedStatusScore strategy and fields

• Adjusts tests to configure 'aggregationTypes.weightedStatusScore' and assert the renamed result fields and metadata aggregation type.

workspaces/scorecard/plugins/scorecard-backend/src/service/aggregations/AggregationsService.test.ts

registerStrategies.test.tsUpdate strategy registry tests to expect weightedStatusScore registration +4/-4

Update strategy registry tests to expect weightedStatusScore registration

• Updates registry expectations to assert 'weightedStatusScore' is registered alongside 'statusGrouped'.

workspaces/scorecard/plugins/scorecard-backend/src/service/aggregations/strategies/registerStrategies.test.ts

weightedStatusScoreAggregationStrategy.test.tsRename strategy tests and expected output fields +28/-26

Rename strategy tests and expected output fields

• Renames the test suite and updates expectations to assert 'weightedStatusScore*' result fields, updated log messages, and the renamed default thresholds constant.

workspaces/scorecard/plugins/scorecard-backend/src/service/aggregations/strategies/weightedStatusScoreAggregationStrategy.test.ts

mappers.test.tsUpdate mapper tests for weightedStatusScore metadata + result shape +11/-9

Update mapper tests for weightedStatusScore metadata + result shape

• Adjusts mapper tests to assert 'aggregationType: weightedStatusScore' and the renamed score fields in the mapped result.

workspaces/scorecard/plugins/scorecard-backend/src/service/mappers.test.ts

router.test.tsUpdate router tests to use weightedStatusScore KPI config and path +5/-5

Update router tests to use weightedStatusScore KPI config and path

• Updates the configured KPI id/type and request path in router tests to match 'weightedKpi' and 'type: weightedStatusScore'.

workspaces/scorecard/plugins/scorecard-backend/src/service/router.test.ts

buildAggregationConfig.test.tsUpdate buildAggregationConfig tests for weightedStatusScore options mapping +11/-11

Update buildAggregationConfig tests for weightedStatusScore options mapping

• Renames test fixtures and assertions to ensure options (statusScores/thresholds) are mapped only for 'type: weightedStatusScore'.

workspaces/scorecard/plugins/scorecard-backend/src/utils/buildAggregationConfig.test.ts

validateAggregationConfig.test.tsUpdate validation tests for weightedStatusScore required options and thresholds +22/-22

Update validation tests for weightedStatusScore required options and thresholds

• Renames validation scenarios to use 'weightedStatusScore', updates KPI ids/descriptions, and keeps the same threshold gap coverage validations under the new type.

workspaces/scorecard/plugins/scorecard-backend/src/validation/validateAggregationConfig.test.ts

scorecardData.tsUpdate fixture aggregated data to weightedStatusScore fields +6/-6

Update fixture aggregated data to weightedStatusScore fields

• Renames the fixture key from 'aggregationTypes.average' to 'aggregationTypes.weightedStatusScore' and updates mock result fields accordingly.

workspaces/scorecard/plugins/scorecard/fixtures/scorecardData.ts

CustomLegend.test.tsxUpdate legend tests for weightedStatusScore donut slice names +12/-10

Update legend tests for weightedStatusScore donut slice names

• Updates the test data and assertions to expect the renamed donut slice names for weightedStatusScore cards.

workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/tests/CustomLegend.test.tsx

ScorecardHomepageCard.test.tsxUpdate homepage card tests for weightedStatusScore aggregation type +15/-15

Update homepage card tests for weightedStatusScore aggregation type

• Renames mocked aggregated results and updates assertions to target the new slice/test IDs and result fields for weightedStatusScore donut cards.

workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/tests/ScorecardHomepageCard.test.tsx

Documentation (10) +74 / -73
README.mdUpdate workspace docs to reference weightedStatusScore KPI type +7/-7

Update workspace docs to reference weightedStatusScore KPI type

• Refreshes the documentation table to replace 'average' with 'weightedStatusScore' references and descriptions.

workspaces/scorecard/README.md

README.mdUpdate backend README for weightedStatusScore KPI type and API fields +12/-12

Update backend README for weightedStatusScore KPI type and API fields

• Replaces 'average' references with 'weightedStatusScore' in configuration docs, validation notes, and the API field listing. Updates inline comments and examples to match renamed result fields.

workspaces/scorecard/plugins/scorecard-backend/README.md

config.d.tsRename config schema comments to weightedStatusScore terminology +2/-2

Rename config schema comments to weightedStatusScore terminology

• Updates inline TypeScript config schema documentation to describe required options/threshold semantics for 'weightedStatusScore'.

workspaces/scorecard/plugins/scorecard-backend/config.d.ts

aggregation.mdRename aggregation type docs and result field names +16/-16

Rename aggregation type docs and result field names

• Updates the aggregation type explanation, table, algorithm steps, and API response docs to use 'weightedStatusScore' and renamed result fields. Aligns default-threshold strategy name and constant references.

workspaces/scorecard/plugins/scorecard-backend/docs/aggregation.md

drill-down.mdUpdate drill-down doc note for weightedStatusScore KPIs +1/-1

Update drill-down doc note for weightedStatusScore KPIs

• Replaces the drill-down note that referenced 'type: average' with 'type: weightedStatusScore'.

workspaces/scorecard/plugins/scorecard-backend/docs/drill-down.md

thresholds.mdRename KPI result thresholds section to weightedStatusScore +7/-7

Rename KPI result thresholds section to weightedStatusScore

• Updates the section title and all references from average KPI result thresholds to weightedStatusScore KPI result thresholds, including defaults and validation semantics.

workspaces/scorecard/plugins/scorecard-backend/docs/thresholds.md

report.api.mdUpdate public API report for weightedStatusScore aggregation result +11/-10

Update public API report for weightedStatusScore aggregation result

• Removes the 'AggregatedMetricAverageResult' export and replaces it with 'WeightedStatusScoreAggregationResult'. Updates unions and aggregationTypes accordingly.

workspaces/scorecard/plugins/scorecard-common/report.api.md

README.mdUpdate frontend README to document weightedStatusScore homepage KPI type +4/-4

Update frontend README to document weightedStatusScore homepage KPI type

• Replaces 'average' terminology with 'weightedStatusScore' in feature descriptions, widget descriptions, and homepage card behavior notes.

workspaces/scorecard/plugins/scorecard/README.md

report-alpha.api.mdRename translation key types for weightedStatusScore tooltips +7/-7

Rename translation key types for weightedStatusScore tooltips

• Updates the generated API report to replace 'metric.average*' translation key entries with 'metric.weightedStatusScore*'.

workspaces/scorecard/plugins/scorecard/report-alpha.api.md

report.api.mdRename translation key types for weightedStatusScore tooltips +7/-7

Rename translation key types for weightedStatusScore tooltips

• Updates the generated API report to replace 'metric.average*' translation key entries with 'metric.weightedStatusScore*'.

workspaces/scorecard/plugins/scorecard/report.api.md

Other (3) +24 / -4
stupid-knives-wonder.mdAdd changeset documenting breaking rename for aggregation KPI type +20/-0

Add changeset documenting breaking rename for aggregation KPI type

• Introduces a changeset describing the rename from 'average' to 'weightedStatusScore'. Calls out breaking app-config and '/aggregations/:aggregationId' response field changes.

workspaces/scorecard/.changeset/stupid-knives-wonder.md

app-config.local.EXAMPLE.yamlRename example KPI type to weightedStatusScore +2/-2

Rename example KPI type to weightedStatusScore

• Updates the local example Scorecard KPI configuration to use 'type: weightedStatusScore' and adjusts wording from “average” to “score”.

workspaces/scorecard/app-config.local.EXAMPLE.yaml

app-config.yamlRename configured KPI type to weightedStatusScore +2/-2

Rename configured KPI type to weightedStatusScore

• Updates the repository app-config example to use 'type: weightedStatusScore' and adjusts the KPI description accordingly.

workspaces/scorecard/app-config.yaml

@rhdh-qodo-merge

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used
✅ Tickets: RHIDP-14172

Grey Divider


Action required

1. Breaking bump level 🐞 Bug ⚙ Maintainability
Description
The changeset documents a breaking rename (averageweightedStatusScore) but bumps the affected
packages as minor, which can ship breaking changes to consumers on semver ranges like ^2.x. This
can cause runtime/config/API contract failures after what appears to be a safe minor upgrade.
Code

workspaces/scorecard/.changeset/stupid-knives-wonder.md[R1-4]

+---
+'@red-hat-developer-hub/backstage-plugin-scorecard-backend': minor
+'@red-hat-developer-hub/backstage-plugin-scorecard-common': minor
+'@red-hat-developer-hub/backstage-plugin-scorecard': minor
Relevance

⭐⭐⭐ High

Team has enforced correct changeset bump levels and breaking flags in past (PRs 3264, 1587, 2609).

PR-#3264
PR-#1587
PR-#2609

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The changeset explicitly labels the change as breaking while requesting minor bumps; the packages
are already on major version 2, so a breaking change should not be released as a minor update under
standard semver expectations.

workspaces/scorecard/.changeset/stupid-knives-wonder.md[1-20]
workspaces/scorecard/plugins/scorecard-common/package.json[1-6]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The changeset declares **breaking changes** (config key + API field renames) but sets the version bump to `minor` for the affected packages. With current package versions in the `2.x` range, this violates semver expectations and can cause downstream breakages on routine upgrades.

### Issue Context
This PR renames an aggregation type and multiple API result fields; the changeset itself labels this as breaking.

### Fix Focus Areas
- workspaces/scorecard/.changeset/stupid-knives-wonder.md[1-5]

### Suggested fix
Update the changeset bump type(s) from `minor` to `major` for the impacted packages (backend/common/frontend). If your release policy intentionally differs from semver, document that policy explicitly and ensure tooling/docs reflect it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@rhdh-qodo-merge rhdh-qodo-merge Bot added documentation Improvements or additions to documentation enhancement New feature or request Tests labels Jun 17, 2026

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

averageMaxPossible: number;
aggregationChartDisplayColor: string;
};
export type WeightedStatusScoreAggregationResult =

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[critical] breaking-api-change

The public type AggregatedMetricAverageResult (@public in report.api.md) is renamed to WeightedStatusScoreAggregationResult with no deprecated alias. External consumers importing this type get compile-time errors. Fields averageScore, averageWeightedSum, averageMaxPossible are also renamed, breaking runtime consumers.

Suggested fix: Either bump to major, or keep old type as deprecated alias with @deprecated JSDoc tag.

statusGrouped: STATUS_GROUPED,
average: AVERAGE,
weightedStatusScore: WEIGHTED_STATUS_SCORE,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[critical] breaking-api-change

The public constant aggregationTypes.average is renamed to aggregationTypes.weightedStatusScore. JS consumers using aggregationTypes.average get undefined at runtime. Also changes the string literal in API responses and config files.

Suggested fix: Major bump, or add new key while keeping old as deprecated.

averageMaxPossible: number;
aggregationChartDisplayColor: string;
};
export type WeightedStatusScoreAggregationResult =

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] naming-consistency

The old type AggregatedMetricAverageResult followed the AggregatedMetric*Result pattern, while the new name WeightedStatusScoreAggregationResult follows the *AggregationResult pattern used by sibling StatusGroupedAggregationResult. The rename moves toward consistency with the sibling, but the two naming patterns now coexist.

@@ -101,11 +104,11 @@ export class AverageAggregationStrategy implements AggregationStrategy {
score: options.statusScores[rule.key] ?? 0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] api-response-field-rename

Wire-protocol change affecting REST API consumers beyond TypeScript. HTTP clients parsing JSON fields averageScore, averageWeightedSum, averageMaxPossible by name will break.

@fullsend-ai-review

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:29 AM UTC · Completed 9:46 AM UTC
Commit: bbcdc56 · View workflow run →

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request Tests workspace/scorecard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant