Skip to content

coverage: publish a dashboard-readable coverage-floor.json - #825

Open
fpigeonjr wants to merge 3 commits into
masterfrom
gh-822-publish-a-coverage-floor-json-for-the-component-st
Open

coverage: publish a dashboard-readable coverage-floor.json#825
fpigeonjr wants to merge 3 commits into
masterfrom
gh-822-publish-a-coverage-floor-json-for-the-component-st

Conversation

@fpigeonjr

Copy link
Copy Markdown
Contributor

What

Publishes a dashboard-readable coverage result for the component/story coverage check, and fixes test.yml's trigger to also run on push to master.

  • Adds coverage-floor.json (repo root) — a single-percentage ratchet ({ "lines": 90 }) the cross-repo angular-upgrade-dashboard can read directly, adapted to this repo's story-smoke metric rather than the 4-key {statements, branches, functions, lines} shape used by line-coverage repos (ngx-uswds, sam-ui-elements) — that shape doesn't map cleanly onto story coverage.
  • scripts/coverage-report.mjs now defaults its threshold to that floor file instead of a hardcoded --threshold=90 literal in package.json, so there's a single source of truth for the number (--threshold=<n> / COVERAGE_THRESHOLD still work as explicit overrides).
  • Commits coverage/component-coverage.json (previously fully gitignored as a CI-only artifact). Its new lines key mirrors the floor. coverage/component-coverage.md and the rest of coverage/ stay CI-artifact-only.
  • Adds scripts/check-coverage-workflow.mjs (npm run test:coverage-workflow) asserting: the floor file's shape/range, that the coverage script doesn't hardcode a threshold, that the JSON stays committed while the markdown stays ignored, and that CI guards against a stale snapshot.
  • test.yml: adds a git diff --exit-code guard after the coverage step so a committed report can't silently drift from a freshly generated one, and adds push: branches: [master] to the trigger — previously the coverage/a11y/lint suite only ran on pull_request, so the default branch's statusCheckRollup reported green from CodeQL alone even though the rest of the suite had never run against it.
  • Updates AGENTS.md's coverage section to describe the new floor-file mechanism.

Motivation and Context

sam-styles enforces 90% component/story coverage in CI but committed no machine-readable result, so the dashboard rendered this repo's coverage cell as "not published." This makes the check's result visible to the dashboard while keeping the metric honest to what this repo actually measures (story-smoke coverage, not line coverage).

Closes #822

How to Test

npm ci
npm test                       # stylelint
npm run compile:check          # SCSS compilation
npm run test:security-workflow
npm run test:coverage-workflow # new — validates the floor/report contract
npm run coverage                # writes coverage/component-coverage.json; should exit 0 and match the committed file
git diff --exit-code -- coverage/component-coverage.json  # the freshness guard test.yml now runs
npx playwright install --with-deps chromium
npm run test:storybook
npm run test:a11y
npm run format:check
NODE_OPTIONS=--max_old_space_size=8192 npm run build:storybook

All of the above pass locally on Node 24 (per .nvmrc).

Screenshots

N/A — CI/tooling changes only.

Checklist

  • Branch name follows convention (gh-822-...)
  • PR title follows <scope>: <subject> convention
  • I have self-reviewed the changes
  • npm test, npm run compile:check, npm run test:security-workflow, npm run test:coverage-workflow, npm run coverage, npm run test:storybook, npm run test:a11y, npm run format:check, and npm run build:storybook all pass locally
  • Repository administrator/DevSecOps should confirm no branch-protection required-check names need updating for the new Validate coverage workflow / freshness-guard steps in test.yml

- Add coverage-floor.json (repo root), a single-percentage ratchet
  ({ "lines": 90 }) the cross-repo quality dashboard can read directly.
- scripts/coverage-report.mjs now defaults its threshold to that floor
  file instead of a hardcoded --threshold=90 literal, so there's one
  source of truth for the number (CLI/--env overrides still work).
- Commit coverage/component-coverage.json (was fully gitignored); its
  new lines key mirrors the floor's single-percentage shape. The
  markdown report stays CI-artifact-only.
- Add scripts/check-coverage-workflow.mjs + npm run test:coverage-workflow
  to assert the floor's shape, that the JSON stays committed, and that
  CI guards against a stale snapshot.
- test.yml: add a 'push: branches: [master]' trigger (the suite
  previously only ran on pull_request against the default branch) and
  a git diff --exit-code guard after the coverage step.
- AGENTS.md: document the new floor-file mechanism.

Closes #822
@fpigeonjr fpigeonjr self-assigned this Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://GSA.github.io/sam-styles/pr-preview/pr-825/

Built to branch gh-pages at 2026-09-10 21:46 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

Component / Story Coverage Report

100% coverage (52 / 52 stories have Playwright specs) — threshold: 90%

Summary

Metric Value
Total stories 52
Covered by specs 52
Not covered 0
Coverage % 100%
Threshold 90%
Status PASS ✅

Coverage metric

For this SCSS-only library, "coverage" means every Storybook story (.stories.js)
in sam-styles/packages/ has at least one matching Playwright spec in tests/storybook/.

Uncovered stories

All stories are covered 🎉

Covered stories

