|
#!/bin/bash |
|
# ============================================================================ |
|
# Laravel Auto-Deploy Script for GitHub Webhooks |
|
# ============================================================================ |
|
# |
|
# Purpose: Automatically deploy Laravel applications on AWS Ubuntu servers |
|
# when GitHub webhooks are triggered |
|
# |
|
# Requirements: |
|
# - Git repository owned by 'ubuntu' user (or your server user) |
|
# - Webhook runs as 'www-data' user (Apache/Nginx) |
|
# - SSH keys configured in /var/www/.ssh for www-data |
|
# - Passwordless sudo configured for git/composer/artisan commands |
|
# - Laravel application with DeployLog model (optional, for tracking) |
|
# |
|
# Setup Instructions: |
|
# 1. Place this script in your project root: /var/www/your-project/deploy.sh |
|
# 2. Make it executable: chmod +x deploy.sh |
|
# 3. Configure GitHub webhook to POST to: https://yourdomain.com/deploy |
|
# 4. Ensure www-data can execute: sudo visudo |
|
# Add: www-data ALL=(ubuntu) NOPASSWD: /usr/bin/git |
|
# 5. Copy SSH keys: sudo cp -r ~/.ssh /var/www/.ssh && sudo chown -R www-data:www-data /var/www/.ssh |
|
# |
|
# Usage: |
|
# Manual: ./deploy.sh [deploy_log_id] |
|
# Webhook: Called automatically by GitHub webhook route |
|
# |
|
# Author: Chetan Upare |
|
# License: MIT |
|
# ============================================================================ |
|
|
|
# ============================================================================ |
|
# CONFIGURATION - CUSTOMIZE THESE VALUES FOR YOUR PROJECT |
|
# ============================================================================ |
|
|
|
# Project name (used in output messages) |
|
PROJECT_NAME="Your Project Name" |
|
|
|
# Repository paths (check both common locations) |
|
# Production: /var/www/your-project |
|
# Local/Dev: /var/www/html/your-project |
|
REPO_PATH_PRODUCTION="/var/www/your-project" |
|
REPO_PATH_LOCAL="/var/www/html/your-project" |
|
|
|
# Git branch to deploy (usually 'main' or 'master') |
|
GIT_BRANCH="main" |
|
|
|
# Server user who owns the repository (usually 'ubuntu' on AWS) |
|
REPO_OWNER="ubuntu" |
|
|
|
# Web server user (usually 'www-data' on Ubuntu/Debian, 'apache' on CentOS) |
|
WEB_USER="www-data" |
|
|
|
# ============================================================================ |
|
# SCRIPT START - DO NOT MODIFY BELOW UNLESS YOU KNOW WHAT YOU'RE DOING |
|
# ============================================================================ |
|
|
|
# Get deploy log ID from argument or environment variable |
|
# This is used to track deployment status in database (optional) |
|
DEPLOY_LOG_ID="${1:-${DEPLOY_LOG_ID}}" |
|
|
|
# Create a unique log file for this deployment |
|
if [ -n "$DEPLOY_LOG_ID" ]; then |
|
DEPLOY_LOG_FILE="/tmp/deploy_${DEPLOY_LOG_ID}.log" |
|
PRIMARY_LOG_FILE="$DEPLOY_LOG_FILE" |
|
echo "Deployment started with ID: $DEPLOY_LOG_ID" > "$DEPLOY_LOG_FILE" |
|
echo "Timestamp: $(date '+%Y-%m-%d %H:%M:%S')" >> "$DEPLOY_LOG_FILE" |
|
echo "=========================================" >> "$DEPLOY_LOG_FILE" |
|
else |
|
DEPLOY_LOG_FILE="/tmp/deploy.log" |
|
PRIMARY_LOG_FILE="$DEPLOY_LOG_FILE" |
|
fi |
|
|
|
# Ensure log file is writable (create if needed) |
|
touch "$PRIMARY_LOG_FILE" 2>/dev/null || true |
|
|
|
# ============================================================================ |
|
# FUNCTION: Update deployment status in database |
|
# ============================================================================ |
|
# This function updates the DeployLog model in Laravel to track deployment |
|
# status. It tries the artisan command first, then falls back to tinker. |
|
# ============================================================================ |
|
update_deploy_status() { |
|
local status="$1" |
|
local message="$2" |
|
|
|
if [ -n "$DEPLOY_LOG_ID" ] && [ -n "$status" ]; then |
|
# Determine the correct Laravel directory (production vs local) |
|
local LARAVEL_DIR="" |
|
if [ -d "$REPO_PATH_PRODUCTION" ] && [ -f "$REPO_PATH_PRODUCTION/artisan" ]; then |
|
LARAVEL_DIR="$REPO_PATH_PRODUCTION" |
|
elif [ -d "$REPO_PATH_LOCAL" ] && [ -f "$REPO_PATH_LOCAL/artisan" ]; then |
|
LARAVEL_DIR="$REPO_PATH_LOCAL" |
|
else |
|
# Fallback: use REPO_PATH if set |
|
LARAVEL_DIR="${REPO_PATH:-$REPO_PATH_LOCAL}" |
|
fi |
|
|
|
# Ensure we're in the correct directory |
|
if [ -n "$LARAVEL_DIR" ] && [ -d "$LARAVEL_DIR" ]; then |
|
cd "$LARAVEL_DIR" 2>/dev/null || { |
|
# Try both paths if first fails |
|
cd "$REPO_PATH_PRODUCTION" 2>/dev/null || cd "$REPO_PATH_LOCAL" 2>/dev/null || true |
|
} |
|
else |
|
# Last resort: try both paths |
|
cd "$REPO_PATH_PRODUCTION" 2>/dev/null || cd "$REPO_PATH_LOCAL" 2>/dev/null || true |
|
fi |
|
|
|
# Try artisan command first (cleaner approach) |
|
if php artisan deploy:update-status "$DEPLOY_LOG_ID" "$status" "$message" 2>&1; then |
|
return 0 |
|
else |
|
# Fallback to tinker if artisan command fails |
|
php artisan tinker --execute=" |
|
try { |
|
\$log = \App\Models\DeployLog::find('$DEPLOY_LOG_ID'); |
|
if (\$log) { |
|
\$log->status = '$status'; |
|
\$log->completed_at = now(); |
|
\$log->duration = \$log->started_at ? now()->diffInSeconds(\$log->started_at) : 0; |
|
if ('$status' === 'failed') { |
|
\$log->error_message = '$message'; |
|
} else { |
|
\$log->output = '$message'; |
|
} |
|
\$log->save(); |
|
echo 'Status updated via tinker'; |
|
} else { |
|
echo 'Deploy log not found: $DEPLOY_LOG_ID'; |
|
} |
|
} catch (\Exception \$e) { |
|
echo 'Error: ' . \$e->getMessage(); |
|
} |
|
" 2>&1 || true |
|
fi |
|
fi |
|
} |
|
|
|
# Trap to ensure status is updated on script exit (even if unexpected) |
|
# This prevents deployments from getting stuck in "RUNNING" status |
|
trap 'if [ $? -ne 0 ] && [ -n "$DEPLOY_LOG_ID" ]; then update_deploy_status "failed" "Script exited unexpectedly with code $?"; fi' EXIT |
|
|
|
# ============================================================================ |
|
# COLOR CODES AND SYMBOLS FOR TERMINAL OUTPUT |
|
# ============================================================================ |
|
RED='\033[0;31m' |
|
GREEN='\033[0;32m' |
|
YELLOW='\033[1;33m' |
|
BLUE='\033[0;34m' |
|
CYAN='\033[0;36m' |
|
MAGENTA='\033[0;35m' |
|
WHITE='\033[1;37m' |
|
BOLD='\033[1m' |
|
NC='\033[0m' # No Color |
|
|
|
# Unicode symbols for better visual feedback |
|
CHECK='✓' |
|
CROSS='✗' |
|
ARROW='➜' |
|
ROCKET='🚀' |
|
GEAR='⚙️' |
|
FOLDER='📁' |
|
KEY='🔑' |
|
CACHE='💾' |
|
SERVER='🖥️' |
|
SUCCESS='✅' |
|
ERROR='❌' |
|
INFO='ℹ️' |
|
|
|
# ============================================================================ |
|
# DETECT INTERACTIVE VS WEBHOOK EXECUTION |
|
# ============================================================================ |
|
# When run from terminal: show colored output |
|
# When run from webhook: log to file only (no colors) |
|
# ============================================================================ |
|
if [ -t 0 ]; then |
|
# Running interactively - show colored output |
|
INTERACTIVE=true |
|
USE_COLORS=true |
|
else |
|
# Running from webhook - log to file only (no colors) |
|
INTERACTIVE=false |
|
USE_COLORS=false |
|
fi |
|
|
|
# ============================================================================ |
|
# FUNCTION: Output message with colors and logging |
|
# ============================================================================ |
|
# Usage: output "Message text" "type" |
|
# Types: info, success, error, warning, header |
|
# ============================================================================ |
|
output() { |
|
local message="$1" |
|
local type="${2:-info}" # Default to 'info' if not specified |
|
|
|
if [ "$USE_COLORS" = true ]; then |
|
case $type in |
|
success) |
|
echo -e "${GREEN}${CHECK} ${message}${NC}" |
|
;; |
|
error) |
|
echo -e "${RED}${ERROR} ${message}${NC}" |
|
;; |
|
warning) |
|
echo -e "${YELLOW}${INFO} ${message}${NC}" |
|
;; |
|
info) |
|
echo -e "${CYAN}${ARROW} ${message}${NC}" |
|
;; |
|
header) |
|
echo -e "${BOLD}${MAGENTA}${message}${NC}" |
|
;; |
|
*) |
|
echo -e "${CYAN}${ARROW} ${message}${NC}" |
|
;; |
|
esac |
|
else |
|
echo "$message" |
|
fi |
|
|
|
# Always log to primary log file (deployment-specific or global) |
|
if [ -n "$PRIMARY_LOG_FILE" ]; then |
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$PRIMARY_LOG_FILE" 2>/dev/null || true |
|
fi |
|
|
|
# Also log to global deploy.log if we have write permission (optional) |
|
if [ -n "$PRIMARY_LOG_FILE" ] && [ "$PRIMARY_LOG_FILE" != "/tmp/deploy.log" ] && [ -w /tmp/deploy.log ] 2>/dev/null; then |
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> /tmp/deploy.log 2>/dev/null || true |
|
fi |
|
} |
|
|
|
# ============================================================================ |
|
# FUNCTION: Print deployment header |
|
# ============================================================================ |
|
print_header() { |
|
if [ "$USE_COLORS" = true ]; then |
|
echo "" |
|
echo -e "${BOLD}${BLUE}╔════════════════════════════════════════════════════════════╗${NC}" |
|
echo -e "${BOLD}${BLUE}║${NC} ${WHITE}${ROCKET} ${PROJECT_NAME} - Auto Deployment Script${NC} ${BOLD}${BLUE}║${NC}" |
|
echo -e "${BOLD}${BLUE}╚════════════════════════════════════════════════════════════╝${NC}" |
|
echo "" |
|
else |
|
echo "=========================================" |
|
echo "${PROJECT_NAME} - Auto Deployment Script" |
|
echo "=========================================" |
|
fi |
|
} |
|
|
|
# ============================================================================ |
|
# FUNCTION: Print separator line |
|
# ============================================================================ |
|
print_separator() { |
|
if [ "$USE_COLORS" = true ]; then |
|
echo -e "${CYAN}────────────────────────────────────────────────────────────${NC}" |
|
else |
|
echo "────────────────────────────────────────────────────────────" |
|
fi |
|
} |
|
|
|
# ============================================================================ |
|
# DETERMINE REPOSITORY PATH |
|
# ============================================================================ |
|
# Check both common locations for the Git repository |
|
# ============================================================================ |
|
if [ -d "$REPO_PATH_LOCAL/.git" ]; then |
|
REPO_PATH="$REPO_PATH_LOCAL" |
|
elif [ -d "$REPO_PATH_PRODUCTION/.git" ]; then |
|
REPO_PATH="$REPO_PATH_PRODUCTION" |
|
else |
|
print_header |
|
output "Git repository not found in expected locations" "error" |
|
output "Checked: $REPO_PATH_LOCAL and $REPO_PATH_PRODUCTION" "error" |
|
exit 1 |
|
fi |
|
|
|
# Change to repository directory |
|
cd "$REPO_PATH" || { |
|
print_header |
|
output "Cannot change to $REPO_PATH directory" "error" |
|
if [ -n "$DEPLOY_LOG_ID" ]; then |
|
# Try to find Laravel directory for status update |
|
LARAVEL_DIR="" |
|
if [ -d "$REPO_PATH_PRODUCTION" ] && [ -f "$REPO_PATH_PRODUCTION/artisan" ]; then |
|
LARAVEL_DIR="$REPO_PATH_PRODUCTION" |
|
elif [ -d "$REPO_PATH_LOCAL" ] && [ -f "$REPO_PATH_LOCAL/artisan" ]; then |
|
LARAVEL_DIR="$REPO_PATH_LOCAL" |
|
fi |
|
|
|
if [ -n "$LARAVEL_DIR" ]; then |
|
cd "$LARAVEL_DIR" 2>/dev/null || true |
|
update_deploy_status "failed" "Cannot change to repository directory" |
|
fi |
|
fi |
|
exit 1 |
|
} |
|
|
|
# ============================================================================ |
|
# PRINT HEADER AND START DEPLOYMENT |
|
# ============================================================================ |
|
print_header |
|
output "Deployment started at $(date '+%Y-%m-%d %H:%M:%S')" "info" |
|
output "Repository: ${BOLD}$REPO_PATH${NC}" "info" |
|
print_separator |
|
|
|
# ============================================================================ |
|
# CONFIGURE SSH FOR GITHUB |
|
# ============================================================================ |
|
# The script runs as www-data, so we need to use SSH keys from /var/www/.ssh |
|
# ============================================================================ |
|
output "Configuring SSH for GitHub..." "info" |
|
|
|
# Detect current user |
|
CURRENT_USER=$(whoami) |
|
output "Running as user: $CURRENT_USER" "info" |
|
|
|
# Check for SSH keys in priority order: |
|
# 1. /var/www/.ssh (for www-data user) |
|
# 2. $HOME/.ssh (for current user) |
|
if [ -d "/var/www/.ssh" ] && [ -f "/var/www/.ssh/id_ed25519" ]; then |
|
output "Using ${WEB_USER} SSH keys from /var/www/.ssh" "success" |
|
SSH_DIR="/var/www/.ssh" |
|
SSH_KEY="/var/www/.ssh/id_ed25519" |
|
elif [ -d "/var/www/.ssh" ] && [ -f "/var/www/.ssh/id_rsa" ]; then |
|
output "Using ${WEB_USER} SSH keys from /var/www/.ssh" "success" |
|
SSH_DIR="/var/www/.ssh" |
|
SSH_KEY="/var/www/.ssh/id_rsa" |
|
elif [ "$CURRENT_USER" = "$WEB_USER" ] || [ "$CURRENT_USER" = "apache" ]; then |
|
# Running as web server user - must use /var/www/.ssh |
|
output "Running as web server user, checking /var/www/.ssh..." "info" |
|
if [ -d "/var/www/.ssh" ]; then |
|
output "ERROR: /var/www/.ssh directory exists but no keys found" "error" |
|
if [ -n "$DEPLOY_LOG_ID" ]; then |
|
update_deploy_status "failed" "SSH keys not found in /var/www/.ssh" |
|
fi |
|
exit 1 |
|
else |
|
output "ERROR: /var/www/.ssh directory does not exist" "error" |
|
if [ -n "$DEPLOY_LOG_ID" ]; then |
|
update_deploy_status "failed" "/var/www/.ssh directory not found" |
|
fi |
|
exit 1 |
|
fi |
|
elif [ -f "$HOME/.ssh/id_ed25519" ]; then |
|
output "Using SSH keys from $HOME/.ssh" "success" |
|
SSH_DIR="$HOME/.ssh" |
|
SSH_KEY="$HOME/.ssh/id_ed25519" |
|
elif [ -f "$HOME/.ssh/id_rsa" ]; then |
|
output "Using SSH keys from $HOME/.ssh" "success" |
|
SSH_DIR="$HOME/.ssh" |
|
SSH_KEY="$HOME/.ssh/id_rsa" |
|
else |
|
output "No SSH keys found. Please set up SSH keys for ${WEB_USER} in /var/www/.ssh" "error" |
|
if [ -n "$DEPLOY_LOG_ID" ]; then |
|
update_deploy_status "failed" "No SSH keys found" |
|
fi |
|
exit 1 |
|
fi |
|
|
|
# Ensure known_hosts exists and has GitHub |
|
# This prevents SSH from prompting for host key verification |
|
if [ ! -f "$SSH_DIR/known_hosts" ] || ! grep -q "github.com" "$SSH_DIR/known_hosts" 2>/dev/null; then |
|
output "Adding GitHub to known_hosts..." "info" |
|
ssh-keyscan -t rsa,ecdsa,ed25519 github.com >> "$SSH_DIR/known_hosts" 2>/dev/null |
|
chmod 644 "$SSH_DIR/known_hosts" |
|
output "GitHub SSH host key added" "success" |
|
else |
|
output "GitHub SSH already configured" "success" |
|
fi |
|
|
|
# Configure Git to use SSH with the correct key |
|
export GIT_SSH_COMMAND="ssh -i $SSH_KEY -o StrictHostKeyChecking=accept-new -o IdentitiesOnly=yes" |
|
|
|
# ============================================================================ |
|
# ENSURE REMOTE IS USING SSH (NOT HTTPS) |
|
# ============================================================================ |
|
# Convert HTTPS remotes to SSH for better security and authentication |
|
# ============================================================================ |
|
REMOTE_URL=$(git remote get-url origin 2>/dev/null) |
|
if [[ "$REMOTE_URL" == https://github.com/* ]]; then |
|
output "Converting HTTPS remote to SSH..." "warning" |
|
# Convert https://github.com/user/repo.git to git@github.com:user/repo.git |
|
SSH_URL=$(echo "$REMOTE_URL" | sed 's|https://github.com/|git@github.com:|' | sed 's|\.git$||') |
|
SSH_URL="${SSH_URL}.git" |
|
git remote set-url origin "$SSH_URL" |
|
output "Remote URL converted to SSH" "success" |
|
fi |
|
|
|
# ============================================================================ |
|
# CONFIGURE GIT SAFE DIRECTORY |
|
# ============================================================================ |
|
# Git 2.35.2+ requires safe.directory configuration when repo is owned by |
|
# a different user than the one running the script (www-data vs ubuntu) |
|
# ============================================================================ |
|
output "Configuring Git safe directory..." "info" |
|
# Ensure we're in the repo directory |
|
cd "$REPO_PATH" 2>/dev/null || true |
|
# Configure globally (for www-data user) |
|
git config --global --add safe.directory "$REPO_PATH" 2>/dev/null || true |
|
# Also configure locally (in case global config doesn't work) |
|
git config --add safe.directory "$REPO_PATH" 2>/dev/null || true |
|
output "Git safe directory configured" "success" |
|
|
|
print_separator |
|
|
|
# ============================================================================ |
|
# PULL LATEST CODE FROM GITHUB |
|
# ============================================================================ |
|
# Use sudo -u to run git as the repository owner (avoids permission issues) |
|
# ============================================================================ |
|
output "Pulling latest code from GitHub..." "info" |
|
if [ "$INTERACTIVE" = true ]; then |
|
if sudo -u "$REPO_OWNER" git pull origin "$GIT_BRANCH" 2>&1 | tee -a "$PRIMARY_LOG_FILE"; then |
|
GIT_EXIT=0 |
|
else |
|
GIT_EXIT=${PIPESTATUS[0]} |
|
fi |
|
else |
|
sudo -u "$REPO_OWNER" git pull origin "$GIT_BRANCH" >> "$PRIMARY_LOG_FILE" 2>&1 |
|
GIT_EXIT=$? |
|
fi |
|
|
|
# Check if git pull was successful |
|
if [ $GIT_EXIT -ne 0 ]; then |
|
output "Git pull failed" "error" |
|
output "Current remote URL: $(git remote get-url origin)" "error" |
|
if [ -n "$DEPLOY_LOG_ID" ]; then |
|
ERROR_MSG="Git pull failed: $(git remote get-url origin)" |
|
update_deploy_status "failed" "$ERROR_MSG" |
|
fi |
|
exit 1 |
|
fi |
|
|
|
# ============================================================================ |
|
# UPDATE GIT COMMIT INFO IN DATABASE (OPTIONAL) |
|
# ============================================================================ |
|
# If DeployLog model exists, update it with current commit hash and branch |
|
# ============================================================================ |
|
if [ -n "$DEPLOY_LOG_ID" ]; then |
|
# Determine Laravel directory (same logic as update_deploy_status) |
|
LARAVEL_DIR="" |
|
if [ -d "$REPO_PATH_PRODUCTION" ] && [ -f "$REPO_PATH_PRODUCTION/artisan" ]; then |
|
LARAVEL_DIR="$REPO_PATH_PRODUCTION" |
|
elif [ -d "$REPO_PATH_LOCAL" ] && [ -f "$REPO_PATH_LOCAL/artisan" ]; then |
|
LARAVEL_DIR="$REPO_PATH_LOCAL" |
|
else |
|
LARAVEL_DIR="${REPO_PATH:-$REPO_PATH_LOCAL}" |
|
fi |
|
|
|
# Ensure we're in the correct directory |
|
cd "$LARAVEL_DIR" 2>/dev/null || cd "$REPO_PATH" 2>/dev/null || true |
|
|
|
# Get current commit hash and branch |
|
GIT_COMMIT=$(git rev-parse HEAD 2>/dev/null || echo "") |
|
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "$GIT_BRANCH") |
|
if [ -n "$GIT_COMMIT" ]; then |
|
output "Updating git commit info in database..." "info" |
|
php artisan tinker --execute=" |
|
\$log = \App\Models\DeployLog::find('$DEPLOY_LOG_ID'); |
|
if (\$log) { |
|
\$log->git_commit = '$GIT_COMMIT'; |
|
\$log->git_branch = '$GIT_BRANCH'; |
|
\$log->save(); |
|
echo 'Git info updated'; |
|
} else { |
|
echo 'Deploy log not found'; |
|
} |
|
" 2>&1 || output "Failed to update git commit info" "warning" |
|
fi |
|
fi |
|
|
|
output "Code pulled successfully" "success" |
|
print_separator |
|
|
|
# ============================================================================ |
|
# CLEAR AND OPTIMIZE LARAVEL CACHE |
|
# ============================================================================ |
|
# Clear all caches and optimize for production |
|
# ============================================================================ |
|
output "Clearing Laravel cache..." "info" |
|
if [ "$INTERACTIVE" = true ]; then |
|
php artisan optimize:clear 2>&1 | tee -a "$PRIMARY_LOG_FILE" |
|
else |
|
php artisan optimize:clear >> "$PRIMARY_LOG_FILE" 2>&1 |
|
fi |
|
|
|
output "Optimizing Laravel..." "info" |
|
if [ "$INTERACTIVE" = true ]; then |
|
php artisan optimize 2>&1 | tee -a "$PRIMARY_LOG_FILE" |
|
else |
|
php artisan optimize >> "$PRIMARY_LOG_FILE" 2>&1 |
|
fi |
|
|
|
output "Cache cleared and optimized" "success" |
|
print_separator |
|
|
|
# ============================================================================ |
|
# RESTART WEB SERVER |
|
# ============================================================================ |
|
# Restart Apache/Nginx to ensure all changes are loaded |
|
# ============================================================================ |
|
output "Restarting Apache..." "info" |
|
|
|
# Check if we can use sudo without password |
|
APACHE_EXIT=0 |
|
if command -v sudo >/dev/null 2>&1 && sudo -n true 2>/dev/null; then |
|
# Sudo available and passwordless - use it |
|
if [ "$INTERACTIVE" = true ]; then |
|
if sudo systemctl restart apache2 2>&1 | tee -a "$PRIMARY_LOG_FILE"; then |
|
APACHE_EXIT=0 |
|
else |
|
APACHE_EXIT=${PIPESTATUS[0]} |
|
fi |
|
else |
|
sudo systemctl restart apache2 >> "$PRIMARY_LOG_FILE" 2>&1 |
|
APACHE_EXIT=$? |
|
fi |
|
else |
|
# Sudo not available or requires password - try alternative methods |
|
output "Sudo not available for Apache restart, trying alternative methods..." "warning" |
|
|
|
# Try systemctl directly (if running as root) |
|
if systemctl restart apache2 >> "$PRIMARY_LOG_FILE" 2>&1; then |
|
APACHE_EXIT=0 |
|
output "Apache restarted using systemctl" "success" |
|
# Try service command |
|
elif command -v service >/dev/null 2>&1 && service apache2 restart >> "$PRIMARY_LOG_FILE" 2>&1; then |
|
APACHE_EXIT=0 |
|
output "Apache restarted using service command" "success" |
|
# Try init.d script |
|
elif [ -f /etc/init.d/apache2 ] && /etc/init.d/apache2 restart >> "$PRIMARY_LOG_FILE" 2>&1; then |
|
APACHE_EXIT=0 |
|
output "Apache restarted using init.d script" "success" |
|
else |
|
APACHE_EXIT=1 |
|
output "Could not restart Apache automatically - please restart manually" "warning" |
|
output "Deployment completed but Apache restart is required" "warning" |
|
fi |
|
fi |
|
|
|
# Don't fail deployment if Apache restart fails - it's not critical |
|
if [ $APACHE_EXIT -ne 0 ]; then |
|
output "Note: Apache restart failed but deployment was successful" "warning" |
|
# Continue - don't exit |
|
fi |
|
|
|
output "Apache restarted successfully" "success" |
|
print_separator |
|
|
|
# ============================================================================ |
|
# PRINT SUCCESS FOOTER |
|
# ============================================================================ |
|
if [ "$USE_COLORS" = true ]; then |
|
echo "" |
|
echo -e "${BOLD}${GREEN}╔════════════════════════════════════════════════════════════╗${NC}" |
|
echo -e "${BOLD}${GREEN}║${NC} ${WHITE}${SUCCESS} Deployment completed successfully!${NC} ${BOLD}${GREEN}║${NC}" |
|
echo -e "${BOLD}${GREEN}║${NC} ${CYAN} Completed at: $(date '+%Y-%m-%d %H:%M:%S')${NC} ${BOLD}${GREEN}║${NC}" |
|
echo -e "${BOLD}${GREEN}╚════════════════════════════════════════════════════════════╝${NC}" |
|
echo "" |
|
else |
|
echo "=========================================" |
|
echo "Deployment completed successfully!" |
|
echo "Completed at: $(date '+%Y-%m-%d %H:%M:%S')" |
|
echo "=========================================" |
|
fi |
|
|
|
# ============================================================================ |
|
# UPDATE DEPLOYMENT STATUS IN DATABASE (SUCCESS) |
|
# ============================================================================ |
|
# Mark deployment as successful in the database |
|
# ============================================================================ |
|
if [ -n "$DEPLOY_LOG_ID" ]; then |
|
# Get deployment output from log file |
|
DEPLOY_OUTPUT=$(tail -100 "$PRIMARY_LOG_FILE" 2>/dev/null | head -50 || echo "Deployment completed successfully") |
|
|
|
# Update status - ensure this runs even if previous steps had issues |
|
output "Updating deployment status in database..." "info" |
|
|
|
# Use the update function (has built-in error handling and fallback) |
|
update_deploy_status "success" "$DEPLOY_OUTPUT" |
|
|
|
output "Deployment status updated to success" "success" |
|
fi |
|
|
|
# Clear the trap since we're exiting successfully |
|
trap - EXIT |
|
|
|
exit 0 |