You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							187 lines
						
					
					
						
							4.8 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							187 lines
						
					
					
						
							4.8 KiB
						
					
					
				| #!/usr/bin/env bash | |
| # | |
| # Build Architecture Guard Script | |
| #  | |
| # Author: Matthew Raymer | |
| # Date: 2025-08-20 | |
| # Purpose: Protects build-critical files by requiring BUILDING.md updates | |
| # | |
| # Usage: | |
| #   ./scripts/build-arch-guard.sh --staged     # Check staged files (pre-commit) | |
| #   ./scripts/build-arch-guard.sh --range      # Check range (pre-push) | |
| #   ./scripts/build-arch-guard.sh              # Check working directory | |
| # | |
| 
 | |
| set -euo pipefail | |
| 
 | |
| # Sensitive paths that require BUILDING.md updates when modified | |
| SENSITIVE=( | |
|   "vite.config.*"  | |
|   "scripts/**"  | |
|   "electron/**"  | |
|   "android/**"  | |
|   "ios/**" | |
|   "sw_scripts/**"  | |
|   "sw_combine.js"  | |
|   "Dockerfile"  | |
|   "docker/**" | |
|   "capacitor.config.ts" | |
|   "package.json" | |
|   "package-lock.json" | |
|   "yarn.lock" | |
|   "pnpm-lock.yaml" | |
| ) | |
| 
 | |
| # Documentation files that must be updated alongside sensitive changes | |
| DOCS_REQUIRED=("BUILDING.md") | |
| 
 | |
| # Colors for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| NC='\033[0m' # No Color | |
| 
 | |
| log_info() { | |
|     echo -e "${BLUE}[guard]${NC} $1" | |
| } | |
| 
 | |
| log_warn() { | |
|     echo -e "${YELLOW}[guard]${NC} $1" | |
| } | |
| 
 | |
| log_error() { | |
|     echo -e "${RED}[guard]${NC} $1" | |
| } | |
| 
 | |
| log_success() { | |
|     echo -e "${GREEN}[guard]${NC} $1" | |
| } | |
| 
 | |
| # Collect files based on mode | |
| collect_files() { | |
|     if [[ "${1:-}" == "--staged" ]]; then | |
|         # Pre-commit: check staged files | |
|         git diff --name-only --cached | |
|     elif [[ "${1:-}" == "--range" ]]; then | |
|         # Pre-push: check commits being pushed | |
|         RANGE="${2:-HEAD~1..HEAD}" | |
|         git diff --name-only "$RANGE" | |
|     else | |
|         # Default: check working directory changes | |
|         git diff --name-only HEAD | |
|     fi | |
| } | |
| 
 | |
| # Check if a file matches any sensitive pattern | |
| matches_sensitive() { | |
|     local f="$1" | |
|     for pat in "${SENSITIVE[@]}"; do | |
|         # Convert glob pattern to regex | |
|         local rx="^${pat//\./\.}$" | |
|         rx="${rx//\*\*/.*}" | |
|         rx="${rx//\*/[^/]*}" | |
|          | |
|         if [[ "$f" =~ $rx ]]; then | |
|             return 0 | |
|         fi | |
|     done | |
|     return 1 | |
| } | |
| 
 | |
| # Check if documentation was updated | |
| check_docs_updated() { | |
|     local changed_files=("$@") | |
|      | |
|     for changed_file in "${changed_files[@]}"; do | |
|         for required_doc in "${DOCS_REQUIRED[@]}"; do | |
|             if [[ "$changed_file" == "$required_doc" ]]; then | |
|                 return 0 | |
|             fi | |
|         done | |
|     done | |
|     return 1 | |
| } | |
| 
 | |
| # Main guard logic | |
| main() { | |
|     local mode="${1:-}" | |
|     local arg="${2:-}" | |
|      | |
|     log_info "Running Build Architecture Guard..." | |
|      | |
|     # Collect changed files | |
|     mapfile -t changed_files < <(collect_files "$mode" "$arg") | |
|      | |
|     if [[ ${#changed_files[@]} -eq 0 ]]; then | |
|         log_info "No files changed, guard check passed" | |
|         exit 0 | |
|     fi | |
|      | |
|     log_info "Checking ${#changed_files[@]} changed files..." | |
|      | |
|     # Find sensitive files that were touched | |
|     sensitive_touched=() | |
|     for file in "${changed_files[@]}"; do | |
|         if matches_sensitive "$file"; then | |
|             sensitive_touched+=("$file") | |
|         fi | |
|     done | |
|      | |
|     # If no sensitive files were touched, allow the change | |
|     if [[ ${#sensitive_touched[@]} -eq 0 ]]; then | |
|         log_success "No build-sensitive files changed, guard check passed" | |
|         exit 0 | |
|     fi | |
|      | |
|     # Sensitive files were touched, log them | |
|     log_warn "Build-sensitive paths changed:" | |
|     for file in "${sensitive_touched[@]}"; do | |
|         echo "  - $file" | |
|     done | |
|      | |
|     # Check if required documentation was updated | |
|     if check_docs_updated "${changed_files[@]}"; then | |
|         log_success "BUILDING.md updated alongside build changes, guard check passed" | |
|         exit 0 | |
|     else | |
|         log_error "Build-sensitive files changed but BUILDING.md was not updated!" | |
|         echo | |
|         echo "The following build-sensitive files were modified:" | |
|         for file in "${sensitive_touched[@]}"; do | |
|             echo "  - $file" | |
|         done | |
|         echo | |
|         echo "When modifying build-critical files, you must also update BUILDING.md" | |
|         echo "to document any changes to the build process." | |
|         echo | |
|         echo "Please:" | |
|         echo "  1. Update BUILDING.md with relevant changes" | |
|         echo "  2. Stage the BUILDING.md changes: git add BUILDING.md" | |
|         echo "  3. Retry your commit/push" | |
|         echo | |
|         exit 2 | |
|     fi | |
| } | |
| 
 | |
| # Handle help flag | |
| if [[ "${1:-}" =~ ^(-h|--help)$ ]]; then | |
|     echo "Build Architecture Guard Script" | |
|     echo | |
|     echo "Usage:" | |
|     echo "  $0 [--staged|--range [RANGE]]" | |
|     echo | |
|     echo "Options:" | |
|     echo "  --staged          Check staged files (for pre-commit hook)" | |
|     echo "  --range [RANGE]   Check git range (for pre-push hook)" | |
|     echo "                    Default range: HEAD~1..HEAD" | |
|     echo "  (no args)         Check working directory changes" | |
|     echo | |
|     echo "Examples:" | |
|     echo "  $0 --staged                    # Pre-commit check" | |
|     echo "  $0 --range origin/main..HEAD   # Pre-push check" | |
|     echo "  $0                             # Working directory check" | |
|     exit 0 | |
| fi | |
| 
 | |
| main "$@"
 | |
| 
 |