diff --git a/gitapply.sh b/gitapply.sh index da1443ba7..611b8cf5c 100755 --- a/gitapply.sh +++ b/gitapply.sh @@ -22,8 +22,11 @@ BOLD='\e[1m' DIM='\e[2m' NC='\e[0m' -# Spinner frames +# Animation characters SPIN=('⣾' '⣽' '⣻' '⢿' '⡿' '⣟' '⣯' '⣷') +DOTS=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏') +BARS=('▁' '▂' '▃' '▄' '▅' '▆' '▇' '█' '▇' '▆' '▅' '▄' '▃' '▂') +PULSE=('○' '◎' '●' '◉' '●' '◎') # Node list NODES=( @@ -53,32 +56,90 @@ mkdir -p "$STATUS_DIR" SSH_KEY="/root/.ssh/virtnet_deploy" # ============================================================================ -# FUNCTIONS +# ANIMATION FUNCTIONS # ============================================================================ +# Typewriter effect +typewriter() { + local text="$1" + local delay="${2:-0.02}" + for ((i=0; i<${#text}; i++)); do + printf "%s" "${text:$i:1}" + sleep "$delay" + done +} + +# Animated line draw +draw_line() { + local width=$1 + local char="${2:-━}" + local color="${3:-$C4}" + printf " ${color}" + for ((i=0; i/dev/null; do - printf "\r ${C3}${SPIN[$i]}${NC} %s" "$msg" + printf "\r ${C3}${SPIN[$i]}${NC} %s ${DIM}${DOTS[$((i % 10))]}${NC}" "$msg" i=$(( (i + 1) % 8 )) sleep 0.1 done @@ -86,34 +147,76 @@ spinner() { return $? } +# Wave spinner for waiting +wave_spinner() { + local pid=$1 + local msg=$2 + local i=0 + local colors=("$C1" "$C2" "$C3" "$C4" "$C5" "$C6") + while kill -0 "$pid" 2>/dev/null; do + printf "\r " + for ((j=0; j<6; j++)); do + local idx=$(( (i + j) % 14 )) + local cidx=$(( (i + j) % 6 )) + printf "${colors[$cidx]}${BARS[$idx]}${NC}" + done + printf " %s" "$msg" + i=$(( (i + 1) % 14 )) + sleep 0.08 + done + wait "$pid" + return $? +} + +# Task section header with animation task_start() { - echo -e "\n${C4}┌─${NC} ${C5}${BOLD}$1${NC}" + echo "" + printf "${C4}┌─${NC} ${C5}${BOLD}" + typewriter "$1" 0.02 + printf "${NC}\n" } +# Task completion with checkmark animation task_done() { - printf "\r ${C6}●${NC} %s ${GREEN}✓${NC}\n" "$1" + local msg=$1 + printf "\r " + for p in "${PULSE[@]}"; do + printf "\r ${C6}${p}${NC}" + sleep 0.05 + done + printf "\r ${C6}●${NC} %s ${GREEN}✓${NC}\n" "$msg" } +# Task failure task_fail() { printf "\r ${RED}●${NC} %s ${RED}✗${NC}\n" "$1" } +# Animated countdown countdown() { local secs=$1 + local circle=('◜' '◠' '◝' '◞' '◡' '◟') + for ((i=secs; i>0; i--)); do - printf "\r ${C3}◐${NC} Waiting ${C5}${BOLD}%d${NC}s " "$i" - sleep 0.25 - printf "\r ${C3}◓${NC} Waiting ${C5}${BOLD}%d${NC}s " "$i" - sleep 0.25 - printf "\r ${C3}◑${NC} Waiting ${C5}${BOLD}%d${NC}s " "$i" - sleep 0.25 - printf "\r ${C3}◒${NC} Waiting ${C5}${BOLD}%d${NC}s " "$i" - sleep 0.25 + for c in "${circle[@]}"; do + printf "\r ${C3}${c}${NC} Waiting ${C5}${BOLD}%d${NC}s " "$i" + sleep 0.166 + done + done + + # Completion animation + printf "\r " + for p in "${PULSE[@]}"; do + printf "\r ${C6}${p}${NC} Ready! " + sleep 0.08 done printf "\r ${C6}●${NC} Ready! ${GREEN}✓${NC}\n" } -# Run update on remote node +# ============================================================================ +# NODE FUNCTIONS +# ============================================================================ + run_remote_update() { local node=$1 local status_file="$STATUS_DIR/$node" @@ -132,7 +235,6 @@ run_remote_update() { fi } -# Get list of remote nodes (excluding current) get_remote_nodes() { local remotes=() for node in "${NODES[@]}"; do @@ -143,16 +245,24 @@ get_remote_nodes() { echo "${remotes[@]}" } -# Print node grid +# Animated node grid print_node_grid() { local title=$1 shift local show_status=$1 shift local nodes=("$@") + local animate=${1:-false} - echo -e "\n${C4}┌─${NC} ${C5}${BOLD}${title}${NC}" - echo -e " ${GRAY}┌──────────┬──────────┬──────────┬──────────┬──────────┐${NC}" + echo "" + printf "${C4}┌─${NC} ${C5}${BOLD}" + typewriter "$title" 0.02 + printf "${NC}\n" + + # Animated border + printf " ${GRAY}" + typewriter "┌──────────┬──────────┬──────────┬──────────┬──────────┐" 0.005 + printf "${NC}\n" local col=0 local row_started=0 @@ -186,10 +296,10 @@ print_node_grid() { if [ $((col % 5)) -eq 0 ]; then echo "" row_started=0 + sleep 0.03 fi done - # Fill remaining cells if row not complete while [ $((col % 5)) -ne 0 ]; do printf " ${GRAY}│${NC}" col=$((col + 1)) @@ -198,10 +308,11 @@ print_node_grid() { echo "" fi - echo -e " ${GRAY}└──────────┴──────────┴──────────┴──────────┴──────────┘${NC}" + printf " ${GRAY}" + typewriter "└──────────┴──────────┴──────────┴──────────┴──────────┘" 0.005 + printf "${NC}\n" } -# Get failed nodes get_failed_nodes() { local failed=() for node in "${NODES[@]}"; do @@ -215,7 +326,6 @@ get_failed_nodes() { echo "${failed[@]}" } -# Count results count_results() { local success=0 local failed=0 @@ -236,6 +346,7 @@ count_results() { echo "$success $failed" } +# Animated completion message print_complete() { local results results=$(count_results) @@ -243,14 +354,47 @@ print_complete() { local failed=$(echo $results | cut -d' ' -f2) echo "" - echo -e " ${C4}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + draw_line 57 echo "" - echo -e " ${C6}${BOLD}🚀 UPDATE COMPLETE${NC}" + + # Rocket animation + local rocket_frames=('🚀' '✨🚀' '✨ 🚀' '✨ 🚀' ' ✨🚀' ' 🚀') + for frame in "${rocket_frames[@]}"; do + printf "\r ${C6}${BOLD}%s UPDATE COMPLETE${NC} " "$frame" + sleep 0.12 + done + printf "\r ${C6}${BOLD}🚀 UPDATE COMPLETE${NC} \n" + echo "" - echo -e " ${GRAY}Local node updated successfully.${NC}" - echo -e " ${GREEN}●${NC} ${success} nodes updated ${RED}●${NC} ${failed} nodes failed" + printf " ${GRAY}" + typewriter "Local node updated successfully." 0.02 + printf "${NC}\n" + + # Animated stats + printf " " + for ((i=0; i<=success; i++)); do + printf "\r ${GREEN}●${NC} ${GREEN}%d${NC} nodes updated" "$i" + sleep 0.05 + done + printf " ${RED}●${NC} " + for ((i=0; i<=failed; i++)); do + printf "\r ${GREEN}●${NC} ${success} nodes updated ${RED}●${NC} ${RED}%d${NC} nodes failed" "$i" + sleep 0.05 + done + echo "" + + echo "" + draw_line 57 + + # Sparkle animation + echo "" + printf " " + local sparkles=('✨' '⭐' '💫' '✨' '⭐') + for s in "${sparkles[@]}"; do + printf "%s " "$s" + sleep 0.15 + done echo "" - echo -e " ${C4}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" } @@ -265,13 +409,17 @@ trap cleanup EXIT print_header -echo -e " ${C3}→${NC} ${GRAY}Current Node:${NC} ${C5}${CURRENT_IP}${NC}" -echo -e " ${C3}→${NC} ${GRAY}Target Nodes:${NC} ${C5}${#NODES[@]} nodes in cluster${NC}" +# Animated info display +printf " ${C3}→${NC} ${GRAY}Current Node:${NC} ${C5}" +typewriter "$CURRENT_IP" 0.03 +printf "${NC}\n" + +printf " ${C3}→${NC} ${GRAY}Target Nodes:${NC} ${C5}" +typewriter "${#NODES[@]} nodes in cluster" 0.03 +printf "${NC}\n" -# Get remote nodes REMOTE_NODES=($(get_remote_nodes)) -# Random delay sleep_time=$((RANDOM % 5 + 1)) cd /var/www/paymenter @@ -279,22 +427,26 @@ cd /var/www/paymenter task_start "Preparing Update" countdown "$sleep_time" -# Start remote updates in background +# Deploy with progress task_start "Deploying to Remote Nodes" -echo -e " ${GRAY}Starting deployment on ${#REMOTE_NODES[@]} remote nodes...${NC}" +printf " ${GRAY}Initiating deployment to ${#REMOTE_NODES[@]} remote nodes" +for ((i=0; i<3; i++)); do + printf "." + sleep 0.3 +done +printf "${NC}\n" for node in "${REMOTE_NODES[@]}"; do run_remote_update "$node" & done -# Show initial node grid print_node_grid "Initial Cluster Status" "false" "${REMOTE_NODES[@]}" # Local Git Pull task_start "Local: Pulling Latest Changes" printf " ${C3}○${NC} Fetching from remote..." git pull > /tmp/git_output.txt 2>&1 & -spinner $! "Fetching from remote..." +wave_spinner $! "Fetching from remote..." GIT_STATUS=$? if [ $GIT_STATUS -ne 0 ]; then @@ -302,14 +454,18 @@ if [ $GIT_STATUS -ne 0 ]; then echo "" cat /tmp/git_output.txt echo "" - echo -e " ${YELLOW}↻${NC} ${YELLOW}Restarting script in 2 seconds...${NC}" + printf " ${YELLOW}↻${NC} ${YELLOW}" + typewriter "Restarting script in 2 seconds..." 0.03 + printf "${NC}\n" sleep 2 exec "$0" "$@" fi task_done "Git pull completed" head -3 /tmp/git_output.txt 2>/dev/null | while IFS= read -r line; do - echo -e " ${DIM}${line}${NC}" + printf " ${DIM}" + typewriter "$line" 0.01 + printf "${NC}\n" done # Clear Caches @@ -317,31 +473,30 @@ task_start "Local: Clearing Caches" printf " ${C3}○${NC} View cache..." php artisan view:clear > /dev/null 2>&1 & -spinner $! "View cache..." +spinner $! "View cache" task_done "View cache cleared" printf " ${C3}○${NC} Application cache..." php artisan cache:clear > /dev/null 2>&1 & -spinner $! "Application cache..." +spinner $! "Application cache" task_done "Application cache cleared" # Restart PHP-FPM task_start "Local: Restarting Services" printf " ${C3}○${NC} PHP 8.3 FPM..." systemctl restart php8.3-fpm & -spinner $! "PHP 8.3 FPM..." +spinner $! "PHP 8.3 FPM" task_done "PHP 8.3 FPM restarted" -# Wait for initial remote deployment +# Wait for remote nodes task_start "Waiting for Remote Nodes" printf " ${C3}○${NC} Syncing cluster..." wait task_done "Initial sync complete" -# Show status after first attempt print_node_grid "Cluster Status (Attempt 1/${MAX_RETRIES})" "true" "${REMOTE_NODES[@]}" -# Retry failed nodes +# Retry logic attempt=1 while [ $attempt -lt $MAX_RETRIES ]; do FAILED_NODES=($(get_failed_nodes)) @@ -353,7 +508,9 @@ while [ $attempt -lt $MAX_RETRIES ]; do attempt=$((attempt + 1)) task_start "Retrying Failed Nodes (Attempt ${attempt}/${MAX_RETRIES})" - echo -e " ${YELLOW}↻${NC} ${YELLOW}${#FAILED_NODES[@]} node(s) failed, retrying...${NC}" + printf " ${YELLOW}↻${NC} ${YELLOW}" + typewriter "${#FAILED_NODES[@]} node(s) failed, retrying..." 0.02 + printf "${NC}\n" for node in "${FAILED_NODES[@]}"; do run_remote_update "$node" & @@ -366,8 +523,6 @@ while [ $attempt -lt $MAX_RETRIES ]; do print_node_grid "Cluster Status (Attempt ${attempt}/${MAX_RETRIES})" "true" "${REMOTE_NODES[@]}" done -# Final status print_node_grid "Final Cluster Status" "true" "${REMOTE_NODES[@]}" -# Complete print_complete