Files
rxminder/scripts/pre-commit-checks.sh
William Valentin 8fa2d3fb60 feat: Switch project tooling from npm to bun and add enhanced pre-commit
checks

- Replace npm commands with bun/bunx in scripts, docs, and CI - Add
enhanced pre-commit checks with parallel execution - Document pre-commit
hook behavior in PRE_COMMIT_HOOKS.md - Update .gitignore/.dockerignore
for bun-debug.log - Refine ESLint config for bun and Prettier
integration - Add scripts/type-check-staged.sh for fast staged type
checks - Improve developer workflow and code quality automation
2025-09-07 12:40:57 -07:00

171 lines
5.1 KiB
Bash
Executable File

#!/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