Skip to content

Comments

chore: multi-metric coverage badges & extraction script#67

Merged
docdyhr merged 2 commits intomainfrom
feat/multi-metric-coverage-badges
Aug 9, 2025
Merged

chore: multi-metric coverage badges & extraction script#67
docdyhr merged 2 commits intomainfrom
feat/multi-metric-coverage-badges

Conversation

@docdyhr
Copy link
Owner

@docdyhr docdyhr commented Aug 9, 2025

Summary

Introduce multi-metric (lines / branches / functions) coverage visibility and automated badge updates. Expands test suite from 207 to 404 tests (all passing) and adds a guardrail script enforcing minimal thresholds (lines>=30, branches>=5, functions>=5) as a foundation for future ratcheting.

Key Changes

  • Add workflow .github/workflows/test-coverage-badges.yml:
    • Runs tests with coverage
    • Spins up MySQL + WordPress containers for live compatibility tests
    • Extracts line/branch/function coverage via new script
    • Posts PR comment with metrics
    • Updates README badges (tests + line/branch/function coverage)
    • Appends metrics history on main
    • Enforces guardrail thresholds (configurable via env)
  • Add scripts/extract-coverage-metrics.js (deterministic parsing of coverage-final.json).
  • Extend guardrail (scripts/coverage-guardrail.js) to include branches and functions.
  • README: Replace single coverage badge with three granular badges; update test counts (404/404).
  • Documentation wording adjustments (production readiness / coverage growth framing).

Rationale

Granular coverage metrics improve signal and help focus future improvements (e.g., branch coverage often lags lines). Guardrail starts permissive to avoid blocking while establishing baseline after large test suite expansion. History file will enable trend visualization in a later PR.

Follow-Up Ideas (Not in this PR)

  • Incrementally ratchet thresholds (e.g., +2–5% per milestone).
  • Generate SVG trend badge from metrics/history.jsonl.
  • Separate live WordPress tests into a matrix job.
  • Add per-package or critical-path coverage deltas.

Testing

  • Local run: 404/404 tests passing.
  • Workflow YAML indentation and failure surfacing validated (removed masking of test failures).
  • Guardrail script correctly exits non-zero when thresholds are unmet (simulated locally).

Security & Quality

  • No secrets added.
  • Added explicit failure surfacing (removed || true masking in test step).
  • Improved error logging with stack trace in extraction script.

Checklist

  • Tests pass
  • Coverage artifacts generated
  • Guardrail thresholds applied
  • README badges updated
  • Review feedback addressed

Copilot AI review requested due to automatic review settings August 9, 2025 13:38
@sourcery-ai
Copy link

sourcery-ai bot commented Aug 9, 2025

Reviewer's Guide

Introduces multi-metric coverage tracking by updating the README badges to show line, branch, and function coverage, and automates extraction, validation, and updating of these metrics via a new GitHub Actions workflow and support script.

Flow diagram for coverage metrics extraction script

flowchart TD
    Start([Start]) --> CheckFile{Does coverage-final.json exist?}
    CheckFile -- No --> Error1[Exit: Coverage file missing]
    CheckFile -- Yes --> ParseFile[Parse coverage-final.json]
    ParseFile -- Error --> Error2[Exit: Failed to parse]
    ParseFile -- Success --> Aggregate[Aggregate line, branch, function totals]
    Aggregate --> Calc[Calculate percentages]
    Calc --> OutputType{JSON_OUTPUT=true?}
    OutputType -- Yes --> JsonOut[Print JSON]
    OutputType -- No --> ShellOut[Print shell exports]
    JsonOut --> End([End])
    ShellOut --> End
Loading

File-Level Changes

Change Details Files
Update README for multi-metric coverage badges and related documentation tweaks
  • Replace single test coverage badge with separate line, branch, and function coverage badges
  • Update test counts to 404 and adjust Production Ready callouts
  • Revise status tables and test summary sections to display new metrics
  • Adjust navigation links and section headings (e.g., ‘Why This MCP Server?’, ‘Site Management’ label)
README.md
Add GitHub Actions workflow to generate and update test and coverage badges
  • Define triggers for push, pull_request, cron schedule, and manual dispatch
  • Setup MySQL and WordPress services for live compatibility tests
  • Run unit, integration, compatibility, and coverage tests with guardrails
  • Extract metrics, enforce coverage thresholds, upload artifacts, and append history
  • Comment metrics on PRs and automatically update README badges with new values
