Skip to content

fix(scorecard): entity calculation health on aggregation and drill-down APIs#2865

Merged
PatAKnight merged 8 commits intoredhat-developer:mainfrom
PatAKnight:scorecard-errors
Apr 28, 2026
Merged

fix(scorecard): entity calculation health on aggregation and drill-down APIs#2865
PatAKnight merged 8 commits intoredhat-developer:mainfrom
PatAKnight:scorecard-errors

Conversation

@PatAKnight
Copy link
Copy Markdown
Member

@PatAKnight PatAKnight commented Apr 22, 2026

Hey, I just made a Pull Request!

  • Problem: Drill-down always showed a warning; homepage totals did not reflect metric calculation failures vs entities in scope.

  • Approach: Extended existing scorecard JSON contracts with entityHealth (drill-down) and entitiesConsidered / calculationErrorCount (aggregation); UI keys warning and subheader off those fields; shared isMetricCalculationError helper.

  • Fixes: https://redhat.atlassian.net/browse/RHIDP-13128

Screenshots

Screenshot From 2026-04-27 09-29-55 Screenshot From 2026-04-27 10-01-04 Screenshot From 2026-04-27 10-52-05

✔️ 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)

@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge Bot commented Apr 22, 2026

Code Review by Qodo

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

Grey Divider


Remediation recommended

1. Unvalidated health fields 🐞 Bug ☼ Reliability
Description
ScorecardHomepageCard/ScorecardHomepageCardComponent assume result.entitiesConsidered and
result.calculationErrorCount exist and are numbers; if they’re missing/null, the homepage can
render “NaN” health text and may throw when reading result.total.
ScorecardApiClient.getAggregatedScorecard only checks for the presence of the result key, not
the shape of result, so such responses pass client validation.
Code

workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/ScorecardHomepageCard.tsx[R80-86]

