Skip to content

Add code coverage tracking and enforce 90% minimum#25

Merged
gcko merged 5 commits intomainfrom
feature/test-and-workflows
Feb 7, 2026
Merged

Add code coverage tracking and enforce 90% minimum#25
gcko merged 5 commits intomainfrom
feature/test-and-workflows

Conversation

@gcko
Copy link
Owner

@gcko gcko commented Feb 7, 2026

PR checklist

  • Ensure you have added or ran the appropriate tests for your PR.
  • DCO signed

What type of PR is this?

Test / CI enhancement

What this PR does / why we need it:

Adds code coverage tracking, enforcement, and PR reporting to the repository without relying on third-party web services:

Coverage enforcement

  • Installs @vitest/coverage-v8 as the coverage provider
  • Configures 90% minimum thresholds on all four metrics (statements, branches, functions, lines) in vitest.config.ts
  • Adds test:coverage and test:coverage:summary scripts to package.json
  • Updates pre-commit hook to run pnpm test:coverage (blocks commits below 90%)
  • Updates CI workflow to run coverage and upload coverage-final.json as a GitHub Actions artifact

Coverage report workflow

  • Adds a coverage-report.yml workflow that triggers after CI completes on PRs
  • Downloads coverage artifacts from both the PR branch and master (baseline)
  • Runs scripts/coverage-report.cjs to compare coverage and generate a markdown report
  • Posts (or updates) a PR comment showing overall coverage delta and per-file breakdown for changed files
  • CI now also runs on push to master to maintain a baseline coverage artifact

Workflow security hardening

  • Checks out the default branch (trusted code) instead of the PR head, preventing a malicious PR from modifying scripts/coverage-report.cjs to exfiltrate secrets via the pull-requests:write permission
  • Moves all attacker-controllable workflow_run context values (head_branch, head_repository.owner.login, pull_requests[0].number) into env: variables to prevent shell injection via crafted branch names
  • Routes all step outputs (steps.pr.outputs.number, steps.changed.outputs.files) through env: variables instead of direct ${{ }} interpolation in run: blocks
  • Replaces tj-actions/changed-files with gh pr diff --name-only via the GitHub API, eliminating the need to check out untrusted PR code

Test improvements

  • Adds 50 new tests (34 to 84 total) achieving 100% coverage on all metrics
  • 21 new tests for main.ts and service_worker.ts covering all branches, functions, and error paths
  • 29 new tests for scripts/coverage-report.cjs (unit tests for each function + CLI integration tests)
  • Adds coverage/ to .gitignore and biome ignore list

Which issue(s) this PR fixes:

N/A - new quality enforcement

Special notes for your reviewer:

Coverage results after this change:

Metric Before After
Statements 93.58% 100%
Branches 74.64% 100%
Functions 81.81% 100%
Lines 93.50% 100%

The 90% threshold is enforced in both pre-commit hooks and CI. The coverage report workflow pattern is adapted from other OSS repositories, simplified for a frontend-only repository with the report script written in JavaScript (not Python) to match the project tech stack and enable Vitest testing.

The coverage-report.yml workflow follows the GitHub Security Lab guidance for safe workflow_run usage: no untrusted code checkout, no expression injection in shell contexts, and all external inputs sanitized through environment variables.

Does this PR introduce a user-facing change?:

NONE

gcko and others added 3 commits February 7, 2026 13:51
Add @vitest/coverage-v8 with 90% thresholds on statements, branches,
functions, and lines. Coverage enforcement runs in both pre-commit hooks
and CI, with coverage-final.json uploaded as a GitHub Actions artifact.

Added 21 new tests (34 -> 55) to achieve 100% coverage across all
metrics for main.ts, service_worker.ts, and utils.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jared Scott <jared.scott@variable.team>
Add a coverage-report workflow that triggers after CI completes on PRs.
It downloads coverage artifacts from both the PR and master branches,
compares them, and posts a markdown summary as a PR comment showing
overall coverage delta and per-file coverage for changed files.

Changes:
- ci.yml: trigger on push to master, upload coverage-main artifact
- coverage-report.yml: new workflow_run-triggered reporter
- scripts/coverage-report.cjs: coverage comparison and report generation
- src/coverage-report.spec.ts: 29 tests for the report script

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jared Scott <jared.scott@variable.team>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jared Scott <jared.scott@variable.team>
- Checkout default branch instead of PR head to prevent untrusted code
  execution in a privileged workflow_run context
- Move attacker-controllable values (head_branch, head_owner) to env
  variables to prevent shell injection via crafted branch names
- Replace tj-actions/changed-files with gh pr diff API call to avoid
  needing PR code checkout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jared Scott <jared.scott@variable.team>
Move steps.pr.outputs.number and steps.changed.outputs.files from
direct ${{ }} interpolation in run: blocks to env: variables,
preventing potential shell injection via attacker-controlled values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jared Scott <jared.scott@variable.team>
@gcko gcko merged commit c316f89 into main Feb 7, 2026
6 checks passed
@gcko gcko deleted the feature/test-and-workflows branch February 7, 2026 06:25
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