#!/usr/bin/env bash # deploy-frontend.sh — Build Vuetify frontend and deploy to server # # Docker 生产:前端在镜像内构建,远程执行 nexus-1panel.sh upgrade # Supervisor:tar 上传到 web/app + supervisorctl restart # # Usage: bash deploy/deploy-frontend.sh set -euo pipefail NEXUS_SSH_HOST="${NEXUS_SSH:-nexus}" SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=15) if [[ -n "${NEXUS_SSH_KEY:-}" ]]; then SSH_OPTS+=(-i "${NEXUS_SSH_KEY}") fi ssh_cmd() { ssh "${SSH_OPTS[@]}" "${NEXUS_SSH_HOST}" "$@"; } echo "═══ Nexus Frontend Deploy ═══" REMOTE_RUNTIME=$(ssh_cmd 'bash -s' <<'REMOTE' set -euo pipefail docker_cmd() { if docker "$@" 2>/dev/null; then return 0; fi sudo docker "$@" 2>/dev/null } compose_cmd() { if docker compose "$@" 2>/dev/null; then return 0; fi sudo docker compose "$@" 2>/dev/null } for d in /opt/nexus /www/wwwroot/api.synaglobal.vip; do [[ -d "$d/server" ]] || continue if [[ -f "$d/docker/.env.prod" ]] && compose_cmd version >/dev/null 2>&1; then prof="$d/docker/.host-profile" [[ -f "$prof" ]] || prof="$d/docker/profiles/2c8g.env" if [[ -f "$prof" ]]; then args=(-f "$d/docker/docker-compose.prod.yml") docker_cmd network inspect 1panel-network >/dev/null 2>&1 && \ [[ -f "$d/docker/docker-compose.1panel.yml" ]] && \ args+=(-f "$d/docker/docker-compose.1panel.yml") q=$(cd "$d" && compose_cmd "${args[@]}" \ --env-file "$d/docker/.env.prod" --env-file "$prof" ps -q nexus 2>/dev/null || true) [[ -n "$q" ]] && echo "docker $d" && exit 0 fi fi if [[ -f "$d/deploy/nexus-1panel.sh" ]]; then q=$(docker_cmd ps --format '{{.Names}}' 2>/dev/null | grep -E '^nexus-prod-nexus-' || true) [[ -n "$q" ]] && echo "docker $d" && exit 0 fi if command -v supervisorctl >/dev/null 2>&1 && supervisorctl status nexus >/dev/null 2>&1; then echo "supervisor $d" exit 0 fi done echo "unknown" REMOTE ) RUNTIME="${REMOTE_RUNTIME%% *}" DEPLOY_PATH="${REMOTE_RUNTIME#* }" [[ "$DEPLOY_PATH" == "$REMOTE_RUNTIME" ]] && DEPLOY_PATH="/www/wwwroot/api.synaglobal.vip" echo "Remote runtime: ${RUNTIME} @ ${DEPLOY_PATH}" echo "▶ Building frontend (local verify)..." cd frontend && npx vite build && cd .. echo "✓ Build complete" if [[ "$RUNTIME" == "docker" ]]; then echo "▶ Docker 生产:重建镜像以包含新前端(非 tar 热更新)..." ssh_cmd "cd ${DEPLOY_PATH} && sudo env NEXUS_ROOT=${DEPLOY_PATH} bash ${DEPLOY_PATH}/deploy/nexus-1panel.sh upgrade" else echo "▶ Packaging..." tar czf /tmp/nexus-frontend.tar.gz -C web/app index.html assets/ echo "✓ Package ready ($(du -h /tmp/nexus-frontend.tar.gz | cut -f1))" echo "▶ Uploading to server..." scp "${SSH_OPTS[@]}" /tmp/nexus-frontend.tar.gz "${NEXUS_SSH_HOST}:/tmp/nexus-frontend.tar.gz" echo "✓ Upload complete" echo "▶ Deploying on server..." ssh_cmd "cd ${DEPLOY_PATH}/web/app && tar xzf /tmp/nexus-frontend.tar.gz && rm /tmp/nexus-frontend.tar.gz" echo "▶ Pruning orphaned assets..." if ! ssh_cmd "python3 ${DEPLOY_PATH}/deploy/prune_frontend_assets.py --dry-run"; then echo "✗ Prune dry-run failed" exit 1 fi ssh_cmd "python3 ${DEPLOY_PATH}/deploy/prune_frontend_assets.py" echo "✓ Extracted and pruned" echo "▶ Restarting backend..." ssh_cmd "supervisorctl restart nexus" echo "✓ Restarted" fi sleep 3 HEALTH=$(ssh_cmd "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8600/health" 2>/dev/null || echo "000") SPA=$(ssh_cmd "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8600/app/" 2>/dev/null || echo "000") echo "" echo "═══ Verification ═══" echo " /health → $HEALTH" echo " /app/ → $SPA" if [[ "$HEALTH" == "200" || "$HEALTH" == "ok" ]] && [[ "$SPA" == "200" ]]; then echo "✓ Deploy successful!" else echo "✗ Verification failed — check server logs" exit 1 fi