+  const result = data.result;
+  const hasNoRenderableAggregation =
+    result.total === 0 &&
+    result.calculationErrorCount === 0 &&
+    result.entitiesConsidered === 0;
+
+  if (hasNoRenderableAggregation) {
Relevance

⭐⭐⭐ High

Team has history of hardening Scorecard API/UI against malformed/empty responses; this NaN/crash
risk is real.

PR-#2201
PR-#2035
PR-#2509

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The homepage card now dereferences and compares the new fields directly
(result.calculationErrorCount, result.entitiesConsidered) and the homepage subheader computes
healthyCount from them, but the API client returns any object that merely contains a result
property (even if result is null or missing those subfields). That makes the UI brittle to
malformed responses and to backend/frontend skew.

workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/ScorecardHomepageCard.tsx[76-97]
workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/ScorecardHomepageCardComponent.tsx[121-135]
workspaces/scorecard/plugins/scorecard/src/api/index.ts[109-146]

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 homepage aggregation card assumes `result.entitiesConsidered` and `result.calculationErrorCount` exist and are numeric. If the backend response is missing these (or `result` is null), the card can render `NaN` health text and may crash when dereferencing `result.total`.

### Issue Context
`ScorecardApiClient.getAggregatedScorecard` currently validates only top-level keys (`result`, `metadata`, `id`, `status`) and returns the parsed JSON as-is. The homepage components then do arithmetic and equality checks on nested fields without defaults.

### Fix Focus Areas
- workspaces/scorecard/plugins/scorecard/src/api/index.ts[109-154]
- workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/ScorecardHomepageCard.tsx[76-97]
- workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/ScorecardHomepageCardComponent.tsx[121-135]

### What to change
1. In `ScorecardApiClient.getAggregatedScorecard`, add a minimal runtime shape check for `data.result` being a non-null object.
2. Normalize/default the new numeric fields when absent, e.g.:
  - `entitiesConsidered: Number(data.result.entitiesConsidered ?? 0)`
  - `calculationErrorCount: Number(data.result.calculationErrorCount ?? 0)`
  (and consider also defaulting `total`/`timestamp` if you want full robustness).
  If values are non-finite (NaN), throw a `TypeError`.
3. In the homepage components, defensively read these fields with `?? 0` to avoid rendering `NaN` even if validation is bypassed (e.g., tests/mocks or future refactors).
4. Ensure the empty-state condition continues to behave sensibly when fields are absent (treat missing as 0).

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


Grey Divider

Qodo Logo

@rhdh-gh-app
Copy link
Copy Markdown

rhdh-gh-app Bot commented Apr 22, 2026

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 patch v2.6.0
@red-hat-developer-hub/backstage-plugin-scorecard-common workspaces/scorecard/plugins/scorecard-common patch v2.6.0
@red-hat-developer-hub/backstage-plugin-scorecard workspaces/scorecard/plugins/scorecard patch v2.6.0

@rhdh-qodo-merge
Copy link
Copy Markdown

Review Summary by Qodo

Expose entity calculation health on aggregation and drill-down APIs

🐞 Bug fix ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Extended scorecard JSON contracts with entityHealth (drill-down) and entitiesConsidered /
  calculationErrorCount (aggregation) fields
• Updated database layer to track metric calculation failures and entity counts separately from
  threshold status
• Aligned homepage KPI subheader and drill-down warning icon with actual calculation health metrics
• Improved E2E test reliability by using direct component navigation and entity slug-based lookups
Diagram
flowchart LR
  DB["Database Layer<br/>calculation_error_count<br/>latest_entity_count"]
  MAPPER["AggregatedMetricMapper<br/>entitiesConsidered<br/>calculationErrorCount"]
  AGG["Aggregation API<br/>GET /aggregations/:id"]
  DRILL["Drill-down API<br/>GET /entities"]
  UI["UI Components<br/>Homepage Subheader<br/>Entities Table Warning"]
  
  DB -->|DbAggregatedMetric| MAPPER
  MAPPER -->|AggregatedMetric| AGG
  MAPPER -->|AggregatedMetric| DRILL
  AGG -->|result fields| UI
  DRILL -->|entityHealth| UI
Loading

Grey Divider

File Changes

1. workspaces/scorecard/plugins/scorecard-backend/src/database/DatabaseMetricValues.ts ✨ Enhancement +60/-14

Track calculation errors and entity counts in aggregation

workspaces/scorecard/plugins/scorecard-backend/src/database/DatabaseMetricValues.ts


2. workspaces/scorecard/plugins/scorecard-backend/src/database/DatabaseMetricValues.test.ts 🧪 Tests +48/-0

Add tests for calculation error aggregation

workspaces/scorecard/plugins/scorecard-backend/src/database/DatabaseMetricValues.test.ts


3. workspaces/scorecard/plugins/scorecard-backend/src/database/types.ts ✨ Enhancement +7/-0

Add calculation_error_count and latest_entity_count fields

workspaces/scorecard/plugins/scorecard-backend/src/database/types.ts


View more (39)
4. workspaces/scorecard/plugins/scorecard-backend/src/service/CatalogMetricService.ts ✨ Enhancement +31/-2

Compute entityHealth summary for drill-down responses

workspaces/scorecard/plugins/scorecard-backend/src/service/CatalogMetricService.ts


5. workspaces/scorecard/plugins/scorecard-backend/src/service/CatalogMetricService.test.ts 🧪 Tests +82/-1

Test entityHealth calculation and sparse entity scenarios

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


6. workspaces/scorecard/plugins/scorecard-backend/src/service/mappers.ts ✨ Enhancement +2/-0

Map database fields to AggregatedMetric contract

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


7. workspaces/scorecard/plugins/scorecard-backend/src/service/mappers.test.ts 🧪 Tests +22/-0

Test AggregatedMetric mapping with new fields

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


8. workspaces/scorecard/plugins/scorecard-backend/src/service/router.test.ts 🧪 Tests +26/-2

Update router tests with new aggregation fields

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


9. workspaces/scorecard/plugins/scorecard-backend/src/utils/metricCalculationError.ts ✨ Enhancement +28/-0

Add shared helper for metric calculation error detection

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


10. workspaces/scorecard/plugins/scorecard-backend/docs/aggregation.md 📝 Documentation +5/-1

Document entitiesConsidered and calculationErrorCount fields

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


11. workspaces/scorecard/plugins/scorecard-backend/docs/drill-down.md 📝 Documentation +6/-0

Document entityHealth response structure

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


12. workspaces/scorecard/plugins/scorecard-common/src/types/Metric.ts ✨ Enhancement +15/-0

Add ScorecardEntityHealthSummary type definition

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


13. workspaces/scorecard/plugins/scorecard-common/src/types/aggregation.ts ✨ Enhancement +10/-0

Add entitiesConsidered and calculationErrorCount to AggregatedMetric

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


14. workspaces/scorecard/plugins/scorecard-common/report.api.md 📝 Documentation +10/-0

Update API report with new type exports

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


15. workspaces/scorecard/plugins/scorecard/src/translations/ref.ts ✨ Enhancement +5/-1

Add translation keys for calculation health messaging

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


16. workspaces/scorecard/plugins/scorecard/src/translations/de.ts ✨ Enhancement +4/-0

Add German translations for calculation health

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


17. workspaces/scorecard/plugins/scorecard/src/translations/es.ts ✨ Enhancement +4/-0

Add Spanish translations for calculation health

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


18. workspaces/scorecard/plugins/scorecard/src/translations/fr.ts ✨ Enhancement +4/-0

Add French translations for calculation health

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


19. workspaces/scorecard/plugins/scorecard/src/translations/it.ts ✨ Enhancement +4/-0

Add Italian translations for calculation health

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


20. workspaces/scorecard/plugins/scorecard/src/translations/ja.ts ✨ Enhancement +4/-0

Add Japanese translations for calculation health

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


21. workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/ScorecardHomepageCard.tsx 🐞 Bug fix +7/-1

Use entitiesConsidered for empty state detection

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


22. workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/ScorecardHomepageCardComponent.tsx ✨ Enhancement +29/-16

Display healthy entity ratio and calculation warning

workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/ScorecardHomepageCardComponent.tsx


23. workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/__tests__/ScorecardHomepageCard.test.tsx 🧪 Tests +10/-2

Update tests for new entity health display

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


24. workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/__tests__/ScorecardHomepageSection.test.tsx 🧪 Tests +4/-0

Add calculation error count to mock data

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


25. workspaces/scorecard/plugins/scorecard/src/components/ScorecardPage/EntitiesTable/EntitiesTable.tsx ✨ Enhancement +6/-1

Show calculation warning based on entityHealth

workspaces/scorecard/plugins/scorecard/src/components/ScorecardPage/EntitiesTable/EntitiesTable.tsx


26. workspaces/scorecard/plugins/scorecard/src/components/ScorecardPage/EntitiesTable/EntitiesTableWrapper.tsx ✨ Enhancement +5/-4

Replace error flag with calculation warning prop

workspaces/scorecard/plugins/scorecard/src/components/ScorecardPage/EntitiesTable/EntitiesTableWrapper.tsx


27. workspaces/scorecard/plugins/scorecard/src/components/ScorecardPage/EntitiesTable/__tests__/EntitiesTable.test.tsx 🧪 Tests +36/-3

Update tests with entityHealth structure

workspaces/scorecard/plugins/scorecard/src/components/ScorecardPage/EntitiesTable/tests/EntitiesTable.test.tsx


28. workspaces/scorecard/plugins/scorecard/src/components/ScorecardPage/EntitiesTable/__tests__/EntitiesTableWrapper.test.tsx 🧪 Tests +21/-8

Test calculation warning icon display logic

workspaces/scorecard/plugins/scorecard/src/components/ScorecardPage/EntitiesTable/tests/EntitiesTableWrapper.test.tsx


29. workspaces/scorecard/plugins/scorecard/src/hooks/__tests__/useAggregatedScorecard.test.tsx 🧪 Tests +2/-0

Add new fields to mock aggregated scorecard data

workspaces/scorecard/plugins/scorecard/src/hooks/tests/useAggregatedScorecard.test.tsx


30. workspaces/scorecard/plugins/scorecard/__fixtures__/scorecardData.ts 🧪 Tests +2/-0

Add calculation health fields to mock data

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


31. workspaces/scorecard/plugins/scorecard/__fixtures__/aggregatedScorecardEntitiesData.ts 🧪 Tests +5/-0

Add entityHealth to mock drill-down response

workspaces/scorecard/plugins/scorecard/fixtures/aggregatedScorecardEntitiesData.ts


32. workspaces/scorecard/plugins/scorecard/report.api.md 📝 Documentation +2/-0

Update API report with translation keys

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


33. workspaces/scorecard/plugins/scorecard/report-alpha.api.md 📝 Documentation +2/-0

Update alpha API report with translation keys

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


34. workspaces/scorecard/packages/app-legacy/e2e-tests/pages/CatalogPage.ts 🧪 Tests +12/-14

Improve test reliability with direct navigation

workspaces/scorecard/packages/app-legacy/e2e-tests/pages/CatalogPage.ts


35. workspaces/scorecard/packages/app-legacy/e2e-tests/pages/HomePage.ts 🧪 Tests +14/-3

Update drill-down link selector to use health text

workspaces/scorecard/packages/app-legacy/e2e-tests/pages/HomePage.ts


36. workspaces/scorecard/packages/app-legacy/e2e-tests/pages/ScorecardDrillDownPage.ts 🧪 Tests +23/-9

Replace tooltip test with calculation warning check

workspaces/scorecard/packages/app-legacy/e2e-tests/pages/ScorecardDrillDownPage.ts


37. workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts 🧪 Tests +8/-31

Update E2E tests with new navigation and assertions

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


38. workspaces/scorecard/packages/app-legacy/e2e-tests/utils/scorecardResponseUtils.ts 🧪 Tests +23/-0

Add entityHealth to mock API responses

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


39. workspaces/scorecard/packages/app-legacy/e2e-tests/utils/translationUtils.ts 🧪 Tests +23/-29

Add health text helper and remove deprecated tooltip function

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


40. workspaces/scorecard/.changeset/rhidp-13128-entity-health.md 📝 Documentation +7/-0

Add changeset for entity health feature

workspaces/scorecard/.changeset/rhidp-13128-entity-health.md


41. workspaces/scorecard/app-config.yaml ⚙️ Configuration changes +2/-1

Configure guest auth with explicit user entity ref

workspaces/scorecard/app-config.yaml


42. workspaces/scorecard/plugins/scorecard/src/api/ScorecardApiClient.test.ts Additional files +2/-0

...

workspaces/scorecard/plugins/scorecard/src/api/ScorecardApiClient.test.ts


Grey Divider

Qodo Logo

@rhdh-qodo-merge rhdh-qodo-merge Bot added documentation Improvements or additions to documentation enhancement New feature or request Tests Bug fix labels Apr 22, 2026
@PatAKnight PatAKnight force-pushed the scorecard-errors branch 3 times, most recently from d828f3e to 5e8c8bc Compare April 23, 2026 15:04
Copy link
Copy Markdown
Contributor

@AndrienkoAleksandr AndrienkoAleksandr left a comment

Choose a reason for hiding this comment

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

It works:

Image

@PatAKnight PatAKnight force-pushed the scorecard-errors branch 4 times, most recently from 69666b0 to 21e7a49 Compare April 27, 2026 14:35
Copy link
Copy Markdown
Member

@Eswaraiahsapram Eswaraiahsapram left a comment

Choose a reason for hiding this comment

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

Thanks @PatAKnight, Reviewed the frontend changes and tested locally. Looks good to me 🎉

Screen.Recording.2026-04-27.at.9.34.15.PM.mov

@imykhno
Copy link
Copy Markdown
Contributor

imykhno commented Apr 28, 2026

I have tested this locally. All primary logic functions as expected.

Screen.Recording.2026-04-28.at.14.03.27.mov

However when all entities return a failed metric load the card didn't display a chart. We can address this issue within this PR, or we can create a separate bug ticket if that is preferred.

Screen.Recording.2026-04-28.at.14.19.40.mov

…wn APIs

Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
…semantics

Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
@sonarqubecloud
Copy link
Copy Markdown

@imykhno
Copy link
Copy Markdown
Contributor

imykhno commented Apr 28, 2026

Tested locally, it works as it did before the conflict resolution. Thanks!
/lgtm

@openshift-ci openshift-ci Bot added the lgtm label Apr 28, 2026
@PatAKnight PatAKnight merged commit 91e724f into redhat-developer:main Apr 28, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants