#!/bin/bash # Pre-commit hook for monorepo quality checks # Install: ./scripts/setup-hooks.sh set -e RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color echo "Running pre-commit checks..." # Get staged files STAGED_GO_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.go$' || true) STAGED_TS_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(ts|tsx|js|jsx)$' || true) ERRORS=0 # ============================================ # 1. File Length Check (500 lines max) # ============================================ echo "Checking file lengths..." for file in $STAGED_GO_FILES $STAGED_TS_FILES; do if [ -f "$file" ]; then LINE_COUNT=$(wc -l < "$file" | tr -d ' ') if [ "$LINE_COUNT" -gt 500 ]; then echo -e "${RED}ERROR: $file has $LINE_COUNT lines (max 500)${NC}" ERRORS=$((ERRORS + 1)) fi fi done # ============================================ # 2. Go Checks (if Go files are staged) # ============================================ if [ -n "$STAGED_GO_FILES" ]; then echo "Running Go checks..." # gofmt echo " - gofmt..." GOFMT_OUTPUT=$(gofmt -l $STAGED_GO_FILES 2>&1 || true) if [ -n "$GOFMT_OUTPUT" ]; then echo -e "${YELLOW}Auto-fixing gofmt issues...${NC}" gofmt -w $STAGED_GO_FILES git add $STAGED_GO_FILES fi # goimports (if available) if command -v goimports &> /dev/null; then echo " - goimports..." GOIMPORTS_OUTPUT=$(goimports -l $STAGED_GO_FILES 2>&1 || true) if [ -n "$GOIMPORTS_OUTPUT" ]; then echo -e "${YELLOW}Auto-fixing goimports issues...${NC}" goimports -w $STAGED_GO_FILES git add $STAGED_GO_FILES fi fi # golangci-lint (if available) if command -v golangci-lint &> /dev/null; then echo " - golangci-lint..." # Get unique directories with Go files DIRS=$(echo "$STAGED_GO_FILES" | xargs -n1 dirname | sort -u) for dir in $DIRS; do if ! golangci-lint run "$dir/..." --fast 2>/dev/null; then echo -e "${RED}golangci-lint found issues in $dir${NC}" ERRORS=$((ERRORS + 1)) fi done fi # go vet echo " - go vet..." if ! go vet ./... 2>/dev/null; then echo -e "${RED}go vet found issues${NC}" ERRORS=$((ERRORS + 1)) fi fi # ============================================ # 3. TypeScript/JavaScript Checks # ============================================ if [ -n "$STAGED_TS_FILES" ]; then echo "Running TypeScript checks..." # Get component directories with TS files TS_DIRS=$(echo "$STAGED_TS_FILES" | xargs -n1 dirname | sort -u | grep -E '^apps/' | cut -d'/' -f1-2 | sort -u || true) for dir in $TS_DIRS; do if [ -f "$dir/package.json" ]; then # Use subshell to automatically restore directory on exit ( cd "$dir" # Get files relative to this component directory COMPONENT_FILES=$(echo "$STAGED_TS_FILES" | grep "^$dir/" | xargs) # prettier (if available) if [ -f "node_modules/.bin/prettier" ] || command -v prettier &> /dev/null; then echo " - prettier in $dir..." npx prettier --write $COMPONENT_FILES 2>/dev/null || true fi # eslint (if available) if [ -f "node_modules/.bin/eslint" ] || command -v eslint &> /dev/null; then echo " - eslint in $dir..." if ! npx eslint --fix $COMPONENT_FILES 2>/dev/null; then echo -e "${RED}eslint found issues in $dir${NC}" # Note: ERRORS can't propagate from subshell, so we exit with error exit 1 fi fi ) || ERRORS=$((ERRORS + 1)) fi done # Re-add auto-fixed files for file in $STAGED_TS_FILES; do if [ -f "$file" ]; then git add "$file" fi done fi # ============================================ # 4. Final Result # ============================================ if [ $ERRORS -gt 0 ]; then echo -e "${RED}Pre-commit checks failed with $ERRORS error(s)${NC}" exit 1 fi echo -e "${GREEN}Pre-commit checks passed!${NC}" exit 0