#!/bin/bash # Pre-commit hook: auto-fix formatting and fast checks # Skip with: git commit --no-verify # # This hook is contextual - it only runs checks for file types that are staged. set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' BOLD='\033[1m' NC='\033[0m' # No Color # Detect which file types are staged STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR) HAS_GO_FILES=$(echo "$STAGED_FILES" | grep -E '\.go$' || true) HAS_MD_FILES=$(echo "$STAGED_FILES" | grep -E '\.md$' || true) HAS_TS_FILES=$(echo "$STAGED_FILES" | grep -E '\.(ts|tsx)$' || true) # Exit early if no relevant files are staged if [ -z "$HAS_GO_FILES" ] && [ -z "$HAS_MD_FILES" ] && [ -z "$HAS_TS_FILES" ]; then echo -e "${GREEN}✓${NC} No Go, Markdown, or TypeScript files staged, skipping checks" exit 0 fi # Header echo "" echo -e "${BLUE}╔═══════════════════════════════════════════════════╗${NC}" echo -e "${BLUE}║${NC} ${BOLD}PRE-COMMIT CHECKS${NC} ${BLUE}║${NC}" echo -e "${BLUE}╚═══════════════════════════════════════════════════╝${NC}" echo "" # Show what's being checked if [ -n "$HAS_GO_FILES" ]; then echo -e "${YELLOW}Go files staged:${NC} $(echo "$HAS_GO_FILES" | wc -l | tr -d ' ') file(s)" fi if [ -n "$HAS_MD_FILES" ]; then echo -e "${YELLOW}Markdown files staged:${NC} $(echo "$HAS_MD_FILES" | wc -l | tr -d ' ') file(s)" fi if [ -n "$HAS_TS_FILES" ]; then echo -e "${YELLOW}TypeScript files staged:${NC} $(echo "$HAS_TS_FILES" | wc -l | tr -d ' ') file(s)" fi echo "" # Track if any check fails FAILED=0 # Go checks (only if .go files are staged) if [ -n "$HAS_GO_FILES" ]; then # 1. Auto-format Go code echo -e "${YELLOW}▶${NC} Auto-formatting Go code..." if make fmt > /tmp/hook-output.txt 2>&1; then # Check if any files were modified if git diff --name-only | grep -q "\.go$"; then echo -e "${GREEN}✓${NC} Go code formatted (changes staged)" git add -u # Stage modified tracked files else echo -e "${GREEN}✓${NC} Go code already formatted" fi else echo -e "${RED}✗${NC} Go formatting failed" cat /tmp/hook-output.txt FAILED=1 fi # 2. Run go vet echo -e "${YELLOW}▶${NC} Running go vet (static analysis)..." if make vet > /tmp/hook-output.txt 2>&1; then echo -e "${GREEN}✓${NC} go vet passed" else echo -e "${RED}✗${NC} go vet failed" cat /tmp/hook-output.txt FAILED=1 fi # 3. Run golangci-lint echo -e "${YELLOW}▶${NC} Running golangci-lint..." if make lint-go > /tmp/hook-output.txt 2>&1; then echo -e "${GREEN}✓${NC} golangci-lint passed" else echo -e "${RED}✗${NC} golangci-lint failed" cat /tmp/hook-output.txt FAILED=1 fi # 4. Run gosec (high-severity security scan) — sprung here so findings # surface at commit time, not only at pre-push. echo -e "${YELLOW}▶${NC} Running gosec (security scan)..." if make gosec > /tmp/hook-output.txt 2>&1; then echo -e "${GREEN}✓${NC} gosec passed" else echo -e "${RED}✗${NC} gosec failed" cat /tmp/hook-output.txt FAILED=1 fi fi # Markdown checks (only if .md files are staged) if [ -n "$HAS_MD_FILES" ]; then echo -e "${YELLOW}▶${NC} Running markdownlint..." if make lint-md > /tmp/hook-output.txt 2>&1; then echo -e "${GREEN}✓${NC} markdownlint passed" else echo -e "${RED}✗${NC} markdownlint failed" cat /tmp/hook-output.txt FAILED=1 fi fi # TypeScript checks (only if .ts/.tsx files are staged) if [ -n "$HAS_TS_FILES" ]; then echo -e "${YELLOW}▶${NC} Running ESLint (TypeScript)..." if (cd web && pnpm lint) > /tmp/hook-output.txt 2>&1; then echo -e "${GREEN}✓${NC} ESLint passed" else echo -e "${RED}✗${NC} ESLint failed" cat /tmp/hook-output.txt FAILED=1 fi echo -e "${YELLOW}▶${NC} Running TypeScript type check (tsc --noEmit)..." if make tsc > /tmp/hook-output.txt 2>&1; then echo -e "${GREEN}✓${NC} TypeScript type check passed" else echo -e "${RED}✗${NC} TypeScript type check failed" cat /tmp/hook-output.txt FAILED=1 fi fi echo "" echo -e "${BLUE}╔═══════════════════════════════════════════════════╗${NC}" if [ $FAILED -eq 0 ]; then echo -e "${BLUE}║${NC} ${GREEN}${BOLD}✓ ALL CHECKS PASSED!${NC} ${BLUE}║${NC}" echo -e "${BLUE}╚═══════════════════════════════════════════════════╝${NC}" exit 0 else echo -e "${BLUE}║${NC} ${RED}${BOLD}✗ CHECKS FAILED${NC} ${BLUE}║${NC}" echo -e "${BLUE}╚═══════════════════════════════════════════════════╝${NC}" echo -e "${YELLOW}Fix the issues above or use --no-verify to skip${NC}" exit 1 fi