Compare commits

...

7 Commits

Author SHA1 Message Date
Alan Buscaglia
2a3c71c435 refactor: simplify gga script and exclude api/ via config 2025-12-16 14:07:42 +01:00
Alan Buscaglia
07a995a210 docs(changelog): add gga integration entry for PR #9571 2025-12-16 14:05:05 +01:00
Alan Buscaglia
73bf93a036 refactor: optimize AGENTS-CODE-REVIEW.md for LLM parsing
- Use REJECT/REQUIRE/PREFER keywords for clear action items
- Remove verbose explanations
- Use bullet points instead of paragraphs
- Add clear section separators
- Condense rules to single lines where possible
2025-12-16 13:52:27 +01:00
Alan Buscaglia
d53e76e30a fix: add missing UI rules (shadcn, DRY/KISS, responsive) 2025-12-16 13:51:17 +01:00
Alan Buscaglia
e2344b4fc6 fix: skip AI review for directories without AGENTS.md (opt-in model)
Components must have their own AGENTS.md to be included in AI code review.
This allows teams like API to opt-in when ready without blocking their workflow.
2025-12-16 13:49:13 +01:00
Alan Buscaglia
eb1fc2b269 fix: add explicit brew tap before installing gga 2025-12-16 13:46:55 +01:00
Alan Buscaglia
4931564648 feat: replace custom Claude validation with Gentleman Guardian Angel (gga)
- Add .gga config in repo root for monorepo support (UI + Python)
- Add AGENTS-CODE-REVIEW.md with centralized code review rules
- Add scripts/gga-review.sh for pre-commit integration with auto-install
- Update .pre-commit-config.yaml to run gga after all formatters/linters
- Simplify ui/.husky/pre-commit to only run healthcheck + build
- Update ui/README.md with new gga documentation

Benefits:
- Provider agnostic: supports Claude, Gemini, Codex, Ollama
- Smart caching: skips unchanged files
- Monorepo support: reviews both TypeScript and Python
- Runs last: reviews code after formatting is applied
- Controlled by CODE_REVIEW_ENABLED environment variable
2025-12-16 13:40:04 +01:00
7 changed files with 241 additions and 141 deletions

20
.gga Normal file
View File

@@ -0,0 +1,20 @@
# Gentleman Guardian Angel (gga) Configuration
# https://github.com/Gentleman-Programming/gentleman-guardian-angel
# AI Provider (required)
# Options: claude, gemini, codex, ollama:<model>
PROVIDER="claude"
# File patterns to include in review (comma-separated globs)
# Review both TypeScript (UI) and Python (SDK, API, MCP) files
FILE_PATTERNS="*.ts,*.tsx,*.js,*.jsx,*.py"
# File patterns to exclude from review (comma-separated globs)
# Excludes: test files, type definitions, and api/ folder (no AGENTS.md yet)
EXCLUDE_PATTERNS="*.test.ts,*.test.tsx,*.spec.ts,*.spec.tsx,*.d.ts,*_test.py,test_*.py,conftest.py,api/*"
# File containing your coding standards (relative to repo root)
RULES_FILE="AGENTS-CODE-REVIEW.md"
# Strict mode: fail if AI response is ambiguous (recommended)
STRICT_MODE="true"

View File

@@ -82,7 +82,6 @@ repos:
args: ["--directory=./"]
pass_filenames: false
- repo: https://github.com/hadolint/hadolint
rev: v2.13.0-beta
hooks:
@@ -129,9 +128,20 @@ repos:
- id: ui-checks
name: UI - Husky Pre-commit
description: "Run UI pre-commit checks (Claude Code validation + healthcheck)"
description: "Run UI pre-commit checks (healthcheck + build)"
entry: bash -c 'cd ui && .husky/pre-commit'
language: system
files: '^ui/.*\.(ts|tsx|js|jsx|json|css)$'
pass_filenames: false
verbose: true
- id: gga
name: Gentleman Guardian Angel (AI Code Review)
description: "AI-powered code review - runs last after all formatters/linters"
entry: ./scripts/gga-review.sh
language: system
files: '\.(ts|tsx|js|jsx|py)$'
exclude: '(\.test\.|\.spec\.|_test\.py|test_.*\.py|conftest\.py|\.d\.ts)'
pass_filenames: false
stages: ["pre-commit"]
verbose: true

89
AGENTS-CODE-REVIEW.md Normal file
View File

