Resolved multiple critical discovery system issues: ## Discovery System Fixes - Fixed console commands not being discovered on first run - Implemented fallback discovery for empty caches - Added context-aware caching with separate cache keys - Fixed object serialization preventing __PHP_Incomplete_Class ## Cache System Improvements - Smart caching that only caches meaningful results - Separate caches for different execution contexts (console, web, test) - Proper array serialization/deserialization for cache compatibility - Cache hit logging for debugging and monitoring ## Object Serialization Fixes - Fixed DiscoveredAttribute serialization with proper string conversion - Sanitized additional data to prevent object reference issues - Added fallback for corrupted cache entries ## Performance & Reliability - All 69 console commands properly discovered and cached - 534 total discovery items successfully cached and restored - No more __PHP_Incomplete_Class cache corruption - Improved error handling and graceful fallbacks ## Testing & Quality - Fixed code style issues across discovery components - Enhanced logging for better debugging capabilities - Improved cache validation and error recovery Ready for production deployment with stable discovery system. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
528 lines
17 KiB
Bash
Executable File
528 lines
17 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# Interactive Setup Wizard for Custom PHP Framework Deployment
|
||
# Provides step-by-step guided configuration for production-ready deployments
|
||
# Domain: michaelschiemer.de | Email: kontakt@michaelschiemer.de | PHP: 8.4
|
||
|
||
set -euo pipefail
|
||
|
||
# Script configuration
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../" && pwd)"
|
||
DEPLOYMENT_DIR="${SCRIPT_DIR}"
|
||
|
||
# Configuration state
|
||
CURRENT_STEP=1
|
||
TOTAL_STEPS=8
|
||
ENVIRONMENT=""
|
||
DOMAIN=""
|
||
EMAIL=""
|
||
SERVER_IP=""
|
||
SSH_KEY_PATH=""
|
||
|
||
# Configuration storage
|
||
declare -A CONFIG_VALUES
|
||
declare -A PASSWORD_STORE
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
PURPLE='\033[0;35m'
|
||
CYAN='\033[0;36m'
|
||
WHITE='\033[1;37m'
|
||
NC='\033[0m'
|
||
|
||
# Enhanced logging functions
|
||
log() { echo -e "${GREEN}[$(date +'%H:%M:%S')] ✅ $1${NC}"; }
|
||
warn() { echo -e "${YELLOW}[$(date +'%H:%M:%S')] ⚠️ $1${NC}"; }
|
||
error() { echo -e "${RED}[$(date +'%H:%M:%S')] ❌ $1${NC}"; }
|
||
info() { echo -e "${BLUE}[$(date +'%H:%M:%S')] ℹ️ $1${NC}"; }
|
||
success() { echo -e "${WHITE}[$(date +'%H:%M:%S')] 🎉 $1${NC}"; }
|
||
|
||
# Progress indicator
|
||
show_progress() {
|
||
local step=$1
|
||
local total=$2
|
||
local description="$3"
|
||
|
||
local progress=$((step * 100 / total))
|
||
local bars=$((progress / 5))
|
||
local spaces=$((20 - bars))
|
||
|
||
printf "\n${PURPLE}[Step %d/%d] ${WHITE}%s${NC}\n" "$step" "$total" "$description"
|
||
printf "${CYAN}Progress: [${GREEN}"
|
||
printf "█%.0s" $(seq 1 $bars)
|
||
printf "${CYAN}"
|
||
printf "░%.0s" $(seq 1 $spaces)
|
||
printf "${CYAN}] %d%%${NC}\n\n" "$progress"
|
||
}
|
||
|
||
# Welcome screen
|
||
show_welcome() {
|
||
clear
|
||
cat << 'EOF'
|
||
|
||
███████╗███████╗████████╗██╗ ██╗██████╗
|
||
██╔════╝██╔════╝╚══██╔══╝██║ ██║██╔══██╗
|
||
███████╗█████╗ ██║ ██║ ██║██████╔╝
|
||
╚════██║██╔══╝ ██║ ██║ ██║██╔═══╝
|
||
███████║███████╗ ██║ ╚██████╔╝██║
|
||
╚══════╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝
|
||
|
||
EOF
|
||
cat << EOF
|
||
${WHITE}Custom PHP Framework Deployment Setup Wizard${NC}
|
||
${CYAN}Domain: michaelschiemer.de | Email: kontakt@michaelschiemer.de | PHP: 8.4${NC}
|
||
|
||
${GREEN}This wizard will guide you through setting up a production-ready deployment:${NC}
|
||
|
||
✅ Environment configuration with secure defaults
|
||
✅ Automatic password generation and validation
|
||
✅ SSH key setup and server connectivity testing
|
||
✅ SSL/TLS certificate configuration
|
||
✅ Docker and Ansible integration
|
||
✅ Complete deployment validation
|
||
|
||
${YELLOW}Prerequisites:${NC} Internet connection, sudo access (if needed)
|
||
${YELLOW}Time Required:${NC} 10-15 minutes
|
||
${YELLOW}What You'll Need:${NC} Server details and domain information
|
||
|
||
${WHITE}Press Enter to start, or Ctrl+C to exit...${NC}
|
||
EOF
|
||
read -r
|
||
}
|
||
|
||
# Step 1: Environment Selection
|
||
step_environment_selection() {
|
||
show_progress $CURRENT_STEP $TOTAL_STEPS "Environment Selection"
|
||
|
||
cat << EOF
|
||
${WHITE}Select Deployment Environment${NC}
|
||
|
||
${CYAN}Available environments:${NC}
|
||
1) ${GREEN}Development${NC} - Local development with debug enabled
|
||
2) ${YELLOW}Staging${NC} - Pre-production testing environment
|
||
3) ${RED}Production${NC} - Live production environment (recommended)
|
||
|
||
${WHITE}Which environment would you like to configure?${NC}
|
||
EOF
|
||
|
||
while true; do
|
||
printf "${CYAN}Enter choice (1-3): ${NC}"
|
||
read -r choice
|
||
|
||
case $choice in
|
||
1)
|
||
ENVIRONMENT="development"
|
||
DOMAIN="dev.michaelschiemer.de"
|
||
info "Selected: Development environment"
|
||
break
|
||
;;
|
||
2)
|
||
ENVIRONMENT="staging"
|
||
DOMAIN="staging.michaelschiemer.de"
|
||
info "Selected: Staging environment"
|
||
break
|
||
;;
|
||
3)
|
||
ENVIRONMENT="production"
|
||
DOMAIN="michaelschiemer.de"
|
||
info "Selected: Production environment"
|
||
break
|
||
;;
|
||
*)
|
||
error "Invalid choice. Please enter 1, 2, or 3."
|
||
;;
|
||
esac
|
||
done
|
||
|
||
CONFIG_VALUES[ENVIRONMENT]=$ENVIRONMENT
|
||
CONFIG_VALUES[DOMAIN]=$DOMAIN
|
||
}
|
||
|
||
# Step 2: Domain and Contact Configuration
|
||
step_domain_configuration() {
|
||
show_progress $CURRENT_STEP $TOTAL_STEPS "Domain and Contact Information"
|
||
|
||
cat << EOF
|
||
${WHITE}Domain and Contact Configuration${NC}
|
||
|
||
Current settings:
|
||
• Environment: ${GREEN}${ENVIRONMENT}${NC}
|
||
• Suggested domain: ${GREEN}${DOMAIN}${NC}
|
||
• Contact email: ${GREEN}kontakt@michaelschiemer.de${NC}
|
||
EOF
|
||
|
||
printf "\n${CYAN}Is this domain correct? [Y/n]: ${NC}"
|
||
read -r confirm
|
||
|
||
if [[ $confirm =~ ^[Nn]$ ]]; then
|
||
printf "${CYAN}Enter your domain name: ${NC}"
|
||
read -r custom_domain
|
||
if [[ -n "$custom_domain" ]]; then
|
||
DOMAIN="$custom_domain"
|
||
CONFIG_VALUES[DOMAIN]="$custom_domain"
|
||
info "Domain updated to: $custom_domain"
|
||
fi
|
||
fi
|
||
|
||
EMAIL="kontakt@michaelschiemer.de"
|
||
printf "${CYAN}Contact email for SSL certificates [${EMAIL}]: ${NC}"
|
||
read -r custom_email
|
||
if [[ -n "$custom_email" ]]; then
|
||
EMAIL="$custom_email"
|
||
fi
|
||
|
||
CONFIG_VALUES[EMAIL]=$EMAIL
|
||
success "Domain configuration completed"
|
||
}
|
||
|
||
# Step 3: Server Configuration
|
||
step_server_configuration() {
|
||
show_progress $CURRENT_STEP $TOTAL_STEPS "Server Configuration"
|
||
|
||
cat << EOF
|
||
${WHITE}Server Configuration${NC}
|
||
|
||
Enter your deployment server details:
|
||
EOF
|
||
|
||
while true; do
|
||
printf "${CYAN}Server IP address or hostname: ${NC}"
|
||
read -r server_ip
|
||
|
||
if [[ -n "$server_ip" ]]; then
|
||
if [[ $server_ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] || [[ $server_ip =~ ^[a-zA-Z0-9.-]+$ ]]; then
|
||
SERVER_IP="$server_ip"
|
||
CONFIG_VALUES[SERVER_IP]="$server_ip"
|
||
break
|
||
else
|
||
error "Invalid IP address or hostname format"
|
||
fi
|
||
else
|
||
error "Server IP/hostname is required"
|
||
fi
|
||
done
|
||
|
||
printf "${CYAN}SSH username [root]: ${NC}"
|
||
read -r ssh_user
|
||
ssh_user=${ssh_user:-root}
|
||
CONFIG_VALUES[SSH_USER]="$ssh_user"
|
||
|
||
printf "${CYAN}SSH port [22]: ${NC}"
|
||
read -r ssh_port
|
||
ssh_port=${ssh_port:-22}
|
||
CONFIG_VALUES[SSH_PORT]="$ssh_port"
|
||
|
||
info "Server: ${ssh_user}@${SERVER_IP}:${ssh_port}"
|
||
success "Server configuration completed"
|
||
}
|
||
|
||
# Step 4: SSH Key Setup
|
||
step_ssh_key_setup() {
|
||
show_progress $CURRENT_STEP $TOTAL_STEPS "SSH Key Configuration"
|
||
|
||
cat << EOF
|
||
${WHITE}SSH Key Setup${NC}
|
||
|
||
We need SSH access to your server for deployment.
|
||
EOF
|
||
|
||
local default_key="$HOME/.ssh/production"
|
||
printf "${CYAN}SSH private key path [${default_key}]: ${NC}"
|
||
read -r key_path
|
||
SSH_KEY_PATH=${key_path:-$default_key}
|
||
|
||
if [[ ! -f "$SSH_KEY_PATH" ]]; then
|
||
warn "SSH key not found: $SSH_KEY_PATH"
|
||
printf "${CYAN}Generate new SSH key pair? [Y/n]: ${NC}"
|
||
read -r generate_key
|
||
|
||
if [[ ! $generate_key =~ ^[Nn]$ ]]; then
|
||
info "Generating SSH key pair..."
|
||
|
||
mkdir -p "$(dirname "$SSH_KEY_PATH")"
|
||
ssh-keygen -t ed25519 -C "deploy@${DOMAIN}" -f "$SSH_KEY_PATH" -N ""
|
||
|
||
success "SSH key pair generated:"
|
||
info "Private key: $SSH_KEY_PATH"
|
||
info "Public key: ${SSH_KEY_PATH}.pub"
|
||
|
||
cat << EOF
|
||
|
||
${YELLOW}📋 COPY THIS PUBLIC KEY TO YOUR SERVER:${NC}
|
||
|
||
$(cat "${SSH_KEY_PATH}.pub")
|
||
|
||
${YELLOW}Add this key to ~/.ssh/authorized_keys on your server.${NC}
|
||
|
||
EOF
|
||
printf "${CYAN}Press Enter when you've added the key to your server...${NC}"
|
||
read -r
|
||
fi
|
||
else
|
||
success "Found existing SSH key: $SSH_KEY_PATH"
|
||
fi
|
||
|
||
CONFIG_VALUES[SSH_KEY_PATH]="$SSH_KEY_PATH"
|
||
}
|
||
|
||
# Step 5: Test Server Connectivity
|
||
step_test_connectivity() {
|
||
show_progress $CURRENT_STEP $TOTAL_STEPS "Server Connectivity Test"
|
||
|
||
cat << EOF
|
||
${WHITE}Testing Server Connectivity${NC}
|
||
|
||
Testing SSH connection to ${CONFIG_VALUES[SSH_USER]}@${CONFIG_VALUES[SERVER_IP]}...
|
||
EOF
|
||
|
||
if ssh -i "$SSH_KEY_PATH" -p "${CONFIG_VALUES[SSH_PORT]}" \
|
||
-o ConnectTimeout=10 -o BatchMode=yes \
|
||
"${CONFIG_VALUES[SSH_USER]}@${CONFIG_VALUES[SERVER_IP]}" \
|
||
"echo 'Connection successful'" 2>/dev/null; then
|
||
success "SSH connection test passed"
|
||
|
||
info "Testing server requirements..."
|
||
local server_info
|
||
server_info=$(ssh -i "$SSH_KEY_PATH" -p "${CONFIG_VALUES[SSH_PORT]}" \
|
||
"${CONFIG_VALUES[SSH_USER]}@${CONFIG_VALUES[SERVER_IP]}" \
|
||
"uname -a && free -h && df -h /" 2>/dev/null)
|
||
|
||
echo -e "${BLUE}Server Information:${NC}"
|
||
echo "$server_info"
|
||
|
||
else
|
||
error "SSH connection failed"
|
||
cat << EOF
|
||
|
||
${YELLOW}Troubleshooting tips:${NC}
|
||
1. Verify the server IP and SSH port
|
||
2. Ensure your SSH public key is in ~/.ssh/authorized_keys on the server
|
||
3. Check if SSH service is running on the server
|
||
4. Verify firewall allows SSH connections
|
||
|
||
EOF
|
||
printf "${CYAN}Continue anyway? [y/N]: ${NC}"
|
||
read -r continue_anyway
|
||
if [[ ! $continue_anyway =~ ^[Yy]$ ]]; then
|
||
error "Setup cancelled due to connectivity issues"
|
||
exit 1
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Step 6: Secure Password Generation
|
||
step_password_generation() {
|
||
show_progress $CURRENT_STEP $TOTAL_STEPS "Secure Credential Generation"
|
||
|
||
cat << EOF
|
||
${WHITE}Generating Secure Credentials${NC}
|
||
|
||
Creating secure passwords and keys for your deployment...
|
||
EOF
|
||
|
||
if ! command -v openssl >/dev/null 2>&1; then
|
||
error "OpenSSL not found. Please install OpenSSL first."
|
||
exit 1
|
||
fi
|
||
|
||
info "Generating database passwords..."
|
||
PASSWORD_STORE[DB_PASSWORD]=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
|
||
PASSWORD_STORE[DB_ROOT_PASSWORD]=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
|
||
|
||
info "Generating Redis password..."
|
||
PASSWORD_STORE[REDIS_PASSWORD]=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
|
||
|
||
info "Generating application key..."
|
||
PASSWORD_STORE[APP_KEY]=$(openssl rand -base64 32)
|
||
|
||
if [[ "$ENVIRONMENT" == "production" ]]; then
|
||
info "Generating monitoring passwords..."
|
||
PASSWORD_STORE[GRAFANA_ADMIN_PASSWORD]=$(openssl rand -base64 16 | tr -d "=+/" | cut -c1-16)
|
||
fi
|
||
|
||
success "All credentials generated securely"
|
||
|
||
# Show password strength
|
||
cat << EOF
|
||
|
||
${CYAN}Password Strength Summary:${NC}
|
||
• Database passwords: 25 characters, alphanumeric
|
||
• Redis password: 25 characters, alphanumeric
|
||
• Application key: 32 characters, base64 encoded
|
||
• All passwords cryptographically secure
|
||
EOF
|
||
}
|
||
|
||
# Step 7: Configuration File Creation
|
||
step_create_configuration() {
|
||
show_progress $CURRENT_STEP $TOTAL_STEPS "Configuration File Creation"
|
||
|
||
cat << EOF
|
||
${WHITE}Creating Configuration Files${NC}
|
||
|
||
Building environment configuration for ${ENVIRONMENT}...
|
||
EOF
|
||
|
||
local env_file="${DEPLOYMENT_DIR}/applications/environments/.env.${ENVIRONMENT}"
|
||
local template_file="${env_file}.template"
|
||
|
||
if [[ ! -f "$template_file" ]]; then
|
||
error "Template file not found: $template_file"
|
||
exit 1
|
||
fi
|
||
|
||
info "Creating .env.${ENVIRONMENT} from template..."
|
||
cp "$template_file" "$env_file"
|
||
|
||
# Apply configurations
|
||
info "Applying domain and email settings..."
|
||
sed -i "s|DOMAIN_NAME=.*|DOMAIN_NAME=${CONFIG_VALUES[DOMAIN]}|g" "$env_file"
|
||
sed -i "s|MAIL_FROM_ADDRESS=.*|MAIL_FROM_ADDRESS=${CONFIG_VALUES[EMAIL]}|g" "$env_file"
|
||
|
||
# Apply generated passwords
|
||
info "Applying secure credentials..."
|
||
for key in "${!PASSWORD_STORE[@]}"; do
|
||
local value="${PASSWORD_STORE[$key]}"
|
||
sed -i "s|${key}=\*\*\* REQUIRED \*\*\*|${key}=${value}|g" "$env_file"
|
||
sed -i "s|${key}=changeme|${key}=${value}|g" "$env_file"
|
||
done
|
||
|
||
# Environment-specific settings
|
||
if [[ "$ENVIRONMENT" == "production" ]]; then
|
||
sed -i 's|APP_DEBUG=.*|APP_DEBUG=false|g' "$env_file"
|
||
sed -i 's|LOG_LEVEL=.*|LOG_LEVEL=warning|g' "$env_file"
|
||
fi
|
||
|
||
# Set secure permissions
|
||
chmod 600 "$env_file"
|
||
|
||
success "Configuration file created: $env_file"
|
||
|
||
# Update Ansible inventory
|
||
info "Updating Ansible inventory..."
|
||
local inventory_file="${DEPLOYMENT_DIR}/infrastructure/inventories/${ENVIRONMENT}/hosts.yml"
|
||
|
||
if [[ -f "$inventory_file" ]]; then
|
||
# Backup original
|
||
cp "$inventory_file" "${inventory_file}.backup"
|
||
|
||
# Update server details
|
||
sed -i "s|ansible_host:.*|ansible_host: ${CONFIG_VALUES[SERVER_IP]}|g" "$inventory_file"
|
||
sed -i "s|ansible_user:.*|ansible_user: ${CONFIG_VALUES[SSH_USER]}|g" "$inventory_file"
|
||
sed -i "s|ansible_port:.*|ansible_port: ${CONFIG_VALUES[SSH_PORT]}|g" "$inventory_file"
|
||
sed -i "s|ansible_ssh_private_key_file:.*|ansible_ssh_private_key_file: ${CONFIG_VALUES[SSH_KEY_PATH]}|g" "$inventory_file"
|
||
|
||
success "Ansible inventory updated: $inventory_file"
|
||
else
|
||
warn "Ansible inventory not found: $inventory_file"
|
||
fi
|
||
}
|
||
|
||
# Step 8: Final Validation and Summary
|
||
step_final_validation() {
|
||
show_progress $CURRENT_STEP $TOTAL_STEPS "Final Validation"
|
||
|
||
cat << EOF
|
||
${WHITE}Final Validation and Summary${NC}
|
||
|
||
Running configuration validation...
|
||
EOF
|
||
|
||
# Validate configuration
|
||
local env_file="${DEPLOYMENT_DIR}/applications/environments/.env.${ENVIRONMENT}"
|
||
|
||
info "Validating environment configuration..."
|
||
if grep -q "\*\*\* REQUIRED \*\*\*" "$env_file" 2>/dev/null; then
|
||
error "Some required fields are still unfilled:"
|
||
grep "\*\*\* REQUIRED \*\*\*" "$env_file"
|
||
exit 1
|
||
fi
|
||
|
||
success "All required fields are configured"
|
||
|
||
# Test Docker Compose configuration
|
||
info "Validating Docker Compose configuration..."
|
||
cd "$PROJECT_ROOT"
|
||
if docker-compose -f docker-compose.yml -f "deployment/applications/docker-compose.${ENVIRONMENT}.yml" config >/dev/null 2>&1; then
|
||
success "Docker Compose configuration is valid"
|
||
else
|
||
warn "Docker Compose validation failed - may need manual review"
|
||
fi
|
||
|
||
# Show summary
|
||
cat << EOF
|
||
|
||
${WHITE}🎉 SETUP WIZARD COMPLETED SUCCESSFULLY! 🎉${NC}
|
||
|
||
${CYAN}Configuration Summary:${NC}
|
||
• Environment: ${WHITE}${ENVIRONMENT}${NC}
|
||
• Domain: ${WHITE}${CONFIG_VALUES[DOMAIN]}${NC}
|
||
• Server: ${WHITE}${CONFIG_VALUES[SSH_USER]}@${CONFIG_VALUES[SERVER_IP]}:${CONFIG_VALUES[SSH_PORT]}${NC}
|
||
• SSH Key: ${WHITE}${CONFIG_VALUES[SSH_KEY_PATH]}${NC}
|
||
• Configuration: ${WHITE}.env.${ENVIRONMENT}${NC}
|
||
|
||
${CYAN}Generated Secure Credentials:${NC}
|
||
• Database passwords: ${GREEN}Generated${NC}
|
||
• Redis password: ${GREEN}Generated${NC}
|
||
• Application key: ${GREEN}Generated${NC}
|
||
EOF
|
||
|
||
if [[ "$ENVIRONMENT" == "production" ]]; then
|
||
echo "• Monitoring passwords: ${GREEN}Generated${NC}"
|
||
fi
|
||
|
||
cat << EOF
|
||
|
||
${CYAN}Files Created/Updated:${NC}
|
||
• ${YELLOW}deployment/applications/environments/.env.${ENVIRONMENT}${NC}
|
||
• ${YELLOW}deployment/infrastructure/inventories/${ENVIRONMENT}/hosts.yml${NC}
|
||
• ${YELLOW}${CONFIG_VALUES[SSH_KEY_PATH]} (if generated)${NC}
|
||
|
||
${CYAN}Next Steps:${NC}
|
||
1. Review configuration: ${YELLOW}less deployment/applications/environments/.env.${ENVIRONMENT}${NC}
|
||
2. Test deployment: ${YELLOW}./deployment/deploy.sh ${ENVIRONMENT} --dry-run${NC}
|
||
3. Deploy: ${YELLOW}./deployment/deploy.sh ${ENVIRONMENT}${NC}
|
||
|
||
${GREEN}Your Custom PHP Framework is ready for deployment!${NC}
|
||
${CYAN}Domain: ${CONFIG_VALUES[DOMAIN]} | Environment: ${ENVIRONMENT}${NC}
|
||
|
||
EOF
|
||
}
|
||
|
||
# Main wizard flow
|
||
main() {
|
||
show_welcome
|
||
|
||
# Execute wizard steps
|
||
CURRENT_STEP=1; step_environment_selection; ((CURRENT_STEP++))
|
||
CURRENT_STEP=2; step_domain_configuration; ((CURRENT_STEP++))
|
||
CURRENT_STEP=3; step_server_configuration; ((CURRENT_STEP++))
|
||
CURRENT_STEP=4; step_ssh_key_setup; ((CURRENT_STEP++))
|
||
CURRENT_STEP=5; step_test_connectivity; ((CURRENT_STEP++))
|
||
CURRENT_STEP=6; step_password_generation; ((CURRENT_STEP++))
|
||
CURRENT_STEP=7; step_create_configuration; ((CURRENT_STEP++))
|
||
CURRENT_STEP=8; step_final_validation; ((CURRENT_STEP++))
|
||
|
||
success "Setup wizard completed successfully!"
|
||
}
|
||
|
||
# Error handling
|
||
cleanup() {
|
||
local exit_code=$?
|
||
if [ $exit_code -ne 0 ]; then
|
||
error "Setup wizard failed with exit code: $exit_code"
|
||
echo
|
||
echo -e "${RED}If you need help, check the troubleshooting guide or start over.${NC}"
|
||
fi
|
||
}
|
||
|
||
trap cleanup EXIT
|
||
|
||
# Execute if run directly
|
||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||
main "$@"
|
||
fi |