feat(coverage): add configurable coverage thresholds (#35056)
Teams that gate CI on coverage had no way to make Deno fail when
coverage dropped below a target; `deno coverage` and `deno test --coverage`
always exited zero regardless of the numbers. This was the long-standing ask in
issues #9669 and #29076.
This adds a minimum-coverage threshold that exits non-zero when unmet.
`deno coverage --threshold=<percent>` and `deno test --coverage
--coverage-threshold=<percent>` apply one percentage to line, branch,
and function coverage. For finer control, a `coverage` section in deno.json
sets per-metric thresholds, modelled on Vitest's `coverage.thresholds`:
{
"coverage": {
"thresholds": { "lines": 90, "branches": 80, "functions": 90 }
}
}
When the CLI flag is given it applies its single value to all three
metrics, overriding whatever the config sets for each. With no flag, the
per-metric config is honored by both `deno coverage` and `deno test --coverage`.
The check runs against the aggregate across all reported files, and reuses
the same accumulation the summary reporter prints so the checked numbers
match the displayed ones. A metric with no configured threshold is not checked
(e.g. a `branches` threshold passes vacuously for files that have no
branches), and a malformed or out-of-range `coverage` config is a hard
error rather than being silently ignored.
CLI flags take integer percentages in 0-100 (validated by the parser);
the deno.json config accepts fractional values in 0-100 for finer per-metric
targets. Per-file thresholds (Vitest's `perFile`) are not included here
and could be a follow-up.
Closes #9669
Closes #29076