#!/usr/bin/env bash # Enforce the coverage ratchet: total statement coverage must not regress # below a floor. # # This is a regression GUARD, not a vanity target -- deleting a covered test # or adding uncovered code below the floor fails CI. The floor sits just below # the measured current total (with a small noise margin) and is raised as the # foundation test net grows; never chase the number for its own sake. # # Reads coverage.out (produced by `make cover`) and compares its total against # FLOOR below. awk does the float compare so there is no `bc` dependency. # # Run locally: make cover-check (or: make cover && bash scripts/check-coverage.sh) # CI: the `coverage` step in .github/workflows/ci.yml runs `make cover-check`. set -euo pipefail # Ratchet floor, not a target. Raised 80 -> 83 at H1 close (measured total # 84.8%); raise again as the net grows -- keep it below total with a margin. FLOOR=83 ROOT="$(cd "$(dirname "$0")/.." && pwd)" PROFILE="$ROOT/coverage.out" if [ ! -f "$PROFILE" ]; then echo "check-coverage: $PROFILE not found -- run \`make cover\` first" >&2 exit 1 fi total="$(go tool cover -func="$PROFILE" | awk '/^total:/ {print $NF}' | tr -d '%')" if [ -z "$total" ]; then echo "check-coverage: could not parse total coverage from $PROFILE" >&2 exit 1 fi if ! awk -v t="$total" -v f="$FLOOR" 'BEGIN { exit !(t+0 >= f+0) }'; then echo "check-coverage: total ${total}% is below floor ${FLOOR}% -- add tests or justify" >&2 exit 1 fi echo "check-coverage: total ${total}% >= floor ${FLOOR}% -- ratchet holds"