Skip to content

Commit 4831a52

Browse files
committed
refactor (scorecard): aggregation KPI type from average to weightedStatusScore
Signed-off-by: Ihor Mykhno <imykhno@redhat.com>
1 parent efb4c4f commit 4831a52

51 files changed

Lines changed: 446 additions & 377 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-scorecard': major
3+
'@red-hat-developer-hub/backstage-plugin-scorecard-backend': major
4+
'@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-github': major
5+
'@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-jira': major
6+
'@red-hat-developer-hub/backstage-plugin-scorecard-common': major
7+
'@red-hat-developer-hub/backstage-plugin-scorecard-node': major
8+
---
9+
10+
Rename aggregation KPI type `average` to `weightedStatusScore`.
11+
12+
**Breaking changes**
13+
14+
### App config
15+
16+
- `scorecard.aggregationKPIs.*.type`: `average``weightedStatusScore`
17+
18+
### `GET /aggregations/:aggregationId` API
19+
20+
- `metadata.aggregationType`: `average``weightedStatusScore`
21+
- `result.averageScore``result.weightedStatusScore`
22+
- `result.averageWeightedSum``result.weightedStatusSum`
23+
- `result.averageMaxPossible``result.weightedStatusMaxPossible`

workspaces/scorecard/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ yarn install
1515
1616
## Documentation
1717

18-
| Topic | Location |
19-
| ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
20-
| Aggregation KPIs (`statusGrouped`, `average`), API, ownership | [plugins/scorecard-backend/docs/aggregation.md](plugins/scorecard-backend/docs/aggregation.md) |
21-
| Backend installation and RBAC, **`scorecard.aggregationKPIs`** examples | [plugins/scorecard-backend/README.md](plugins/scorecard-backend/README.md) |
22-
| Drill-down (entity list for a metric) | [plugins/scorecard-backend/docs/drill-down.md](plugins/scorecard-backend/docs/drill-down.md) |
23-
| Metric thresholds, annotations, **average KPI result colors** | [plugins/scorecard-backend/docs/thresholds.md](plugins/scorecard-backend/docs/thresholds.md) |
24-
| Frontend (homepage cards, NFS) | [plugins/scorecard/README.md](plugins/scorecard/README.md) |
18+
| Topic | Location |
19+
| ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
20+
| Aggregation KPIs (`statusGrouped`, `weightedStatusScore`), API, ownership | [plugins/scorecard-backend/docs/aggregation.md](plugins/scorecard-backend/docs/aggregation.md) |
21+
| Backend installation and RBAC, **`scorecard.aggregationKPIs`** examples | [plugins/scorecard-backend/README.md](plugins/scorecard-backend/README.md) |
22+
| Drill-down (entity list for a metric) | [plugins/scorecard-backend/docs/drill-down.md](plugins/scorecard-backend/docs/drill-down.md) |
23+
| Metric thresholds, annotations, **weightedStatusScore KPI result colors** | [plugins/scorecard-backend/docs/thresholds.md](plugins/scorecard-backend/docs/thresholds.md) |
24+
| Frontend (homepage cards, NFS) | [plugins/scorecard/README.md](plugins/scorecard/README.md) |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ jira:
5757
scorecard:
5858
openPrsWeightedKpi:
5959
title: GitHub Open PRs (weighted health)
60-
type: average
61-
description: Weighted health average for open PRs by threshold status across your entities.
60+
type: weightedStatusScore
61+
description: Weighted health score for open PRs by threshold status across your entities.
6262
metricId: github.open_prs
6363
options:
6464
statusScores:

workspaces/scorecard/app-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ scorecard:
235235
metricId: github.open_prs
236236
openPrsWeightedKpi:
237237
title: GitHub Open PRs (weighted health)
238-
type: average
239-
description: Weighted health average for open PRs by threshold status across your entities.
238+
type: weightedStatusScore
239+
description: Weighted health score for open PRs by threshold status across your entities.
240240
metricId: github.open_prs
241241
options:
242242
statusScores:

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import {
5959
getTranslations,
6060
getEntityCount,
6161
getStatusGroupedCardSnapshot,
62-
getAverageCardSnapshot,
62+
getWeightedStatusScoreCardSnapshot,
6363
getTableFooterSnapshot,
6464
getEntitiesTableFooterRowsLabel,
6565
} from './utils/translationUtils';
@@ -73,10 +73,10 @@ import {
7373
setupHomepageAllCardsNoData,
7474
} from './utils/homepageWidgetUtils';
7575
import {
76-
expectAverageCardCenterPercent,
77-
verifyAverageDonutCenterTooltip,
78-
verifyAverageCenterTooltipBreakdownRows,
79-
} from './utils/averageCardAssertions';
76+
expectWeightedStatusScoreCardCenterPercent,
77+
verifyWeightedStatusScoreDonutCenterTooltip,
78+
verifyWeightedStatusScoreCenterTooltipBreakdownRows,
79+
} from './utils/weightedStatusScoreCardAssertions';
8080
import { runAccessibilityTests } from './utils/accessibility';
8181
import { ScorecardRoutes } from './constants/routes';
8282
import {
@@ -714,7 +714,7 @@ test.describe('Scorecard Plugin Tests', () => {
714714
});
715715
});
716716

