#!/usr/bin/env bash # ============================================================================= # PRE-COMMIT VALIDATION SCRIPT # ============================================================================= # Run this script before committing to ensure all CI checks will pass. # # Usage: # ./devops/scripts/validate-before-commit.sh [level] # # Levels: # quick - Smoke test only (~2 min) # pr - Full PR-gating suite (~15 min) [default] # full - All tests including extended (~45 min) # # Examples: # ./devops/scripts/validate-before-commit.sh # PR-gating # ./devops/scripts/validate-before-commit.sh quick # Smoke only # ./devops/scripts/validate-before-commit.sh full # Everything # # ============================================================================= set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # Validation level LEVEL="${1:-pr}" # ============================================================================= # UTILITIES # ============================================================================= print_header() { echo "" echo -e "${CYAN}=============================================${NC}" echo -e "${CYAN} $1${NC}" echo -e "${CYAN}=============================================${NC}" echo "" } print_step() { echo -e "${BLUE}>>> $1${NC}" } print_success() { echo -e "${GREEN}[PASS] $1${NC}" } print_fail() { echo -e "${RED}[FAIL] $1${NC}" } print_warn() { echo -e "${YELLOW}[WARN] $1${NC}" } print_info() { echo -e "${CYAN}[INFO] $1${NC}" } # ============================================================================= # CHECKS # ============================================================================= check_git_status() { print_step "Checking git status..." # Check for uncommitted changes if ! git diff --quiet 2>/dev/null; then print_warn "You have unstaged changes" fi # Check for untracked files local untracked untracked=$(git ls-files --others --exclude-standard 2>/dev/null | wc -l) if [[ "$untracked" -gt 0 ]]; then print_warn "You have $untracked untracked file(s)" fi # Show current branch local branch branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) print_info "Current branch: $branch" } check_dependencies() { print_step "Checking dependencies..." local missing=0 # Check .NET if ! command -v dotnet &>/dev/null; then print_fail ".NET SDK not found" missing=1 else local version version=$(dotnet --version) print_success ".NET SDK: $version" fi # Check Docker if ! command -v docker &>/dev/null; then print_warn "Docker not found (some tests may fail)" else if docker info &>/dev/null; then print_success "Docker: running" else print_warn "Docker: not running" fi fi # Check Git if ! command -v git &>/dev/null; then print_fail "Git not found" missing=1 else print_success "Git: installed" fi return $missing } run_smoke_tests() { print_step "Running smoke tests..." if "$SCRIPT_DIR/local-ci.sh" smoke; then print_success "Smoke tests passed" return 0 else print_fail "Smoke tests failed" return 1 fi } run_pr_tests() { print_step "Running PR-gating suite..." if "$SCRIPT_DIR/local-ci.sh" pr; then print_success "PR-gating suite passed" return 0 else print_fail "PR-gating suite failed" return 1 fi } run_full_tests() { print_step "Running full test suite..." if "$SCRIPT_DIR/local-ci.sh" full; then print_success "Full test suite passed" return 0 else print_fail "Full test suite failed" return 1 fi } run_module_tests() { print_step "Running module tests..." if "$SCRIPT_DIR/local-ci.sh" module; then print_success "Module tests passed" return 0 else print_fail "Module tests failed" return 1 fi } validate_helm() { if command -v helm &>/dev/null; then print_step "Validating Helm chart..." local chart="$REPO_ROOT/devops/helm/stellaops" if [[ -d "$chart" ]]; then if helm lint "$chart" &>/dev/null; then print_success "Helm chart valid" else print_warn "Helm chart has warnings" fi fi fi } validate_compose() { print_step "Validating Docker Compose..." local compose="$REPO_ROOT/devops/compose/docker-compose.ci.yaml" if [[ -f "$compose" ]]; then if docker compose -f "$compose" config &>/dev/null; then print_success "Docker Compose valid" else print_warn "Docker Compose has issues" fi fi } # ============================================================================= # MAIN # ============================================================================= main() { print_header "Pre-Commit Validation" print_info "Level: $LEVEL" print_info "Repository: $REPO_ROOT" local start_time start_time=$(date +%s) local failed=0 # Always run these checks check_git_status check_dependencies || failed=1 if [[ $failed -eq 1 ]]; then print_fail "Dependency check failed" exit 1 fi # Run appropriate test level case "$LEVEL" in quick|smoke) run_smoke_tests || failed=1 ;; pr|default) run_smoke_tests || failed=1 if [[ $failed -eq 0 ]]; then run_module_tests || failed=1 fi if [[ $failed -eq 0 ]]; then run_pr_tests || failed=1 fi validate_helm validate_compose ;; full|all) run_smoke_tests || failed=1 if [[ $failed -eq 0 ]]; then run_full_tests || failed=1 fi validate_helm validate_compose ;; *) print_fail "Unknown level: $LEVEL" echo "Valid levels: quick, pr, full" exit 1 ;; esac # Calculate duration local end_time end_time=$(date +%s) local duration=$((end_time - start_time)) local minutes=$((duration / 60)) local seconds=$((duration % 60)) # Final summary print_header "Summary" print_info "Duration: ${minutes}m ${seconds}s" if [[ $failed -eq 0 ]]; then echo "" echo -e "${GREEN}=============================================${NC}" echo -e "${GREEN} ALL CHECKS PASSED - Ready to commit!${NC}" echo -e "${GREEN}=============================================${NC}" echo "" echo "Next steps:" echo " git add -A" echo " git commit -m \"Your commit message\"" echo "" exit 0 else echo "" echo -e "${RED}=============================================${NC}" echo -e "${RED} VALIDATION FAILED - Do not commit!${NC}" echo -e "${RED}=============================================${NC}" echo "" echo "Check the logs in: out/local-ci/logs/" echo "" exit 1 fi } # Show usage if --help if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then cat <