chore(gate): every lane reports how long it took, and a run can log the times for comparison
This commit is contained in:
@@ -1307,21 +1307,39 @@
|
|||||||
"export MSYS_NO_PATHCONV=1 # Git Bash: do not rewrite the in-container paths below",
|
"export MSYS_NO_PATHCONV=1 # Git Bash: do not rewrite the in-container paths below",
|
||||||
"TESTCOMPOSE=backend/docker-compose.test.yml",
|
"TESTCOMPOSE=backend/docker-compose.test.yml",
|
||||||
"failed=()",
|
"failed=()",
|
||||||
|
"timings=()",
|
||||||
|
"ms() { date +%s%3N; }",
|
||||||
|
"secs() { awk -v t=\"$1\" 'BEGIN { printf \"%.1f\", t / 1000 }'; }",
|
||||||
|
"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",
|
"lane() { # lane <name> <command…> — run it, remember a failure, never stop",
|
||||||
" local name=\"$1\"",
|
" local name=\"$1\" t0 result=ok",
|
||||||
" shift",
|
" shift",
|
||||||
|
" t0=\"$(ms)\"",
|
||||||
" if [ \"$brief\" = 0 ]; then",
|
" if [ \"$brief\" = 0 ]; then",
|
||||||
" echo \">> $name…\"",
|
" echo \">> $name…\"",
|
||||||
" \"$@\" || failed+=(\"$name\")",
|
" \"$@\" || { failed+=(\"$name\"); result=red; }",
|
||||||
|
" timed \"$name\" \"$result\" \"$t0\"",
|
||||||
|
" echo \"<< $name: $took s\"",
|
||||||
" return 0",
|
" return 0",
|
||||||
" fi",
|
" fi",
|
||||||
" local out",
|
" local out",
|
||||||
" out=\"$(mktemp)\"",
|
" out=\"$(mktemp)\"",
|
||||||
" if \"$@\" >\"$out\" 2>&1; then",
|
" if \"$@\" >\"$out\" 2>&1; then",
|
||||||
" echo \">> $name: ok\"",
|
" timed \"$name\" ok \"$t0\"",
|
||||||
|
" echo \">> $name: ok ($took s)\"",
|
||||||
" else",
|
" else",
|
||||||
" failed+=(\"$name\")",
|
" failed+=(\"$name\")",
|
||||||
" echo \">> $name: FAILED\"",
|
" timed \"$name\" red \"$t0\"",
|
||||||
|
" echo \">> $name: FAILED ($took s)\"",
|
||||||
" brief_excerpt \"$out\"",
|
" brief_excerpt \"$out\"",
|
||||||
" fi",
|
" fi",
|
||||||
" rm -f \"$out\"",
|
" rm -f \"$out\"",
|
||||||
@@ -1361,6 +1379,7 @@
|
|||||||
" return 1",
|
" return 1",
|
||||||
"}",
|
"}",
|
||||||
"frontend() { (cd frontend && \"$@\"); }",
|
"frontend() { (cd frontend && \"$@\"); }",
|
||||||
|
"gate_t0=\"$(ms)\"",
|
||||||
"lane \"ruff\" ruff_check",
|
"lane \"ruff\" ruff_check",
|
||||||
"lane \"ruff format --check\" ruff_format",
|
"lane \"ruff format --check\" ruff_format",
|
||||||
"lane \"basedpyright (new errors only)\" basedpyright",
|
"lane \"basedpyright (new errors only)\" basedpyright",
|
||||||
@@ -1387,6 +1406,9 @@
|
|||||||
" lane \"pip-audit (backend lock)\" pip_audit",
|
" lane \"pip-audit (backend lock)\" pip_audit",
|
||||||
" lane \"npm audit (production dependencies)\" frontend npm audit --omit=dev --audit-level=high",
|
" lane \"npm audit (production dependencies)\" frontend npm audit --omit=dev --audit-level=high",
|
||||||
"fi",
|
"fi",
|
||||||
|
"echo \">> lane times:\"",
|
||||||
|
"printf '%s\\n' \"${timings[@]}\"",
|
||||||
|
"echo \"$(printf '%8s' \"$(secs $(($(ms) - gate_t0)))\") s total\"",
|
||||||
"if [ ${#failed[@]} -eq 0 ]; then",
|
"if [ ${#failed[@]} -eq 0 ]; then",
|
||||||
" echo \">> gate ($mode): green ✓\"",
|
" echo \">> gate ($mode): green ✓\"",
|
||||||
" exit 0",
|
" exit 0",
|
||||||
|
|||||||
+31
-4
@@ -9,6 +9,8 @@
|
|||||||
# bash scripts/check.sh lint the static lanes only: no tests, no build, no audits
|
# 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
|
# … --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
|
# 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
|
# 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
|
# 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
|
export MSYS_NO_PATHCONV=1 # Git Bash: do not rewrite the in-container paths below
|
||||||
TESTCOMPOSE=backend/docker-compose.test.yml
|
TESTCOMPOSE=backend/docker-compose.test.yml
|
||||||
failed=()
|
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
|
lane() { # lane <name> <command…> — run it, remember a failure, never stop
|
||||||
local name="$1"
|
local name="$1" t0 result=ok
|
||||||
shift
|
shift
|
||||||
|
t0="$(ms)"
|
||||||
if [ "$brief" = 0 ]; then
|
if [ "$brief" = 0 ]; then
|
||||||
echo ">> $name…"
|
echo ">> $name…"
|
||||||
"$@" || failed+=("$name")
|
"$@" || { failed+=("$name"); result=red; }
|
||||||
|
timed "$name" "$result" "$t0"
|
||||||
|
echo "<< $name: $took s"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
local out
|
local out
|
||||||
out="$(mktemp)"
|
out="$(mktemp)"
|
||||||
if "$@" >"$out" 2>&1; then
|
if "$@" >"$out" 2>&1; then
|
||||||
echo ">> $name: ok"
|
timed "$name" ok "$t0"
|
||||||
|
echo ">> $name: ok ($took s)"
|
||||||
else
|
else
|
||||||
failed+=("$name")
|
failed+=("$name")
|
||||||
echo ">> $name: FAILED"
|
timed "$name" red "$t0"
|
||||||
|
echo ">> $name: FAILED ($took s)"
|
||||||
brief_excerpt "$out"
|
brief_excerpt "$out"
|
||||||
fi
|
fi
|
||||||
rm -f "$out"
|
rm -f "$out"
|
||||||
@@ -102,6 +125,7 @@ basedpyright() {
|
|||||||
|
|
||||||
frontend() { (cd frontend && "$@"); }
|
frontend() { (cd frontend && "$@"); }
|
||||||
|
|
||||||
|
gate_t0="$(ms)"
|
||||||
lane "ruff" ruff_check
|
lane "ruff" ruff_check
|
||||||
lane "ruff format --check" ruff_format
|
lane "ruff format --check" ruff_format
|
||||||
lane "basedpyright (new errors only)" basedpyright
|
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
|
lane "npm audit (production dependencies)" frontend npm audit --omit=dev --audit-level=high
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo ">> lane times:"
|
||||||
|
printf '%s\n' "${timings[@]}"
|
||||||
|
echo "$(printf '%8s' "$(secs $(($(ms) - gate_t0)))") s total"
|
||||||
if [ ${#failed[@]} -eq 0 ]; then
|
if [ ${#failed[@]} -eq 0 ]; then
|
||||||
echo ">> gate ($mode): green ✓"
|
echo ">> gate ($mode): green ✓"
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user