sandbox-notebookllamalm-nextjs/scripts/3_cleanup.sh
Vadym Samoilenko 23494552e7 Fix health check URL: /health -> /api/health
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:50:32 +00:00

198 lines
7.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# scripts/3_cleanup.sh — Step 3: Post-migration cleanup
# Run ONLY after verifying that the Docker deployment is working correctly.
# Frees disk space by removing build artifacts and source files now in volumes.
#
# Usage:
# bash 3_cleanup.sh # interactive — prompts before each rm
# bash 3_cleanup.sh --yes # skip confirmation prompts (use with care)
set -euo pipefail
REPO_DIR="/opt/sandbox-notebookllamalm-nextjs"
VOLUME_PREFIX="sandbox-notebookllamalm-nextjs_"
BACKEND_SVC="notebookllama-backend"
FRONTEND_SVC="notebookllama-frontend"
BACKEND_PORT=9000
FRONTEND_PORT=4000
AUTO_YES=false
# ── Parse args ────────────────────────────────────────────────────────────────
for arg in "$@"; do
[[ "$arg" == "--yes" ]] && AUTO_YES=true
done
# ── Colors ──────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
step() { echo -e "\n${CYAN}══ $* ${NC}"; }
# ── Confirm helper ────────────────────────────────────────────────────────────
confirm() {
local prompt="$1"
if $AUTO_YES; then
info "${prompt} — auto-confirmed (--yes)"
return 0
fi
echo -en "${YELLOW}${prompt} [y/N]: ${NC}"
read -r answer
[[ "$answer" =~ ^[Yy]$ ]]
}
cd "$REPO_DIR"
# ── Step 1: Verify all containers are running ─────────────────────────────────
step "1 / Verify Docker containers"
EXPECTED_SERVICES=(postgres redis backend frontend)
ALL_RUNNING=true
for svc in "${EXPECTED_SERVICES[@]}"; do
STATUS=$(docker compose ps --format '{{.Service}} {{.State}}' 2>/dev/null \
| grep "^${svc} " | awk '{print $2}' || echo "missing")
if [[ "$STATUS" == "running" ]]; then
info " ${svc}: running"
else
error " ${svc}: ${STATUS:-not found}"
ALL_RUNNING=false
fi
done
if ! $ALL_RUNNING; then
error "Not all containers are running. Fix the deployment before cleaning up."
echo " docker compose ps"
exit 1
fi
# Double-check via HTTP
check_alive() {
local name="$1"; local url="$2"
local code
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$url" 2>/dev/null || echo "000")
if [[ "$code" == "200" ]]; then
info " ${name}: HTTP 200 OK"
else
warn " ${name}: HTTP ${code} — proceeding anyway (container is up)"
fi
}
check_alive "Backend" "http://localhost:${BACKEND_PORT}/api/health"
check_alive "Frontend" "http://localhost:${FRONTEND_PORT}/notebookllama"
# ── Step 2: Verify data in podcasts_data volume ────────────────────────────────
step "2 / Verify data in Docker volumes"
PODCASTS_VOLUME="${VOLUME_PREFIX}podcasts_data"
UPLOADS_VOLUME="${VOLUME_PREFIX}uploads_data"
VOL_MP3=$(docker run --rm -v "${PODCASTS_VOLUME}:/d:ro" alpine \
sh -c 'find /d -name "*.mp3" | wc -l' 2>/dev/null || echo "0")
SRC_MP3=$(find backend/conversations -name '*.mp3' 2>/dev/null | wc -l | tr -d ' ')
info "podcasts_data volume: ${VOL_MP3} MP3 file(s)"
info "backend/conversations source: ${SRC_MP3} MP3 file(s)"
if [[ "$VOL_MP3" -lt "$SRC_MP3" ]]; then
error "Volume has fewer MP3s (${VOL_MP3}) than source (${SRC_MP3}). Copy may be incomplete."
error "Aborting cleanup. Re-run 2_deploy.sh or copy manually."
exit 1
fi
if [[ "$SRC_MP3" -gt 0 && "$VOL_MP3" -ge "$SRC_MP3" ]]; then
info "Volume data matches source — safe to remove source files"
elif [[ "$SRC_MP3" -eq 0 ]]; then
info "No MP3 files in source directory (already cleaned or never populated)"
fi
# ── Step 3: Remove source MP3s (now in volume) ────────────────────────────────
step "3 / Remove backend/conversations/ (data is in Docker volume)"
if [[ -d "backend/conversations" ]] && [[ -n "$(ls -A backend/conversations 2>/dev/null)" ]]; then
CONV_SIZE=$(du -sh backend/conversations | cut -f1)
warn "Will delete: backend/conversations/ (${CONV_SIZE})"
if confirm "Delete backend/conversations/?"; then
sudo rm -rf backend/conversations/
info "Deleted backend/conversations/"
else
info "Skipped — keeping backend/conversations/"
fi
else
info "backend/conversations/ is empty or does not exist — nothing to remove"
fi
# ── Step 4: Remove build artifacts ────────────────────────────────────────────
step "4 / Remove build artifacts (Docker builds its own)"
remove_dir() {
local path="$1"
local label="$2"
if [[ -d "$path" ]]; then
local size
size=$(du -sh "$path" 2>/dev/null | cut -f1)
warn "Will delete: ${path} (${size}) — ${label}"
if confirm "Delete ${path}?"; then
sudo rm -rf "$path"
info "Deleted ${path}"
else
info "Skipped — keeping ${path}"
fi
else
info "${path} does not exist — skipping"
fi
}
remove_dir "frontend/.next" "Next.js build cache (Docker builds its own)"
remove_dir "frontend/node_modules" "Node.js deps (Docker installs its own)"
remove_dir "backend/.venv" "Python virtualenv (Docker uses uv)"
# ── Step 5: Prune dangling Docker images ──────────────────────────────────────
step "5 / Prune dangling Docker images"
if confirm "Run docker image prune -f (remove dangling images)?"; then
docker image prune -f
info "Dangling images removed"
else
info "Skipped image prune"
fi
# ── Step 6: Show freed disk space ────────────────────────────────────────────
step "6 / Disk usage"
df -h /opt
echo ""
info "Docker disk usage:"
docker system df
# ── Step 7: Finalize systemd ──────────────────────────────────────────────────
step "7 / Finalize systemd"
for svc in "$BACKEND_SVC" "$FRONTEND_SVC"; do
if sudo systemctl is-enabled --quiet "$svc" 2>/dev/null; then
warn "${svc} is still enabled — disabling now..."
sudo systemctl disable "$svc"
info " → disabled"
else
info "${svc}: already disabled"
fi
done
sudo systemctl daemon-reload
info "systemd daemon reloaded"
# ── Done ──────────────────────────────────────────────────────────────────────
echo ""
info "── Cleanup complete ──────────────────────────────────────────────"
echo ""
info "Docker containers (should all be running):"
docker compose ps
echo ""
info "Docker volumes (should still exist):"
docker volume ls | grep "$VOLUME_PREFIX" || true
echo ""
info "Note: .service files in the repository have NOT been deleted."
echo " They serve as a reference in case you need to roll back to systemd."
echo ""
info "Docker containers are configured with 'restart: unless-stopped' and will"
info "start automatically when the server reboots — no systemd required."
echo ""
info "Cleanup finished at $(date)"