Skip to content

Commit 3dda494

Browse files
committed
chore(hooks): track git hooks via core.hooksPath
Hooks lived in untracked .git/hooks -- invisible to git, absent from fresh clones. Also guards the secret scan against an empty staged list (BSD xargs false positive).
1 parent 65e2506 commit 3dda494

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

scripts/hooks/pre-commit

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
# Tracked pre-commit hook. Activated by scripts/setup.sh (git config core.hooksPath scripts/hooks).
3+
# Local convenience only -- CI runs gitleaks server-side where it cannot be skipped.
4+
5+
# Shadow-hook warning. core.hooksPath makes git ignore .git/hooks/ entirely, so an edit
6+
# landing there is silently dead -- enforcement disappears with no error.
7+
if [ -e ".git/hooks/pre-commit" ]; then
8+
echo "warning: .git/hooks/pre-commit exists but is SHADOWED by core.hooksPath=scripts/hooks." >&2
9+
echo " Git is not running it. Port anything it contains here, then delete it." >&2
10+
fi
11+
12+
# Staged-secret scan.
13+
# The [ -n ] guard is load-bearing. BSD xargs runs its command once even on empty input,
14+
# so an empty staged list became `grep -lE pattern` with no file operands, which reads
15+
# stdin, hits EOF and exits 0 -- reported to the user as "secrets detected" on a commit
16+
# staging nothing. A scanner that cries wolf teaches --no-verify, which disarms it entirely.
17+
patterns="password\s*[=:]\s*['\"][^'\"]{8,}['\"]|secret\s*[=:]\s*['\"][^'\"]{16,}['\"]|token\s*[=:]\s*['\"][^'\"]{20,}['\"]"
18+
staged=$(git diff --cached --name-only --diff-filter=ACM)
19+
if [ -n "$staged" ] && echo "$staged" | xargs grep -lE "$patterns" 2>/dev/null; then
20+
echo "Potential secrets detected in commit"
21+
echo "Review files and remove sensitive data"
22+
exit 1
23+
fi

scripts/setup.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
# Repo bootstrap -- run once per clone/machine. Idempotent.
3+
#
4+
# This file is duplicated across repos on purpose: a fresh clone has to bootstrap itself
5+
# with no sibling checkout present, so a shared copy would defeat the point.
6+
set -euo pipefail
7+
cd "$(git rev-parse --show-toplevel)"
8+
9+
echo "==> Git hooks (core.hooksPath -> scripts/hooks)"
10+
git config core.hooksPath scripts/hooks
11+
chmod +x scripts/hooks/*
12+
echo " active: $(ls scripts/hooks | tr '\n' ' ')"
13+
14+
# Anything left in .git/hooks/ is now dead weight that still looks alive. Editing it is a
15+
# silent no-op -- report it rather than let the next edit vanish into it.
16+
shadowed=$(ls .git/hooks 2>/dev/null | grep -v '\.sample$' || true)
17+
if [ -n "$shadowed" ]; then
18+
echo " [warn] shadowed by hooksPath, git ignores these: $(echo "$shadowed" | tr '\n' ' ')"
19+
echo " port any real checks into scripts/hooks/, then: rm .git/hooks/<name>"
20+
fi
21+
22+
echo "==> Setup complete."

0 commit comments

Comments
 (0)