Skip to content

feat(#3474): add code-coverage module for scorecard#3476

Open
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/3474-code-coverage-module
Open

feat(#3474): add code-coverage module for scorecard#3476
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/3474-code-coverage-module

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Create a new scorecard-backend-module-code-coverage that integrates with the Backstage Community code-coverage plugin to provide 8 metrics: line/branch percentage, available, covered, and missed counts.

The module fetches data from the code-coverage-backend API using the Backstage discovery service and maps the aggregate line and branch fields to individual MetricProviders.

Entities are filtered by the backstage.io/code-coverage annotation. Percentage metrics include default thresholds (>80 success, 50-80 warning, <50 error).

Includes:

  • CodeCoverageClient for API communication
  • Type definitions for the code-coverage API response
  • 8 MetricProvider implementations via factory pattern
  • Unit tests for client, providers, and factory (28 tests)
  • Example entity with code-coverage annotation
  • Backend app integration

Closes #3474

Post-script verification

  • Branch is not main/master (agent/3474-code-coverage-module)
  • Secret scan passed (gitleaks — 7ccaff17753df64c7ab288cdcba34cee5a657254..HEAD)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

Create a new scorecard-backend-module-code-coverage that
integrates with the Backstage Community code-coverage plugin
to provide 8 metrics: line/branch percentage, available,
covered, and missed counts.

The module fetches data from the code-coverage-backend API
using the Backstage discovery service and maps the aggregate
line and branch fields to individual MetricProviders.

Entities are filtered by the backstage.io/code-coverage
annotation. Percentage metrics include default thresholds
(>80 success, 50-80 warning, <50 error).

Includes:
- CodeCoverageClient for API communication
- Type definitions for the code-coverage API response
- 8 MetricProvider implementations via factory pattern
- Unit tests for client, providers, and factory (28 tests)
- Example entity with code-coverage annotation
- Backend app integration

Closes #3474
@rhdh-gh-app

rhdh-gh-app Bot commented Jun 19, 2026

Copy link
Copy Markdown

Missing Changesets

The following package(s) are changed by this PR but do not have a changeset:

  • @red-hat-developer-hub/backstage-plugin-scorecard-backend-module-code-coverage

See CONTRIBUTING.md for more information about how to add changesets.

Changed Packages

Package Name Package Path Changeset Bump Current Version
backend workspaces/scorecard/packages/backend none v0.0.0
@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-code-coverage workspaces/scorecard/plugins/scorecard-backend-module-code-coverage none v0.1.0

@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

⚠️ JUnit XML file not found

The CLI was unable to find any JUnit XML files to upload.
For more help, visit our troubleshooting guide.

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 19, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:30 PM UTC · Completed 1:42 PM UTC
Commit: 7ccaff1 · View workflow run →

@fullsend-ai-review

Copy link
Copy Markdown

Review

Findings

Medium

  • [Missing service-to-service authentication] workspaces/scorecard/plugins/scorecard-backend-module-code-coverage/src/clients/CodeCoverageClient.ts:42 — The client uses bare fetch() without Backstage service-to-service authentication tokens. The code-coverage API is an internal Backstage plugin discovered via DiscoveryService. The Jira module's ProxyConnectionStrategy uses AuthService.getPluginRequestToken() for similar internal plugin calls. Whether this causes 401/403 depends on the target plugin's auth enforcement configuration, but the code-coverage-backend plugin may enforce service auth by default in newer Backstage versions.
    Remediation: Inject AuthService (from coreServices.auth) into the client. Before each fetch, call auth.getPluginRequestToken({ onBehalfOf: await auth.getOwnServiceCredentials(), targetPluginId: 'code-coverage' }) and pass the token as a Bearer header.

Low

  • [edge-case] workspaces/scorecard/plugins/scorecard-backend-module-code-coverage/src/metricProviders/CodeCoverageMetricProvider.ts:69 — The calculateMetric method accesses report.aggregate[mapping.section][mapping.field] without null checks. If the code-coverage API returns a report where the aggregate section is missing or null, this will throw an unhandled TypeError. The TypeScript type defines these as required fields, so this is a defensive programming concern rather than a likely production bug.

  • [missing-test] workspaces/scorecard/plugins/scorecard-backend-module-code-coverage/src/metricProviders/CodeCoverageMetricProvider.test.ts:170 — The test suite has no test case for calculateMetric when the API returns a report with missing or null aggregate section data.

  • [test-inadequate] workspaces/scorecard/plugins/scorecard-backend-module-code-coverage/src/clients/CodeCoverageClient.test.ts:47 — The error-case test asserts toThrow('Code coverage API error: 404 Not Found'), but the production code produces 'Code coverage API error: 404 Not Found for ${url}'. While toThrow(string) uses substring match so the test passes, the test does not verify the URL is included in the error message.

Info

  • [logic-error] workspaces/scorecard/plugins/scorecard-backend-module-code-coverage/src/metricProviders/CodeCoverageMetricProviderFactory.ts:33 — The createCodeCoverageMetricProvider function creates a new CodeCoverageClient instance for each of the 8 metric providers. Each entity will have its code-coverage report fetched 8 separate times. The MetricProvider interface supports a calculateMetrics() batch method that could compute all 8 metrics from a single API call.

  • [data-exposure] workspaces/scorecard/plugins/scorecard-backend-module-code-coverage/src/clients/CodeCoverageClient.ts:42 — The error message on non-OK responses includes the full internal URL, which contains the resolved DiscoveryService base URL. This is consistent with existing patterns in the workspace (e.g., SonarQubeClient).

  • [No response body validation] workspaces/scorecard/plugins/scorecard-backend-module-code-coverage/src/clients/CodeCoverageClient.ts:45 — The JSON response from the code-coverage API is cast directly to CodeCoverageReport without runtime validation. This is consistent with other modules in the workspace.

@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.

if (!response.ok) {
throw new Error(
`Code coverage API error: ${response.status} ${response.statusText} for ${url}`,
);

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] Missing service-to-service authentication

The client uses bare fetch() without Backstage service-to-service authentication tokens. The code-coverage API is an internal Backstage plugin discovered via DiscoveryService.

Suggested fix: Inject AuthService (from coreServices.auth) into the client. Before each fetch, call auth.getPluginRequestToken() and pass the token as a Bearer header.

type: this.getMetricType(),
history: true,
};
}

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] edge-case

The calculateMetric method accesses report.aggregate[mapping.section][mapping.field] without null checks.

});
});

describe('getCatalogFilter', () => {

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] missing-test

No test case for calculateMetric when the API returns a report with missing or null aggregate section data.

it('should call the correct URL and return the report', async () => {
jest.spyOn(global, 'fetch').mockResolvedValueOnce({
ok: true,
json: async () => sampleReport,

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] test-inadequate

The error-case test does not verify the URL is included in the error message due to substring matching.

* Creates a single code-coverage metric provider for the given metric ID.
*/
export function createCodeCoverageMetricProvider(
discovery: DiscoveryService,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[info] logic-error

Creates a new CodeCoverageClient instance for each of the 8 metric providers, causing 8x API calls per entity.

if (!response.ok) {
throw new Error(
`Code coverage API error: ${response.status} ${response.statusText} for ${url}`,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[info] data-exposure

Error message includes the full internal URL. Consistent with existing patterns.

);
}
return response.json() as Promise<CodeCoverageReport>;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[info] No response body validation

JSON response cast directly to CodeCoverageReport without runtime validation. Consistent with other modules.

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires-manual-review Review requires human judgment workspace/scorecard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a new code-coverage module for scorecard

0 participants