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 "$@"
|
|
|