Add project guidelines verification script
Created comprehensive verification script to check codebase against PROJECT_GUIDELINES.md Features: - Checks for custom CSS (TailwindCSS requirement) - Detects JavaScript files that should be TypeScript - Verifies no secrets committed (.env, credentials.json) - Validates code compiles (go build) - Finds local binaries (should use container builds) - Quick checks with clear pass/fail/warning output Usage: make verify-guidelines ./scripts/verify-quick.sh Current codebase status: - 12 templates with custom CSS (need Tailwind conversion) - 2 .js files in web/static/ (need TypeScript conversion) - 1 binary file (./bookhoard) This addresses the trust issue: AI now has a tool to prove guideline compliance
This commit is contained in:
@@ -57,3 +57,8 @@ test-env-up:
|
|||||||
# Stop test environment
|
# Stop test environment
|
||||||
test-env-down:
|
test-env-down:
|
||||||
podman compose down -v
|
podman compose down -v
|
||||||
|
|
||||||
|
# Verify project guidelines compliance
|
||||||
|
verify-guidelines:
|
||||||
|
@echo "Running project guidelines verification..."
|
||||||
|
@./scripts/verify-quick.sh
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# Project Guidelines Verification
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
Run the quick verification script:
|
||||||
|
```bash
|
||||||
|
make verify-guidelines
|
||||||
|
# or
|
||||||
|
./scripts/verify-quick.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Checks
|
||||||
|
|
||||||
|
1. **Custom CSS**: Detects `<style>` tags in template files (should use TailwindCSS)
|
||||||
|
2. **JavaScript Files**: Finds .js files outside node_modules/ (should be TypeScript)
|
||||||
|
3. **Secrets**: Checks for .env, credentials.json in repository
|
||||||
|
4. **Build**: Verifies code compiles with `go build`
|
||||||
|
5. **Binaries**: Finds compiled binaries in repository (should build through containers)
|
||||||
|
|
||||||
|
## Understanding Results
|
||||||
|
|
||||||
|
- ✅ **PASS**: Guideline followed correctly
|
||||||
|
- ⚠️ **WARNING**: Minor issue, consider fixing
|
||||||
|
- ❌ **ERROR**: Critical violation, should fix before committing
|
||||||
|
|
||||||
|
## Exit Codes
|
||||||
|
|
||||||
|
- `0`: All checks passed (or only warnings)
|
||||||
|
- `1`: Errors found, fix before committing
|
||||||
|
|
||||||
|
## Pre-commit Hook Integration (Optional)
|
||||||
|
|
||||||
|
Add to `.git/hooks/pre-commit`:
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
./scripts/verify-quick.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This will automatically check guidelines before every commit.
|
||||||
|
|
||||||
|
## CI/CD Integration
|
||||||
|
|
||||||
|
Add to your GitHub Actions or GitLab CI:
|
||||||
|
```yaml
|
||||||
|
- name: Verify Project Guidelines
|
||||||
|
run: make verify-guidelines
|
||||||
|
```
|
||||||
|
|
||||||
|
## Current Known Issues
|
||||||
|
|
||||||
|
The script will currently report:
|
||||||
|
- 12 templates with custom CSS (these need Tailwind conversion)
|
||||||
|
- 2 JavaScript files (web/static/header.js, web/static/search.js)
|
||||||
|
- 1 binary file (./bookhoard)
|
||||||
|
|
||||||
|
These should be addressed to fully comply with PROJECT_GUIDELINES.md.
|
||||||
Executable
+285
@@ -0,0 +1,285 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Bookhoard Project Guidelines Verification Script
|
||||||
|
# Checks entire codebase against PROJECT_GUIDELINES.md
|
||||||
|
# Usage: make verify-guidelines or ./scripts/verify-guidelines.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Counters
|
||||||
|
ERRORS=0
|
||||||
|
WARNINGS=0
|
||||||
|
PASSED=0
|
||||||
|
|
||||||
|
echo -e "${BLUE}=== Bookhoard Project Guidelines Verification ===${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Function to print error
|
||||||
|
error_msg() {
|
||||||
|
echo -e "${RED}✗ ERROR: $1${NC}"
|
||||||
|
((ERRORS++))
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to print warning
|
||||||
|
warning_msg() {
|
||||||
|
echo -e "${YELLOW}⚠ WARNING: $1${NC}"
|
||||||
|
((WARNINGS++))
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to print success
|
||||||
|
success_msg() {
|
||||||
|
echo -e "${GREEN}✓ PASS: $1${NC}"
|
||||||
|
((PASSED++))
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to print section header
|
||||||
|
section() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}--- $1 ---${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 1: No Custom CSS (Frontend & Styling)
|
||||||
|
###############################################################################
|
||||||
|
section "Frontend: Custom CSS Check"
|
||||||
|
|
||||||
|
# Check for <style> tags in templates
|
||||||
|
echo "Checking for <style> tags in template files..."
|
||||||
|
STYLE_FILES=$(grep -l '<style>' templates/*.templ 2>/dev/null || true)
|
||||||
|
STYLE_COUNT=$(echo "$STYLE_FILES" | grep -v "^$" | wc -l)
|
||||||
|
if [ "$STYLE_COUNT" -gt 0 ]; then
|
||||||
|
error_msg "Found $STYLE_COUNT template files with <style> tags"
|
||||||
|
echo "$STYLE_FILES"
|
||||||
|
else
|
||||||
|
success_msg "No <style> tags found in templates"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for .css files
|
||||||
|
echo "Checking for .css files..."
|
||||||
|
CSS_FILES=$(find . -name "*.css" -not -path "./node_modules/*" 2>/dev/null | wc -l)
|
||||||
|
if [ "$CSS_FILES" -gt 0 ]; then
|
||||||
|
error_msg "Found $CSS_FILES .css files (should use TailwindCSS)"
|
||||||
|
find . -name "*.css" -not -path "./node_modules/*" 2>/dev/null
|
||||||
|
else
|
||||||
|
success_msg "No .css files found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 2: No JavaScript Files (Use TypeScript)
|
||||||
|
###############################################################################
|
||||||
|
section "Frontend: JavaScript vs TypeScript"
|
||||||
|
|
||||||
|
echo "Checking for .js files (should be .ts)..."
|
||||||
|
JS_FILES=$(find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" 2>/dev/null | wc -l)
|
||||||
|
if [ "$JS_FILES" -gt 0 ]; then
|
||||||
|
error_msg "Found $JS_FILES .js files outside node_modules/"
|
||||||
|
find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" 2>/dev/null
|
||||||
|
else
|
||||||
|
success_msg "No .js files found (TypeScript used)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 3: No Secrets Committed
|
||||||
|
###############################################################################
|
||||||
|
section "Security: No Secrets Committed"
|
||||||
|
|
||||||
|
echo "Checking for .env files..."
|
||||||
|
ENV_FILES=$(find . -name ".env*" -not -name ".env.example" 2>/dev/null | wc -l)
|
||||||
|
if [ "$ENV_FILES" -gt 0 ]; then
|
||||||
|
error_msg "Found .env files in repository"
|
||||||
|
find . -name ".env*" -not -name ".env.example" 2>/dev/null
|
||||||
|
else
|
||||||
|
success_msg "No .env files found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checking for credentials files..."
|
||||||
|
CRED_FILES=$(find . -type f \( -name "*credentials*" -o -name "*secret*" -o -name "*password*" \) | grep -v node_modules | grep -v ".git" | wc -l)
|
||||||
|
if [ "$CRED_FILES" -gt 0 ]; then
|
||||||
|
warning_msg "Found $CRED_FILES files with credential-related names"
|
||||||
|
find . -type f \( -name "*credentials*" -o -name "*secret*" -o -name "*password*" \) | grep -v node_modules | grep -v ".git"
|
||||||
|
else
|
||||||
|
success_msg "No credential files found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checking for secrets in git history..."
|
||||||
|
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||||||
|
SECRETS_IN_HISTORY=$(git log --all --full-history --source -- "*credentials.json" "*.env" 2>/dev/null | wc -l)
|
||||||
|
if [ "$SECRETS_IN_HISTORY" -gt 0 ]; then
|
||||||
|
warning_msg "Found $SECRETS_IN_HISTORY references to secrets in git history"
|
||||||
|
else
|
||||||
|
success_msg "No secrets in git history"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 4: No Local Server Binaries
|
||||||
|
###############################################################################
|
||||||
|
section "Build: No Local Binaries"
|
||||||
|
|
||||||
|
echo "Checking for server binaries in repository..."
|
||||||
|
BINARIES=$(find . -type f -name "bookhoard" -o -name "server" -o -name "bookhoard.exe" -o -name "server.exe" 2>/dev/null | grep -v node_modules | grep -v ".git" | wc -l)
|
||||||
|
if [ "$BINARIES" -gt 0 ]; then
|
||||||
|
error_msg "Found $BINARIES binary files (should build through Dockerfile)"
|
||||||
|
find . -type f \( -name "bookhoard" -o -name "server" \) 2>/dev/null | grep -v node_modules | grep -v ".git"
|
||||||
|
else
|
||||||
|
success_msg "No server binaries found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 5: No New Migration Files
|
||||||
|
###############################################################################
|
||||||
|
section "Database: No New Migration Files"
|
||||||
|
|
||||||
|
echo "Checking for 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)"
|
||||||
|
find migrations/ -name "*.sql" 2>/dev/null
|
||||||
|
else
|
||||||
|
success_msg "Migration structure OK (single file or no migrations)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
success_msg "No migrations directory found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 6: Go Code Quality
|
||||||
|
###############################################################################
|
||||||
|
section "Backend: Go Code Standards"
|
||||||
|
|
||||||
|
echo "Checking Go version..."
|
||||||
|
if [ -f "go.mod" ]; then
|
||||||
|
GO_VERSION=$(grep "go " go.mod | head -1)
|
||||||
|
success_msg "Go version: $GO_VERSION"
|
||||||
|
else
|
||||||
|
error_msg "go.mod not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checking for pgx v5 driver usage..."
|
||||||
|
PGX_V4=$(grep -r "github.com/jackc/pgx/v4" . --include="*.go" 2>/dev/null | wc -l)
|
||||||
|
PGX_V5=$(grep -r "github.com/jackc/pgx/v5" . --include="*.go" 2>/dev/null | wc -l)
|
||||||
|
if [ "$PGX_V4" -gt 0 ]; then
|
||||||
|
error_msg "Found pgx v4 usage (should use v5): $PGX_V4 occurrences"
|
||||||
|
elif [ "$PGX_V5" -eq 0 ]; then
|
||||||
|
warning_msg "No pgx driver found (is database implemented yet?)"
|
||||||
|
else
|
||||||
|
success_msg "Using pgx v5 driver"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checking for OOP patterns (class keyword)..."
|
||||||
|
CLASS_PATTERNS=$(grep -r "type [A-Z].*struct {" internal/ --include="*.go" | grep -v "// OOP" | wc -l)
|
||||||
|
if [ "$CLASS_PATTERNS" -gt 50 ]; then
|
||||||
|
warning_msg "Found $CLASS_PATTERNS struct definitions (review for OOP patterns)"
|
||||||
|
else
|
||||||
|
success_msg "Struct definitions within reasonable range"
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 7: File Organization
|
||||||
|
###############################################################################
|
||||||
|
section "Code Organization: File Placement"
|
||||||
|
|
||||||
|
echo "Checking for .js files in wrong locations..."
|
||||||
|
JS_IN_WRONG_PLACE=$(find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./build/*" 2>/dev/null | wc -l)
|
||||||
|
if [ "$JS_IN_WRONG_PLACE" -gt 0 ]; then
|
||||||
|
error_msg "Found .js files outside allowed directories"
|
||||||
|
find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./build/*" 2>/dev/null
|
||||||
|
else
|
||||||
|
success_msg "JavaScript files properly located"
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 8: Build Verification
|
||||||
|
###############################################################################
|
||||||
|
section "Build: Code Compiles"
|
||||||
|
|
||||||
|
echo "Testing Go build..."
|
||||||
|
if go build -o /tmp/bookhoard-test ./cmd/server 2>&1 | tee /tmp/build.log; then
|
||||||
|
success_msg "Go build successful"
|
||||||
|
rm -f /tmp/bookhoard-test
|
||||||
|
else
|
||||||
|
error_msg "Go build failed - check /tmp/build.log"
|
||||||
|
cat /tmp/build.log
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 9: Docker/Podman Files
|
||||||
|
###############################################################################
|
||||||
|
section "Containerization: Docker/Podman"
|
||||||
|
|
||||||
|
echo "Checking for Dockerfile..."
|
||||||
|
if [ -f "Dockerfile" ]; then
|
||||||
|
success_msg "Dockerfile found (build system uses containers)"
|
||||||
|
else
|
||||||
|
error_msg "Dockerfile not found (required for builds)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checking for docker-compose.yml..."
|
||||||
|
if [ -f "docker-compose.yml" ] || [ -f "docker-compose.yaml" ]; then
|
||||||
|
success_msg "docker-compose file found"
|
||||||
|
else
|
||||||
|
error_msg "docker-compose.yml not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 10: Recent Commit Quality
|
||||||
|
###############################################################################
|
||||||
|
section "Git: Recent Commit Quality"
|
||||||
|
|
||||||
|
echo "Checking for large commits (potential problems)..."
|
||||||
|
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||||||
|
LARGE_COMMITS=$(git log --oneline -10 --pretty=format:"%h %s" | while read hash msg; do
|
||||||
|
FILES_CHANGED=$(git diff-tree --no-commit-id --name-only -r $hash | wc -l)
|
||||||
|
if [ "$FILES_CHANGED" -gt 10 ]; then
|
||||||
|
echo "$hash: $msg ($FILES_CHANGED files)"
|
||||||
|
fi
|
||||||
|
done | wc -l)
|
||||||
|
|
||||||
|
if [ "$LARGE_COMMITS" -gt 0 ]; then
|
||||||
|
warning_msg "Found $LARGE_COMMITS recent commits changing >10 files each"
|
||||||
|
else
|
||||||
|
success_msg "Recent commits are well-scoped"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Check 11: Documentation Updates
|
||||||
|
###############################################################################
|
||||||
|
section "Documentation: README Updated"
|
||||||
|
|
||||||
|
echo "Checking if docs/ directory exists..."
|
||||||
|
if [ -d "docs" ]; then
|
||||||
|
success_msg "Documentation directory exists"
|
||||||
|
else
|
||||||
|
warning_msg "No docs/ directory found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## Summary
|
||||||
|
###############################################################################
|
||||||
|
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 "Please fix the errors above before committing."
|
||||||
|
exit 1
|
||||||
|
elif [ $WARNINGS -gt 0 ]; then
|
||||||
|
echo -e "${YELLOW}⚠️ VERIFICATION PASSED WITH WARNINGS${NC}"
|
||||||
|
echo "Review warnings above and consider addressing them."
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}✅ ALL GUIDELINE CHECKS PASSED${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
Executable
+74
@@ -0,0 +1,74 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Quick verification script for immediate use
|
||||||
|
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}=== Quick Guidelines Check ===${NC}"
|
||||||
|
|
||||||
|
section "1. Custom CSS Check"
|
||||||
|
STYLE_COUNT=$(grep -l '<style>' templates/*.templ 2>/dev/null | wc -l || echo 0)
|
||||||
|
if [ "$STYLE_COUNT" -gt 0 ]; then
|
||||||
|
error_msg "Found $STYLE_COUNT templates with <style> tags"
|
||||||
|
grep -l '<style>' templates/*.templ 2>/dev/null | head -5
|
||||||
|
else
|
||||||
|
success_msg "No <style> in templates"
|
||||||
|
fi
|
||||||
|
|
||||||
|
section "2. JavaScript Files Check"
|
||||||
|
JS_COUNT=$(find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./.git/*" 2>/dev/null | wc -l)
|
||||||
|
if [ "$JS_COUNT" -gt 0 ]; then
|
||||||
|
error_msg "Found $JS_COUNT .js files"
|
||||||
|
find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./.git/*" 2>/dev/null | head -5
|
||||||
|
else
|
||||||
|
success_msg "No .js files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
section "3. Secrets Check"
|
||||||
|
if [ -f ".env" ] || [ -f "credentials.json" ]; then
|
||||||
|
error_msg "Found .env or credentials.json in repo"
|
||||||
|
else
|
||||||
|
success_msg "No secrets found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
section "4. Build Check"
|
||||||
|
echo "Building..."
|
||||||
|
if go build -o /tmp/bookhoard-test ./cmd/server 2>/dev/null; then
|
||||||
|
success_msg "Code compiles"
|
||||||
|
rm -f /tmp/bookhoard-test
|
||||||
|
else
|
||||||
|
error_msg "Build failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
section "5. Binary Check"
|
||||||
|
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"
|
||||||
|
find . -type f \( -name "bookhoard" -o -name "server" \) -not -path "./node_modules/*" -not -path "./.git/*" 2>/dev/null
|
||||||
|
else
|
||||||
|
success_msg "No binaries"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== Summary ===${NC}"
|
||||||
|
echo -e "${GREEN}PASSED: $PASSED${NC}"
|
||||||
|
echo -e "${YELLOW}WARNINGS: $WARNINGS${NC}"
|
||||||
|
echo -e "${RED}ERRORS: $ERRORS${NC}"
|
||||||
|
|
||||||
|
if [ $ERRORS -gt 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
Reference in New Issue
Block a user