Skip to content

Commit 2aa5d1b

Browse files
committed
chore(hooks): add husky pre-push type-check gate
The local dev build (tsup/esbuild) only transpiles and skips type-checking, so type errors stayed invisible locally and surfaced only in CI. Add a husky pre-push hook that runs the same tsc --noEmit as CI's lint step, failing the push locally for the same reason CI would. - husky devDependency + prepare script (installs hooks on npm install) - .husky/pre-push: tsc --noEmit gate, then an optional gitignored local scanner hook if present - .husky/pre-commit: optional local staged-scan hook only (kept light) - gitignore scripts/local/ for maintainer-only scripts
1 parent 574e92a commit 2aa5d1b

5 files changed

Lines changed: 64 additions & 1 deletion

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,6 @@ tools/
6666

6767
# Local demo assets (4K video, clips, thumbnails, launch kit) — large + local-only, never committed
6868
demo/
69+
70+
# Local-only maintainer scripts (sensitive-content scanners — contain private grep patterns, never commit)
71+
scripts/local/

.husky/pre-commit

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Pre-commit gate (committed). Intentionally light — the heavy checks
2+
# (type-check, full scan) run at push time in .husky/pre-push.
3+
#
4+
# Runs an OPTIONAL local-only scanner (scripts/local/scan-sensitive-staged.sh,
5+
# gitignored) if present — the maintainer uses it to catch private content in
6+
# staged changes before it ever lands in a commit. Absent for everyone else,
7+
# so this hook is a no-op for them.
8+
#
9+
# Bypass with `git commit --no-verify`.
10+
11+
if [ -x scripts/local/scan-sensitive-staged.sh ]; then
12+
scripts/local/scan-sensitive-staged.sh || exit 1
13+
fi

.husky/pre-push

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Pre-push gate (committed; runs for everyone who installs deps).
2+
#
3+
# 1. TypeScript type-check — matches CI's `npm run lint` (tsc --noEmit).
4+
# The local dev build uses tsup/esbuild, which ONLY transpiles and SKIPS
5+
# type-checking, so type errors stay invisible locally and surface only in
6+
# CI. This makes a local push fail for the same reason CI would, before the
7+
# error reaches the remote.
8+
#
9+
# 2. An OPTIONAL local-only scanner (scripts/local/scan-sensitive.sh, gitignored)
10+
# runs afterwards if present — used by this repo's maintainer to scan for
11+
# private content before pushing to the public mirror. Absent for everyone
12+
# else, so this hook degrades to just the type-check.
13+
#
14+
# Bypass everything with `git push --no-verify` (not recommended).
15+
16+
echo "Type-checking before push (tsc --noEmit)…"
17+
if ! npm run --silent lint; then
18+
echo ""
19+
echo "Push blocked: TypeScript errors above (CI would fail too)."
20+
echo "Fix them, or bypass with: git push --no-verify"
21+
exit 1
22+
fi
23+
echo "✓ Type-check passed."
24+
25+
# Optional local sensitive-content scanner — forward stdin (the pre-push refs).
26+
if [ -x scripts/local/scan-sensitive.sh ]; then
27+
scripts/local/scan-sensitive.sh || exit 1
28+
fi

package-lock.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
"web:build": "bash scripts/build-daemon.sh && tsup && cp -r src/data dist/ && for d in src/integrations/*/manifest.json; do cp \"$d\" \"dist/integrations/$(basename $(dirname $d))/\"; done && cd web && npx vite build",
5555
"dev:ephemeral": "npm run web:build && node dist/cli.js web --ephemeral",
5656
"dev:demo": "npm run web:build && (lsof -ti:3457 -sTCP:LISTEN | xargs kill -15 2>/dev/null || true); (cat /tmp/open-walnut-demo/daemon.pid 2>/dev/null | xargs kill -15 2>/dev/null || true); sleep 1; echo \"Demo server: http://localhost:3457 (data: $HOME/.open-walnut-demo, daemon: /tmp/open-walnut-demo — fully isolated from prod)\"; OPEN_WALNUT_HOME=\"$HOME/.open-walnut-demo\" WALNUT_DAEMON_DIR=/tmp/open-walnut-demo node dist/cli.js web --port 3457",
57-
"dev:prod": "npm run web:build && lsof -ti:3456 -sTCP:LISTEN | xargs kill -15 2>/dev/null; for i in 1 2 3 4 5 6 7 8 9 10; do lsof -ti:3456 -sTCP:LISTEN >/dev/null 2>&1 || break; sleep 0.5; done; node dist/cli.js web --port 3456 & PID=$!; for i in 1 2 3 4 5 6 7 8 9 10; do curl -sf http://localhost:3456/api/config >/dev/null 2>&1 && break || sleep 0.5; done; echo \"Server ready (PID: $PID)\""
57+
"dev:prod": "npm run web:build && lsof -ti:3456 -sTCP:LISTEN | xargs kill -15 2>/dev/null; for i in 1 2 3 4 5 6 7 8 9 10; do lsof -ti:3456 -sTCP:LISTEN >/dev/null 2>&1 || break; sleep 0.5; done; node dist/cli.js web --port 3456 & PID=$!; for i in 1 2 3 4 5 6 7 8 9 10; do curl -sf http://localhost:3456/api/config >/dev/null 2>&1 && break || sleep 0.5; done; echo \"Server ready (PID: $PID)\"",
58+
"prepare": "husky"
5859
},
5960
"dependencies": {
6061
"@anthropic-ai/bedrock-sdk": "^0.26.3",
@@ -101,6 +102,7 @@
101102
"@types/ws": "^8.18.1",
102103
"@vitest/coverage-v8": "^3.1.0",
103104
"concurrently": "^9.2.1",
105+
"husky": "^9.1.7",
104106
"patch-package": "^8.0.1",
105107
"supertest": "^7.2.2",
106108
"tsup": "^8.5.0",

0 commit comments

Comments
 (0)