chore(gate): every lane reports how long it took, and a run can log the times for comparison

This commit is contained in:
2026-10-16 00:13:47 +02:00
parent 08a9f4e255
commit 011f269152
2 changed files with 57 additions and 8 deletions
+31 -4
View File
@@ -9,6 +9,8 @@
# bash scripts/check.sh lint the static lanes only: no tests, no build, no audits
# … --brief (either mode) a lane's output only when it fails, and only its first
# error lines — for an agent, whose context the full log would flood
# GATE_TIMES_FILE=<file> … also append each lane's time as a TSV row (UTC, mode, lane, seconds,
# ok|red, HEAD's tree) — to compare runs; every run prints the times anyway
#
# Each lane runs even when an earlier one failed, and the summary names every red one: a gate that
# stops at the first failure hides the second until the first is fixed. The backend lanes run in the
@@ -29,21 +31,42 @@ done
export MSYS_NO_PATHCONV=1 # Git Bash: do not rewrite the in-container paths below
TESTCOMPOSE=backend/docker-compose.test.yml
failed=()
timings=()
ms() { date +%s%3N; }
secs() { awk -v t="$1" 'BEGIN { printf "%.1f", t / 1000 }'; }
# How long each lane took: a line after the lane, a table at the end, and — when GATE_TIMES_FILE names a
# file — one tab-separated row per lane appended to it (UTC time, mode, lane, seconds, ok|red, tree), so
# runs can be compared. The script writes no file unless asked to.
took=""
timed() { # timed <name> <ok|red> <start-ms> — sets $took (no subshell: it must add to $timings)
took="$(secs $(($(ms) - $3)))"
timings+=("$(printf '%8s s %s' "$took" "$1")$([ "$2" = red ] && echo ' (red)')")
if [ -n "${GATE_TIMES_FILE:-}" ]; then
printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$(date -u +%FT%TZ)" "$mode" "$1" "$took" "$2" \
"$(git rev-parse --short 'HEAD^{tree}' 2>/dev/null)" >>"$GATE_TIMES_FILE"
fi
return 0
}
lane() { # lane <name> <command…> — run it, remember a failure, never stop
local name="$1"
local name="$1" t0 result=ok
shift
t0="$(ms)"
if [ "$brief" = 0 ]; then
echo ">> $name…"
"$@" || failed+=("$name")
"$@" || { failed+=("$name"); result=red; }
timed "$name" "$result" "$t0"
echo "<< $name: $took s"
return 0
fi
local out
out="$(mktemp)"
if "$@" >"$out" 2>&1; then
echo ">> $name: ok"
timed "$name" ok "$t0"
echo ">> $name: ok ($took s)"
else
failed+=("$name")
echo ">> $name: FAILED"
timed "$name" red "$t0"
echo ">> $name: FAILED ($took s)"
brief_excerpt "$out"
fi
rm -f "$out"
@@ -102,6 +125,7 @@ basedpyright() {
frontend() { (cd frontend && "$@"); }
gate_t0="$(ms)"
lane "ruff" ruff_check
lane "ruff format --check" ruff_format
lane "basedpyright (new errors only)" basedpyright
@@ -139,6 +163,9 @@ if [ "$mode" = all ]; then
lane "npm audit (production dependencies)" frontend npm audit --omit=dev --audit-level=high
fi
echo ">> lane times:"
printf '%s\n' "${timings[@]}"
echo "$(printf '%8s' "$(secs $(($(ms) - gate_t0)))") s total"
if [ ${#failed[@]} -eq 0 ]; then
echo ">> gate ($mode): green ✓"
exit 0