summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-10-31 18:16:41 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-10-31 18:16:41 +0000
commit3cba8487e76694da4f70bb4942faa7671d3e8b46 (patch)
treeadfed06e17f2519e54131daa57d655d9b58ba149
parent42c4c670c1d73fc19dc84405497ca59ce5e1faa7 (diff)
Gate the server too, and stop reading go test with grep
The commit hook had nine steps and not one of them touched the server. Every server change for a week -- twenty-five commits, including the ad detectors and the thing that publishes skips -- went in on somebody remembering to type "go test" and reading the output. That is exactly the habit the Gradle wrappers exist to replace, in the half of the repo nobody had wrapped. go-verify reports from exit codes and parsed `go test -json`: gofmt, build, vet and a real test count. It was watched catching both failures that look like success in a terminal -- a failing test, named; and a package that fails to compile, where go test exits non-zero with no failing test and the count silently drops from 366 to 356. 366 is a number I did not have until now, because "go test ./... | grep -v ok" cannot produce one. It runs first in the hook, because ten seconds before the Android build beats several minutes after it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
-rwxr-xr-x.githooks/pre-commit32
-rw-r--r--CLAUDE.md11
2 files changed, 34 insertions, 9 deletions
diff --git a/.githooks/pre-commit b/.githooks/pre-commit
index 4a3bcc5..9b12c78 100755
--- a/.githooks/pre-commit
+++ b/.githooks/pre-commit
@@ -9,23 +9,37 @@ fail() {
exit 1
}
-echo "== [1/9] Build =="
+# The server first, because it is the fast one: ten seconds against several minutes, so a Go
+# mistake is reported before the Android build has begun rather than after it.
+#
+# It had no gate at all until now. Twenty-five server commits went in on a human remembering to
+# type "go test" and reading the output -- the exact habit the Gradle wrappers exist to replace.
+echo "== [1/10] Server: format, build, vet, tests =="
+if [ -f server/go.mod ]; then
+ if ! /workspace/devtools/bin/go-verify server; then
+ fail "the server did not pass -- see the report above."
+ fi
+else
+ echo "pre-commit: no server module here, skipping."
+fi
+
+echo "== [2/10] Build =="
./gradlew :app:compileDebugKotlin -q
-echo "== [2/9] Tests =="
+echo "== [3/10] Tests =="
./gradlew :app:testDebugUnitTest -q
-echo "== [3/9] Static analysis: lint =="
+echo "== [4/10] Static analysis: lint =="
if ! ./gradlew :app:lintDebug -q; then
fail "lint failed -- fix all lint ERRORS before committing (warnings are fine to accumulate, see CLAUDE.md)."
fi
-echo "== [4/9] Static analysis: detekt (code-quality auditor) =="
+echo "== [5/10] Static analysis: detekt (code-quality auditor) =="
if ! ./gradlew :app:detekt -q; then
fail "detekt found new issues beyond the tracked baseline. Fix them, or if they're genuinely pre-existing debt being touched incidentally, regenerate the baseline with './gradlew :app:detektBaseline' and explain why in the commit message."
fi
-echo "== [5/9] Coverage must not decrease =="
+echo "== [6/10] Coverage must not decrease =="
./gradlew :app:jacocoTestReport -q
REPORT="app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml"
BASELINE_FILE=".coverage-baseline"
@@ -59,7 +73,7 @@ else
echo "pre-commit: coverage ${BASELINE}% -> ${CURRENT}%"
fi
-echo "== [6/9] WebView JavaScript justification =="
+echo "== [7/10] WebView JavaScript justification =="
STAGED_KT=$(git diff --cached --name-only --diff-filter=ACM -- '*.kt' || true)
if [ -n "$STAGED_KT" ]; then
for f in $STAGED_KT; do
@@ -73,14 +87,14 @@ if [ -n "$STAGED_KT" ]; then
done
fi
-echo "== [7/9] Manifest permission diff =="
+echo "== [8/10] Manifest permission diff =="
if git diff --cached --name-only | grep -q '^app/src/main/AndroidManifest.xml$'; then
if git diff --cached -- app/src/main/AndroidManifest.xml | grep -qE '^\+.*<uses-permission'; then
echo "pre-commit: WARNING -- AndroidManifest.xml adds a new <uses-permission>. Make sure the commit message says why."
fi
fi
-echo "== [8/9] Secret scan =="
+echo "== [9/10] Secret scan =="
if [ -z "${SECRET_SCAN_OVERRIDE:-}" ]; then
SECRET_HIT=$(git diff --cached -U0 -- . ':!*.lock' | grep -E '^\+' | grep -viE '^\+\+\+' | grep -E '(api[_-]?key|secret|password|token)["'\'' ]*[:=]["'\'' ]*[A-Za-z0-9_\-]{16,}' || true)
if [ -n "$SECRET_HIT" ]; then
@@ -91,7 +105,7 @@ else
echo "pre-commit: secret scan skipped (SECRET_SCAN_OVERRIDE set)"
fi
-echo "== [9/9] Exported Room schemas are append-only =="
+echo "== [10/10] Exported Room schemas are append-only =="
# A schema JSON already committed describes a database version that exists on a phone. Room
# rewrites the file for whatever version the @Database annotation declares, so editing an entity
# before bumping that number silently overwrites the record of the old shape -- and the migration
diff --git a/CLAUDE.md b/CLAUDE.md
index 4faa0f4..b5e4e5e 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -54,6 +54,7 @@ with `adb shell monkey`. Use the shared wrappers, which report from exit codes,
and a logcat capture started before launch:
```
+/workspace/devtools/bin/go-verify /workspace/listen/server
/workspace/devtools/bin/gradle-test /workspace/listen -- --rerun-tasks
/workspace/devtools/bin/gradle-report /workspace/listen detekt
/workspace/devtools/bin/android-launch-check org.terst.listen \
@@ -83,6 +84,16 @@ claims three separate times across these repos.
## Quality gate — every commit
+0. **Server** — `/workspace/devtools/bin/go-verify server` passes: gofmt clean, builds, vets,
+ and every test runs. First because it is the fast one, ten seconds against several minutes.
+
+ It had no gate at all until 2026-10-31. Twenty-five server commits went in on somebody
+ remembering to type `go test` and reading the output — the exact habit the Gradle wrappers
+ exist to replace, in the half of the repo nobody had wrapped. `go-verify` reports from exit
+ codes and parsed `go test -json`, and catches the two failures that look like success in a
+ terminal: a package whose tests fail to compile (the count silently drops) and a run where
+ nothing executed at all.
+
1. **Build** — `./gradlew compileDebugKotlin` succeeds.
2. **Tests** — `./gradlew testDebugUnitTest` passes in full.
3. **Static analysis** — `./gradlew detekt lintDebug` clean: zero lint errors, zero new detekt