Story file Status
branding/colors/colors.stories.js ✅ Covered
branding/elements/elements.stories.js ✅ Covered
branding/icons/icons.stories.js ✅ Covered
branding/typography/fields/fields.stories.js ✅ Covered
branding/typography/heading/heading.stories.js ✅ Covered
branding/typography/lists/lists.stories.js ✅ Covered
branding/typography/paragraph/paragraph.stories.js ✅ Covered
branding/typography/typesetting/typesetting.stories.js ✅ Covered
components/accordion/accordion.stories.js ✅ Covered
components/actions/actions.stories.js ✅ Covered
components/alerts/alert.stories.js ✅ Covered
components/autocomplete/autocomplete.stories.js ✅ Covered
components/button-group/button-grop.stories.js ✅ Covered
components/button-row/button-row.stories.js ✅ Covered
components/button/circle/circle-button.stories.js ✅ Covered
components/button/pill/pill-button.stories.js ✅ Covered
components/button/standard/Button.stories.js ✅ Covered
components/card/card.stories.js ✅ Covered
components/collection/collection.stories.js ✅ Covered
components/dashboard/event/event.stories.js ✅ Covered
components/dashboard/statistics/alt.stories.js ✅ Covered
components/dashboard/statistics/default.stories.js ✅ Covered
components/dashboard/tile/SDStile-outline/tileoutline.stories.js ✅ Covered
components/dashboard/tile/SDStile/sdstile.stories.js ✅ Covered
components/history/history.stories.js ✅ Covered
components/pagination/Pagination.stories.js ✅ Covered
components/process-list/process-list.stories.js ✅ Covered
components/range-slider/range-slider.stories.js ✅ Covered
components/side-nav/side-nav.stories.js ✅ Covered
components/stepindicator/stepindicator.stories.js ✅ Covered
components/summarybox/summarybox.stories.js ✅ Covered
components/tables/tables.stories.js ✅ Covered
components/tags/tags.stories.js ✅ Covered
components/toasts/toasts.stories.js ✅ Covered
form-controls/address-form/address-form.stories.js ✅ Covered
form-controls/checkbox/checkbox.stories.js ✅ Covered
form-controls/dropdown/dropdown.stories.js ✅ Covered
form-controls/input/input.stories.js ✅ Covered
form-controls/name-form/name-form.stories.js ✅ Covered
form-controls/radio/radio.stories.js ✅ Covered
form-controls/search/search.stories.js ✅ Covered
misc/pop-up/pop-up.stories.js ✅ Covered
misc/search-layout/search-layout.stories.js ✅ Covered
misc/sort/sort.stories.js ✅ Covered
misc/toolbar/toolbar.stories.js ✅ Covered
patterns/pages/pages.stories.js ✅ Covered
sds-styles/stories/sds-styles.stories.js ✅ Covered
structure/banner/banner.stories.js ✅ Covered
structure/footer/footer.stories.js ✅ Covered
structure/header/header.stories.js ✅ Covered
structure/sds-navbar/sds-navbar.stories.js ✅ Covered
structure/seal/seal.stories.js ✅ Covered

Copilot AI 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.

🟡 Changes recommended

The new coverage workflow contract check is missing key validations (integer floor and tracked report) and the committed JSON output should be stabilized to avoid CI drift/flakiness.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR publishes a dashboard-readable component/story coverage result by committing a machine-readable coverage snapshot (coverage/component-coverage.json) and introducing a repo-root coverage-floor.json ratchet as the single source of truth for the default threshold, while also ensuring the main CI workflow runs on pushes to master.

Changes:

  • Add coverage-floor.json and update scripts/coverage-report.mjs to default its threshold from that ratchet (with CLI/env overrides preserved).
  • Commit coverage/component-coverage.json and adjust .gitignore/CI to keep the committed snapshot from drifting.
  • Add scripts/check-coverage-workflow.mjs plus a new CI step to validate the coverage contract and fix test.yml to trigger on push to master.
File summaries
File Description
scripts/coverage-report.mjs Reads default threshold from coverage-floor.json and writes a committed JSON report including a lines key for dashboards.
scripts/check-coverage-workflow.mjs New contract-check script validating floor/report/CI expectations for component-story coverage publishing.
package.json Adds test:coverage-workflow and removes the hardcoded --threshold=90 from the coverage script.
coverage/component-coverage.json New committed machine-readable snapshot of current story/spec coverage results.
coverage-floor.json New committed “ratchet” floor file with { "lines": 90 } as the default threshold source.
AGENTS.md Updates documentation to describe the new floor-file mechanism and coverage workflow validation.
.gitignore Keeps coverage/ ignored except for committed coverage/component-coverage.json.
.github/workflows/test.yml Runs on push to master, validates the new coverage workflow contract, and guards against stale committed coverage output.
Review details
  • Files reviewed: 6/8 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/check-coverage-workflow.mjs
Comment thread scripts/check-coverage-workflow.mjs
Comment thread scripts/coverage-report.mjs
- check-coverage-workflow.mjs: require coverage-floor.json's lines to be
  an integer (Number.isInteger), not just a number in range \u2014 a
  fractional value would pass this check but coverage-report.mjs's own
  integer check would then fail npm run coverage.
- check-coverage-workflow.mjs: git check-ignore only proves the ignore
  rules allow the file; add a git ls-files --error-unmatch assertion so
  the check actually proves coverage/component-coverage.json is tracked,
  not just unignored.
- coverage-report.mjs: sort the stories array by path before writing the
  JSON report. readdirSync's traversal order isn't guaranteed stable
  across filesystems, which could produce false-positive diffs against
  the committed snapshot across environments.
@fpigeonjr
fpigeonjr marked this pull request as ready for review September 8, 2026 21:23
@fpigeonjr
fpigeonjr requested a review from a team September 8, 2026 21:23
@fpigeonjr
fpigeonjr requested review from a team and christyhermansen as code owners September 8, 2026 21:23
beverly-n
beverly-n previously approved these changes Sep 9, 2026

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

LGTM

…verage-floor-json-for-the-component-st

# Conflicts:
#	AGENTS.md
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.

Publish a coverage-floor.json for the component/story coverage check

3 participants