2.1 KiB · text History fe05dfe
#!/bin/sh
# gitgud-prereceive — invoked by pre-receive in each bare repo.
#
# Reads `<old> <new> <ref>` lines from stdin and POSTs them to the
# Phoenix node for branch-protection evaluation. If Phoenix says DENY,
# we print the reason on stderr (visible to the pushing client) and
# exit non-zero so git aborts the push.
#
# **Fail-closed**: if the protection backend is unreachable (curl
# missing, Phoenix down, DNS broken, etc.), the push is REJECTED.
# Better to refuse than to silently bypass branch protection. Operator
# can override by setting `GITGUD_PREHOOK_FAIL_OPEN=1` if they
# explicitly want fail-open behavior (e.g. during an emergency
# unblock).

set -eu

GITGUD_PREHOOK_URL="${GITGUD_PREHOOK_URL:-http://127.0.0.1:4000/_hooks/pre-receive}"
REPO_PATH="${GIT_DIR:-$(pwd)}"
REPO_PATH="$(cd "$REPO_PATH" && pwd)"

STDIN_PAYLOAD="$(cat)"

if ! command -v curl >/dev/null 2>&1; then
  echo "gitgud: curl not installed; cannot reach protection backend" >&2
  if [ "${GITGUD_PREHOOK_FAIL_OPEN:-}" = "1" ]; then
    echo "gitgud: GITGUD_PREHOOK_FAIL_OPEN=1 — allowing push anyway" >&2
    exit 0
  fi
  exit 1
fi

# The node's hook secret (GitGudWeb.Plugs.HookAuth), inherited from the
# git process that runs this hook. Fed to curl on stdin rather than as
# an argument, so it doesn't show up in `ps`.
RESP=$(printf 'x-gitgud-hook-token: %s\n' "${GITGUD_HOOK_SECRET:-}" | curl -sf -X POST \
  -H @- \
  -H "content-type: text/plain" \
  -H "x-repo-path: ${REPO_PATH}" \
  --data-binary "${STDIN_PAYLOAD}" \
  "${GITGUD_PREHOOK_URL}" 2>/dev/null) || {
    echo "gitgud: protection backend unreachable at ${GITGUD_PREHOOK_URL}" >&2
    if [ "${GITGUD_PREHOOK_FAIL_OPEN:-}" = "1" ]; then
      echo "gitgud: GITGUD_PREHOOK_FAIL_OPEN=1 — allowing push anyway" >&2
      exit 0
    fi
    echo "gitgud: refusing push (branch protection cannot be evaluated)" >&2
    exit 1
  }

STATUS=$(printf '%s' "$RESP" | head -n1 | awk '{print $1}')
REASON=$(printf '%s' "$RESP" | tail -n +2)

if [ "$STATUS" = "OK" ]; then
  exit 0
fi

echo "gitgud: push denied" >&2
printf '%s\n' "$REASON" >&2
exit 1