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.
		
		
		
		
		
			
		
			
				
					
					
						
							355 lines
						
					
					
						
							11 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							355 lines
						
					
					
						
							11 KiB
						
					
					
				
								#!/usr/bin/env bash
							 | 
						|
								#
							 | 
						|
								# Build Architecture Guard Script
							 | 
						|
								# 
							 | 
						|
								# Author: Matthew Raymer
							 | 
						|
								# Date: 2025-08-22
							 | 
						|
								# Purpose: Protects build-critical files by requiring BUILDING.md updates
							 | 
						|
								# Enhanced to protect Android build system including asset validation, 
							 | 
						|
								# API routing, and resource generation logic
							 | 
						|
								#
							 | 
						|
								# 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"
							 | 
						|
								  "capacitor-assets.config.json"  # Critical for Android assets
							 | 
						|
								  "package.json"
							 | 
						|
								  "package-lock.json"
							 | 
						|
								  "yarn.lock"
							 | 
						|
								  "pnpm-lock.yaml"
							 | 
						|
								  "resources/**"                   # Source assets for Android
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								# Documentation files that must be updated alongside sensitive changes
							 | 
						|
								DOCS_REQUIRED=(
							 | 
						|
								  "BUILDING.md"
							 | 
						|
								  "doc/README-BUILD-GUARD.md"     # Guard documentation
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								# 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
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Check if Android build system was modified
							 | 
						|
								check_android_build_changes() {
							 | 
						|
								    local changed_files=("$@")
							 | 
						|
								    
							 | 
						|
								    for file in "${changed_files[@]}"; do
							 | 
						|
								        if [[ "$file" =~ ^android/ ]] || [[ "$file" =~ ^scripts/build-android\.sh$ ]]; then
							 | 
						|
								            return 0
							 | 
						|
								        fi
							 | 
						|
								    done
							 | 
						|
								    return 1
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Check if asset configuration was modified
							 | 
						|
								check_asset_config_changes() {
							 | 
						|
								    local changed_files=("$@")
							 | 
						|
								    
							 | 
						|
								    for file in "${changed_files[@]}"; do
							 | 
						|
								        if [[ "$file" =~ ^capacitor-assets\.config\.json$ ]] || [[ "$file" =~ ^resources/ ]]; then
							 | 
						|
								            return 0
							 | 
						|
								        fi
							 | 
						|
								    done
							 | 
						|
								    return 1
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Enhanced validation for Android changes
							 | 
						|
								validate_android_changes() {
							 | 
						|
								    local changed_files=("$@")
							 | 
						|
								    
							 | 
						|
								    if check_android_build_changes "${changed_files[@]}"; then
							 | 
						|
								        log_warn "Android build system changes detected!"
							 | 
						|
								        echo
							 | 
						|
								        echo "Android build system changes require enhanced validation:"
							 | 
						|
								        echo "  - Test asset generation: npm run build:android --assets"
							 | 
						|
								        echo "  - Test API routing modes: --dev and --dev --api-ip <custom>"
							 | 
						|
								        echo "  - Verify resource fallback mechanisms"
							 | 
						|
								        echo "  - Test across development/test/production modes"
							 | 
						|
								        echo
							 | 
						|
								        echo "Please ensure BUILDING.md includes Android-specific testing procedures."
							 | 
						|
								        echo
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    if check_asset_config_changes "${changed_files[@]}"; then
							 | 
						|
								        log_warn "Asset configuration changes detected!"
							 | 
						|
								        echo
							 | 
						|
								        echo "Asset configuration changes require validation:"
							 | 
						|
								        echo "  - Test asset generation across all platforms"
							 | 
						|
								        echo "  - Verify resource files are properly created"
							 | 
						|
								        echo "  - Test asset validation scripts"
							 | 
						|
								        echo
							 | 
						|
								    fi
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Feedback collection for continuous improvement
							 | 
						|
								collect_feedback_data() {
							 | 
						|
								    local mode="$1"
							 | 
						|
								    local sensitive_touched=("${@:2}")
							 | 
						|
								    local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
							 | 
						|
								    
							 | 
						|
								    # Create feedback log entry
							 | 
						|
								    local feedback_log=".guard-feedback.log"
							 | 
						|
								    echo "[$timestamp] Guard execution: $mode" >> "$feedback_log"
							 | 
						|
								    echo "  Sensitive files: ${sensitive_touched[*]}" >> "$feedback_log"
							 | 
						|
								    
							 | 
						|
								    # Log Android-specific changes for analysis
							 | 
						|
								    if check_android_build_changes "${sensitive_touched[@]}"; then
							 | 
						|
								        echo "  Android changes detected" >> "$feedback_log"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Log asset configuration changes for analysis
							 | 
						|
								    if check_asset_config_changes "${sensitive_touched[@]}"; then
							 | 
						|
								        echo "  Asset config changes detected" >> "$feedback_log"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    echo "" >> "$feedback_log"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Enhanced error handling with Android-specific guidance
							 | 
						|
								handle_documentation_error() {
							 | 
						|
								    local sensitive_touched=("$@")
							 | 
						|
								    
							 | 
						|
								    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
							 | 
						|
								
							 | 
						|
								    # Add Android-specific guidance
							 | 
						|
								    if check_android_build_changes "${sensitive_touched[@]}"; then
							 | 
						|
								        echo "⚠️  ANDROID BUILD SYSTEM CHANGES DETECTED ⚠️"
							 | 
						|
								        echo "Android changes require enhanced documentation including:"
							 | 
						|
								        echo "  - Asset validation procedures"
							 | 
						|
								        echo "  - API routing configuration"
							 | 
						|
								        echo "  - Resource generation testing"
							 | 
						|
								        echo "  - Platform-specific build modes"
							 | 
						|
								        echo
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    if check_asset_config_changes "${sensitive_touched[@]}"; then
							 | 
						|
								        echo "🎨 ASSET CONFIGURATION CHANGES DETECTED 🎨"
							 | 
						|
								        echo "Asset changes require documentation including:"
							 | 
						|
								        echo "  - Asset generation procedures"
							 | 
						|
								        echo "  - Resource validation steps"
							 | 
						|
								        echo "  - Platform-specific asset requirements"
							 | 
						|
								        echo
							 | 
						|
								    fi
							 | 
						|
								
							 | 
						|
								    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
							 | 
						|
								    echo "💡 Feedback: If this guard is too strict or missing patterns,"
							 | 
						|
								    echo "   please report to the development team for continuous improvement."
							 | 
						|
								    echo
							 | 
						|
								    echo "📊 Feedback Categories:"
							 | 
						|
								    echo "  - False positives (files flagged that shouldn't be)"
							 | 
						|
								    echo "  - False negatives (sensitive files not caught)"
							 | 
						|
								    echo "  - Missing patterns (new file types to protect)"
							 | 
						|
								    echo "  - Overly strict (patterns too restrictive)"
							 | 
						|
								    echo "  - Documentation gaps (missing guidance)"
							 | 
						|
								    echo "  - Testing improvements (better procedures)"
							 | 
						|
								    echo
							 | 
						|
								    echo "📝 Report feedback to: Development team with specific examples"
							 | 
						|
								    echo
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Main guard logic
							 | 
						|
								main() {
							 | 
						|
								    local mode="${1:-}"
							 | 
						|
								    local arg="${2:-}"
							 | 
						|
								    
							 | 
						|
								    log_info "Running Build Architecture Guard..."
							 | 
						|
								    
							 | 
						|
								    # Collect changed files
							 | 
						|
								    changed_files=()
							 | 
						|
								    while IFS= read -r line; do
							 | 
						|
								        [[ -n "$line" ]] && changed_files+=("$line")
							 | 
						|
								    done < <(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
							 | 
						|
								    
							 | 
						|
								    # Enhanced validation for Android changes
							 | 
						|
								    validate_android_changes "${changed_files[@]}"
							 | 
						|
								    
							 | 
						|
								    # Collect feedback data for continuous improvement
							 | 
						|
								    collect_feedback_data "$mode" "${sensitive_touched[@]}"
							 | 
						|
								    
							 | 
						|
								    # 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
							 | 
						|
								        # Enhanced error handling with Android-specific guidance
							 | 
						|
								        handle_documentation_error "${sensitive_touched[@]}"
							 | 
						|
								        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 "  --feedback        Show feedback analysis (for maintainers)"
							 | 
						|
								    echo
							 | 
						|
								    echo "Examples:"
							 | 
						|
								    echo "  $0 --staged                    # Pre-commit check"
							 | 
						|
								    echo "  $0 --range origin/main..HEAD   # Pre-push check"
							 | 
						|
								    echo "  $0                             # Working directory check"
							 | 
						|
								    echo "  $0 --feedback                  # Analyze guard effectiveness"
							 | 
						|
								    exit 0
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Handle feedback analysis
							 | 
						|
								if [[ "${1:-}" == "--feedback" ]]; then
							 | 
						|
								    if [[ -f ".guard-feedback.log" ]]; then
							 | 
						|
								        echo "Build Architecture Guard Feedback Analysis"
							 | 
						|
								        echo "=========================================="
							 | 
						|
								        echo
							 | 
						|
								        echo "Recent guard executions:"
							 | 
						|
								        echo
							 | 
						|
								        tail -20 ".guard-feedback.log" | while IFS= read -r line; do
							 | 
						|
								            if [[ "$line" =~ ^\[ ]]; then
							 | 
						|
								                echo "📅 $line"
							 | 
						|
								            elif [[ "$line" =~ ^\s*Sensitive\ files: ]]; then
							 | 
						|
								                echo "🔍 $line"
							 | 
						|
								            elif [[ "$line" =~ ^\s*Android\ changes ]]; then
							 | 
						|
								                echo "🤖 $line"
							 | 
						|
								            elif [[ "$line" =~ ^\s*Asset\ config ]]; then
							 | 
						|
								                echo "🎨 $line"
							 | 
						|
								            elif [[ "$line" =~ ^\s*$ ]]; then
							 | 
						|
								                echo ""
							 | 
						|
								            else
							 | 
						|
								                echo "  $line"
							 | 
						|
								            fi
							 | 
						|
								        done
							 | 
						|
								        echo
							 | 
						|
								        echo "💡 Use this data to improve guard patterns and documentation"
							 | 
						|
								        echo "📊 Total executions: $(grep -c "Guard execution" .guard-feedback.log 2>/dev/null || echo "0")"
							 | 
						|
								    else
							 | 
						|
								        echo "No feedback data available yet. Run the guard to collect data."
							 | 
						|
								    fi
							 | 
						|
								    exit 0
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								main "$@"
							 | 
						|
								
							 |