Skip to content

fix(#3532): standardize metric IDs from snake_case to lowerCamelCase#3534

Open
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/3532-snake-case-to-camel-case
Open

fix(#3532): standardize metric IDs from snake_case to lowerCamelCase#3534
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/3532-snake-case-to-camel-case

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Rename all Scorecard metric and provider IDs from snake_case to lowerCamelCase to align with the app-config.yaml naming convention and the planned Scorecard design.

Key changes:

  • Provider ID definitions (e.g. github.open_prs -> github.openPrs)
  • SonarQube metric config keys and type members
  • OpenSSF dynamic ID generation (hyphen-to-camelCase conversion)
  • Translation keys in ref.ts and all 5 locale files
  • Config schema (config.d.ts) and YAML config keys
  • All test fixtures, e2e tests, and documentation
  • MetricProvidersRegistry error message format

SonarQube API metric keys (e.g. security_rating, code_smells) are preserved as-is since they are external API field names.

This is a breaking change for existing configurations that reference metric IDs by name.


Closes #3532

Post-script verification

  • Branch is not main/master (agent/3532-snake-case-to-camel-case)
  • Secret scan passed (gitleaks — ed84b21fc3f37da0e0d2ffb05b78432d11ec7ce6..HEAD)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

@rhdh-gh-app

rhdh-gh-app Bot commented Jun 22, 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-module-dependabot workspaces/scorecard/plugins/scorecard-backend-module-dependabot major v0.2.13
@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-github workspaces/scorecard/plugins/scorecard-backend-module-github major v2.7.9
@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-jira workspaces/scorecard/plugins/scorecard-backend-module-jira major v2.7.9
@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf workspaces/scorecard/plugins/scorecard-backend-module-openssf major v0.2.13
@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-sonarqube workspaces/scorecard/plugins/scorecard-backend-module-sonarqube major v0.1.8
@red-hat-developer-hub/backstage-plugin-scorecard-backend workspaces/scorecard/plugins/scorecard-backend major v2.7.9
@red-hat-developer-hub/backstage-plugin-scorecard workspaces/scorecard/plugins/scorecard major v2.7.9

@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 54.28%. Comparing base (2b27956) to head (60e9a1b).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3534   +/-   ##
=======================================
  Coverage   54.28%   54.28%           
=======================================
  Files        2346     2346           
  Lines       89642    89644    +2     
  Branches    25056    25056           
=======================================
+ Hits        48662    48664    +2     
  Misses      40744    40744           
  Partials      236      236           
Flag Coverage Δ *Carryforward flag
adoption-insights 83.70% <ø> (ø) Carriedforward from 2b27956
ai-integrations 67.95% <ø> (ø) Carriedforward from 2b27956
app-defaults 69.79% <ø> (ø) Carriedforward from 2b27956
augment 46.39% <ø> (ø) Carriedforward from 2b27956
boost 74.68% <ø> (ø) Carriedforward from 2b27956
bulk-import 72.46% <ø> (ø) Carriedforward from 2b27956
cost-management 14.10% <ø> (ø) Carriedforward from 2b27956
dcm 61.81% <ø> (ø) Carriedforward from 2b27956
extensions 61.53% <ø> (ø) Carriedforward from 2b27956
global-floating-action-button 71.18% <ø> (ø) Carriedforward from 2b27956
global-header 59.71% <ø> (ø) Carriedforward from 2b27956
homepage 50.23% <ø> (ø) Carriedforward from 2b27956
install-dynamic-plugins 56.77% <ø> (ø) Carriedforward from 2b27956
konflux 91.49% <ø> (ø) Carriedforward from 2b27956
lightspeed 68.81% <ø> (ø) Carriedforward from 2b27956
mcp-integrations 85.46% <ø> (ø) Carriedforward from 2b27956
orchestrator 39.51% <ø> (ø) Carriedforward from 2b27956
quickstart 65.63% <ø> (ø) Carriedforward from 2b27956
sandbox 79.56% <ø> (ø) Carriedforward from 2b27956
scorecard 82.68% <85.71%> (+0.01%) ⬆️
theme 61.26% <ø> (ø) Carriedforward from 2b27956
translations 7.25% <ø> (ø) Carriedforward from 2b27956
x2a 78.68% <ø> (ø) Carriedforward from 2b27956

*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 2b27956...60e9a1b. 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 22, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 5:09 PM UTC · Completed 5:22 PM UTC
Commit: ed84b21 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review — PR #3534

Verdict: Request changes

Summary

This PR renames all scorecard metric and provider IDs from snake_case to lowerCamelCase across 7 packages, correctly marked as a major/breaking change. The rename is mechanically consistent across config schemas, translation keys, tests, and documentation for most modules.

However, the OpenSSF module's dynamic ID generation regex produces incorrect IDs for 3 out of 18 metrics, and the tests fail to catch this because they either mirror the same buggy regex or don't cover the problematic inputs.

Findings

🔴 HIGH — logic-error: OpenSSF ID generation regex fails for all-caps metric names

File: workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/OpenSSFMetricProvider.ts (lines 59-60)

The new regex in getProviderId():

.replace(/-([a-zA-Z])/g, (_, c) => c.toUpperCase())
.replace(/^[A-Z]/, c => c.toLowerCase())

only lowercases the first character of the string, which is incorrect when the OpenSSF check name starts with multiple uppercase letters or is fully uppercase. This produces IDs that don't match the README documentation:

Check name Code produces README documents Match?
CII-Best-Practices cIIBestPractices ciiBestPractices
CI-Tests cITests ciTests
SAST sAST sast

Remediation: Either apply .toLowerCase() first then convert hyphens to camelCase:

.toLowerCase()
.replace(/-([a-z])/g, (_, c) => c.toUpperCase())

Or change the second replace to lowercase all leading uppercase characters: .replace(/^[A-Z]+/, m => m.toLowerCase()).

🔴 HIGH — test-integrity: Bulk provider ID assertion is a tautology

File: workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/OpenSSFMetricProvider.test.ts (line 231)

The bulk assertion that validates all 18 provider IDs computes expected values using the exact same regex as the production code:

const expectedProviderIds = OPENSSF_METRICS.map(metric => {
  const normalizedName = metric.name
    .replace(/-([a-zA-Z])/g, (_, c) => c.toUpperCase())
    .replace(/^[A-Z]/, c => c.toLowerCase());
  return `openssf.${normalizedName}`;
});

This test will always pass regardless of whether the output is correct — it validates the buggy behavior rather than the intended behavior. The test should assert against hardcoded expected values.

Remediation: Replace the computed expectedProviderIds with a hardcoded array of all 18 expected provider IDs (e.g., ['openssf.binaryArtifacts', 'openssf.branchProtection', 'openssf.ciiBestPractices', 'openssf.ciTests', ...]).

🟡 MEDIUM — test-inadequate: Missing edge case tests for uppercase acronym inputs

File: workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/OpenSSFMetricProvider.test.ts (line 80)

The unit test only validates normalization for Code-Review (a simple hyphenated case) and Maintained (no hyphen). It does not test any of the three problematic inputs: CII-Best-Practices, CI-Tests, or SAST. Adding specific assertions for these edge cases would catch the regex bug.

Remediation: Add test cases for CII-Best-Practices (expected: openssf.ciiBestPractices), CI-Tests (expected: openssf.ciTests), and SAST (expected: openssf.sast).

🟡 LOW — tier-mismatch: "fix" prefix on a breaking change

The PR title uses a fix prefix (fix(#3532): standardize metric IDs...) but the change is explicitly breaking — the changeset marks all 7 packages as major. A feat! or refactor! conventional commit prefix would more accurately signal the nature of this change.

Dimensions reviewed

  • Correctness — Three findings (regex bug + test integrity issues)
  • Security — No auth, secrets, or injection concerns
  • Intent & coherence — Change traces to issue Unify Scorecard metric and provider IDs - Snake Case to Lower Camel Case #3532; scope is appropriate
  • Style & conventions — Mechanical rename applied consistently
  • Documentation currency — All docs with old IDs are updated in this PR
  • Cross-repo contracts — Changeset correctly marks all 7 packages as major
Previous run

Review

Findings

High

  • [logic-error] workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/OpenSSFMetricProvider.ts:59 — The camelCase conversion regex .replace(/-([a-zA-Z])/g, (_, c) => c.toUpperCase()).replace(/^[A-Z]/, c => c.toLowerCase()) only lowercases a single leading uppercase character, not a run of them. For metric names starting with uppercase acronyms, this produces incorrect IDs: CII-Best-PracticescIIBestPractices (documented: ciiBestPractices), CI-TestscITests (documented: ciTests), SASTsAST (documented: sast). Three of eighteen OpenSSF metrics will have provider IDs that do not match the README or any downstream configuration referencing the documented names.
    Remediation: Apply .toLowerCase() first, then camelCase the hyphens: name.toLowerCase().replace(/-([a-z])/g, (_, c) => c.toUpperCase()). This yields ciiBestPractices, ciTests, and sast as documented.

  • [test-integrity] workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/OpenSSFMetricProvider.test.ts:231 — The test computes expectedProviderIds using the same broken regex as the production code. Because the expected values are derived from the same buggy logic, the test passes but cannot detect that the generated IDs diverge from the documented/intended values for CII-Best-Practices, CI-Tests, and SAST.
    Remediation: Fix the regex in both production and test code, or hardcode the expected provider IDs in the test so it serves as an independent correctness check.

Info

  • [sub-agent-failure] N/A — The intent-coherence, style-conventions, and docs-currency sub-agents did not return findings due to model unavailability (claude-sonnet-4-5@20250929 not available on vertex deployment). The correctness dimension (opus) was fully evaluated.

fullsend-ai-review[bot]

This comment was marked as outdated.

@christoph-jerolimov christoph-jerolimov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Lgtm!

@christoph-jerolimov

Copy link
Copy Markdown
Member

/fs-fix rename openPrs to openPRs

@fullsend-ai-coder

fullsend-ai-coder Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Fix · ❌ Terminated · Started 9:09 AM UTC · Ended 10:44 AM UTC
Commit: 2b27956 · View workflow run →

Rename all Scorecard metric and provider IDs from snake_case
to lowerCamelCase to align with the app-config.yaml naming
convention and the planned Scorecard design.

Key changes:
- Provider ID definitions (e.g. github.open_prs -> github.openPrs)
- SonarQube metric config keys and type members
- OpenSSF dynamic ID generation (hyphen-to-camelCase conversion)
- Translation keys in ref.ts and all 5 locale files
- Config schema (config.d.ts) and YAML config keys
- All test fixtures, e2e tests, and documentation
- MetricProvidersRegistry error message format

SonarQube API metric keys (e.g. security_rating, code_smells)
are preserved as-is since they are external API field names.

This is a breaking change for existing configurations that
reference metric IDs by name.

Closes #3532
@fullsend-ai-coder fullsend-ai-coder Bot force-pushed the agent/3532-snake-case-to-camel-case branch from a97e9fd to 60e9a1b Compare July 3, 2026 09:09
@sonarqubecloud

sonarqubecloud Bot commented Jul 3, 2026

Copy link
Copy Markdown

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ❌ Failure · Started 9:09 AM UTC · Completed 10:44 AM UTC
Commit: 2b27956 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 3, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 10:47 AM UTC · Completed 11:03 AM UTC
Commit: 2b27956 · View workflow run →

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

const normalizedName = this.getMetricName()
.toLowerCase()
.replace(/-/g, '_');
.replace(/-([a-zA-Z])/g, (_, c) => c.toUpperCase())

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] logic-error

The new camelCase conversion regex fails for OpenSSF check names starting with consecutive uppercase letters. replace(/^[A-Z]/, c => c.toLowerCase()) only lowercases the first character, producing incorrect IDs: CII-Best-Practices → cIIBestPractices (should be ciiBestPractices), CI-Tests → cITests (should be ciTests), SAST → sAST (should be sast). 3 out of 18 metrics produce IDs that don't match the README documentation.

Suggested fix: Apply .toLowerCase() first, then convert hyphens to camelCase: .toLowerCase().replace(/-([a-z])/g, (_, c) => c.toUpperCase()). Alternatively, change the second replace to lowercase all leading uppercase characters: .replace(/^[A-Z]+/, m => m.toLowerCase()). Update the test to match.

const providerIds = providers.map(provider => provider.getProviderId());
const expectedProviderIds = OPENSSF_METRICS.map(metric => {
const normalizedName = metric.name.toLowerCase().replace(/-/g, '_');
const normalizedName = metric.name

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

The bulk assertion that validates all 18 provider IDs computes expected values using the exact same (buggy) regex as the production code. This is a tautological test that will always pass regardless of whether the output is correct, masking the bug where CII-Best-Practices produces cIIBestPractices instead of the documented ciiBestPractices.

Suggested fix: Replace the computed expectedProviderIds with a hardcoded array of all 18 expected provider IDs (e.g., ['openssf.binaryArtifacts', 'openssf.branchProtection', 'openssf.ciiBestPractices', 'openssf.ciTests', ...]). This would catch the uppercase acronym bug.

it('normalizes hyphenated check names for provider id', () => {
const provider = new OpenSSFMetricProvider(hyphenatedCheckConfig);
expect(provider.getProviderId()).toBe('openssf.code_review');
expect(provider.getProviderId()).toBe('openssf.codeReview');

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

The unit test only validates normalization for Code-Review (simple case) and Maintained (no hyphen). It does not test any of the three problematic inputs with consecutive uppercase letters: CII-Best-Practices, CI-Tests, or SAST.

Suggested fix: Add test cases for CII-Best-Practices (expected: openssf.ciiBestPractices), CI-Tests (expected: openssf.ciTests), and SAST (expected: openssf.sast) to verify correct handling of uppercase acronyms.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unify Scorecard metric and provider IDs - Snake Case to Lower Camel Case

1 participant