@@ -0,0 +1,89 @@
# Code Review Rules
## References
- UI details: `ui/AGENTS.md`
- SDK details: `prowler/AGENTS.md`
- MCP details: `mcp_server/AGENTS.md`
---
## ALL FILES
REJECT if:
- Hardcoded secrets/credentials
- `any` type (TypeScript) or missing type hints (Python)
- Code duplication (violates DRY)
- Silent error handling (no logging)
---
## TypeScript/React (ui/)
REJECT if:
- `import React` or `import * as React` → use `import { useState }`
- Union types `type X = "a" | "b"` → use `const X = {...} as const`
- `var()` or hex colors in className → use Tailwind classes
- `useMemo` or `useCallback` without justification (React 19 Compiler)
- `z.string().email()` → use `z.email()` (Zod v4)
- `z.string().nonempty()` → use `z.string().min(1)` (Zod v4)
- Missing `"use client"` in client components
- Missing `"use server"` in server actions
- Images without `alt` attribute
- Interactive elements without `aria` labels
- Non-semantic HTML when semantic exists
PREFER:
- `components/shadcn/` over custom components
- `cn()` for conditional/merged classes
- Local files if used 1 place, `components/shared/` if 2+
- Responsive classes: `sm:`, `md:`, `lg:`, `xl:`
EXCEPTION:
- `var()` allowed in chart/graph component props (not className)
---
## Python (prowler/, mcp_server/)
REJECT if:
- Missing type hints on public functions
- Missing docstrings on classes/public methods
- Bare `except:` without specific exception
- `print()` instead of `logger`
REQUIRE for SDK checks:
- Inherit from `Check`
- `execute()` returns `list[CheckReport]`
- `report.status` = `"PASS"` | `"FAIL"`
- `.metadata.json` file exists
REQUIRE for MCP tools:
- Extend `BaseTool` (auto-registration)
- `MinimalSerializerMixin` for responses
- `from_api_response()` for API transforms
---
## Response Format
FIRST LINE must be exactly:
```
STATUS: PASSED
```
or
```
STATUS: FAILED
```
If FAILED, list: `file:line - rule - issue`

49
scripts/gga-review.sh Executable file
View File

@@ -0,0 +1,49 @@
#!/bin/bash
# Gentleman Guardian Angel (gga) - AI Code Review Hook
# This script is called by pre-commit after all formatters/linters have run
set -e
# Colors
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Check if AI code review is enabled
if [ "${CODE_REVIEW_ENABLED:-false}" != "true" ]; then
echo -e "${YELLOW}⏭️ AI code review disabled (CODE_REVIEW_ENABLED!=true)${NC}"
exit 0
fi
# Check if AGENTS-CODE-REVIEW.md exists
if [ ! -f "AGENTS-CODE-REVIEW.md" ]; then
echo -e "${YELLOW}⏭️ AI code review skipped (AGENTS-CODE-REVIEW.md not found)${NC}"
exit 0
fi
# Install gga if not present
if ! command -v gga &> /dev/null; then
echo -e "${BLUE}📦 Installing Gentleman Guardian Angel (gga)...${NC}"
if command -v brew &> /dev/null; then
brew tap gentleman-programming/tap 2>/dev/null || true
brew install gga
else
# Fallback: install from source for Linux/CI environments
GGA_TMP_DIR=$(mktemp -d)
git clone --depth 1 https://github.com/Gentleman-Programming/gentleman-guardian-angel.git "$GGA_TMP_DIR"
chmod +x "$GGA_TMP_DIR/install.sh"
"$GGA_TMP_DIR/install.sh"
rm -rf "$GGA_TMP_DIR"
fi
fi
# Verify gga is available
if ! command -v gga &> /dev/null; then
echo "❌ Failed to install gga"
echo "Please install manually: https://github.com/Gentleman-Programming/gentleman-guardian-angel"
exit 1
fi
# Run gga code review
# Exclusions are configured in .gga file (EXCLUDE_PATTERNS)
exec gga run

View File

@@ -1,15 +1,14 @@
#!/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
# Runs healthcheck (typecheck + lint) and build for UI changes
# AI code review is handled by gga in .pre-commit-config.yaml
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
@@ -19,127 +18,14 @@ echo "🚀 Prowler UI - Pre-Commit Hook"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Load .env file (look in git root directory)
# Get git root and navigate to ui 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. Exception: `var()` is allowed when passing colors to chart/graph components that require CSS color strings (not Tailwind classes) for their APIs.
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
cd "$GIT_ROOT/ui" || exit 1
# Run healthcheck (typecheck and lint check)
echo -e "${BLUE}🏥 Running healthcheck...${NC}"
echo ""
cd ui || cd .
if pnpm run healthcheck; then
echo ""
echo -e "${GREEN}✅ Healthcheck passed${NC}"

View File

