#!/bin/bash # ============================================ # 从 GitHub 部署到生产环境(迁移后:Git 根 = wildgrowth-backend,应用根 = backend) # ============================================ # 使用方法: # ssh root@120.55.112.195 # cd /var/www/wildgrowth-backend/backend && bash deploy/deploy-from-github.sh [分支名] # 默认分支:1.30dazhi合并前(不部署 main 上的错误合并) # git pull 超时 60s,失败会提示在本机执行 backend/deploy/deploy-rsync-from-local.sh # SKIP_GIT_PULL=1 时跳过拉取(供 rsync 回退后使用);GIT_PULL_TIMEOUT=90 可改超时秒数 # 回滚:bash deploy/deploy-from-github.sh rollback # ============================================ set -e GIT_ROOT="/var/www/wildgrowth-backend" APP_ROOT="/var/www/wildgrowth-backend/backend" # ---------- 回滚模式 ---------- if [ "$1" = "rollback" ]; then echo "═══════════════════════════════════════════════════════════" echo " 🔄 回滚模式:回退到上次成功部署的版本" echo "═══════════════════════════════════════════════════════════" echo "" if [ ! -d "$APP_ROOT" ]; then echo "❌ 错误: $APP_ROOT 不存在" exit 1 fi if [ ! -f "$APP_ROOT/.deploy-last" ]; then echo "❌ 无上次部署记录(.deploy-last 不存在)" echo " 请手动:git -C $GIT_ROOT log --oneline -5,checkout 后重新 build 并 pm2 restart" exit 1 fi PREV=$(cat "$APP_ROOT/.deploy-last" | tr -d '[:space:]') if [ -z "$PREV" ]; then echo "❌ .deploy-last 为空,无法回滚" exit 1 fi echo "📌 回滚到: $PREV" echo "" (cd "$GIT_ROOT" && git fetch origin && git checkout "$PREV") echo "📦 安装依赖..." (cd "$APP_ROOT" && npm install) echo "🔧 Prisma generate..." (cd "$APP_ROOT" && npx prisma generate) echo "🗄️ 数据库迁移..." MIGRATIONS="$APP_ROOT/prisma/migrations" if [ -d "$MIGRATIONS" ]; then for d in "$MIGRATIONS"/*/; do [ -d "$d" ] || continue if [ ! -f "${d}migration.sql" ]; then rm -rf "$d"; fi done fi (cd "$APP_ROOT" && npx prisma migrate deploy) echo "🔨 构建..." (cd "$APP_ROOT" && npm run build) echo "🔄 重启服务..." pm2 restart wildgrowth-api echo "⏳ 等待 3s 后健康检查..." sleep 3 if curl -sf http://localhost:3000/health > /dev/null; then echo "✅ 回滚完成,服务正常" else echo "⚠️ 健康检查未通过,请检查: pm2 logs wildgrowth-api" fi echo "" exit 0 fi # ---------- 正常部署 ---------- BRANCH=${1:-1.30dazhi合并前} GIT_PULL_TIMEOUT=${GIT_PULL_TIMEOUT:-60} echo "═══════════════════════════════════════════════════════════" echo " 🚀 开始从 GitHub 部署到生产环境" echo " 📦 部署分支: $BRANCH" echo "═══════════════════════════════════════════════════════════" echo "" if [ ! -d "$APP_ROOT" ]; then echo "❌ 错误: $APP_ROOT 不存在" exit 1 fi if [ ! -f "$APP_ROOT/.env" ]; then echo "❌ 错误: $APP_ROOT/.env 不存在" exit 1 fi # 1. 拉取最新代码(在 Git 根);若 SKIP_GIT_PULL=1 则跳过(供 rsync 回退后使用) if [ -n "$SKIP_GIT_PULL" ]; then echo "📥 步骤 1: 跳过 git pull(SKIP_GIT_PULL=1,代码已由 rsync 同步)" else echo "📥 步骤 1: 拉取最新代码(超时 ${GIT_PULL_TIMEOUT}s)..." (cd "$GIT_ROOT" && git fetch origin) if ! (cd "$GIT_ROOT" && git show-ref --verify --quiet refs/remotes/origin/$BRANCH); then echo "❌ 分支 $BRANCH 不存在" (cd "$GIT_ROOT" && git branch -r | grep -v HEAD | sed 's/origin\///' | sed 's/^/ - /') exit 1 fi if ! (cd "$GIT_ROOT" && timeout "$GIT_PULL_TIMEOUT" git checkout $BRANCH && timeout "$GIT_PULL_TIMEOUT" git pull origin $BRANCH); then echo "" echo "❌ Git 拉取失败(超时或网络/凭据问题)。请在本机执行 rsync 回退部署:" echo " cd <项目根目录> && bash backend/deploy/deploy-rsync-from-local.sh" echo " 详见 DEPLOY_QUICK.md「三、git pull 超时:rsync 回退部署」。" exit 1 fi echo "✅ 代码已更新 (分支: $BRANCH)" fi echo "" # 2. 安装依赖 echo "📦 步骤 2: 安装依赖..." (cd "$APP_ROOT" && npm install) echo "✅ 依赖已安装" echo "" # 3. Prisma generate echo "🔧 步骤 3: Prisma generate..." (cd "$APP_ROOT" && npx prisma generate) echo "" # 4. 数据库迁移(先删缺 migration.sql 的目录,避免 P3015) echo "🗄️ 步骤 4: 数据库迁移..." MIGRATIONS="$APP_ROOT/prisma/migrations" if [ -d "$MIGRATIONS" ]; then for d in "$MIGRATIONS"/*/; do [ -d "$d" ] || continue if [ ! -f "${d}migration.sql" ]; then echo " 删除残缺 migration 目录: $(basename "$d")" rm -rf "$d" fi done fi (cd "$APP_ROOT" && npx prisma migrate deploy) echo "✅ 数据库迁移完成" echo "" # 4.5. 迁移Prompt配置(如果脚本存在) echo "📝 步骤 4.5: 迁移Prompt配置..." if [ -f "$APP_ROOT/scripts/migrate-prompt-configs.ts" ]; then (cd "$APP_ROOT" && npx ts-node scripts/migrate-prompt-configs.ts) || echo "⚠️ Prompt配置迁移失败,但继续部署" echo "✅ Prompt配置迁移完成" else echo "ℹ️ Prompt配置迁移脚本不存在,跳过" fi echo "" # 5. 构建 echo "🔨 步骤 5: 构建项目..." (cd "$APP_ROOT" && npm run build) echo "✅ 项目已构建" echo "" # 6. 重启服务 echo "🔄 步骤 6: 重启服务..." pm2 restart wildgrowth-api echo "" # 7. 健康检查 echo "🏥 步骤 7: 健康检查..." sleep 2 if curl -sf http://localhost:3000/health > /dev/null; then echo "✅ 健康检查通过" (cd "$GIT_ROOT" && git rev-parse HEAD) > "$APP_ROOT/.deploy-last" echo " (已记录到 .deploy-last,供 rollback 使用)" else echo "❌ 健康检查失败: curl http://localhost:3000/health 未返回成功" echo " 请检查: pm2 logs wildgrowth-api" exit 1 fi echo "" # 8. 状态与日志 echo "📊 步骤 8: 服务状态" pm2 status wildgrowth-api echo "📝 最近日志:" pm2 logs wildgrowth-api --lines 20 --nostream echo "" echo "═══════════════════════════════════════════════════════════" echo " ✅ 部署完成!分支: $BRANCH" echo "═══════════════════════════════════════════════════════════" echo "💡 回滚: bash deploy/deploy-from-github.sh rollback" echo ""