Files
prowler/ui/.husky/pre-commit

170 lines
5.9 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Prowler UI - Pre-Commit Hook
# Optionally validates ONLY staged files against AGENTS.md standards using Claude Code
# Controlled by CODE_REVIEW_ENABLED in .env
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🚀 Prowler UI - Pre-Commit Hook"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Load .env file (look in git root directory)
GIT_ROOT=$(git rev-parse --show-toplevel)
if [ -f "$GIT_ROOT/ui/.env" ]; then
CODE_REVIEW_ENABLED=$(grep "^CODE_REVIEW_ENABLED" "$GIT_ROOT/ui/.env" | cut -d'=' -f2 | tr -d ' ')
elif [ -f "$GIT_ROOT/.env" ]; then
CODE_REVIEW_ENABLED=$(grep "^CODE_REVIEW_ENABLED" "$GIT_ROOT/.env" | cut -d'=' -f2 | tr -d ' ')
elif [ -f ".env" ]; then
CODE_REVIEW_ENABLED=$(grep "^CODE_REVIEW_ENABLED" .env | cut -d'=' -f2 | tr -d ' ')
else
CODE_REVIEW_ENABLED="false"
fi
# Normalize the value to lowercase
CODE_REVIEW_ENABLED=$(echo "$CODE_REVIEW_ENABLED" | tr '[:upper:]' '[:lower:]')
echo -e "${BLUE} Code Review Status: ${CODE_REVIEW_ENABLED}${NC}"
echo ""
# Get staged files (what will be committed)
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(tsx?|jsx?)$' || true)
if [ "$CODE_REVIEW_ENABLED" = "true" ]; then
if [ -z "$STAGED_FILES" ]; then
echo -e "${YELLOW}⚠️ No TypeScript/JavaScript files staged to validate${NC}"
echo ""
else
echo -e "${YELLOW}🔍 Running Claude Code standards validation...${NC}"
echo ""
echo -e "${BLUE}📋 Files to validate:${NC}"
echo "$STAGED_FILES" | while IFS= read -r file; do echo " - $file"; done
echo ""
echo -e "${BLUE}📤 Sending to Claude Code for validation...${NC}"
echo ""
# Build prompt with full file contents
VALIDATION_PROMPT=$(
cat <<'PROMPT_EOF'
You are a code reviewer for the Prowler UI project. Analyze the full file contents of changed files below and validate they comply with AGENTS.md standards.
**RULES TO CHECK:**
1. React Imports: NO `import * as React` or `import React, {` → Use `import { useState }`
2. TypeScript: NO union types like `type X = "a" | "b"` → Use const-based: `const X = {...} as const`
3. Tailwind: NO `var()` or hex colors in className → Use Tailwind utilities and semantic color classes.
4. cn(): Use for merging multiple classes or for conditionals (handles Tailwind conflicts with twMerge) → `cn(BUTTON_STYLES.base, BUTTON_STYLES.active, isLoading && "opacity-50")`
5. React 19: NO `useMemo`/`useCallback` without reason
6. Zod v4: Use `.min(1)` not `.nonempty()`, `z.email()` not `z.string().email()`. All inputs must be validated with Zod.
7. File Org: 1 feature = local, 2+ features = shared
8. Directives: Server Actions need "use server", clients need "use client"
9. Implement DRY, KISS principles. (example: reusable components, avoid repetition)
10. Layout must work for all the responsive breakpoints (mobile, tablet, desktop)
11. ANY types cannot be used - CRITICAL: Check for `: any` in all visible lines
12. Use the components inside components/shadcn if possible
13. Check Accessibility best practices (like alt tags in images, semantic HTML, Aria labels, etc.)
=== FILES TO REVIEW ===
PROMPT_EOF
)
# Add full file contents for each staged file
for file in $STAGED_FILES; do
VALIDATION_PROMPT="$VALIDATION_PROMPT
=== FILE: $file ===
$(cat "$file" 2>/dev/null || echo "Error reading file")"
done
VALIDATION_PROMPT="$VALIDATION_PROMPT
=== END FILES ===
**IMPORTANT: Your response MUST start with exactly one of these lines:**
STATUS: PASSED
STATUS: FAILED
**If FAILED:** List each violation with File, Line Number, Rule Number, and Issue.
**If PASSED:** Confirm all files comply with AGENTS.md standards.
**Start your response now with STATUS:**"
# Send to Claude Code
if VALIDATION_OUTPUT=$(echo "$VALIDATION_PROMPT" | claude 2>&1); then
echo "$VALIDATION_OUTPUT"
echo ""
# Check result - STRICT MODE: fail if status unclear
if echo "$VALIDATION_OUTPUT" | grep -q "^STATUS: PASSED"; then
echo ""
echo -e "${GREEN}✅ VALIDATION PASSED${NC}"
echo ""
elif echo "$VALIDATION_OUTPUT" | grep -q "^STATUS: FAILED"; then
echo ""
echo -e "${RED}❌ VALIDATION FAILED${NC}"
echo -e "${RED}Fix violations before committing${NC}"
echo ""
exit 1
else
echo ""
echo -e "${RED}❌ VALIDATION ERROR${NC}"
echo -e "${RED}Could not determine validation status from Claude Code response${NC}"
echo -e "${YELLOW}Response must start with 'STATUS: PASSED' or 'STATUS: FAILED'${NC}"
echo ""
echo -e "${YELLOW}To bypass validation temporarily, set CODE_REVIEW_ENABLED=false in .env${NC}"
echo ""
exit 1
fi
else
echo -e "${YELLOW}⚠️ Claude Code not available${NC}"
fi
echo ""
fi
else
echo -e "${YELLOW}⏭️ Code review disabled (CODE_REVIEW_ENABLED=false)${NC}"
echo ""
fi
# Run healthcheck (typecheck and lint check)
echo -e "${BLUE}🏥 Running healthcheck...${NC}"
echo ""
cd ui || cd .
if npm run healthcheck; then
echo ""
echo -e "${GREEN}✅ Healthcheck passed${NC}"
echo ""
else
echo ""
echo -e "${RED}❌ Healthcheck failed${NC}"
echo -e "${RED}Fix type errors and linting issues before committing${NC}"
echo ""
exit 1
fi
# Run build
echo -e "${BLUE}🔨 Running build...${NC}"
echo ""
if npm run build; then
echo ""
echo -e "${GREEN}✅ Build passed${NC}"
echo ""
else
echo ""
echo -e "${RED}❌ Build failed${NC}"
echo -e "${RED}Fix build errors before committing${NC}"
echo ""
exit 1
fi