First child of T-89. Codifies "don't make coverage worse" as a durable pre-push contract before any test-writing children land. - pubspec.yaml: new `coverage_floor: 34` key. Single source of truth for the floor; ratchets up only. - ci/coverage_gate.sh: parses coverage/lcov.info (LH/LF), reads the floor from pubspec.yaml, exits non-zero if integer-truncated measured % drops below it. Self-contained awk parser — no `lcov` CLI dependency. - ci/test.sh: flutter test now runs with --coverage, so the gate reads fresh data without an extra test invocation. Wall time delta is small and stays inside the < 90 s pre-push budget (D-29). - Makefile: new `coverage-gate` target wires the script in; `push-check` adds it as a dependency. The .githooks/pre-push hook (already wired) picks this up automatically. - .gitignore: ignore /coverage/ wholesale; the floor lives in pubspec.yaml, nothing under coverage/ is committed. Decision recorded as D-66 (decisions/testing.md). End target is 95%; reaching it is tracked as the rest of T-89's children. Co-Authored-By: Claude <noreply@anthropic.com>
51 lines
1.7 KiB
Bash
Executable File
51 lines
1.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Coverage gate — fails if total line coverage drops below the
|
|
# `coverage_floor:` value in pubspec.yaml. Driven by D-66.
|
|
#
|
|
# Reads coverage/lcov.info (generated by `flutter test --coverage`,
|
|
# which `ci/test.sh` runs as part of the fast suite). Parses the
|
|
# total LF/LH counts and compares the integer percentage against
|
|
# the floor. The floor only ratchets up — bumping it requires an
|
|
# explicit edit to pubspec.yaml committed alongside the test
|
|
# additions that earned the bump.
|
|
#
|
|
# Self-contained parser (awk) — does not depend on `lcov` being
|
|
# installed on the dev machine.
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
|
|
LCOV=coverage/lcov.info
|
|
|
|
if [[ ! -f "$LCOV" ]]; then
|
|
echo "==> coverage gate: $LCOV missing — run \`make test\` first (it writes lcov)" >&2
|
|
exit 2
|
|
fi
|
|
|
|
floor=$(awk -F: '/^coverage_floor:/ {gsub(/ /,"",$2); print $2; exit}' pubspec.yaml)
|
|
if [[ -z "$floor" ]]; then
|
|
echo "==> coverage gate: pubspec.yaml is missing coverage_floor: — see D-66" >&2
|
|
exit 2
|
|
fi
|
|
read measured measured_int < <(
|
|
awk -F: '
|
|
/^LF:/ { lf += $2 }
|
|
/^LH:/ { lh += $2 }
|
|
END {
|
|
pct = (lh / lf) * 100
|
|
printf "%.2f %d\n", pct, int(pct)
|
|
}
|
|
' "$LCOV"
|
|
)
|
|
|
|
if (( measured_int < floor )); then
|
|
echo "==> coverage gate FAIL: ${measured}% < floor ${floor}%"
|
|
echo " Add tests, or — if the drop is intentional — explain in the commit and lower the floor explicitly."
|
|
exit 1
|
|
fi
|
|
|
|
if (( measured_int > floor )); then
|
|
echo "==> coverage gate OK: ${measured}% (floor ${floor}%) — ${measured_int}% available; consider bumping coverage/floor.txt to ${measured_int}"
|
|
else
|
|
echo "==> coverage gate OK: ${measured}% (floor ${floor}%)"
|
|
fi
|