Last active
February 3, 2026 11:48
-
-
Save arif98741/edfc9daa121a2a7f301ecc17919dba6c to your computer and use it in GitHub Desktop.
Laravel 10 Deployment Gist
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| #=============================================================================== | |
| # Laravel Deployment Script | |
| # Version: 1.0 | |
| # Description: Automated deployment script for Laravel 10 applications | |
| #=============================================================================== | |
| # Colors for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| CYAN='\033[0;36m' | |
| NC='\033[0m' # No Color | |
| # Configuration | |
| PROJECT_DIR="" | |
| START_TIME=$(date +%s) | |
| # Project Directories - Add your projects here | |
| PROJECTS=( | |
| "/var/www/html/laravel10" | |
| "/var/www/html/clients/stanbic-staging" | |
| ) | |
| # Project Names (for display) | |
| PROJECT_NAMES=( | |
| "Client Demo" | |
| "Stanbic Staging" | |
| ) | |
| # Project Shortcodes (for quick selection) | |
| PROJECT_CODES=( | |
| "demo" | |
| "stanbic-staging" | |
| ) | |
| # Counters for report | |
| STEPS_TOTAL=9 | |
| STEPS_PASSED=0 | |
| STEPS_FAILED=0 | |
| # Step Results Tracking (0=pending, 1=passed, 2=failed, 3=skipped) | |
| declare -a STEP_RESULTS=(0 0 0 0 0 0 0 0 0) | |
| declare -a STEP_NAMES=( | |
| "Change Directory" | |
| "Git Pull" | |
| "Composer Install" | |
| "Database Migration" | |
| "Laravel Optimization" | |
| "NPM Build" | |
| "Permission Import" | |
| "File Permissions" | |
| "Supervisor Restart" | |
| ) | |
| #=============================================================================== | |
| # Helper Functions | |
| #=============================================================================== | |
| print_header() { | |
| echo "" | |
| echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}" | |
| echo -e "${CYAN}║ LARAVEL DEPLOYMENT SCRIPT v1.0 ║${NC}" | |
| echo -e "${CYAN}║ $(date '+%Y-%m-%d %H:%M:%S') ║${NC}" | |
| echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}" | |
| echo "" | |
| } | |
| print_step() { | |
| local step_num=$1 | |
| local step_name=$2 | |
| echo "" | |
| echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" | |
| echo -e "${BLUE} STEP ${step_num}/${STEPS_TOTAL}: ${step_name}${NC}" | |
| echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" | |
| } | |
| print_success() { | |
| echo -e "${GREEN} ✓ $1${NC}" | |
| } | |
| print_error() { | |
| echo -e "${RED} ✗ $1${NC}" | |
| } | |
| print_warning() { | |
| echo -e "${YELLOW} ⚠ $1${NC}" | |
| } | |
| print_info() { | |
| echo -e "${CYAN} ℹ $1${NC}" | |
| } | |
| # Check if command exists | |
| command_exists() { | |
| command -v "$1" >/dev/null 2>&1 | |
| } | |
| # Mark step result (step_index, status: 1=passed, 2=failed, 3=skipped) | |
| mark_step() { | |
| local step_index=$1 | |
| local status=$2 | |
| STEP_RESULTS[$step_index]=$status | |
| } | |
| # Display project selection menu | |
| select_project() { | |
| echo "" | |
| local num_projects=${#PROJECTS[@]} | |
| echo -e "${CYAN}┌────────────────────────────────────────────────────────────────────────────────────────────────────┐${NC}" | |
| echo -e "${CYAN}│${NC} ${YELLOW}SELECT PROJECT TO DEPLOY${NC} ${CYAN}│${NC}" | |
| echo -e "${CYAN}├──────┬──────────────────┬────────────────────┬──────────────────────────────────────────────────────┤${NC}" | |
| echo -e "${CYAN}│${NC} ${YELLOW} #${NC} ${CYAN}│${NC} ${YELLOW}CODE${NC} ${CYAN}│${NC} ${YELLOW}PROJECT NAME${NC} ${CYAN}│${NC} ${YELLOW}PATH${NC} ${CYAN}│${NC}" | |
| echo -e "${CYAN}├──────┼──────────────────┼────────────────────┼──────────────────────────────────────────────────────┤${NC}" | |
| for i in "${!PROJECTS[@]}"; do | |
| local num=$((i + 1)) | |
| printf "${CYAN}│${NC} ${GREEN}%d${NC} ${CYAN}│${NC} ${BLUE}%-16s${NC} ${CYAN}│${NC} %-18s ${CYAN}│${NC} %-52s ${CYAN}│${NC}\n" "$num" "${PROJECT_CODES[$i]}" "${PROJECT_NAMES[$i]}" "${PROJECTS[$i]}" | |
| done | |
| echo -e "${CYAN}├──────┼──────────────────┼────────────────────┴──────────────────────────────────────────────────────┤${NC}" | |
| printf "${CYAN}│${NC} ${RED}0${NC} ${CYAN}│${NC} ${RED}exit${NC} ${CYAN}│${NC} ${RED}Exit the deployment script${NC} ${CYAN}│${NC}\n" | |
| echo -e "${CYAN}└──────┴──────────────────┴─────────────────────────────────────────────────────────────────────────────┘${NC}" | |
| echo "" | |
| while true; do | |
| echo -ne "${GREEN}Enter number or code: ${NC}" | |
| read -r choice | |
| # Check for exit | |
| if [[ "$choice" == "0" ]] || [[ "$choice" == "exit" ]]; then | |
| echo -e "${YELLOW}Deployment cancelled.${NC}" | |
| exit 0 | |
| fi | |
| # Check if input is a number | |
| if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "$num_projects" ]; then | |
| local index=$((choice - 1)) | |
| PROJECT_DIR="${PROJECTS[$index]}" | |
| echo "" | |
| echo -e "${GREEN}✓ Selected: ${PROJECT_NAMES[$index]}${NC}" | |
| echo -e "${CYAN} Path: ${PROJECT_DIR}${NC}" | |
| return 0 | |
| fi | |
| # Check if input is a shortcode | |
| for i in "${!PROJECT_CODES[@]}"; do | |
| if [[ "${PROJECT_CODES[$i]}" == "$choice" ]]; then | |
| PROJECT_DIR="${PROJECTS[$i]}" | |
| echo "" | |
| echo -e "${GREEN}✓ Selected: ${PROJECT_NAMES[$i]}${NC}" | |
| echo -e "${CYAN} Path: ${PROJECT_DIR}${NC}" | |
| return 0 | |
| fi | |
| done | |
| echo -e "${RED}Invalid choice. Enter a number (1-${num_projects}) or shortcode${NC}" | |
| done | |
| } | |
| #=============================================================================== | |
| # Step 1: Change Directory | |
| #=============================================================================== | |
| step_change_directory() { | |
| print_step 1 "SWITCHING TO PROJECT DIRECTORY" | |
| if [ -z "$PROJECT_DIR" ]; then | |
| print_error "Project directory not specified!" | |
| print_info "Please select a project from the menu" | |
| mark_step 0 2 | |
| return 1 | |
| fi | |
| if [ ! -d "$PROJECT_DIR" ]; then | |
| print_error "Directory does not exist: $PROJECT_DIR" | |
| mark_step 0 2 | |
| return 1 | |
| fi | |
| cd "$PROJECT_DIR" || { | |
| print_error "Failed to change to directory: $PROJECT_DIR" | |
| mark_step 0 2 | |
| return 1 | |
| } | |
| print_success "Changed to directory: $(pwd)" | |
| # Verify it's a Laravel project | |
| if [ ! -f "artisan" ]; then | |
| print_error "This does not appear to be a Laravel project (artisan not found)" | |
| mark_step 0 2 | |
| return 1 | |
| fi | |
| print_success "Laravel project detected" | |
| mark_step 0 1 | |
| return 0 | |
| } | |
| #=============================================================================== | |
| # Step 2: Git Pull | |
| #=============================================================================== | |
| step_git_pull() { | |
| print_step 2 "PULLING LATEST CHANGES FROM GIT" | |
| if [ ! -d ".git" ]; then | |
| print_warning "Not a git repository, skipping git pull" | |
| mark_step 1 3 | |
| return 0 | |
| fi | |
| # Show current branch | |
| CURRENT_BRANCH=$(git branch --show-current 2>/dev/null) | |
| print_info "Current branch: $CURRENT_BRANCH" | |
| # Check for uncommitted changes | |
| if ! git diff-index --quiet HEAD -- 2>/dev/null; then | |
| print_warning "You have uncommitted changes" | |
| git status --short | |
| fi | |
| # Ask for branch to deploy | |
| echo "" | |
| echo -ne "${GREEN}Enter branch name to deploy (default: $CURRENT_BRANCH): ${NC}" | |
| read -r TARGET_BRANCH | |
| # Use current branch if no input | |
| if [ -z "$TARGET_BRANCH" ]; then | |
| TARGET_BRANCH="$CURRENT_BRANCH" | |
| fi | |
| print_info "Target branch: $TARGET_BRANCH" | |
| # Fetch only the specific branch from origin | |
| print_info "Fetching origin/$TARGET_BRANCH..." | |
| FETCH_OUTPUT=$(git fetch origin "$TARGET_BRANCH" 2>&1) | |
| FETCH_STATUS=$? | |
| if [ $FETCH_STATUS -ne 0 ]; then | |
| echo "$FETCH_OUTPUT" | |
| print_error "Failed to fetch branch: $TARGET_BRANCH" | |
| mark_step 1 2 | |
| return 1 | |
| fi | |
| print_success "Fetched origin/$TARGET_BRANCH" | |
| # Checkout the target branch if different from current | |
| if [ "$TARGET_BRANCH" != "$CURRENT_BRANCH" ]; then | |
| print_info "Checking out branch: $TARGET_BRANCH..." | |
| CHECKOUT_OUTPUT=$(git checkout "$TARGET_BRANCH" 2>&1) | |
| CHECKOUT_STATUS=$? | |
| if [ $CHECKOUT_STATUS -ne 0 ]; then | |
| echo "$CHECKOUT_OUTPUT" | |
| print_error "Failed to checkout branch: $TARGET_BRANCH" | |
| mark_step 1 2 | |
| return 1 | |
| fi | |
| print_success "Checked out branch: $TARGET_BRANCH" | |
| fi | |
| # Pull latest changes | |
| print_info "Pulling latest changes from origin/$TARGET_BRANCH..." | |
| GIT_OUTPUT=$(git pull origin "$TARGET_BRANCH" 2>&1) | |
| GIT_STATUS=$? | |
| if [ $GIT_STATUS -eq 0 ]; then | |
| echo "$GIT_OUTPUT" | |
| print_success "Git pull completed successfully" | |
| mark_step 1 1 | |
| return 0 | |
| else | |
| echo "$GIT_OUTPUT" | |
| print_error "Git pull failed" | |
| mark_step 1 2 | |
| return 1 | |
| fi | |
| } | |
| #=============================================================================== | |
| # Step 3: Install/Update Composer Dependencies | |
| #=============================================================================== | |
| step_composer_install() { | |
| print_step 3 "INSTALLING COMPOSER DEPENDENCIES" | |
| if ! command_exists composer; then | |
| print_error "Composer is not installed" | |
| mark_step 2 2 | |
| return 1 | |
| fi | |
| print_info "Running composer install --no-interaction --prefer-dist --optimize-autoloader" | |
| COMPOSER_OUTPUT=$(composer install --no-interaction --prefer-dist --optimize-autoloader 2>&1) | |
| COMPOSER_STATUS=$? | |
| if [ $COMPOSER_STATUS -eq 0 ]; then | |
| echo "$COMPOSER_OUTPUT" | tail -10 | |
| print_success "Composer dependencies installed successfully" | |
| mark_step 2 1 | |
| return 0 | |
| else | |
| echo "$COMPOSER_OUTPUT" | |
| print_error "Composer install failed" | |
| mark_step 2 2 | |
| return 1 | |
| fi | |
| } | |
| #=============================================================================== | |
| # Step 4: Run Database Migrations | |
| #=============================================================================== | |
| step_run_migrations() { | |
| print_step 4 "RUNNING DATABASE MIGRATIONS" | |
| echo "" | |
| echo -ne "${GREEN}Do you want to run database migrations? (y/n): ${NC}" | |
| read -r MIGRATE_CHOICE | |
| # Flush any remaining stdin to prevent buffered input issues | |
| read -t 0.1 -n 10000 discard 2>/dev/null || true | |
| if [[ "$MIGRATE_CHOICE" != "y" && "$MIGRATE_CHOICE" != "Y" ]]; then | |
| print_warning "Database migrations skipped by user" | |
| mark_step 3 3 | |
| return 0 | |
| fi | |
| print_info "Executing: php artisan migrate --force" | |
| MIGRATION_OUTPUT=$(php artisan migrate --force 2>&1) | |
| MIGRATION_STATUS=$? | |
| if [ $MIGRATION_STATUS -eq 0 ]; then | |
| echo "$MIGRATION_OUTPUT" | |
| print_success "Database migrations completed successfully" | |
| mark_step 3 1 | |
| return 0 | |
| else | |
| echo "$MIGRATION_OUTPUT" | |
| print_error "Database migrations failed" | |
| mark_step 3 2 | |
| return 1 | |
| fi | |
| } | |
| #=============================================================================== | |
| # Step 5: Run Laravel Optimizations | |
| #=============================================================================== | |
| step_run_optimizations() { | |
| print_step 5 "RUNNING LARAVEL OPTIMIZATIONS" | |
| print_info "Running optimize:clear..." | |
| OPTIMIZE_OUTPUT=$(php artisan optimize:clear 2>&1) | |
| OPTIMIZE_STATUS=$? | |
| if [ $OPTIMIZE_STATUS -eq 0 ]; then | |
| echo "$OPTIMIZE_OUTPUT" | |
| print_success "Optimization cache cleared successfully" | |
| mark_step 4 1 | |
| return 0 | |
| else | |
| echo "$OPTIMIZE_OUTPUT" | |
| print_error "optimize:clear failed" | |
| mark_step 4 2 | |
| return 1 | |
| fi | |
| } | |
| #=============================================================================== | |
| # Step 6: Build Frontend Assets | |
| #=============================================================================== | |
| step_npm_build() { | |
| print_step 6 "BUILDING FRONTEND ASSETS" | |
| # Check if package.json exists | |
| if [ ! -f "package.json" ]; then | |
| print_warning "No package.json found, skipping npm build" | |
| mark_step 5 3 | |
| return 0 | |
| fi | |
| # Check for npm | |
| if ! command_exists npm; then | |
| print_error "npm is not installed" | |
| mark_step 5 2 | |
| return 1 | |
| fi | |
| # Install npm dependencies | |
| print_info "Installing npm dependencies..." | |
| NPM_INSTALL_OUTPUT=$(npm install 2>&1) | |
| NPM_INSTALL_STATUS=$? | |
| if [ $NPM_INSTALL_STATUS -ne 0 ]; then | |
| echo "$NPM_INSTALL_OUTPUT" | |
| print_error "npm install failed" | |
| mark_step 5 2 | |
| return 1 | |
| fi | |
| print_success "npm dependencies installed" | |
| # Run production build | |
| print_info "Building production assets (npm run prod)..." | |
| # Check which script is available | |
| if grep -q '"prod"' package.json; then | |
| NPM_BUILD_OUTPUT=$(npm run prod 2>&1) | |
| elif grep -q '"build"' package.json; then | |
| print_info "Using 'npm run build' instead of 'npm run prod'" | |
| NPM_BUILD_OUTPUT=$(npm run build 2>&1) | |
| else | |
| print_warning "No 'prod' or 'build' script found in package.json" | |
| mark_step 5 3 | |
| return 0 | |
| fi | |
| NPM_BUILD_STATUS=$? | |
| if [ $NPM_BUILD_STATUS -eq 0 ]; then | |
| echo "$NPM_BUILD_OUTPUT" | tail -15 | |
| print_success "Frontend assets built successfully" | |
| mark_step 5 1 | |
| return 0 | |
| else | |
| echo "$NPM_BUILD_OUTPUT" | |
| print_error "Frontend build failed" | |
| mark_step 5 2 | |
| return 1 | |
| fi | |
| } | |
| #=============================================================================== | |
| # Step 7: Import Permissions | |
| #=============================================================================== | |
| step_permission_import() { | |
| print_step 7 "IMPORTING PERMISSIONS" | |
| print_info "Executing: php artisan permission:import" | |
| PERMISSION_OUTPUT=$(php artisan permission:import 2>&1) | |
| PERMISSION_STATUS=$? | |
| if [ $PERMISSION_STATUS -eq 0 ]; then | |
| echo "$PERMISSION_OUTPUT" | |
| print_success "Permissions imported successfully" | |
| mark_step 6 1 | |
| return 0 | |
| else | |
| echo "$PERMISSION_OUTPUT" | |
| print_error "Permission import failed" | |
| mark_step 6 2 | |
| return 1 | |
| fi | |
| } | |
| #=============================================================================== | |
| # Step 8: File Permissions | |
| #=============================================================================== | |
| step_file_permissions() { | |
| print_step 8 "SETTING FILE PERMISSIONS" | |
| echo "" | |
| echo -ne "${GREEN}Do you want to set file permissions? (y/n): ${NC}" | |
| read -r PERM_CHOICE | |
| # Flush any remaining stdin to prevent buffered input issues | |
| read -t 0.1 -n 10000 discard 2>/dev/null || true | |
| if [[ "$PERM_CHOICE" != "y" && "$PERM_CHOICE" != "Y" ]]; then | |
| print_warning "File permissions skipped by user" | |
| mark_step 7 3 | |
| return 0 | |
| fi | |
| # Show permission options menu | |
| echo "" | |
| echo -e "${CYAN}┌────────────────────────────────────────────────────────────────────────┐${NC}" | |
| echo -e "${CYAN}│${NC} ${YELLOW}FILE PERMISSION OPTIONS${NC} ${CYAN}│${NC}" | |
| echo -e "${CYAN}├──────┬─────────────────────────────┬───────────────────────────────────┤${NC}" | |
| echo -e "${CYAN}│${NC} ${YELLOW} #${NC} ${CYAN}│${NC} ${YELLOW}DIRECTORY${NC} ${CYAN}│${NC} ${YELLOW}COMMAND${NC} ${CYAN}│${NC}" | |
| echo -e "${CYAN}├──────┼─────────────────────────────┼───────────────────────────────────┤${NC}" | |
| printf "${CYAN}│${NC} ${GREEN}1${NC} ${CYAN}│${NC} %-27s ${CYAN}│${NC} %-33s ${CYAN}│${NC}\n" "storage/" "sudo chmod -R 775 storage/" | |
| printf "${CYAN}│${NC} ${GREEN}2${NC} ${CYAN}│${NC} %-27s ${CYAN}│${NC} %-33s ${CYAN}│${NC}\n" "bootstrap/cache/" "sudo chmod -R 775 bootstrap/cache/" | |
| printf "${CYAN}│${NC} ${GREEN}3${NC} ${CYAN}│${NC} %-27s ${CYAN}│${NC} %-33s ${CYAN}│${NC}\n" "public/" "sudo chmod -R 755 public/" | |
| printf "${CYAN}│${NC} ${GREEN}4${NC} ${CYAN}│${NC} %-27s ${CYAN}│${NC} %-33s ${CYAN}│${NC}\n" "All above" "Run options 1, 2, and 3" | |
| printf "${CYAN}│${NC} ${GREEN}5${NC} ${CYAN}│${NC} %-27s ${CYAN}│${NC} %-33s ${CYAN}│${NC}\n" "Custom command" "Enter your own chmod command" | |
| echo -e "${CYAN}├──────┼─────────────────────────────┴───────────────────────────────────┤${NC}" | |
| printf "${CYAN}│${NC} ${RED}0${NC} ${CYAN}│${NC} ${RED}Skip - Do not set any permissions${NC} ${CYAN}│${NC}\n" | |
| echo -e "${CYAN}└──────┴─────────────────────────────────────────────────────────────────┘${NC}" | |
| echo -e "${CYAN} Project directory: ${GREEN}${PROJECT_DIR}${NC}" | |
| echo "" | |
| echo -ne "${GREEN}Enter option number (0-5): ${NC}" | |
| read -r PERM_OPTION | |
| # Flush any remaining stdin | |
| read -t 0.1 -n 10000 discard 2>/dev/null || true | |
| local perm_success=true | |
| case "$PERM_OPTION" in | |
| 0) | |
| print_warning "File permissions skipped by user" | |
| mark_step 7 3 | |
| return 0 | |
| ;; | |
| 1) | |
| print_info "Setting permissions on storage/..." | |
| if sudo chmod -R 775 storage/ 2>&1; then | |
| print_success "Permissions set on storage/" | |
| else | |
| print_error "Failed to set permissions on storage/" | |
| perm_success=false | |
| fi | |
| ;; | |
| 2) | |
| print_info "Setting permissions on bootstrap/cache/..." | |
| if sudo chmod -R 775 bootstrap/cache/ 2>&1; then | |
| print_success "Permissions set on bootstrap/cache/" | |
| else | |
| print_error "Failed to set permissions on bootstrap/cache/" | |
| perm_success=false | |
| fi | |
| ;; | |
| 3) | |
| print_info "Setting permissions on public/..." | |
| if sudo chmod -R 755 public/ 2>&1; then | |
| print_success "Permissions set on public/" | |
| else | |
| print_error "Failed to set permissions on public/" | |
| perm_success=false | |
| fi | |
| ;; | |
| 4) | |
| print_info "Setting permissions on all directories..." | |
| print_info "Setting permissions on storage/..." | |
| if sudo chmod -R 775 storage/ 2>&1; then | |
| print_success "Permissions set on storage/" | |
| else | |
| print_error "Failed to set permissions on storage/" | |
| perm_success=false | |
| fi | |
| print_info "Setting permissions on bootstrap/cache/..." | |
| if sudo chmod -R 775 bootstrap/cache/ 2>&1; then | |
| print_success "Permissions set on bootstrap/cache/" | |
| else | |
| print_error "Failed to set permissions on bootstrap/cache/" | |
| perm_success=false | |
| fi | |
| print_info "Setting permissions on public/..." | |
| if sudo chmod -R 755 public/ 2>&1; then | |
| print_success "Permissions set on public/" | |
| else | |
| print_error "Failed to set permissions on public/" | |
| perm_success=false | |
| fi | |
| ;; | |
| 5) | |
| echo "" | |
| echo -e "${CYAN}Enter your custom chmod command (without sudo):${NC}" | |
| echo -e "${YELLOW}Example: chmod -R 775 storage/logs${NC}" | |
| echo -ne "${GREEN}Command: sudo ${NC}" | |
| read -r CUSTOM_CMD | |
| # Flush any remaining stdin | |
| read -t 0.1 -n 10000 discard 2>/dev/null || true | |
| if [ -z "$CUSTOM_CMD" ]; then | |
| print_warning "No command entered, skipping" | |
| mark_step 7 3 | |
| return 0 | |
| fi | |
| print_info "Executing: sudo $CUSTOM_CMD" | |
| if eval "sudo $CUSTOM_CMD" 2>&1; then | |
| print_success "Custom permission command executed successfully" | |
| else | |
| print_error "Custom permission command failed" | |
| perm_success=false | |
| fi | |
| ;; | |
| *) | |
| print_error "Invalid option selected" | |
| mark_step 7 2 | |
| return 1 | |
| ;; | |
| esac | |
| if [ "$perm_success" = true ]; then | |
| print_success "File permissions set successfully" | |
| mark_step 7 1 | |
| return 0 | |
| else | |
| print_error "Some file permissions failed" | |
| mark_step 7 2 | |
| return 1 | |
| fi | |
| } | |
| #=============================================================================== | |
| # Step 9: Restart Supervisor | |
| #=============================================================================== | |
| step_restart_supervisor() { | |
| print_step 9 "SUPERVISOR RESTART" | |
| echo "" | |
| echo -ne "${GREEN}Do you want to restart Supervisor? (y/n): ${NC}" | |
| read -r RESTART_CHOICE | |
| # Flush any remaining stdin to prevent buffered input issues | |
| read -t 0.1 -n 10000 discard 2>/dev/null || true | |
| if [[ "$RESTART_CHOICE" != "y" && "$RESTART_CHOICE" != "Y" ]]; then | |
| print_warning "Supervisor restart skipped by user" | |
| mark_step 8 3 | |
| return 0 | |
| fi | |
| # Check if supervisorctl exists | |
| if ! command_exists supervisorctl; then | |
| print_error "supervisorctl is not installed" | |
| mark_step 8 2 | |
| return 1 | |
| fi | |
| # Stop supervisor | |
| print_info "Stopping Supervisor..." | |
| STOP_OUTPUT=$(sudo systemctl stop supervisor 2>&1) | |
| STOP_STATUS=$? | |
| if [ $STOP_STATUS -ne 0 ]; then | |
| echo "$STOP_OUTPUT" | |
| print_error "Failed to stop Supervisor" | |
| mark_step 8 2 | |
| return 1 | |
| fi | |
| print_success "Supervisor stopped" | |
| # Start supervisor | |
| print_info "Starting Supervisor..." | |
| START_OUTPUT=$(sudo systemctl start supervisor 2>&1) | |
| START_STATUS=$? | |
| if [ $START_STATUS -ne 0 ]; then | |
| echo "$START_OUTPUT" | |
| print_error "Failed to start Supervisor" | |
| mark_step 8 2 | |
| return 1 | |
| fi | |
| print_success "Supervisor started" | |
| # Show supervisor status | |
| print_info "Supervisor status:" | |
| sudo systemctl status supervisor --no-pager < /dev/null | head -15 | |
| print_success "Supervisor restarted successfully" | |
| mark_step 8 1 | |
| return 0 | |
| } | |
| #=============================================================================== | |
| # Generate Report | |
| #=============================================================================== | |
| generate_report() { | |
| END_TIME=$(date +%s) | |
| DURATION=$((END_TIME - START_TIME)) | |
| MINUTES=$((DURATION / 60)) | |
| SECONDS=$((DURATION % 60)) | |
| # Calculate counts from STEP_RESULTS array | |
| local passed=0 | |
| local failed=0 | |
| local skipped=0 | |
| for result in "${STEP_RESULTS[@]}"; do | |
| case $result in | |
| 1) ((passed++)) ;; | |
| 2) ((failed++)) ;; | |
| 3) ((skipped++)) ;; | |
| esac | |
| done | |
| # Get version information | |
| local laravel_version="N/A" | |
| local os_version="N/A" | |
| local php_version="N/A" | |
| local npm_version="N/A" | |
| local composer_version="N/A" | |
| # Laravel version | |
| if [ -f "artisan" ]; then | |
| laravel_version=$(php artisan --version 2>/dev/null | grep -oP 'Laravel Framework \K[\d.]+' || echo "N/A") | |
| fi | |
| # OS version | |
| if [ -f /etc/os-release ]; then | |
| os_version=$(grep -oP 'PRETTY_NAME="\K[^"]+' /etc/os-release 2>/dev/null || echo "N/A") | |
| elif command_exists uname; then | |
| os_version=$(uname -sr 2>/dev/null || echo "N/A") | |
| fi | |
| # PHP version | |
| if command_exists php; then | |
| php_version=$(php -v 2>/dev/null | head -1 | grep -oP 'PHP \K[\d.]+' || echo "N/A") | |
| fi | |
| # NPM version | |
| if command_exists npm; then | |
| npm_version=$(npm -v 2>/dev/null || echo "N/A") | |
| fi | |
| # Composer version | |
| if command_exists composer; then | |
| composer_version=$(composer -V 2>/dev/null | grep -oP 'Composer version \K[\d.]+' || echo "N/A") | |
| fi | |
| echo "" | |
| echo "" | |
| echo -e "${CYAN}┌────────────────────────────────────────────────────────────────────────┐${NC}" | |
| echo -e "${CYAN}│${NC} ${YELLOW}DEPLOYMENT AND ENVIRONMENT REPORT${NC} ${CYAN}│${NC}" | |
| echo -e "${CYAN}├────────────────────────────────────────────────────────────────────────┤${NC}" | |
| printf "${CYAN}│${NC} ${GREEN}%-70s${NC} ${CYAN}│${NC}\n" "$PROJECT_DIR" | |
| echo -e "${CYAN}├───────────────────────────────────┬────────────────────────────────────┤${NC}" | |
| echo -e "${CYAN}│${NC} ${YELLOW}DEPLOYMENT INFO${NC} ${CYAN}│${NC} ${YELLOW}ENVIRONMENT${NC} ${CYAN}│${NC}" | |
| echo -e "${CYAN}├───────────────────────────────────┼────────────────────────────────────┤${NC}" | |
| printf "${CYAN}│${NC} Completed : ${GREEN}%-19s${NC} ${CYAN}│${NC} OS : ${GREEN}%-21s${NC} ${CYAN}│${NC}\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$os_version" | |
| printf "${CYAN}│${NC} Duration : ${GREEN}%-19s${NC} ${CYAN}│${NC} PHP : ${GREEN}%-21s${NC} ${CYAN}│${NC}\n" "${MINUTES}m ${SECONDS}s" "$php_version" | |
| printf "${CYAN}│${NC} %-31s ${CYAN}│${NC} Laravel : ${GREEN}%-21s${NC} ${CYAN}│${NC}\n" "" "$laravel_version" | |
| printf "${CYAN}│${NC} %-31s ${CYAN}│${NC} Composer : ${GREEN}%-21s${NC} ${CYAN}│${NC}\n" "" "$composer_version" | |
| printf "${CYAN}│${NC} %-31s ${CYAN}│${NC} NPM : ${GREEN}%-21s${NC} ${CYAN}│${NC}\n" "" "$npm_version" | |
| echo -e "${CYAN}└───────────────────────────────────┴────────────────────────────────────┘${NC}" | |
| echo "" | |
| echo -e "${CYAN}┌────────────────────────────────────────────────────────────────────────┐${NC}" | |
| echo -e "${CYAN}│${NC} ${YELLOW}STEP DETAILS${NC} ${CYAN}│${NC}" | |
| echo -e "${CYAN}├──────┬─────────────────────────────┬─────────────┬──────────────────────┤${NC}" | |
| echo -e "${CYAN}│${NC} ${YELLOW}STEP${NC} ${CYAN}│${NC} ${YELLOW}DESCRIPTION${NC} ${CYAN}│${NC} ${YELLOW}MESSAGE${NC} ${CYAN}│${NC} ${YELLOW}STATUS${NC} ${CYAN}│${NC}" | |
| echo -e "${CYAN}├──────┼─────────────────────────────┼─────────────┼──────────────────────┤${NC}" | |
| for i in "${!STEP_NAMES[@]}"; do | |
| local step_num=$((i + 1)) | |
| local step_name="${STEP_NAMES[$i]}" | |
| local result=${STEP_RESULTS[$i]} | |
| local message="" | |
| local status_icon="" | |
| local msg_color="" | |
| local icon_color="" | |
| case $result in | |
| 1) message="PASSED"; status_icon="✓"; msg_color="${GREEN}"; icon_color="${GREEN}" ;; | |
| 2) message="FAILED"; status_icon="✗"; msg_color="${RED}"; icon_color="${RED}" ;; | |
| 3) message="SKIPPED"; status_icon="⊘"; msg_color="${YELLOW}"; icon_color="${YELLOW}" ;; | |
| *) message="PENDING"; status_icon="○"; msg_color="${BLUE}"; icon_color="${BLUE}" ;; | |
| esac | |
| printf "${CYAN}│${NC} %d ${CYAN}│${NC} %-27s ${CYAN}│${NC} ${msg_color}%-11s${NC} ${CYAN}│${NC} ${icon_color}%s${NC} ${CYAN}│${NC}\n" "$step_num" "$step_name" "$message" "$status_icon" | |
| done | |
| echo -e "${CYAN}└──────┴─────────────────────────────┴─────────────┴──────────────────────┘${NC}" | |
| echo "" | |
| echo -e "${CYAN}┌────────────────────────────────────────────────────────────────────────┐${NC}" | |
| echo -e "${CYAN}│${NC} ${YELLOW}SUMMARY${NC} ${CYAN}│${NC}" | |
| echo -e "${CYAN}├────────────────────────────────────────────────────────────────────────┤${NC}" | |
| printf "${CYAN}│${NC} ${GREEN}Passed: %d${NC} ${RED}Failed: %d${NC} ${YELLOW}Skipped: %d${NC} Total: %d ${CYAN}│${NC}\n" "$passed" "$failed" "$skipped" "$STEPS_TOTAL" | |
| echo -e "${CYAN}├────────────────────────────────────────────────────────────────────────┤${NC}" | |
| if [ $failed -eq 0 ]; then | |
| echo -e "${CYAN}│${NC} ${GREEN}✓ ✓ ✓ DEPLOYMENT SUCCESSFUL ✓ ✓ ✓${NC} ${CYAN}│${NC}" | |
| else | |
| echo -e "${CYAN}│${NC} ${RED}✗ ✗ ✗ DEPLOYMENT FAILED ✗ ✗ ✗${NC} ${CYAN}│${NC}" | |
| fi | |
| echo -e "${CYAN}└────────────────────────────────────────────────────────────────────────┘${NC}" | |
| echo "" | |
| } | |
| #=============================================================================== | |
| # Main Execution | |
| #=============================================================================== | |
| main() { | |
| print_header | |
| # Show project selection menu | |
| select_project | |
| # Remove trailing slash if present | |
| PROJECT_DIR="${PROJECT_DIR%/}" | |
| echo -e "${YELLOW}Starting deployment for: ${PROJECT_DIR}${NC}" | |
| echo -e "${YELLOW}Press Ctrl+C to abort at any time${NC}" | |
| echo "" | |
| # Execute deployment steps | |
| step_change_directory || { generate_report; exit 1; } | |
| step_git_pull || { generate_report; exit 1; } | |
| step_composer_install || { generate_report; exit 1; } | |
| step_run_migrations || { generate_report; exit 1; } | |
| step_run_optimizations | |
| step_npm_build || { generate_report; exit 1; } | |
| step_permission_import || { generate_report; exit 1; } | |
| step_file_permissions || { generate_report; exit 1; } | |
| step_restart_supervisor | |
| # Generate final report | |
| generate_report | |
| exit $STEPS_FAILED | |
| } | |
| # Run main function | |
| main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment