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
This commit is contained in:
William Valentin
2025-09-07 12:40:57 -07:00
parent 585c526a65
commit 8fa2d3fb60
14 changed files with 492 additions and 54 deletions

170
scripts/pre-commit-checks.sh Executable file
View File

@@ -0,0 +1,170 @@
#!/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

View File

@@ -20,12 +20,12 @@ fi
# Install browser binaries
echo "🌐 Installing browser binaries..."
npx playwright install
bunx playwright install
# Install system dependencies (Linux)
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo "🐧 Installing system dependencies for Linux..."
npx playwright install-deps
bunx playwright install-deps
fi
# Create .gitignore entries for Playwright
@@ -40,7 +40,7 @@ fi
# Verify installation
echo "✅ Verifying Playwright installation..."
npx playwright --version
bunx playwright --version
echo ""
echo "🎉 Playwright setup complete!"

View File

@@ -66,7 +66,7 @@ echo -e "${YELLOW}Running initial code formatting...${NC}"
if command -v bun &> /dev/null; then
bun run format
elif command -v npm &> /dev/null; then
npm run format
bun run format
fi
# Run initial linting
@@ -74,7 +74,7 @@ echo -e "${YELLOW}Running initial linting...${NC}"
if command -v bun &> /dev/null; then
bun run lint:fix
elif command -v npm &> /dev/null; then
npm run lint:fix
bun run lint:fix
fi
# Run initial markdown linting
@@ -82,7 +82,7 @@ echo -e "${YELLOW}Running initial markdown linting...${NC}"
if command -v bun &> /dev/null; then
bun run lint:markdown:fix || echo "Markdown linting completed with warnings"
elif command -v npm &> /dev/null; then
npm run lint:markdown:fix || echo "Markdown linting completed with warnings"
bun run lint:markdown:fix || echo "Markdown linting completed with warnings"
fi
# Fix EditorConfig issues
@@ -90,7 +90,7 @@ echo -e "${YELLOW}Fixing EditorConfig issues...${NC}"
if command -v bun &> /dev/null; then
bun run fix:editorconfig || echo "EditorConfig fixes completed"
elif command -v npm &> /dev/null; then
npm run fix:editorconfig || echo "EditorConfig fixes completed"
bun run fix:editorconfig || echo "EditorConfig fixes completed"
fi
echo -e "${GREEN}✅ NodeJS-native pre-commit hooks and code formatters have been set up successfully!${NC}"

52
scripts/type-check-staged.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
# Fast TypeScript type checking for staged files only
# This script checks only the staged TypeScript files for type errors
set -e
# Get list of staged TypeScript files
STAGED_TS_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(ts|tsx)$' || true)
if [ -z "$STAGED_TS_FILES" ]; then
echo "📝 No TypeScript files staged, skipping type check"
exit 0
fi
echo "🔍 Type checking staged TypeScript files..."
# Check if we have a tsconfig.json
if [ ! -f "tsconfig.json" ]; then
echo "⚠️ No tsconfig.json found, skipping type check"
exit 0
fi
# Try using the project's existing TypeScript setup
# First, try a quick check with noEmit
if bunx tsc --noEmit --skipLibCheck --incremental false > /dev/null 2>&1; then
echo "✅ TypeScript type check passed"
exit 0
else
echo "⚠️ Full type check failed, checking individual staged files..."
# Fallback: check each staged file individually with minimal config
FAILED_FILES=()
for file in $STAGED_TS_FILES; do
if [ -f "$file" ]; then
# Basic syntax check without full type checking
if ! bunx tsc --noEmit --skipLibCheck --allowJs --jsx preserve "$file" > /dev/null 2>&1; then
FAILED_FILES+=("$file")
fi
fi
done
if [ ${#FAILED_FILES[@]} -eq 0 ]; then
echo "✅ TypeScript syntax check passed for staged files"
exit 0
else
echo "❌ TypeScript errors found in: ${FAILED_FILES[*]}"
echo "💡 Run 'bun run type-check' for detailed errors"
exit 1
fi
fi