.github/workflows/test-coverage-badges.yml
Add coverage metrics extraction script
  • Parse coverage/coverage-final.json to compute line, branch, and function coverage percentages
  • Output metrics as shell exports and JSON when requested
scripts/extract-coverage-metrics.js

Possibly linked issues

  • Create datadog-synthetics.yml #1: The PR implements a new CI workflow to automate updating dynamic test and multi-metric coverage badges as outlined in the issue.
  • Create datadog-synthetics.yml #1: PR updates README badges with current test & coverage metrics using a new CI workflow that extracts them.
  • #0: The PR introduces a new workflow with a 'Coverage guardrail (blocking)' step and related scripts that directly implement the incremental coverage guardrail described in the issue.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@claude
Copy link
Contributor

claude bot commented Aug 9, 2025

Claude finished @docdyhr's task —— View job


Code Review for Multi-Metric Coverage Badges

I've thoroughly analyzed this PR that adds comprehensive test and coverage badge functionality. Here's my detailed review:

Review Progress

  • Read and analyze .github/workflows/test-coverage-badges.yml
  • Review scripts/extract-coverage-metrics.js for code quality and security
  • Review README.md changes
  • Provide comprehensive feedback on all aspects
  • Check for potential bugs and issues
  • Assess performance considerations
  • Evaluate security concerns

🔍 Overall Assessment: Well-Implemented with Some Issues

This PR adds valuable multi-metric coverage badges with automated workflows. The implementation is solid but has several issues that need addressing.


⚠️ Critical Issues

1. Missing Dependency Script (High Priority)

File: .github/workflows/test-coverage-badges.yml:137

run: node scripts/coverage-guardrail.js

Issue: The workflow references scripts/coverage-guardrail.js but this file doesn't exist in the repository.

Impact: The workflow will fail with "file not found" error.

Fix: Either create the missing script or remove this step.

2. Test Result Parsing Fragility (Medium Priority)

File: .github/workflows/test-coverage-badges.yml:96-100

SUMMARY=$(grep -E "Tests:.*total" -R . | tail -1)
TESTS_TOTAL=$(echo "$SUMMARY" | grep -oE '[0-9]+ total' | awk '{print $1}')
TESTS_PASSED=$(echo "$SUMMARY" | grep -oE '[0-9]+ passed' | awk '{print $1}')

Issues:

  • Brittle parsing that depends on specific Jest output format
  • grep -R . searches entire directory (inefficient and unreliable)
  • May fail if Jest output changes or if multiple test files have similar patterns

Recommendation: Use Jest's JSON reporter or parse coverage files directly.


🐛 Bugs & Issues

3. Badge Update Logic Problems (Medium Priority)

File: .github/workflows/test-coverage-badges.yml:175-177

grep -q 'lines%20coverage-' README.md || echo "Adding line coverage badge placeholder" && echo "[![Line Coverage]..."

Issues:

  • Uses && instead of proper if-else logic - will always append badges
  • Could create duplicate badges on subsequent runs
  • Missing proper conditional logic structure

Fix:

if ! grep -q 'lines%20coverage-' README.md; then
  echo "[![Line Coverage](https://img.shields.io/badge/lines%20coverage-${{ steps.metrics.outputs.coverage_lines }}%25-${{ steps.metrics.outputs.coverage_color }}?logo=jest&logoColor=white)](https://github.com/docdyhr/mcp-wordpress)" >> README.md
fi

4. Hard-coded Repository URL (Low Priority)

File: .github/workflows/test-coverage-badges.yml:175-177

