Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
187 lines
6.4 KiB
Bash
Executable File
187 lines
6.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# ============================================================================
|
|
# POUNCE ZERO-DOWNTIME DEPLOY SCRIPT
|
|
# - Builds locally first (optional)
|
|
# - Syncs only changed files
|
|
# - Hot-reloads backend without full restart
|
|
# - Rebuilds frontend in background
|
|
# ============================================================================
|
|
|
|
set -e
|
|
|
|
# Colors
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
RED='\033[0;31m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Server config
|
|
SERVER_USER="user"
|
|
SERVER_HOST="10.42.0.73"
|
|
SERVER_PATH="/home/user/pounce"
|
|
SERVER_PASS="user"
|
|
|
|
# Parse flags
|
|
QUICK_MODE=false
|
|
BACKEND_ONLY=false
|
|
FRONTEND_ONLY=false
|
|
|
|
while [[ "$#" -gt 0 ]]; do
|
|
case $1 in
|
|
-q|--quick) QUICK_MODE=true ;;
|
|
-b|--backend) BACKEND_ONLY=true ;;
|
|
-f|--frontend) FRONTEND_ONLY=true ;;
|
|
*) COMMIT_MSG="$1" ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
echo -e "${BLUE} POUNCE ZERO-DOWNTIME DEPLOY ${NC}"
|
|
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
|
|
if $QUICK_MODE; then
|
|
echo -e "${CYAN}⚡ Quick mode: Skipping git, only syncing changes${NC}"
|
|
fi
|
|
|
|
if $BACKEND_ONLY; then
|
|
echo -e "${CYAN}🔧 Backend only mode${NC}"
|
|
fi
|
|
|
|
if $FRONTEND_ONLY; then
|
|
echo -e "${CYAN}🎨 Frontend only mode${NC}"
|
|
fi
|
|
|
|
# Step 1: Git (unless quick mode)
|
|
if ! $QUICK_MODE; then
|
|
echo -e "\n${YELLOW}[1/4] Git operations...${NC}"
|
|
|
|
# Check for changes
|
|
if git diff --quiet && git diff --staged --quiet; then
|
|
echo " No changes to commit"
|
|
else
|
|
git add -A
|
|
|
|
if [ -z "$COMMIT_MSG" ]; then
|
|
COMMIT_MSG="Deploy: $(date '+%Y-%m-%d %H:%M')"
|
|
fi
|
|
|
|
git commit -m "$COMMIT_MSG" || true
|
|
echo " ✓ Committed: $COMMIT_MSG"
|
|
fi
|
|
|
|
git push origin main 2>/dev/null && echo " ✓ Pushed to git.6bit.ch" || echo " ⚠ Push failed or nothing to push"
|
|
else
|
|
echo -e "\n${YELLOW}[1/4] Skipping git (quick mode)${NC}"
|
|
fi
|
|
|
|
# Step 2: Sync files (only changed)
|
|
echo -e "\n${YELLOW}[2/4] Syncing changed files...${NC}"
|
|
|
|
RSYNC_OPTS="-avz --delete"
|
|
|
|
if ! $BACKEND_ONLY; then
|
|
echo " Frontend:"
|
|
sshpass -p "$SERVER_PASS" rsync $RSYNC_OPTS \
|
|
--exclude 'node_modules' \
|
|
--exclude '.next' \
|
|
--exclude '.git' \
|
|
frontend/ $SERVER_USER@$SERVER_HOST:$SERVER_PATH/frontend/ 2>&1 | sed 's/^/ /'
|
|
fi
|
|
|
|
if ! $FRONTEND_ONLY; then
|
|
echo " Backend:"
|
|
sshpass -p "$SERVER_PASS" rsync $RSYNC_OPTS \
|
|
--exclude '__pycache__' \
|
|
--exclude '.pytest_cache' \
|
|
--exclude 'venv' \
|
|
--exclude '.git' \
|
|
--exclude '*.pyc' \
|
|
--exclude '.env' \
|
|
--exclude '*.db' \
|
|
backend/ $SERVER_USER@$SERVER_HOST:$SERVER_PATH/backend/ 2>&1 | sed 's/^/ /'
|
|
fi
|
|
|
|
# Step 3: Reload backend (graceful, no restart)
|
|
if ! $FRONTEND_ONLY; then
|
|
echo -e "\n${YELLOW}[3/4] Reloading backend (graceful)...${NC}"
|
|
sshpass -p "$SERVER_PASS" ssh $SERVER_USER@$SERVER_HOST << 'BACKEND_EOF'
|
|
# Signal uvicorn to reload (if running with --reload)
|
|
# Otherwise, just check it's running
|
|
BACKEND_PID=$(pgrep -f 'uvicorn app.main:app' | head -1)
|
|
|
|
if [ -n "$BACKEND_PID" ]; then
|
|
# Touch a file to trigger auto-reload if uvicorn has --reload
|
|
touch ~/pounce/backend/app/main.py
|
|
echo " ✓ Backend reload triggered (PID: $BACKEND_PID)"
|
|
else
|
|
echo " ⚠ Backend not running, starting..."
|
|
cd ~/pounce/backend
|
|
source ../venv/bin/activate
|
|
nohup uvicorn app.main:app --host 0.0.0.0 --port 8000 > backend.log 2>&1 &
|
|
sleep 2
|
|
echo " ✓ Backend started"
|
|
fi
|
|
BACKEND_EOF
|
|
else
|
|
echo -e "\n${YELLOW}[3/4] Skipping backend (frontend only)${NC}"
|
|
fi
|
|
|
|
# Step 4: Rebuild frontend (in background to minimize downtime)
|
|
if ! $BACKEND_ONLY; then
|
|
echo -e "\n${YELLOW}[4/4] Rebuilding frontend...${NC}"
|
|
sshpass -p "$SERVER_PASS" ssh $SERVER_USER@$SERVER_HOST << 'FRONTEND_EOF'
|
|
cd ~/pounce/frontend
|
|
|
|
# Build new version
|
|
echo " Building..."
|
|
npm run build 2>&1 | grep -E '(✓|○|λ|Error|error)' | head -10 | sed 's/^/ /'
|
|
|
|
BUILD_EXIT=$?
|
|
|
|
if [ $BUILD_EXIT -eq 0 ]; then
|
|
# Gracefully restart Next.js
|
|
NEXT_PID=$(pgrep -f 'next start' | head -1)
|
|
|
|
if [ -n "$NEXT_PID" ]; then
|
|
echo " Restarting Next.js (PID: $NEXT_PID)..."
|
|
kill $NEXT_PID 2>/dev/null
|
|
sleep 1
|
|
fi
|
|
|
|
# Start new instance
|
|
nohup npm run start > frontend.log 2>&1 &
|
|
sleep 2
|
|
|
|
# Verify
|
|
NEW_PID=$(pgrep -f 'next start' | head -1)
|
|
if [ -n "$NEW_PID" ]; then
|
|
echo " ✓ Frontend running (PID: $NEW_PID)"
|
|
else
|
|
echo " ⚠ Frontend may not have started correctly"
|
|
fi
|
|
else
|
|
echo " ✗ Build failed, keeping old version"
|
|
fi
|
|
FRONTEND_EOF
|
|
else
|
|
echo -e "\n${YELLOW}[4/4] Skipping frontend (backend only)${NC}"
|
|
fi
|
|
|
|
# Summary
|
|
echo -e "\n${GREEN}═══════════════════════════════════════════════════════════════${NC}"
|
|
echo -e "${GREEN} ✅ DEPLOY COMPLETE! ${NC}"
|
|
echo -e "${GREEN}═══════════════════════════════════════════════════════════════${NC}"
|
|
echo -e ""
|
|
echo -e " Frontend: ${BLUE}https://pounce.ch${NC} / http://$SERVER_HOST:3000"
|
|
echo -e " Backend: ${BLUE}https://pounce.ch/api${NC} / http://$SERVER_HOST:8000"
|
|
echo -e ""
|
|
echo -e "${CYAN}Quick commands:${NC}"
|
|
echo -e " ./deploy.sh -q # Quick sync, no git"
|
|
echo -e " ./deploy.sh -b # Backend only"
|
|
echo -e " ./deploy.sh -f # Frontend only"
|
|
echo -e " ./deploy.sh \"message\" # Full deploy with commit message"
|