@@ -11,6 +11,8 @@ All notable changes to the **Prowler UI** are documented in this file.
### 🔄 Changed
- Replace custom Claude pre-commit validation with Gentleman Guardian Angel (gga) for provider-agnostic, monorepo-aware AI code reviews [(#9571)](https://github.com/prowler-cloud/prowler/pull/9571)
### 🐞 Fixed
---

View File

@@ -2,10 +2,12 @@
This repository hosts the UI component for Prowler, providing a user-friendly web interface to interact seamlessly with Prowler's features.
## 🚀 Production deployment
### Docker deployment
#### Clone the repository
```console
# HTTPS
git clone https://github.com/prowler-cloud/ui.git
@@ -14,16 +16,21 @@ git clone https://github.com/prowler-cloud/ui.git
git clone git@github.com:prowler-cloud/ui.git
```
#### Build the Docker image
```bash
docker build -t prowler-cloud/ui . --target prod
```
#### Run the Docker container
```bash
docker run -p 3000:3000 prowler-cloud/ui
```
### Local deployment
#### Clone the repository
```console
@@ -48,8 +55,11 @@ pnpm start
```
## 🧪 Development deployment
### Docker deployment
#### Clone the repository
```console
# HTTPS
git clone https://github.com/prowler-cloud/ui.git
@@ -58,16 +68,21 @@ git clone https://github.com/prowler-cloud/ui.git
git clone git@github.com:prowler-cloud/ui.git
```
#### Build the Docker image
```bash
docker build -t prowler-cloud/ui . --target dev
```
#### Run the Docker container
```bash
docker run -p 3000:3000 prowler-cloud/ui
```
### Local deployment
#### Clone the repository
```console
@@ -109,45 +124,74 @@ pnpm run dev
## 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.
This project uses Git hooks to maintain code quality:
### Enabling Code Review
1. **UI Pre-commit Hook** (`ui/.husky/pre-commit`): Runs healthcheck (typecheck + lint) and build for UI changes
2. **AI Code Review** (`.pre-commit-config.yaml`): Uses [Gentleman Guardian Angel (gga)](https://github.com/Gentleman-Programming/gentleman-guardian-angel) to validate code against `AGENTS-CODE-REVIEW.md` standards
To enable automatic code review on commits, add this to your `.env` file in the project root:
### Enabling AI Code Review
The AI code review runs **after** all formatters and linters have processed the code. To enable it, set in your environment or `.env` file:
```bash
CODE_REVIEW_ENABLED=true
export 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
When enabled:
### Disabling Code Review
- ✅ Validates staged changes against `AGENTS-CODE-REVIEW.md` standards
- ✅ Reviews both TypeScript (UI) and Python (SDK, API, MCP) files
- ✅ Runs last, after black/isort/prettier have formatted the code
- ✅ Smart caching: skips unchanged files for faster reviews
- ✅ Blocks commits that don't comply with standards
To disable code review (faster commits, useful for quick iterations):
### Disabling AI Code Review
```bash
CODE_REVIEW_ENABLED=false
export CODE_REVIEW_ENABLED=false
```
Or remove the variable from your `.env` file.
Or simply don't set the variable (disabled by default).
### Requirements
- [Claude Code CLI](https://github.com/anthropics/claude-code) installed and authenticated
- `.env` file in the project root with `CODE_REVIEW_ENABLED` set
- **AI CLI**: One of the following must be installed and authenticated:
- [Claude Code CLI](https://claude.ai/code) (default, recommended)
- [Gemini CLI](https://github.com/google-gemini/gemini-cli)
- [Codex CLI](https://www.npmjs.com/package/@openai/codex)
- [Ollama](https://ollama.ai) (local models)
**Note:** `gga` will be installed automatically on first commit if not present.
### Configuration
The AI code review is configured via `.gga` in the **repository root**:
```bash
PROVIDER="claude" # AI provider
FILE_PATTERNS="*.ts,*.tsx,*.js,*.jsx,*.py"
EXCLUDE_PATTERNS="*.test.ts,*.spec.ts,*_test.py,test_*.py,conftest.py,*.d.ts"
RULES_FILE="AGENTS-CODE-REVIEW.md" # Centralized review rules
STRICT_MODE="true"
```
Available providers: `claude`, `gemini`, `codex`, `ollama:<model>`
### Troubleshooting
If hooks aren't running after commits:
If gga installation fails:
```bash
# Verify hooks are configured
git config --get core.hooksPath # Should output: ui/.husky
# Homebrew (macOS)
brew install gentleman-programming/tap/gga
# Reconfigure if needed
git config core.hooksPath "ui/.husky"
# From source (Linux/macOS)
git clone https://github.com/Gentleman-Programming/gentleman-guardian-angel.git /tmp/gga
cd /tmp/gga && ./install.sh
```
To clear the gga cache:
```bash
gga cache clear
```