#!/bin/bash
# Install git hooks for commit message validation and pre-commit checks
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
HOOKS_DIR="$PROJECT_ROOT/.git/hooks"
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo "======================================================================="
echo "INSTALLING GIT HOOKS"
echo "======================================================================="
echo ""
# Check if this is a git repository
if [ ! -d "$PROJECT_ROOT/.git" ]; then
echo -e "${RED}Error: Not a git repository${NC}"
exit 1
fi
# Create hooks directory if it doesn't exist
mkdir -p "$HOOKS_DIR"
# ============================================================================
# Commit Message Hook
# ============================================================================
COMMIT_MSG_HOOK="$HOOKS_DIR/commit-msg"
echo "Installing commit-msg hook..."
cat > "$COMMIT_MSG_HOOK" << 'HOOK_EOF'
#!/bin/bash
# Validate commit message follows Conventional Commits format
# Get the commit message file
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Valid types
VALID_TYPES="feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert"
# Get first line
FIRST_LINE=$(echo "$COMMIT_MSG" | head -n 1)
# Skip validation for merge commits
if echo "$FIRST_LINE" | grep -q "^Merge "; then
exit 0
fi
# Skip validation for revert commits (they're auto-generated)
if echo "$FIRST_LINE" | grep -q "^Revert "; then
exit 0
fi
echo ""
echo "Validating commit message..."
# Check format
if ! echo "$FIRST_LINE" | grep -qE "^($VALID_TYPES)(\(.+\))?: .+"; then
echo -e "${RED}✗ Invalid commit message format${NC}"
echo ""
echo "Expected format:"
echo " <type>(<scope>): <description>"
echo " or"
echo " <type>: <description>"
echo ""
echo "Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
echo ""
echo "Examples:"
echo " feat(mcp): add assess_workload tool"
echo " fix(monitor): resolve race condition"
echo " docs: update readme"
echo ""
echo "Your message:"
echo " $FIRST_LINE"
echo ""
exit 1
fi
# Check length
LINE_LENGTH=${#FIRST_LINE}
if [ "$LINE_LENGTH" -gt 72 ]; then
echo -e "${RED}✗ Commit message too long${NC}"
echo " Length: $LINE_LENGTH (max 72)"
echo " Shorten your description"
echo ""
exit 1
fi
echo -e "${GREEN}✓ Commit message valid${NC}"
echo ""
exit 0
HOOK_EOF
chmod +x "$COMMIT_MSG_HOOK"
echo -e "${GREEN}✓ Installed commit-msg hook${NC}"
echo ""
# ============================================================================
# Pre-Commit Hook
# ============================================================================
PRE_COMMIT_HOOK="$HOOKS_DIR/pre-commit"
echo "Installing pre-commit hook..."
cat > "$PRE_COMMIT_HOOK" << 'HOOK_EOF'
#!/bin/bash
# Pre-commit validations
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo ""
echo "Running pre-commit checks..."
# 1. Check for syntax errors in Python files
if git diff --cached --name-only | grep '\.py$' > /dev/null; then
echo "Checking Python syntax..."
for file in $(git diff --cached --name-only | grep '\.py$'); do
if [ -f "$file" ]; then
python -m py_compile "$file" 2>&1
if [ $? -ne 0 ]; then
echo -e "${RED}✗ Syntax error in $file${NC}"
exit 1
fi
fi
done
echo -e "${GREEN}✓ Python syntax OK${NC}"
fi
# 2. Check for large files (>1MB)
echo "Checking file sizes..."
large_files=$(git diff --cached --name-only | while read file; do
if [ -f "$file" ]; then
size=$(wc -c < "$file")
if [ "$size" -gt 1048576 ]; then
echo "$file ($((size/1024))KB)"
fi
fi
done)
if [ -n "$large_files" ]; then
echo -e "${YELLOW}⚠ Warning: Large files detected:${NC}"
echo "$large_files"
echo ""
read -p "Continue anyway? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
# 3. Check for common issues
echo "Checking for common issues..."
# Debug statements
if git diff --cached | grep -E "(console\.log|debugger|import pdb|breakpoint\(\))" > /dev/null; then
echo -e "${YELLOW}⚠ Warning: Debug statements found${NC}"
echo " Remove console.log, debugger, pdb, or breakpoint() calls"
echo ""
git diff --cached | grep -n -E "(console\.log|debugger|import pdb|breakpoint\(\))"
echo ""
read -p "Continue anyway? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
# TODO comments being added
if git diff --cached | grep -E "^\+.*TODO" > /dev/null; then
echo -e "${YELLOW}⚠ Info: TODO comments added${NC}"
fi
# 4. Check version consistency (if version files changed)
if git diff --cached --name-only | grep -E "(pyproject\.toml|src/amicus/__init__\.py)" > /dev/null; then
echo "Checking version consistency..."
if [ -f "scripts/validate_version.sh" ]; then
bash scripts/validate_version.sh > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo -e "${RED}✗ Version inconsistency detected${NC}"
echo " Run: ./scripts/validate_version.sh"
exit 1
fi
echo -e "${GREEN}✓ Version consistency OK${NC}"
fi
fi
echo -e "${GREEN}✓ Pre-commit checks passed${NC}"
echo ""
exit 0
HOOK_EOF
chmod +x "$PRE_COMMIT_HOOK"
echo -e "${GREEN}✓ Installed pre-commit hook${NC}"
echo ""
# ============================================================================
# Prepare Commit Message Hook (provides template)
# ============================================================================
PREPARE_COMMIT_MSG_HOOK="$HOOKS_DIR/prepare-commit-msg"
echo "Installing prepare-commit-msg hook..."
cat > "$PREPARE_COMMIT_MSG_HOOK" << 'HOOK_EOF'
#!/bin/bash
# Provide commit message template for non-merge commits
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
# Only add template for new commits (not amend, merge, etc.)
if [ -z "$COMMIT_SOURCE" ]; then
# Check if message is empty
if ! grep -q '[^[:space:]]' "$COMMIT_MSG_FILE"; then
cat > "$COMMIT_MSG_FILE" << 'TEMPLATE'
# <type>(<scope>): <description>
#
# [optional body]
#
# [optional footer]
#
# Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
# Scopes: mcp, cluster, config, monitor, security, cli, docs, validation, prompts
#
# Examples:
# feat(mcp): add assess_workload tool
# fix(monitor): resolve race condition
# docs: update readme with examples
#
# Remember:
# - Use imperative mood: "add" not "added"
# - Don't capitalize first letter
# - No period at end
# - Max 72 characters
TEMPLATE
fi
fi
HOOK_EOF
chmod +x "$PREPARE_COMMIT_MSG_HOOK"
echo -e "${GREEN}✓ Installed prepare-commit-msg hook${NC}"
echo ""
# ============================================================================
# Summary
# ============================================================================
echo "======================================================================="
echo -e "${GREEN}✓✓✓ GIT HOOKS INSTALLED ✓✓✓${NC}"
echo "======================================================================="
echo ""
echo "Installed hooks:"
echo " - commit-msg: Validates commit message format"
echo " - pre-commit: Checks syntax, file sizes, common issues"
echo " - prepare-commit-msg: Provides commit message template"
echo ""
echo "These hooks will:"
echo " ✓ Enforce Conventional Commits format"
echo " ✓ Check Python syntax before commit"
echo " ✓ Warn about large files and debug statements"
echo " ✓ Validate version consistency"
echo " ✓ Provide commit message templates"
echo ""
echo "To bypass hooks (emergency only):"
echo " git commit --no-verify"
echo ""
echo "To uninstall hooks:"
echo " rm .git/hooks/commit-msg .git/hooks/pre-commit .git/hooks/prepare-commit-msg"
echo ""