2025-07-23 18:14:43 -07:00
|
|
|
|
#!/usr/bin/env bash
|
2025-07-28 10:25:11 -07:00
|
|
|
|
#
|
2025-07-29 10:12:40 -07:00
|
|
|
|
# Install a Git pre‑commit hook that runs `kingfisher scan`.
|
|
|
|
|
|
#
|
|
|
|
|
|
# --global → install once for all repos via core.hooksPath
|
|
|
|
|
|
# --force → overwrite an existing pre‑commit hook
|
2025-07-28 10:25:11 -07:00
|
|
|
|
#
|
2025-07-23 18:14:43 -07:00
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
2025-07-28 10:25:11 -07:00
|
|
|
|
MODE="local"
|
|
|
|
|
|
FORCE=0
|
|
|
|
|
|
|
|
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
|
|
|
case "$1" in
|
|
|
|
|
|
-g|--global) MODE="global" ;;
|
|
|
|
|
|
-f|--force) FORCE=1 ;;
|
|
|
|
|
|
-h|--help)
|
|
|
|
|
|
echo "Usage: $0 [--global] [--force]" && exit 0
|
|
|
|
|
|
;;
|
|
|
|
|
|
*) echo "Unknown flag: $1" >&2; exit 1 ;;
|
|
|
|
|
|
esac
|
|
|
|
|
|
shift
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
if [[ "$MODE" == "local" ]]; then
|
|
|
|
|
|
# ensure we're inside a Git repo
|
|
|
|
|
|
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) \
|
|
|
|
|
|
|| { echo "Not inside a Git repository" >&2; exit 1; }
|
|
|
|
|
|
|
|
|
|
|
|
HOOK_DIR="$(git rev-parse --git-dir)/hooks"
|
|
|
|
|
|
else
|
|
|
|
|
|
# global: honour existing core.hooksPath or default to ~/.git-hooks
|
|
|
|
|
|
HOOK_DIR=$(git config --global --get core.hooksPath || echo "$HOME/.git-hooks")
|
|
|
|
|
|
mkdir -p "$HOOK_DIR"
|
|
|
|
|
|
|
|
|
|
|
|
# if the user hasn’t set core.hooksPath, do it now
|
|
|
|
|
|
if ! git config --global --get core.hooksPath >/dev/null; then
|
|
|
|
|
|
git config --global core.hooksPath "$HOOK_DIR"
|
|
|
|
|
|
echo "Set git config --global core.hooksPath to $HOOK_DIR"
|
|
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2025-07-23 18:14:43 -07:00
|
|
|
|
HOOK_PATH="$HOOK_DIR/pre-commit"
|
|
|
|
|
|
|
2025-07-28 10:25:11 -07:00
|
|
|
|
if [[ -e "$HOOK_PATH" && $FORCE -eq 0 ]]; then
|
|
|
|
|
|
echo "Error: $HOOK_PATH already exists. Use --force to overwrite." >&2
|
2025-07-23 18:14:43 -07:00
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2025-07-28 10:25:11 -07:00
|
|
|
|
cat >"$HOOK_PATH" <<'HOOK'
|
2025-07-23 18:14:43 -07:00
|
|
|
|
#!/usr/bin/env bash
|
2025-07-29 10:12:40 -07:00
|
|
|
|
# Git pre‑commit hook to run Kingfisher on staged changes
|
2025-07-23 18:14:43 -07:00
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
|
|
if ! command -v kingfisher >/dev/null 2>&1; then
|
|
|
|
|
|
echo "kingfisher not found in PATH" >&2
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
git diff --cached --name-only -z | \
|
2025-07-28 11:05:15 -07:00
|
|
|
|
xargs -0 --no-run-if-empty kingfisher scan --only-valid --no-update-check
|
2025-07-23 18:14:43 -07:00
|
|
|
|
status=$?
|
2025-07-29 10:12:40 -07:00
|
|
|
|
|
|
|
|
|
|
# ────────────────────────────────────────────────────────────────
|
|
|
|
|
|
# Treat Kingfisher exit‑code 200 as success (map → 0)
|
|
|
|
|
|
# ────────────────────────────────────────────────────────────────
|
|
|
|
|
|
if [[ $status -eq 200 ]]; then
|
|
|
|
|
|
status=0
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2025-08-01 09:15:24 -07:00
|
|
|
|
if [[ $status -eq 205 ]]; then
|
|
|
|
|
|
status=0
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2025-07-28 10:25:11 -07:00
|
|
|
|
if [[ $status -ne 0 ]]; then
|
2025-07-23 18:14:43 -07:00
|
|
|
|
echo "Kingfisher detected secrets in staged files. Commit aborted." >&2
|
2025-07-28 10:25:11 -07:00
|
|
|
|
exit $status
|
2025-07-23 18:14:43 -07:00
|
|
|
|
fi
|
|
|
|
|
|
HOOK
|
|
|
|
|
|
|
|
|
|
|
|
chmod +x "$HOOK_PATH"
|
2025-07-29 10:12:40 -07:00
|
|
|
|
echo "Pre‑commit hook installed to $HOOK_PATH ($MODE mode)"
|