|
cMCP 0.4.1
Model Context Protocol library in pure C11
|
cMCP's CI publishes line, function, and branch coverage for the library code under src/ on every push and pull request. Tier 7.4 turns that publication into a delta gate: a PR that meaningfully shrinks coverage relative to main does not pass review without an explicit opt-out.
On every PR:
make coverage, which produces coverage/summary.txt via gcovr --print-summary.main-side coverage/summary.txt from GitHub Actions cache.scripts/coverage-delta.sh parses both, writes a markdown delta table to coverage/delta.md, posts it as a sticky PR comment, and exits 1 if either of the following dropped by more than 1.0 percentage point:lines coveragefunctions coverageOn every push to main: CI runs the same coverage step and writes the resulting summary.txt into a cache entry keyed by main. This is what subsequent PRs compare against. GitHub Actions evicts caches after 7 days of inactivity; if the cache disappears (e.g. low main push frequency), the gate becomes informational for one cycle until the next main push refills it.
Below that the noise floor of test ordering + new-file additions makes the gate trip on no-op PRs. Above it, multi-pp degradations would slip through unnoticed. 1.0 pp lets small natural drift through, blocks any material shrinkage.
lines only goes down a little, but a public function has zero hits. This is the consumer-facing regression we care most about.if (x == NULL) return CMCP_EINVAL; would drop branch coverage every time, which is correct C-engineering hygiene, not a regression.For legitimate cleanups that drop coverage (deleting a tested function along with its test, removing dead-but-tested code), opt out by adding [skip-cov] anywhere in the commit-message subject of the PR's HEAD commit. The CI step reads git log -1 --pretty=s and sets SKIP_COV=1 on a match; the delta script then emits a "Skipped" table and exits 0.
The opt-out is intended to be rare. Two consecutive [skip-cov] PRs that aren't paired with test cleanups should prompt review of whether the gate is calibrated correctly (or whether something has rotted).
You don't. The baseline is whatever the latest green main push produced — there is no baseline.json to bump. This is deliberate: the gate is anchored to actual reality, not to a stored aspiration that can age out of alignment.
If a refactor needs to drop coverage and the team agrees that's fine, the PR carries [skip-cov] and lands. The next push to main republishes the (lower) baseline, and subsequent PRs are compared against that.
Exit code is the gate verdict; coverage/delta.md is what CI would post as a comment.
src/ rollup. A PR that improves src/json.c by 3 pp while regressing src/schema.c by 0.5 pp passes as long as the rollup nets above the threshold. Per-file gating is too noisy and too easy to game.make coverage already excludes them via the lcov + gcovr filter chain.Makefile — the coverage target produces the inputsscripts/coverage-delta.sh — the comparator