#!/usr/bin/env bash set -euo pipefail SPINNER=('|' '/' '-' '\') COLORS=(97 37) DELAY=0.1 hide_cursor() { tput civis 2>/dev/null || true; } show_cursor() { tput cnorm 2>/dev/null || true; } spinner() { local pid=$1 msg=$2 i=0 frame color hide_cursor while kill -0 "$pid" 2>/dev/null; do frame="${SPINNER[i % ${#SPINNER[@]}]}" color="${COLORS[i % ${#COLORS[@]}]}" printf "\r\e[36m%s... \e[0m\e[%sm%s\e[0m" "$msg" "$color" "$frame" ((i++)) sleep "$DELAY" done show_cursor } run_with_spinner() { local cmd="$1" msg="$2" rc=0 printf "\e[36m%s... \e[0m" "$msg" bash -c "$cmd" &> /dev/null & local pid=$! spinner "$pid" "$msg" if ! wait "$pid"; then rc=$?; fi if [[ $rc -eq 0 ]]; then printf "\r\e[32m✔\e[0m %s\n" "$msg" else printf "\r\e[33m✖ (exit %d)\e[0m %s\n" "$rc" "$msg" fi } echo run_with_spinner "docker compose --ansi never down || true" \ "Stopping services" run_with_spinner "docker compose --ansi never build" \ "Rebuilding services" run_with_spinner "docker compose --ansi never up -d" \ "Starting services" run_with_spinner "docker compose --ansi never exec app poetry run python manage.py migrate --no-input" \ "Applying database migrations" run_with_spinner "docker compose --ansi never exec app poetry run python manage.py collectstatic --no-input" \ "Collecting static files" run_with_spinner "docker compose --ansi never exec app poetry run python manage.py set_default_caches" \ "Setting default caches" run_with_spinner "docker system prune -f" \ "Cleaning up unused Docker data" echo -e "\n\e[1mAll done! eVibes is up and running.\e[0m"