backend-infra-engineer: Release v0.3.3 snapshot
This commit is contained in:
399
scripts/pre-push-test.sh
Executable file
399
scripts/pre-push-test.sh
Executable file
@@ -0,0 +1,399 @@
|
||||
#!/bin/bash
|
||||
# Pre-Push Test Script for YAZE
|
||||
# Runs fast validation checks before pushing to remote
|
||||
# Catches 90% of CI failures in < 2 minutes
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
# Configuration
|
||||
BUILD_DIR="${BUILD_DIR:-$PROJECT_ROOT/build}"
|
||||
PRESET="${PRESET:-}"
|
||||
CONFIG_ONLY="${CONFIG_ONLY:-0}"
|
||||
SMOKE_ONLY="${SMOKE_ONLY:-0}"
|
||||
SKIP_SYMBOLS="${SKIP_SYMBOLS:-0}"
|
||||
SKIP_TESTS="${SKIP_TESTS:-0}"
|
||||
VERBOSE="${VERBOSE:-0}"
|
||||
|
||||
# Statistics
|
||||
TOTAL_CHECKS=0
|
||||
PASSED_CHECKS=0
|
||||
FAILED_CHECKS=0
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
# Helper functions
|
||||
print_header() {
|
||||
echo -e "\n${BLUE}===${NC} $1 ${BLUE}===${NC}"
|
||||
}
|
||||
|
||||
print_step() {
|
||||
echo -e "${YELLOW}→${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓${NC} $1"
|
||||
((PASSED_CHECKS++))
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}✗${NC} $1"
|
||||
((FAILED_CHECKS++))
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}ℹ${NC} $1"
|
||||
}
|
||||
|
||||
check_command() {
|
||||
if ! command -v "$1" &> /dev/null; then
|
||||
print_error "$1 not found. Please install it."
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
elapsed_time() {
|
||||
local END_TIME=$(date +%s)
|
||||
local ELAPSED=$((END_TIME - START_TIME))
|
||||
echo "${ELAPSED}s"
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
usage() {
|
||||
cat << EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Pre-push validation script that runs fast checks to catch CI failures early.
|
||||
|
||||
OPTIONS:
|
||||
--preset NAME Use specific CMake preset (auto-detect if not specified)
|
||||
--build-dir PATH Build directory (default: build)
|
||||
--config-only Only validate CMake configuration
|
||||
--smoke-only Only run smoke compilation test
|
||||
--skip-symbols Skip symbol conflict checking
|
||||
--skip-tests Skip running unit tests
|
||||
--verbose Show detailed output
|
||||
-h, --help Show this help message
|
||||
|
||||
EXAMPLES:
|
||||
$0 # Run all checks with auto-detected preset
|
||||
$0 --preset mac-dbg # Run all checks with specific preset
|
||||
$0 --config-only # Only validate CMake configuration
|
||||
$0 --smoke-only # Only compile representative files
|
||||
$0 --skip-tests # Skip unit tests (faster)
|
||||
|
||||
TIME BUDGET:
|
||||
Config validation: ~10 seconds
|
||||
Smoke compilation: ~90 seconds
|
||||
Symbol checking: ~30 seconds
|
||||
Unit tests: ~30 seconds
|
||||
─────────────────────────────
|
||||
Total (all checks): ~2 minutes
|
||||
|
||||
WHAT THIS CATCHES:
|
||||
✓ CMake configuration errors
|
||||
✓ Missing include paths
|
||||
✓ Header-only compilation issues
|
||||
✓ Symbol conflicts (ODR violations)
|
||||
✓ Unit test failures
|
||||
✓ Platform-specific issues
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--preset)
|
||||
PRESET="$2"
|
||||
shift 2
|
||||
;;
|
||||
--build-dir)
|
||||
BUILD_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
--config-only)
|
||||
CONFIG_ONLY=1
|
||||
shift
|
||||
;;
|
||||
--smoke-only)
|
||||
SMOKE_ONLY=1
|
||||
shift
|
||||
;;
|
||||
--skip-symbols)
|
||||
SKIP_SYMBOLS=1
|
||||
shift
|
||||
;;
|
||||
--skip-tests)
|
||||
SKIP_TESTS=1
|
||||
shift
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown option: $1"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Auto-detect preset if not specified
|
||||
if [[ -z "$PRESET" ]]; then
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
PRESET="mac-dbg"
|
||||
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
PRESET="lin-dbg"
|
||||
else
|
||||
print_error "Unsupported platform: $OSTYPE"
|
||||
print_info "Please specify --preset manually"
|
||||
exit 1
|
||||
fi
|
||||
print_info "Auto-detected preset: $PRESET"
|
||||
fi
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
print_header "YAZE Pre-Push Validation"
|
||||
print_info "Preset: $PRESET"
|
||||
print_info "Build directory: $BUILD_DIR"
|
||||
print_info "Time budget: ~2 minutes"
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# LEVEL 0: Static Analysis
|
||||
# ============================================================================
|
||||
|
||||
print_header "Level 0: Static Analysis"
|
||||
((TOTAL_CHECKS++))
|
||||
|
||||
print_step "Checking code formatting..."
|
||||
if [[ $VERBOSE -eq 1 ]]; then
|
||||
if cmake --build "$BUILD_DIR" --target yaze-format-check 2>&1; then
|
||||
print_success "Code formatting is correct"
|
||||
else
|
||||
print_error "Code formatting check failed"
|
||||
print_info "Run: cmake --build $BUILD_DIR --target yaze-format"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if cmake --build "$BUILD_DIR" --target yaze-format-check > /dev/null 2>&1; then
|
||||
print_success "Code formatting is correct"
|
||||
else
|
||||
print_error "Code formatting check failed"
|
||||
print_info "Run: cmake --build $BUILD_DIR --target yaze-format"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Skip remaining checks if config-only
|
||||
if [[ $CONFIG_ONLY -eq 1 ]]; then
|
||||
print_header "Summary (Config Only)"
|
||||
print_info "Time elapsed: $(elapsed_time)"
|
||||
print_info "Total checks: $TOTAL_CHECKS"
|
||||
print_info "Passed: ${GREEN}$PASSED_CHECKS${NC}"
|
||||
print_info "Failed: ${RED}$FAILED_CHECKS${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# LEVEL 1: Configuration Validation
|
||||
# ============================================================================
|
||||
|
||||
print_header "Level 1: Configuration Validation"
|
||||
((TOTAL_CHECKS++))
|
||||
|
||||
print_step "Validating CMake preset: $PRESET"
|
||||
if cmake --preset "$PRESET" -DCMAKE_VERBOSE_MAKEFILE=OFF > /dev/null 2>&1; then
|
||||
print_success "CMake configuration successful"
|
||||
else
|
||||
print_error "CMake configuration failed"
|
||||
print_info "Run: cmake --preset $PRESET (with verbose output)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for include path issues
|
||||
((TOTAL_CHECKS++))
|
||||
print_step "Checking include path propagation..."
|
||||
if [[ $VERBOSE -eq 1 ]]; then
|
||||
if grep -q "INCLUDE_DIRECTORIES" "$BUILD_DIR/CMakeCache.txt"; then
|
||||
print_success "Include paths configured"
|
||||
else
|
||||
print_error "Include paths not properly configured"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if grep -q "INCLUDE_DIRECTORIES" "$BUILD_DIR/CMakeCache.txt" 2>/dev/null; then
|
||||
print_success "Include paths configured"
|
||||
else
|
||||
print_error "Include paths not properly configured"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# LEVEL 2: Smoke Compilation
|
||||
# ============================================================================
|
||||
|
||||
if [[ $SMOKE_ONLY -eq 0 ]]; then
|
||||
print_header "Level 2: Smoke Compilation"
|
||||
((TOTAL_CHECKS++))
|
||||
|
||||
print_step "Compiling representative files..."
|
||||
print_info "This validates headers, includes, and preprocessor directives"
|
||||
|
||||
# List of representative files (one per major library)
|
||||
SMOKE_FILES=(
|
||||
"src/app/rom.cc"
|
||||
"src/app/gfx/bitmap.cc"
|
||||
"src/zelda3/overworld/overworld.cc"
|
||||
"src/cli/service/resources/resource_catalog.cc"
|
||||
)
|
||||
|
||||
SMOKE_FAILED=0
|
||||
for file in "${SMOKE_FILES[@]}"; do
|
||||
if [[ ! -f "$PROJECT_ROOT/$file" ]]; then
|
||||
print_info "Skipping $file (not found)"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get object file path
|
||||
OBJ_FILE="$BUILD_DIR/$(echo "$file" | sed 's/src\///' | sed 's/\.cc$/.cc.o/')"
|
||||
|
||||
if [[ $VERBOSE -eq 1 ]]; then
|
||||
print_step " Compiling $file"
|
||||
if cmake --build "$BUILD_DIR" --target "$(basename "$OBJ_FILE")" 2>&1; then
|
||||
print_success " ✓ $file"
|
||||
else
|
||||
print_error " ✗ $file"
|
||||
SMOKE_FAILED=1
|
||||
fi
|
||||
else
|
||||
if cmake --build "$BUILD_DIR" --target "$(basename "$OBJ_FILE")" > /dev/null 2>&1; then
|
||||
print_success " ✓ $file"
|
||||
else
|
||||
print_error " ✗ $file (run with --verbose for details)"
|
||||
SMOKE_FAILED=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $SMOKE_FAILED -eq 0 ]]; then
|
||||
print_success "Smoke compilation successful"
|
||||
else
|
||||
print_error "Smoke compilation failed"
|
||||
print_info "Run: cmake --build $BUILD_DIR -v (for verbose output)"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# LEVEL 3: Symbol Validation
|
||||
# ============================================================================
|
||||
|
||||
if [[ $SKIP_SYMBOLS -eq 0 ]]; then
|
||||
print_header "Level 3: Symbol Validation"
|
||||
((TOTAL_CHECKS++))
|
||||
|
||||
print_step "Checking for symbol conflicts..."
|
||||
print_info "This detects ODR violations and duplicate symbols"
|
||||
|
||||
if [[ -x "$SCRIPT_DIR/verify-symbols.sh" ]]; then
|
||||
if [[ $VERBOSE -eq 1 ]]; then
|
||||
if "$SCRIPT_DIR/verify-symbols.sh" --build-dir "$BUILD_DIR"; then
|
||||
print_success "No symbol conflicts detected"
|
||||
else
|
||||
print_error "Symbol conflicts detected"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if "$SCRIPT_DIR/verify-symbols.sh" --build-dir "$BUILD_DIR" > /dev/null 2>&1; then
|
||||
print_success "No symbol conflicts detected"
|
||||
else
|
||||
print_error "Symbol conflicts detected"
|
||||
print_info "Run: ./scripts/verify-symbols.sh --build-dir $BUILD_DIR"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
print_info "Symbol checker not found (skipping)"
|
||||
print_info "Create: scripts/verify-symbols.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# LEVEL 4: Unit Tests
|
||||
# ============================================================================
|
||||
|
||||
if [[ $SKIP_TESTS -eq 0 ]]; then
|
||||
print_header "Level 4: Unit Tests"
|
||||
((TOTAL_CHECKS++))
|
||||
|
||||
print_step "Running unit tests..."
|
||||
print_info "This validates component logic"
|
||||
|
||||
TEST_BINARY="$BUILD_DIR/bin/yaze_test"
|
||||
if [[ ! -x "$TEST_BINARY" ]]; then
|
||||
print_info "Test binary not found, building..."
|
||||
if cmake --build "$BUILD_DIR" --target yaze_test > /dev/null 2>&1; then
|
||||
print_success "Test binary built"
|
||||
else
|
||||
print_error "Failed to build test binary"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $VERBOSE -eq 1 ]]; then
|
||||
if "$TEST_BINARY" --unit 2>&1; then
|
||||
print_success "All unit tests passed"
|
||||
else
|
||||
print_error "Unit tests failed"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if "$TEST_BINARY" --unit > /dev/null 2>&1; then
|
||||
print_success "All unit tests passed"
|
||||
else
|
||||
print_error "Unit tests failed"
|
||||
print_info "Run: $TEST_BINARY --unit (for detailed output)"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# Summary
|
||||
# ============================================================================
|
||||
|
||||
print_header "Summary"
|
||||
END_TIME=$(date +%s)
|
||||
ELAPSED=$((END_TIME - START_TIME))
|
||||
|
||||
print_info "Time elapsed: ${ELAPSED}s"
|
||||
print_info "Total checks: $TOTAL_CHECKS"
|
||||
print_info "Passed: ${GREEN}$PASSED_CHECKS${NC}"
|
||||
print_info "Failed: ${RED}$FAILED_CHECKS${NC}"
|
||||
|
||||
if [[ $FAILED_CHECKS -eq 0 ]]; then
|
||||
echo ""
|
||||
print_success "All checks passed! Safe to push."
|
||||
exit 0
|
||||
else
|
||||
echo ""
|
||||
print_error "Some checks failed. Please fix before pushing."
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user