litellm/scripts/install_git_hooks.sh
Yassin Kortam 1cef88ffe5 chore(hooks): enforce Conventional Commits and Conventional Branches
Adds opt-in local git hooks plus a CI PR-title check:

- .githooks/commit-msg validates commit subjects against Conventional
  Commits 1.0.0 (feat|fix|docs|style|refactor|perf|test|build|ci|
  chore|revert)(scope)!: subject. Merge/revert/fixup!/squash!/amend!
  messages pass through; --no-verify still works.
- .githooks/pre-push validates branch names against Conventional
  Branches (feature|bugfix|hotfix|release|chore)/desc. Bypasses
  main, litellm_internal_staging, dependabot/*, gh-readonly-queue/*.
  Tag pushes and deletions are skipped.
- scripts/install_git_hooks.sh sets core.hooksPath=.githooks and is
  wired up as 'make install-hooks'. Opt-in — not chained into
  install-dev.
- .github/workflows/conventional-commits.yml validates PR titles via
  amannn/action-semantic-pull-request pinned to v6.1.1's SHA. This is
  the actual gate since squash-merge uses the PR title as the commit
  subject.
- tests/test_litellm/test_git_hooks.py exercises both hooks via
  subprocess for accept / reject / bypass / git-generated-message
  cases.
- CONTRIBUTING.md documents the conventions, the install step, the
  bypass list, and the --no-verify escape hatch.

Resolves LIT-3306

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:57:14 -07:00

38 lines
1.1 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Install the repo's git hooks by pointing core.hooksPath at .githooks.
#
# Idempotent: re-running just reaffirms the config and refreshes chmod bits.
# Run from anywhere inside the repo.
set -euo pipefail
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "install_git_hooks: not inside a git working tree" >&2
exit 1
fi
repo_root=$(git rev-parse --show-toplevel)
hooks_dir="$repo_root/.githooks"
if [ ! -d "$hooks_dir" ]; then
echo "install_git_hooks: $hooks_dir does not exist" >&2
exit 1
fi
# Ensure the hook scripts are executable. New clones on case-preserving
# filesystems sometimes lose the exec bit; this normalizes it.
chmod +x "$hooks_dir"/* 2>/dev/null || true
git config core.hooksPath .githooks
cat <<EOF
✓ Git hooks installed.
core.hooksPath = .githooks
active hooks: $(ls "$hooks_dir" | tr '\n' ' ')
These hooks enforce Conventional Commits and Conventional Branches.
Bypass with --no-verify when you need to (e.g. for emergency hotfixes).
To uninstall: git config --unset core.hooksPath
EOF