Private
Public Access
1
0

feat: enhance gitapply.sh with animated functions and improved user feedback

This commit is contained in:
2025-12-23 21:04:53 -05:00
parent f9f951cd2c
commit 88a364f253

View File

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