717-
test.describe('Configured aggregation KPI - "average" type', () => {
717+
test.describe('Configured aggregation KPI - "weightedStatusScore" type', () => {
718718
const aggregationMetadata =
719719
AGGREGATED_CARDS_METADATA.githubOpenPrsWeightedKpi;
720720

@@ -726,7 +726,7 @@ test.describe('Scorecard Plugin Tests', () => {
726726
});
727727
});
728728

729-
test.describe('Validate "average" type card content', () => {
729+
test.describe('Validate "weightedStatusScore" type card content', () => {
730730
let card: Locator;
731731

732732
test.beforeAll(async () => {
@@ -755,19 +755,19 @@ test.describe('Scorecard Plugin Tests', () => {
755755

756756
test('Verify center score percentage', async () => {
757757
await expect(card).toBeVisible();
758-
await expectAverageCardCenterPercent(card, '51.5%');
758+
await expectWeightedStatusScoreCardCenterPercent(card, '51.5%');
759759
});
760760

761761
test('Verify center tooltip', async () => {
762762
await expect(card).toBeVisible();
763-
await verifyAverageDonutCenterTooltip(
763+
await verifyWeightedStatusScoreDonutCenterTooltip(
764764
page,
765765
card,
766766
translations,
767-
openPrsWeightedAggregatedResponse.result.averageWeightedSum,
768-
openPrsWeightedAggregatedResponse.result.averageMaxPossible,
767+
openPrsWeightedAggregatedResponse.result.weightedStatusSum,
768+
openPrsWeightedAggregatedResponse.result.weightedStatusMaxPossible,
769769
);
770-
await verifyAverageCenterTooltipBreakdownRows(
770+
await verifyWeightedStatusScoreCenterTooltipBreakdownRows(
771771
page,
772772
card,
773773
translations,
@@ -814,12 +814,12 @@ test.describe('Scorecard Plugin Tests', () => {
814814

815815
await expect(card).toBeVisible();
816816
await expect(card).toMatchAriaSnapshot(
817-
getAverageCardSnapshot(translations, {
817+
getWeightedStatusScoreCardSnapshot(translations, {
818818
drillDownMetricId: aggregationMetadata.metricId,
819819
drillDownAggregationId: aggregationMetadata.id,
820820
cardTitle: partialResponse.metadata.title,
821821
cardDescription: partialResponse.metadata.description,
822-
averageScoreLabel: `${partialResponse.result.averageScore}%`,
822+
weightedStatusScoreLabel: `${partialResponse.result.weightedStatusScore}%`,
823823
homepageCalculationHealth: {
824824
healthy: String(entitiesConsidered - calculationErrorCount),
825825
total: String(entitiesConsidered),

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ export function waitForAggregationResponse(
6969
const result = json?.result;
7070

7171
return (
72-
result?.averageScore !== undefined || result?.total !== undefined
72+
result?.weightedStatusScore !== undefined ||
73+
result?.total !== undefined
7374
);
7475
} catch {
7576
return false;

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,14 @@ export const openIssuesKpiMetadataResponse = {
207207
export const openPrsWeightedKpiMetadataResponse = {
208208
title: 'GitHub Open PRs (weighted health)',
209209
description:
210-
'Weighted health average for open PRs by threshold status across your entities.',
210+
'Weighted health score for open PRs by threshold status across your entities.',
211211
type: 'number',
212212
history: true,
213-
aggregationType: aggregationTypes.average,
213+
aggregationType: aggregationTypes.weightedStatusScore,
214214
};
215215

216216
/**
217-
* Average KPI: 3×100 + 5×40 + 1×15 + 1×0 = 515 weighted sum; max 100×10 entities → 51.5% score.
217+
* WeightedStatusScore KPI: 3×100 + 5×40 + 1×15 + 1×0 = 515 weighted sum; max 100×10 entities → 51.5% score.
218218
* Includes `critical` as a non-threshold status name (no `thresholds.critical` copy).
219219
* Colors align with aggregation KPI `options.thresholds` warning band (30–79%) in app-config.
220220
*/
@@ -236,9 +236,9 @@ export const openPrsWeightedAggregatedResponse = {
236236
calculationErrorCount: 0,
237237
timestamp: '2026-01-24T14:10:32.858Z',
238238
thresholds: DEFAULT_NUMBER_THRESHOLDS,
239-
averageScore: 51.5,
240-
averageWeightedSum: 515,
241-
averageMaxPossible: 1000,
239+
weightedStatusScore: 51.5,
240+
weightedStatusSum: 515,
241+
weightedStatusMaxPossible: 1000,
242242
aggregationChartDisplayColor: 'rgb(224, 189, 108)',
243243
},
244244
};
@@ -259,8 +259,8 @@ export const gitHubWeightedPartiallyAggregatedResponse = {
259259
total: 8,
260260
entitiesConsidered: 6,
261261
calculationErrorCount: 2,
262-
averageScore: 46.7,
263-
averageWeightedSum: 466.67,
262+
weightedStatusScore: 46.7,
263+
weightedStatusSum: 466.67,
264264
},
265265
};
266266

@@ -279,9 +279,9 @@ export const emptyOpenPrsWeightedAggregatedResponse = {
279279
],
280280
timestamp: '2026-01-24T14:10:32.858Z',
281281
thresholds: DEFAULT_NUMBER_THRESHOLDS,
282-
averageScore: 0,
283-
averageWeightedSum: 0,
284-
averageMaxPossible: 0,
282+
weightedStatusScore: 0,
283+
weightedStatusSum: 0,
284+
weightedStatusMaxPossible: 0,
285285
aggregationChartDisplayColor: '#6bb300',
286286
},
287287
};

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ export function getSomeEntitiesNotReportingTooltip(
193193
);
194194
}
195195

196-
/** Flat metric-namespace string by key (e.g. averageCenterTooltipTotalLabel). */
196+
/** Flat metric-namespace string by key (e.g. weightedStatusScoreCenterTooltipTotalLabel). */
197197
export function getMetricTranslation(
198198
translations: ScorecardMessages,
199199
key: string,
@@ -451,24 +451,24 @@ export function getStatusGroupedCardSnapshot(
451451
`;
452452
}
453453

454-
/** Snapshot for average-type homepage KPI cards (donut gauge, no threshold legend). */
455-
export function getAverageCardSnapshot(
454+
/** Snapshot for weightedStatusScore-type homepage KPI cards (donut gauge, no threshold legend). */
455+
export function getWeightedStatusScoreCardSnapshot(
456456
translations: ScorecardMessages,
457457
options: {
458458
drillDownMetricId: 'jira.open_issues' | 'github.open_prs';
459459
drillDownAggregationId?: string;
460460
homepageCalculationHealth?: { healthy: string; total: string };
461461
cardTitle: string;
462462
cardDescription: string;
463-
averageScoreLabel: string;
463+
weightedStatusScoreLabel: string;
464464
},
465465
): string {
466466
const {
467467
drillDownMetricId,
468468
drillDownAggregationId,
469469
cardTitle,
470470
cardDescription,
471-
averageScoreLabel,
471+
weightedStatusScoreLabel,
472472
} = options;
473473
const aggregationSegment = drillDownAggregationId ?? drillDownMetricId;
474474
const { healthy, total } = options.homepageCalculationHealth ?? {
@@ -488,7 +488,7 @@ export function getAverageCardSnapshot(
488488
- button
489489
- separator
490490
- paragraph: ${cardDescription}
491-
- application: ${averageScoreLabel}
491+
- application: ${weightedStatusScoreLabel}
492492
`;
493493
}
494494

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

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,33 @@ function interpolate(template: string, vars: Record<string, string>): string {
2828
);
2929
}
3030

31-
function averageCenterTooltipBreakdownTemplateKey(
31+
function weightedStatusScoreCenterTooltipBreakdownTemplateKey(
3232
locale: string,
3333
count: number,
3434
):
35-
| 'averageCenterTooltipBreakdownRow_one'
36-
| 'averageCenterTooltipBreakdownRow_other' {
35+
| 'weightedStatusScoreCenterTooltipBreakdownRow_one'
36+
| 'weightedStatusScoreCenterTooltipBreakdownRow_other' {
3737
if (Number.isNaN(count)) {
38-
return 'averageCenterTooltipBreakdownRow_other';
38+
return 'weightedStatusScoreCenterTooltipBreakdownRow_other';
3939
}
4040
const category = new Intl.PluralRules(locale).select(count);
4141
return category === 'one'
42-
? 'averageCenterTooltipBreakdownRow_one'
43-
: 'averageCenterTooltipBreakdownRow_other';
42+
? 'weightedStatusScoreCenterTooltipBreakdownRow_one'
43+
: 'weightedStatusScoreCenterTooltipBreakdownRow_other';
4444
}
4545

46-
function expectedAverageCenterTooltipBreakdownLine(
46+
function expectedWeightedStatusScoreCenterTooltipBreakdownLine(
4747
translations: ScorecardMessages,
4848
locale: string,
4949
statusKey: string,
5050
count: string,
5151
score: string,
5252
): string {
5353
const n = Number.parseInt(count, 10);
54-
const templateKey = averageCenterTooltipBreakdownTemplateKey(locale, n);
54+
const templateKey = weightedStatusScoreCenterTooltipBreakdownTemplateKey(
55+
locale,
56+
n,
57+
);
5558
const template = getMetricTranslation(translations, templateKey);
5659
const status =
5760
statusKey in translations.thresholds
@@ -60,32 +63,40 @@ function expectedAverageCenterTooltipBreakdownLine(
6063
return interpolate(template, { status, count, score });
6164
}
6265

63-
export async function expectAverageCardCenterPercent(
66+
export async function expectWeightedStatusScoreCardCenterPercent(
6467
card: Locator,
6568
percentLabel: string,
6669
): Promise<void> {
67-
await expect(card.getByTestId('average-card-center-percent')).toHaveText(
68-
percentLabel,
69-
);
70+
await expect(
71+
card.getByTestId('weighted-status-score-card-center-percent'),
72+
).toHaveText(percentLabel);
7073
}
7174

72-
export async function verifyAverageDonutCenterTooltip(
75+
export async function verifyWeightedStatusScoreDonutCenterTooltip(
7376
page: Page,
7477
card: Locator,
7578
translations: ScorecardMessages,
7679
weightedSum: number,
7780
maxPossible: number,
7881
): Promise<void> {
79-
await card.getByTestId('average-card-center-percent-hit-area').hover();
82+
await card
83+
.getByTestId('weighted-status-score-card-center-percent-hit-area')
84+
.hover();
8085
await expect(
8186
page.getByText(
82-
getMetricTranslation(translations, 'averageCenterTooltipTotalLabel'),
87+
getMetricTranslation(
88+
translations,
89+
'weightedStatusScoreCenterTooltipTotalLabel',
90+
),
8391
{ exact: true },
8492
),
8593
).toBeVisible();
8694
await expect(
8795
page.getByText(
88-
getMetricTranslation(translations, 'averageCenterTooltipMaxLabel'),
96+
getMetricTranslation(
97+
translations,
98+
'weightedStatusScoreCenterTooltipMaxLabel',
99+
),
89100
{ exact: true },
90101
),
91102
).toBeVisible();
@@ -112,15 +123,17 @@ const OPEN_PRS_WEIGHTED_MOCK_BREAKDOWN: Array<{
112123
/**
113124
* Per-status lines under total/max in the center donut tooltip (replaces old side-legend tooltips).
114125
*/
115-
export async function verifyAverageCenterTooltipBreakdownRows(
126+
export async function verifyWeightedStatusScoreCenterTooltipBreakdownRows(
116127
page: Page,
117128
card: Locator,
118129
translations: ScorecardMessages,
119130
locale: string,
120131
): Promise<void> {
121-
await card.getByTestId('average-card-center-percent-hit-area').hover();
132+
await card
133+
.getByTestId('weighted-status-score-card-center-percent-hit-area')
134+
.hover();
122135
for (const row of OPEN_PRS_WEIGHTED_MOCK_BREAKDOWN) {
123-
const line = expectedAverageCenterTooltipBreakdownLine(
136+
const line = expectedWeightedStatusScoreCenterTooltipBreakdownLine(
124137
translations,
125138
locale,
126139
row.statusKey,

0 commit comments

Comments
 (0)