diff --git a/ui/.husky/pre-commit b/ui/.husky/pre-commit index e58c0fab37..8e982d4c8a 100755 --- a/ui/.husky/pre-commit +++ b/ui/.husky/pre-commit @@ -54,10 +54,12 @@ if [ "$CODE_REVIEW_ENABLED" = "true" ]; then echo -e "${BLUE}📤 Sending to Claude Code for validation...${NC}" echo "" - # Build prompt with git diff of changes + # Build prompt with git diff of changes AND full context VALIDATION_PROMPT=$( cat <<'PROMPT_EOF' -You are a code reviewer for the Prowler UI project. Analyze the code changes (git diff) below and validate they comply with AGENTS.md standards. +You are a code reviewer for the Prowler UI project. Analyze the code changes (git diff with full context) below and validate they comply with AGENTS.md standards. + +**CRITICAL: You MUST check BOTH the changed lines AND the surrounding context for violations.** **RULES TO CHECK:** 1. React Imports: NO `import * as React` or `import React, {` → Use `import { useState }` @@ -70,35 +72,41 @@ You are a code reviewer for the Prowler UI project. Analyze the code changes (gi 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 +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.) -=== GIT DIFF OF CHANGES === +=== GIT DIFF WITH CONTEXT === PROMPT_EOF ) - # Add git diff to prompt (shows only actual changes) + # Add git diff to prompt with more context (U5 = 5 lines before/after) VALIDATION_PROMPT="$VALIDATION_PROMPT -$(git diff --cached -U0)" +$(git diff --cached -U5)" VALIDATION_PROMPT="$VALIDATION_PROMPT === END DIFF === -**RESPOND WITH:** -STATUS: [PASSED | FAILED] -[If FAILED: list violations with File, Rule, Issue, and line reference] -[If PASSED: confirm all changes comply with AGENTS.md standards]" +**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 visible code (including context) complies 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 + # 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}" @@ -106,8 +114,14 @@ STATUS: [PASSED | FAILED] echo "" exit 1 else - echo -e "${YELLOW}⚠️ Could not determine validation status${NC}" - echo "Continuing (validation inconclusive)" + 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}" diff --git a/ui/README.md b/ui/README.md index 3e334368ff..e0dcb3be33 100644 --- a/ui/README.md +++ b/ui/README.md @@ -87,6 +87,12 @@ You can use one of them `npm`, `yarn`, `pnpm`, `bun`, Example using `npm`: npm install ``` +**Note:** The `npm install` command will automatically configure Git hooks for code quality checks. If you experience issues, you can manually configure them: + +```bash +git config core.hooksPath "ui/.husky" +``` + #### Run the development server ```bash @@ -112,3 +118,48 @@ After modifying the `.npmrc` file, you need to run `pnpm install` again to ensur - [TypeScript](https://www.typescriptlang.org/) - [Framer Motion](https://www.framer.com/motion/) - [next-themes](https://github.com/pacocoursey/next-themes) + +## Git Hooks & Code Review + +This project uses Git hooks to maintain code quality. When you commit changes to TypeScript/JavaScript files, the pre-commit hook can optionally validate them against our coding standards using Claude Code. + +### Enabling Code Review + +To enable automatic code review on commits, add this to your `.env` file in the project root: + +```bash +CODE_REVIEW_ENABLED=true +``` + +When enabled, the hook will: +- ✅ Validate your staged changes against `AGENTS.md` standards +- ✅ Check for common issues (any types, incorrect imports, styling violations, etc.) +- ✅ Block commits that don't comply with the standards +- ✅ Provide helpful feedback on how to fix issues + +### Disabling Code Review + +To disable code review (faster commits, useful for quick iterations): + +```bash +CODE_REVIEW_ENABLED=false +``` + +Or remove the variable from your `.env` file. + +### Requirements + +- [Claude Code CLI](https://github.com/anthropics/claude-code) installed and authenticated +- `.env` file in the project root with `CODE_REVIEW_ENABLED` set + +### Troubleshooting + +If hooks aren't running after commits: + +```bash +# Verify hooks are configured +git config --get core.hooksPath # Should output: ui/.husky + +# Reconfigure if needed +git config core.hooksPath "ui/.husky" +``` diff --git a/ui/package.json b/ui/package.json index db33a08fac..8394a221d9 100644 --- a/ui/package.json +++ b/ui/package.json @@ -7,7 +7,7 @@ "start": "next start", "start:standalone": "node .next/standalone/server.js", "deps:log": "node scripts/update-dependency-log.js", - "postinstall": "node -e \"const fs=require('fs'); if(fs.existsSync('scripts/update-dependency-log.js')) require('./scripts/update-dependency-log.js'); else console.log('skip deps:log (script missing)');\"", + "postinstall": "node -e \"const fs=require('fs'); if(fs.existsSync('scripts/update-dependency-log.js')) require('./scripts/update-dependency-log.js'); else console.log('skip deps:log (script missing)');\" && node scripts/setup-git-hooks.js", "typecheck": "tsc", "healthcheck": "npm run typecheck && npm run lint:check", "lint:check": "eslint . --ext .ts,.tsx -c .eslintrc.cjs", diff --git a/ui/scripts/setup-git-hooks.js b/ui/scripts/setup-git-hooks.js new file mode 100755 index 0000000000..a3f219813f --- /dev/null +++ b/ui/scripts/setup-git-hooks.js @@ -0,0 +1,54 @@ +#!/usr/bin/env node + +/** + * Setup Git Hooks for Prowler UI + * + * This script configures Git to use Husky hooks located in ui/.husky + * It runs automatically after npm install via the postinstall script. + */ + +const { execSync } = require('child_process'); +const path = require('path'); + +try { + // Get the git root directory + const gitRoot = execSync('git rev-parse --show-toplevel', { + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'pipe'] + }).trim(); + + // Check if we're in a git repository + if (!gitRoot) { + console.log('⚠️ Not in a git repository. Skipping git hooks setup.'); + process.exit(0); + } + + // Get current hooks path + let currentHooksPath; + try { + currentHooksPath = execSync('git config --get core.hooksPath', { + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'pipe'] + }).trim(); + } catch { + // core.hooksPath not set yet + currentHooksPath = null; + } + + const expectedHooksPath = 'ui/.husky'; + + // Only configure if not already set correctly + if (currentHooksPath !== expectedHooksPath) { + execSync(`git config core.hooksPath "${expectedHooksPath}"`, { + stdio: 'inherit' + }); + console.log('✅ Git hooks configured: core.hooksPath = ui/.husky'); + } else { + console.log('✅ Git hooks already configured correctly'); + } + +} catch (error) { + // Don't fail the installation if git hooks setup fails + console.warn('⚠️ Could not setup git hooks:', error.message); + console.warn(' You may need to run manually: git config core.hooksPath "ui/.husky"'); +}