#!/usr/bin/env bash
# Secret scan over the commits about to be pushed. Opt in per clone with:
#
#   git config core.hooksPath .githooks
#
# Self-contained on purpose: this repo has no Makefile, and a hook that
# depends on one in a sibling repo breaks the moment the repo is cloned
# anywhere else.
set -euo pipefail

cd "$(git rev-parse --show-toplevel)"

# A non-login shell — which is what git gives a hook — skips /etc/profile.d
# and never sees ~/.local/bin, where the gitleaks release tarball lands.
# Without this the scan reports "not installed" on every push.
[ -d "$HOME/.local/bin" ] && PATH="$HOME/.local/bin:$PATH"

if ! command -v gitleaks >/dev/null 2>&1; then
  echo "FAIL secrets — gitleaks not installed, so this check would be a no-op pretending to pass." >&2
  echo "     https://github.com/gitleaks/gitleaks/releases → ~/.local/bin/gitleaks" >&2
  exit 1
fi

# Scan the outgoing range, not full history. History here carries findings
# that are settled — test fixtures and vendored third-party code — and a gate
# that fails on something unfixable gets bypassed within a week. What matters
# is what is about to leave this machine.
if upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null); then
  range="$upstream..HEAD"
elif git rev-parse --verify --quiet origin/main >/dev/null; then
  range="origin/main..HEAD"
else
  range=""
fi

if [ -z "$range" ]; then
  gitleaks dir . --redact --no-banner --exit-code 1 || {
    echo "FAIL secrets — gitleaks found a credential in the working tree." >&2; exit 1; }
  exit 0
fi

[ -n "$(git log --oneline "$range" 2>/dev/null)" ] || exit 0

gitleaks git . --log-opts="$range" --redact --no-banner --exit-code 1 >/dev/null 2>&1 || {
  echo "FAIL secrets — gitleaks found a credential in the commits being pushed." >&2
  echo "     inspect (values redacted):  gitleaks git . --log-opts=\"$range\" --redact" >&2
  echo "     then remove and rotate it, or suppress deliberately:" >&2
  echo "       inline  '# gitleaks:allow  <reason>'" >&2
  echo "       or add the fingerprint to .gitleaksignore WITH a reason" >&2
  exit 1
}
echo "  ok   secrets"
