Files
sanguo_moziplus_v2/scripts/deploy.sh
T
2026-05-23 13:30:57 +08:00

183 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# deploy.sh — 部署/升级 moziplus v2
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
# 默认值
SOURCE_DIR="$PROJECT_DIR"
TARGET_DIR="${MOZIPLUS_V2_DIR:-$HOME/.sanguo_projects/sanguo_moziplus_v2}"
PM2_NAME="sanguo-moziplus-v2"
SKIP_BUILD=false
usage() {
echo "Usage: $0 [options]"
echo ""
echo "Options:"
echo " --source=DIR 源码目录 (default: 项目开发目录)"
echo " --target=DIR 安装目标目录 (default: ~/.sanguo_projects/sanguo_moziplus_v2)"
echo " --skip-build 跳过前端构建"
echo " -h, --help 显示帮助"
exit 0
}
for arg in "$@"; do
case "$arg" in
--source=*) SOURCE_DIR="${arg#*=}" ;;
--target=*) TARGET_DIR="${arg#*=}" ;;
--skip-build) SKIP_BUILD=true ;;
-h|--help) usage ;;
esac
done
echo "🚀 Deploying moziplus v2"
echo " Source: $SOURCE_DIR"
echo " Target: $TARGET_DIR"
# ── 前置检查 ──
echo ""
echo "📋 Pre-flight checks..."
if ! command -v python3 &>/dev/null; then
echo "❌ python3 not found" && exit 1
fi
PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
echo " Python: $PYTHON_VERSION"
if ! command -v pm2 &>/dev/null; then
echo "❌ pm2 not found" && exit 1
fi
echo " PM2: $(pm2 --version)"
if [ ! -d "$SOURCE_DIR/src" ]; then
echo "❌ Source directory invalid: $SOURCE_DIR/src not found" && exit 1
fi
# ── 前端构建 ──
if [ "$SKIP_BUILD" = false ]; then
echo ""
echo "🔨 Building frontend..."
bash "$SCRIPT_DIR/build-frontend.sh"
else
echo ""
echo "⏭️ Skipping frontend build (--skip-build)"
# 确保前端 dist 存在
if [ ! -d "$SOURCE_DIR/src/frontend/dist" ]; then
echo "❌ Frontend dist not found. Run without --skip-build first." && exit 1
fi
fi
# ── 创建目标目录 ──
FIRST_INSTALL=false
if [ ! -d "$TARGET_DIR" ]; then
FIRST_INSTALL=true
echo ""
echo "📁 Creating target directory: $TARGET_DIR"
mkdir -p "$TARGET_DIR"
fi
# ── 同步代码 ──
echo ""
echo "🔄 Syncing code..."
rsync -a --delete \
--exclude='.git/' \
--exclude='docs/' \
--exclude='tests/' \
--exclude='scripts/' \
--exclude='data/' \
--exclude='logs/' \
--exclude='inbox/' \
--exclude='node_modules/' \
--exclude='tsconfig.tsbuildinfo' \
--exclude='__pycache__/' \
--exclude='.venv/' \
--exclude='.DS_Store' \
--exclude='config/' \
"$SOURCE_DIR/" "$TARGET_DIR/"
# 但不覆盖运行时配置和数据
# rsync --delete 不影响 exclude 的目录
echo " Code synced ✅"
# ── 确保目录结构 ──
mkdir -p "$TARGET_DIR/data"
mkdir -p "$TARGET_DIR/logs"
mkdir -p "$TARGET_DIR/inbox"
# 确保默认配置存在(不覆盖已有配置)
if [ ! -f "$TARGET_DIR/config/default.yaml" ]; then
if [ -f "$SOURCE_DIR/config/default.yaml" ]; then
cp "$SOURCE_DIR/config/default.yaml" "$TARGET_DIR/config/default.yaml"
echo " Created default config ✅"
fi
fi
if [ ! -f "$TARGET_DIR/config/guardrails.yaml" ]; then
if [ -f "$SOURCE_DIR/config/guardrails.yaml" ]; then
cp "$SOURCE_DIR/config/guardrails.yaml" "$TARGET_DIR/config/guardrails.yaml"
echo " Created guardrails config ✅"
fi
fi
# ── PM2 管理 ──
echo ""
if [ "$FIRST_INSTALL" = true ]; then
echo "🆕 First install — starting with PM2..."
cd "$TARGET_DIR"
pm2 start ecosystem.config.cjs
else
echo "♻️ Upgrading — restarting PM2..."
pm2 restart "$PM2_NAME" --update-env
fi
pm2 save
# ── 前端健康检查 ──
echo " Checking frontend..."
FRONTEND_OK=false
for i in $(seq 1 5); do
if curl -sf http://localhost:8083/ >/dev/null 2>&1; then
FRONTEND_OK=true
break
fi
sleep 1
done
if [ "$FRONTEND_OK" = true ]; then
echo " Frontend check passed ✅"
else
echo " ⚠️ Frontend check timeout"
fi
# ── 后端健康检查 ──
echo " Checking backend..."
HEALTH_URL="http://localhost:8083/api/daemon/status"
OK=false
for i in $(seq 1 10); do
if curl -sf "$HEALTH_URL" >/dev/null 2>&1; then
OK=true
break
fi
sleep 1
done
if [ "$OK" = true ]; then
echo " Health check passed ✅"
else
echo " ⚠️ Health check timeout (service may still be starting)"
echo " Check: pm2 logs $PM2_NAME"
fi
# ── 完成 ──
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
if [ "$FIRST_INSTALL" = true ]; then
echo "✅ moziplus v2 installed successfully!"
else
echo "✅ moziplus v2 upgraded successfully!"
fi
echo " URL: http://localhost:8083/"
echo " PM2: pm2 status $PM2_NAME"
echo " Logs: pm2 logs $PM2_NAME"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"