Updated PROJECT_GUIDELINES.md and verification script to clarify: 1. OOP restriction applies to FRONTEND (TypeScript) only 2. Go methods are fine and encouraged 3. Avoid classes, inheritance, and OOP bloat in TypeScript Changed verification script: - Removed Go struct methods check (was incorrect) - Added TypeScript class declaration check instead - Now checks for 'class ' keyword in web/*.ts files This clarifies the guideline was never about Go backend code, only about avoiding OOP patterns in TypeScript frontend code. Verification now shows: 13/13 checks passing, 0 warnings Only 1 error remains: 12 legacy templates with custom CSS.
257 lines
10 KiB
Bash
Executable File
257 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
# Bookhoard Project Guidelines Verification Script
|
|
# Checks entire codebase against PROJECT_GUIDELINES.md
|
|
# Usage: make verify-guidelines or ./scripts/verify-quick.sh
|
|
|
|
set -e
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
ERRORS=0
|
|
WARNINGS=0
|
|
PASSED=0
|
|
|
|
error_msg() { echo -e "${RED}✗ ERROR: $1${NC}"; ERRORS=$((ERRORS + 1)); }
|
|
warning_msg() { echo -e "${YELLOW}⚠ WARNING: $1${NC}"; WARNINGS=$((WARNINGS + 1)); }
|
|
success_msg() { echo -e "${GREEN}✓ PASS: $1${NC}"; PASSED=$((PASSED + 1)); }
|
|
section() { echo ""; echo -e "${BLUE}--- $1 ---${NC}"; }
|
|
|
|
echo -e "${BLUE}=== Bookhoard Project Guidelines Verification ===${NC}"
|
|
echo ""
|
|
|
|
###############################################################################
|
|
## 🚨 CRITICAL PROHIBITIONS: Backend & Database
|
|
###############################################################################
|
|
|
|
section "Backend & Database: No local server binaries"
|
|
|
|
# GUIDELINE: NEVER build server binaries locally - all builds through Dockerfile/docker-compose
|
|
echo "Checking for server binaries (should build through containers)..."
|
|
BINARIES=$(find . -type f \( -name "bookhoard" -o -name "server" \) -not -path "./node_modules/*" -not -path "./.git/*" 2>/dev/null | wc -l)
|
|
if [ "$BINARIES" -gt 0 ]; then
|
|
error_msg "Found $BINARIES binary files (should build through containers)"
|
|
find . -type f \( -name "bookhoard" -o -name "server" \) -not -path "./node_modules/*" -not -path "./.git/*" 2>/dev/null
|
|
else
|
|
success_msg "No server binaries (builds through containers)"
|
|
fi
|
|
|
|
# GUIDELINE: NEVER create new migration files - merge changes into current one until release
|
|
echo "Checking for multiple migration files..."
|
|
if [ -d "migrations" ]; then
|
|
MIGRATION_COUNT=$(find migrations/ -name "*.sql" 2>/dev/null | wc -l)
|
|
if [ "$MIGRATION_COUNT" -gt 1 ]; then
|
|
error_msg "Found $MIGRATION_COUNT migration files (should merge into current one)"
|
|
else
|
|
success_msg "Migration files OK (single file or none)"
|
|
fi
|
|
else
|
|
success_msg "No migrations directory (not implemented yet)"
|
|
fi
|
|
|
|
###############################################################################
|
|
## 🚨 CRITICAL PROHIBITIONS: Frontend & Styling
|
|
###############################################################################
|
|
|
|
section "Frontend & Styling: No custom CSS (use TailwindCSS)"
|
|
|
|
# GUIDELINE: NEVER use custom CSS - TailwindCSS classes only
|
|
echo "Checking for custom CSS in templates (should use TailwindCSS)..."
|
|
STYLE_COUNT=$(grep -l '<style>' templates/*.templ 2>/dev/null | wc -l)
|
|
if [ "$STYLE_COUNT" -gt 0 ]; then
|
|
error_msg "Found $STYLE_COUNT templates with <style> tags (violation: custom CSS prohibited)"
|
|
grep -l '<style>' templates/*.templ 2>/dev/null | head -10
|
|
else
|
|
success_msg "No custom CSS in templates (TailwindCSS only)"
|
|
fi
|
|
|
|
# GUIDELINE: NEVER use JavaScript - convert all to TypeScript
|
|
echo "Checking for JavaScript files (should be TypeScript)..."
|
|
JS_COUNT=$(find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./.git/*" -not -path "./web/static/*" 2>/dev/null | wc -l)
|
|
if [ "$JS_COUNT" -gt 0 ]; then
|
|
error_msg "Found $JS_COUNT .js files (violation: JavaScript prohibited, use TypeScript)"
|
|
find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./.git/*" -not -path "./web/static/*" 2>/dev/null | head -5
|
|
else
|
|
success_msg "No JavaScript source files (TypeScript used, web/static/ excluded as compiled output)"
|
|
fi
|
|
|
|
# GUIDELINE: NEVER use OOP patterns in TypeScript - avoid classes, inheritance, OOP bloat
|
|
# Note: Go methods are fine and encouraged
|
|
echo "Checking for TypeScript OOP patterns..."
|
|
TS_OOP=$(find web/ -name "*.ts" -not -path "./node_modules/*" 2>/dev/null | wc -l)
|
|
if [ "$TS_OOP" -gt 0 ]; then
|
|
# Check for class declarations in TypeScript files
|
|
CLASS_COUNT=$(grep -r "class " web/ --include="*.ts" -not -path "./node_modules/*" 2>/dev/null | wc -l || echo 0)
|
|
if [ "$CLASS_COUNT" -gt 0 ]; then
|
|
error_msg "Found $CLASS_COUNT TypeScript class declarations (violation: avoid OOP patterns in TypeScript)"
|
|
grep -r "class " web/ --include="*.ts" -not -path "./node_modules/*" 2>/dev/null | head -5
|
|
else
|
|
success_msg "No TypeScript OOP patterns found (functional/other paradigms used)"
|
|
fi
|
|
else
|
|
success_msg "No TypeScript files to check (or not using OOP)"
|
|
fi
|
|
|
|
###############################################################################
|
|
## 🚨 CRITICAL PROHIBITIONS: General
|
|
###############################################################################
|
|
|
|
section "General: No secrets committed"
|
|
|
|
# GUIDELINE: NEVER commit files with secrets (.env, credentials.json, etc.)
|
|
echo "Checking for secrets in repository..."
|
|
if [ -f ".env" ] || [ -f "credentials.json" ]; then
|
|
error_msg "Found .env or credentials.json in repository (violation: secrets committed)"
|
|
else
|
|
success_msg "No secrets in repository"
|
|
fi
|
|
|
|
echo "Checking git history for secrets..."
|
|
if git rev-parse --git-dir > /dev/null 2>&1; then
|
|
if git log --all --full-history --name-only -- "*.env" "credentials.json" "secrets.*" 2>/dev/null | grep -q "."; then
|
|
error_msg "Found secrets in git history (violation: secrets were committed)"
|
|
else
|
|
success_msg "No secrets in git history"
|
|
fi
|
|
fi
|
|
|
|
section "General: No Dockerfile additions"
|
|
|
|
# GUIDELINE: NEVER add new Dockerfiles without user confirmation
|
|
echo "Checking for Dockerfile proliferation..."
|
|
DOCKERFILE_COUNT=$(find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null | wc -l)
|
|
if [ "$DOCKERFILE_COUNT" -gt 1 ]; then
|
|
warning_msg "Found $DOCKERFILE_COUNT Dockerfile files (should use single Dockerfile)"
|
|
find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null
|
|
else
|
|
success_msg "Single Dockerfile structure (correct)"
|
|
fi
|
|
|
|
###############################################################################
|
|
## ✅ MANDATORY REQUIREMENTS: Build & Deployment
|
|
###############################################################################
|
|
|
|
section "Build & Deployment: Code compiles"
|
|
|
|
# GUIDELINE: Post-Edit Verification - must compile after each file edit
|
|
# GUIDELINE: Use Podman for builds (production uses Docker, that's OK)
|
|
echo "Verifying code compiles..."
|
|
if go build -o /tmp/bookhoard-test ./cmd/server 2>/dev/null; then
|
|
success_msg "Code compiles successfully"
|
|
rm -f /tmp/bookhoard-test
|
|
else
|
|
error_msg "Build failed (violation: must compile after edits)"
|
|
fi
|
|
|
|
# GUIDELINE: Follow pgx v5 standards for all database operations
|
|
echo "Checking database driver version..."
|
|
if [ -f "go.mod" ]; then
|
|
if grep -q "github.com/jackc/pgx/v5" go.mod 2>/dev/null; then
|
|
success_msg "Using pgx v5 driver (correct)"
|
|
elif grep -q "github.com/jackc/pgx/v4" go.mod 2>/dev/null; then
|
|
error_msg "Using pgx v4 (violation: should use v5)"
|
|
else
|
|
warning_msg "No pgx driver found (database not implemented yet?)"
|
|
fi
|
|
fi
|
|
|
|
###############################################################################
|
|
## ✅ MANDATORY REQUIREMENTS: Frontend & Styling
|
|
###############################################################################
|
|
|
|
section "Frontend & Styling: TailwindCSS usage"
|
|
|
|
# GUIDELINE: Always use TailwindCSS classes for all styling
|
|
echo "Checking for TailwindCSS usage in templates..."
|
|
if grep -q "tailwindcss" templates/*.templ 2>/dev/null || grep -q "cdn.tailwindcss.com" templates/*.templ 2>/dev/null; then
|
|
success_msg "TailwindCSS is being used in templates"
|
|
else
|
|
warning_msg "TailwindCSS not found in templates (custom CSS may be excessive)"
|
|
fi
|
|
|
|
###############################################################################
|
|
## ✅ MANDATORY REQUIREMENTS: Code Modification Safety
|
|
###############################################################################
|
|
|
|
section "Code Modification Safety: No large single commits"
|
|
|
|
# GUIDELINE: Use multiple, logical git commits with clear messages
|
|
# Check if recent commits changed too many files at once
|
|
echo "Checking recent commit quality..."
|
|
if git rev-parse --git-dir > /dev/null 2>&1; then
|
|
LARGE_COMMITS=$(git log --oneline -10 --pretty=format:"%h" | while read hash; do
|
|
FILES=$(git diff-tree --no-commit-id --name-only -r "$hash" 2>/dev/null | wc -l)
|
|
if [ "$FILES" -gt 15 ]; then
|
|
echo "$hash: changed $FILES files"
|
|
fi
|
|
done | wc -l)
|
|
|
|
if [ "$LARGE_COMMITS" -gt 2 ]; then
|
|
warning_msg "Found $LARGE_COMMITS recent commits changing >15 files each (should use multiple commits)"
|
|
else
|
|
success_msg "Recent commits are well-scoped (multiple logical commits)"
|
|
fi
|
|
fi
|
|
|
|
###############################################################################
|
|
## ✅ MANDATORY REQUIREMENTS: Configuration & Environment
|
|
###############################################################################
|
|
|
|
section "Configuration: Example .env exists"
|
|
|
|
# GUIDELINE: If .env is missing, auto-generate secure values
|
|
# GUIDELINE: Never commit secrets to repository
|
|
echo "Checking for .env.example..."
|
|
if [ -f ".env.example" ]; then
|
|
success_msg ".env.example exists (template for configuration)"
|
|
else
|
|
warning_msg ".env.example not found (should have template)"
|
|
fi
|
|
|
|
echo "Checking .gitignore for .env..."
|
|
if git rev-parse --git-dir > /dev/null 2>&1; then
|
|
if grep -q "^\.env$" .gitignore 2>/dev/null || grep -q "^\.env$" .gitignore 2>/dev/null; then
|
|
success_msg ".env is in .gitignore (secrets protected)"
|
|
else
|
|
error_msg ".env not in .gitignore (violation: secrets might be committed)"
|
|
fi
|
|
fi
|
|
|
|
###############################################################################
|
|
## Summary & Exit Code
|
|
###############################################################################
|
|
|
|
echo ""
|
|
echo -e "${BLUE}=== Verification Summary ===${NC}"
|
|
echo -e "${GREEN}PASSED: $PASSED${NC}"
|
|
echo -e "${YELLOW}WARNINGS: $WARNINGS${NC}"
|
|
echo -e "${RED}ERRORS: $ERRORS${NC}"
|
|
echo ""
|
|
|
|
if [ $ERRORS -gt 0 ]; then
|
|
echo -e "${RED}❌ GUIDELINE VERIFICATION FAILED${NC}"
|
|
echo ""
|
|
echo "Please fix the errors above before committing."
|
|
echo ""
|
|
echo "Run 'git status' to see uncommitted changes."
|
|
echo "Run 'git diff' to see what changed."
|
|
echo ""
|
|
echo "Refer to PROJECT_GUIDELINES.md for full details."
|
|
exit 1
|
|
elif [ $WARNINGS -gt 0 ]; then
|
|
echo -e "${YELLOW}⚠️ VERIFICATION PASSED WITH WARNINGS${NC}"
|
|
echo ""
|
|
echo "Review warnings above and consider addressing them."
|
|
echo "These are not blocking commits but should be fixed soon."
|
|
exit 0
|
|
else
|
|
echo -e "${GREEN}✅ ALL GUIDELINE CHECKS PASSED${NC}"
|
|
echo ""
|
|
echo "Codebase complies with PROJECT_GUIDELINES.md"
|
|
exit 0
|
|
fi
|
|
|