install ratcheting line-coverage gate at 34% floor (T-90)
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>
This commit is contained in:
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/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
|
||||
+2
-2
@@ -14,5 +14,5 @@ dart format --set-exit-if-changed .
|
||||
echo "==> dart test (forkpty — incompatible with flutter test runner)"
|
||||
dart test --tags forkpty test/pty/session_test.dart
|
||||
|
||||
echo "==> flutter test (unit + widget + golden)"
|
||||
flutter test --exclude-tags forkpty
|
||||
echo "==> flutter test --coverage (unit + widget + golden)"
|
||||
flutter test --coverage --exclude-tags forkpty
|
||||
|
||||
Reference in New Issue
Block a user