#!/bin/bash # Enhanced pre-commit checks with parallel execution for speed # This script runs multiple checks efficiently on staged files only set -e echo "🚀 Running pre-commit checks..." # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Function to print colored output print_status() { echo -e "${BLUE}[PRE-COMMIT]${NC} $1" } print_success() { echo -e "${GREEN}✅${NC} $1" } print_error() { echo -e "${RED}❌${NC} $1" } print_warning() { echo -e "${YELLOW}⚠️${NC} $1" } # Check if there are any staged files STAGED_FILES=$(git diff --cached --name-only) if [ -z "$STAGED_FILES" ]; then print_warning "No staged files found" exit 0 fi print_status "Found $(echo "$STAGED_FILES" | wc -l) staged files" # Create temporary directory for parallel job management TEMP_DIR=$(mktemp -d) trap "rm -rf $TEMP_DIR" EXIT # Function to run a command and capture its output run_check() { local name="$1" local command="$2" local output_file="$TEMP_DIR/$name.out" local error_file="$TEMP_DIR/$name.err" { echo "Running: $command" eval "$command" > "$output_file" 2> "$error_file" echo $? > "$TEMP_DIR/$name.exit" } & echo $! > "$TEMP_DIR/$name.pid" } # Start parallel checks print_status "Starting parallel checks..." # 1. Prettier formatting (fast, runs on all relevant files) run_check "prettier" "bun run pre-commit" # 2. ESLint on staged JS/TS files only STAGED_JS_TS_FILES=$(echo "$STAGED_FILES" | grep -E '\.(js|jsx|ts|tsx)$' || true) if [ -n "$STAGED_JS_TS_FILES" ]; then run_check "eslint" "bunx eslint --fix --max-warnings 0 $STAGED_JS_TS_FILES" else echo "0" > "$TEMP_DIR/eslint.exit" echo "No JS/TS files to lint" > "$TEMP_DIR/eslint.out" fi # 3. TypeScript type checking on staged files STAGED_TS_FILES=$(echo "$STAGED_FILES" | grep -E '\.(ts|tsx)$' || true) if [ -n "$STAGED_TS_FILES" ]; then run_check "typecheck" "./scripts/type-check-staged.sh" else echo "0" > "$TEMP_DIR/typecheck.exit" echo "No TypeScript files to check" > "$TEMP_DIR/typecheck.out" fi # 4. Markdown linting on staged markdown files STAGED_MD_FILES=$(echo "$STAGED_FILES" | grep -E '\.md$' || true) if [ -n "$STAGED_MD_FILES" ]; then run_check "markdown" "bunx markdownlint-cli2 --fix $STAGED_MD_FILES || echo 'Markdown linting failed but continuing...'" else echo "0" > "$TEMP_DIR/markdown.exit" echo "No markdown files to lint" > "$TEMP_DIR/markdown.out" fi # 5. Secret scanning on staged files (optional check) if command -v secretlint > /dev/null; then run_check "secrets" "bunx secretlint $STAGED_FILES || echo 'Secret scanning failed but continuing...'" else echo "0" > "$TEMP_DIR/secrets.exit" echo "secretlint not available, skipping secret scanning" > "$TEMP_DIR/secrets.out" fi # Wait for all jobs to complete and collect results print_status "Waiting for checks to complete..." FAILED_CHECKS=() ALL_CHECKS=("prettier" "eslint" "typecheck" "markdown" "secrets") for check in "${ALL_CHECKS[@]}"; do if [ -f "$TEMP_DIR/$check.pid" ]; then wait $(cat "$TEMP_DIR/$check.pid") 2>/dev/null || true fi exit_code=$(cat "$TEMP_DIR/$check.exit" 2>/dev/null || echo "1") if [ "$exit_code" = "0" ]; then print_success "$check passed" else # For some checks, failure is not critical if [ "$check" = "secrets" ] || [ "$check" = "markdown" ]; then print_warning "$check had issues (non-critical)" if [ -f "$TEMP_DIR/$check.out" ] && [ -s "$TEMP_DIR/$check.out" ]; then echo -e "${YELLOW}$check output:${NC}" cat "$TEMP_DIR/$check.out" fi else print_error "$check failed" FAILED_CHECKS+=("$check") # Show error output if [ -f "$TEMP_DIR/$check.err" ] && [ -s "$TEMP_DIR/$check.err" ]; then echo -e "${RED}$check errors:${NC}" cat "$TEMP_DIR/$check.err" fi if [ -f "$TEMP_DIR/$check.out" ] && [ -s "$TEMP_DIR/$check.out" ]; then echo -e "${YELLOW}$check output:${NC}" cat "$TEMP_DIR/$check.out" fi fi fi done # Re-stage any files that were modified by formatters git add $STAGED_FILES 2>/dev/null || true # Final result if [ ${#FAILED_CHECKS[@]} -eq 0 ]; then print_success "All critical pre-commit checks passed! 🎉" echo "" echo "Summary of checks:" echo " ✅ Code formatting (Prettier)" echo " ✅ Code linting (ESLint)" echo " ✅ Type checking (TypeScript)" echo " ⚠️ Markdown linting (non-critical)" echo " ⚠️ Secret scanning (optional)" echo "" exit 0 else print_error "The following critical checks failed: ${FAILED_CHECKS[*]}" echo "" echo "💡 Tips to fix:" echo " - Run 'bun run lint:fix' to auto-fix linting issues" echo " - Run 'bun run format' to fix formatting issues" echo " - Run 'bun run type-check' to see detailed type errors" echo "" echo "🚨 Critical failures prevent commit. Fix these issues first." echo "" exit 1 fi