(https://github.com/docdyhr/mcp-wordpress)

Issue: Hard-coded URL won't work for forks.

Fix: Use ${{ github.repository }} or make badges link-free.


Performance Considerations

5. Efficient but Could Be Optimized

Positives:

  • ✅ Good use of Docker services for testing
  • ✅ Smart path filtering to avoid unnecessary runs
  • ✅ Efficient npm cache strategy

Improvements:

  • Consider combining badge update steps
  • Use more targeted grep searches instead of grep -R .

🔒 Security Assessment

6. Generally Secure Implementation

Positives:

  • ✅ Proper permission scoping (contents: write, pull-requests: write)
  • ✅ No credential exposure in scripts
  • ✅ Uses official GitHub actions

Minor Concerns:

  • Environment variable sourcing: . coverage/raw-metrics.env 2>/dev/null || true - could be safer with validation
  • Shell command injection potential in sed operations (low risk)

💎 Code Quality

7. JavaScript Extract Script (scripts/extract-coverage-metrics.js)

Excellent Quality:

  • ✅ Clean, readable ES6 module syntax
  • ✅ Proper error handling with descriptive messages
  • ✅ Flexible output format (shell variables or JSON)
  • ✅ Efficient data aggregation logic
  • ✅ Good mathematical precision with .toFixed(2)

Minor Enhancement:

  • Could add input validation for the data structure

8. Workflow Structure (.github/workflows/test-coverage-badges.yml)

Well-Structured:

  • ✅ Comprehensive service setup (MySQL + WordPress)
  • ✅ Good health check implementation
  • ✅ Smart conditional logic for main branch vs PR
  • ✅ Proper artifact handling

📊 README.md Changes Assessment

9. Badge Integration (Lines 19-22)

Good Implementation:

  • ✅ Consistent styling with existing badges
  • ✅ Proper URL encoding
  • ✅ Good visual hierarchy

Current Values Seem Realistic:

  • Line Coverage: 30.97% (orange) - reasonable for expanding codebase
  • Branch Coverage: 23.84% (red) - could be improved
  • Function Coverage: 27.69% (orange) - aligns with expanding test suite

🎯 Recommendations

Immediate Fixes (Required):

  1. Create missing coverage guardrail script or remove the step
  2. Fix badge append logic to prevent duplicates
  3. Make test parsing more robust using Jest JSON output

Improvements (Suggested):

  1. Add input validation to extract script
  2. Use dynamic repository URLs instead of hard-coded ones
  3. Consider consolidating badge update operations

Code Example for Missing Guardrail Script:

#!/usr/bin/env node
// scripts/coverage-guardrail.js
import fs from 'fs';
import process from 'process';

const metrics = JSON.parse(fs.readFileSync('metrics.json', 'utf-8'));
const minLines = parseFloat(process.env.COVERAGE_MIN_LINES || '30');
const minBranches = parseFloat(process.env.COVERAGE_MIN_BRANCHES || '5');
const minFunctions = parseFloat(process.env.COVERAGE_MIN_FUNCTIONS || '5');

const lineCov = parseFloat(metrics.line_coverage);
const branchCov = parseFloat(metrics.branch_coverage);
const funcCov = parseFloat(metrics.function_coverage);

if (lineCov < minLines) {
  console.error(`Line coverage ${lineCov}% below minimum ${minLines}%`);
  process.exit(1);
}
if (branchCov < minBranches) {
  console.error(`Branch coverage ${branchCov}% below minimum ${minBranches}%`);
  process.exit(1);
}
if (funcCov < minFunctions) {
  console.error(`Function coverage ${funcCov}% below minimum ${minFunctions}%`);
  process.exit(1);
}

console.log('✅ Coverage guardrails passed');

Summary

This PR adds valuable coverage tracking functionality with mostly solid implementation. The main blocker is the missing coverage-guardrail.js script. Once that's addressed along with the badge logic fixes, this will be a great addition to the project's CI/CD pipeline.

Verdict: Approve with changes required - Fix the critical issues and this will be ready to merge.


Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements a comprehensive test coverage badge system with automated metrics extraction and updating. The changes introduce a Node.js script to extract coverage metrics from Jest output and a GitHub Actions workflow to automatically update README badges with current test and coverage statistics.

  • Adds coverage metrics extraction script that parses Jest coverage data and outputs shell variables or JSON
  • Implements automated GitHub Actions workflow for running tests, extracting metrics, and updating badges
  • Updates README badges to show detailed coverage metrics (lines, branches, functions) instead of generic coverage

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
scripts/extract-coverage-metrics.js New script to parse Jest coverage JSON and extract line/branch/function coverage percentages
.github/workflows/test-coverage-badges.yml Complete CI workflow for running tests, extracting metrics, and automatically updating README badges
README.md Updates badges from generic coverage to specific metrics and adjusts test count references
Comments suppressed due to low confidence (1)

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @docdyhr - I've reviewed your changes - here's some feedback:

  • Remove the || true from the "Tests with coverage" step so that test failures fail the workflow immediately instead of being silently ignored.
  • Consider using Jest’s built-in JSON output (--json --outputFile) instead of grepping console summaries, to make your metrics extraction more reliable.
  • The sed-based badge updates in README.md are brittle—think about centralizing badge definitions or using a templating approach to reduce regex maintenance overhead.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Remove the `|| true` from the "Tests with coverage" step so that test failures fail the workflow immediately instead of being silently ignored.
- Consider using Jest’s built-in JSON output (`--json --outputFile`) instead of grepping console summaries, to make your metrics extraction more reliable.
- The sed-based badge updates in README.md are brittle—think about centralizing badge definitions or using a templating approach to reduce regex maintenance overhead.

## Individual Comments

### Comment 1
<location> `scripts/extract-coverage-metrics.js:22` </location>
<code_context>
+try {
+  data = JSON.parse(fs.readFileSync(reportPath, "utf-8"));
+} catch (e) {
+  console.error("# failed to parse coverage-final.json", e.message);
+  process.exit(1);
+}
</code_context>

<issue_to_address>
Consider printing the full error object for debugging.

Printing e.stack instead of just e.message will provide more context for debugging parsing errors.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
  console.error("# failed to parse coverage-final.json", e.message);
=======
  console.error("# failed to parse coverage-final.json", e.stack);
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codecov
Copy link

codecov bot commented Aug 9, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@claude
Copy link
Contributor

claude bot commented Aug 9, 2025

Claude finished @docdyhr's task —— View job


Code Review for Multi-Metric Coverage Badges

I've thoroughly analyzed this PR that adds comprehensive test and coverage badge functionality. Here's my detailed review:

Review Progress

  • Read and analyze .github/workflows/test-coverage-badges.yml
  • Review scripts/extract-coverage-metrics.js for code quality and security
  • Review README.md changes
  • Provide comprehensive feedback on all aspects
  • Check for potential bugs and issues
  • Assess performance considerations
  • Evaluate security concerns

🔍 Overall Assessment: Well-Implemented with Some Issues

This PR adds valuable multi-metric coverage badges with automated workflows. The implementation is solid but has several issues that need addressing.


⚠️ Critical Issues

1. Missing Dependency Script (High Priority)

File: .github/workflows/test-coverage-badges.yml:137

run: node scripts/coverage-guardrail.js

Issue: The workflow references scripts/coverage-guardrail.js but this file doesn't exist in the repository.

Impact: The workflow will fail with "file not found" error.

Fix: Either create the missing script or remove this step.

2. Test Result Parsing Fragility (Medium Priority)

File: .github/workflows/test-coverage-badges.yml:96-100

SUMMARY=$(grep -E "Tests:.*total" -R . | tail -1)
TESTS_TOTAL=$(echo "$SUMMARY" | grep -oE '[0-9]+ total' | awk '{print $1}')
TESTS_PASSED=$(echo "$SUMMARY" | grep -oE '[0-9]+ passed' | awk '{print $1}')

Issues:

  • Brittle parsing that depends on specific Jest output format
  • grep -R . searches entire directory (inefficient and unreliable)
  • May fail if Jest output changes or if multiple test files have similar patterns

Recommendation: Use Jest's JSON reporter or parse coverage files directly.


🐛 Bugs & Issues

3. Badge Update Logic Problems (Medium Priority)

File: .github/workflows/test-coverage-badges.yml:175-177

grep -q 'lines%20coverage-' README.md || echo "Adding line coverage badge placeholder" && echo "[![Line Coverage]..."

Issues:

  • Uses && instead of proper if-else logic - will always append badges
  • Could create duplicate badges on subsequent runs
  • Missing proper conditional logic structure

Fix:

if ! grep -q 'lines%20coverage-' README.md; then
  echo "[![](https://img.shields.io/badge/lines%20coverage-${{ steps.metrics.outputs.coverage_lines }}%25-${{ steps.metrics.outputs.coverage_color }}?logo=jest&logoColor=white)](https://github.com/docdyhr/mcp-wordpress)" >> README.md
fi

4. Hard-coded Repository URL (Low Priority)

File: .github/workflows/test-coverage-badges.yml:175-177

(https://github.com/docdyhr/mcp-wordpress)

Issue: Hard-coded URL won't work for forks.

Fix: Use ${{ github.repository }} or make badges link-free.


Performance Considerations

5. Efficient but Could Be Optimized

Positives:

  • ✅ Good use of Docker services for testing
  • ✅ Smart path filtering to avoid unnecessary runs
  • ✅ Efficient npm cache strategy

Improvements:

  • Consider combining badge update steps
  • Use more targeted grep searches instead of grep -R .

🔒 Security Assessment

6. Generally Secure Implementation

Positives:

  • ✅ Proper permission scoping (contents: write, pull-requests: write)
  • ✅ No credential exposure in scripts
  • ✅ Uses official GitHub actions

Minor Concerns:

  • Environment variable sourcing: . coverage/raw-metrics.env 2>/dev/null || true - could be safer with validation
  • Shell command injection potential in sed operations (low risk)

💎 Code Quality

7. JavaScript Extract Script (scripts/extract-coverage-metrics.js)

Excellent Quality:

  • ✅ Clean, readable ES6 module syntax
  • ✅ Proper error handling with descriptive messages
  • ✅ Flexible output format (shell variables or JSON)
  • ✅ Efficient data aggregation logic
  • ✅ Good mathematical precision with .toFixed(2)

Minor Enhancement:

  • Could add input validation for the data structure

8. Workflow Structure (.github/workflows/test-coverage-badges.yml)

Well-Structured:

  • ✅ Comprehensive service setup (MySQL + WordPress)
  • ✅ Good health check implementation
  • ✅ Smart conditional logic for main branch vs PR
  • ✅ Proper artifact handling

📊 README.md Changes Assessment

9. Badge Integration (Lines 19-22)

Good Implementation:

  • ✅ Consistent styling with existing badges
  • ✅ Proper URL encoding
  • ✅ Good visual hierarchy

Current Values Seem Realistic:

  • Line Coverage: 30.97% (orange) - reasonable for expanding codebase
  • Branch Coverage: 23.84% (red) - could be improved
  • Function Coverage: 27.69% (orange) - aligns with expanding test suite

🎯 Recommendations

Immediate Fixes (Required):

  1. Create missing coverage guardrail script or remove the step
  2. Fix badge append logic to prevent duplicates
  3. Make test parsing more robust using Jest JSON output

Improvements (Suggested):

  1. Add input validation to extract script
  2. Use dynamic repository URLs instead of hard-coded ones
  3. Consider consolidating badge update operations

Code Example for Missing Guardrail Script:

#!/usr/bin/env node
// scripts/coverage-guardrail.js
import fs from 'fs';
import process from 'process';

const metrics = JSON.parse(fs.readFileSync('metrics.json', 'utf-8'));
const minLines = parseFloat(process.env.COVERAGE_MIN_LINES || '30');
const minBranches = parseFloat(process.env.COVERAGE_MIN_BRANCHES || '5');
const minFunctions = parseFloat(process.env.COVERAGE_MIN_FUNCTIONS || '5');

const lineCov = parseFloat(metrics.line_coverage);
const branchCov = parseFloat(metrics.branch_coverage);
const funcCov = parseFloat(metrics.function_coverage);

if (lineCov < minLines) {
  console.error(`Line coverage ${lineCov}% below minimum ${minLines}%`);
  process.exit(1);
}
if (branchCov < minBranches) {
  console.error(`Branch coverage ${branchCov}% below minimum ${minBranches}%`);
  process.exit(1);
}
if (funcCov < minFunctions) {
  console.error(`Function coverage ${funcCov}% below minimum ${minFunctions}%`);
  process.exit(1);
}

console.log('✅ Coverage guardrails passed');

Summary

This PR adds valuable coverage tracking functionality with mostly solid implementation. The main blocker is the missing coverage-guardrail.js script. Once that's addressed along with the badge logic fixes, this will be a great addition to the project's CI/CD pipeline.

Verdict: Approve with changes required - Fix the critical issues and this will be ready to merge.


@docdyhr docdyhr merged commit 47a09b3 into main Aug 9, 2025
37 of 38 checks passed
@docdyhr docdyhr deleted the feat/multi-metric-coverage-badges branch August 9, 2025 14:06
docdyhr added a commit that referenced this pull request Aug 9, 2025
#67) (#68)

* chore: multi-metric coverage badges & extraction script

* chore: address PR feedback (remove masking, fix indentation, improve error logging)

* chore: add coverage guardrail script & contracts test docs (mock/live fallback)

* chore: add structured JSON output to coverage guardrail
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant