- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
153 lines
3.6 KiB
Bash
Executable File
153 lines
3.6 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# 考培练系统自动更新脚本
|
||
# 作者: AI Assistant
|
||
# 日期: 2025-09-25
|
||
|
||
set -e
|
||
|
||
# 配置变量
|
||
PROJECT_DIR="/root/aiedu"
|
||
LOG_FILE="/var/log/kaopeilian_update.log"
|
||
BACKUP_DIR="/root/aiedu/backups/updates"
|
||
|
||
# 日志函数
|
||
log() {
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
# 创建备份目录
|
||
mkdir -p "$BACKUP_DIR"
|
||
|
||
log "=== 开始检查代码更新 ==="
|
||
|
||
cd "$PROJECT_DIR"
|
||
|
||
# 获取当前提交哈希
|
||
LOCAL_COMMIT=$(git rev-parse HEAD)
|
||
log "本地提交: $LOCAL_COMMIT"
|
||
|
||
# 拉取最新代码
|
||
git fetch origin production
|
||
|
||
# 获取远程提交哈希
|
||
REMOTE_COMMIT=$(git rev-parse origin/production)
|
||
log "远程提交: $REMOTE_COMMIT"
|
||
|
||
# 检查是否有更新
|
||
if [ "$LOCAL_COMMIT" = "$REMOTE_COMMIT" ]; then
|
||
log "代码已是最新版本,无需更新"
|
||
exit 0
|
||
fi
|
||
|
||
log "发现代码更新,开始部署流程..."
|
||
|
||
# 创建备份
|
||
BACKUP_NAME="backup_$(date '+%Y%m%d_%H%M%S')"
|
||
log "创建备份: $BACKUP_NAME"
|
||
|
||
# 备份当前代码
|
||
git stash push -m "Auto backup before update $BACKUP_NAME"
|
||
|
||
# 备份数据库(如果MySQL容器在运行)
|
||
if docker ps | grep -q kaopeilian-mysql; then
|
||
docker exec kaopeilian-mysql mysqldump -u root -p'Kaopeilian2025!@#' kaopeilian > "$BACKUP_DIR/${BACKUP_NAME}_database.sql"
|
||
log "数据库备份完成"
|
||
fi
|
||
|
||
# 拉取最新代码
|
||
log "拉取最新代码..."
|
||
git pull origin production
|
||
|
||
# 检查是否需要重新构建
|
||
NEED_REBUILD=false
|
||
|
||
# 检查Docker文件变化
|
||
if git diff --name-only "$LOCAL_COMMIT" "$REMOTE_COMMIT" | grep -E "(Dockerfile|docker-compose\.yml|requirements\.txt|package\.json)"; then
|
||
NEED_REBUILD=true
|
||
log "检测到构建文件变化,需要重新构建镜像"
|
||
fi
|
||
|
||
# 检查前端文件变化并构建
|
||
if git diff --name-only "$LOCAL_COMMIT" "$REMOTE_COMMIT" | grep -E "kaopeilian-frontend/(src/|package\.json|vite\.config\.ts)"; then
|
||
log "检测到前端代码变化,开始构建前端..."
|
||
|
||
cd "$PROJECT_DIR/kaopeilian-frontend"
|
||
|
||
# 确保依赖已安装
|
||
if [ ! -d "node_modules" ]; then
|
||
log "安装前端依赖..."
|
||
npm install
|
||
fi
|
||
|
||
# 构建前端
|
||
log "构建前端应用..."
|
||
npm run build
|
||
|
||
if [ $? -eq 0 ]; then
|
||
log "前端构建成功"
|
||
NEED_REBUILD=true
|
||
else
|
||
log "⚠️ 前端构建失败,但继续部署流程"
|
||
fi
|
||
|
||
cd "$PROJECT_DIR"
|
||
fi
|
||
|
||
# 停止服务
|
||
log "停止当前服务..."
|
||
docker compose down
|
||
|
||
# 重新构建(如果需要)
|
||
if [ "$NEED_REBUILD" = true ]; then
|
||
log "重新构建Docker镜像..."
|
||
docker compose build --no-cache
|
||
else
|
||
log "使用现有镜像启动服务..."
|
||
fi
|
||
|
||
# 启动服务
|
||
log "启动更新后的服务..."
|
||
docker compose up -d
|
||
|
||
# 等待服务启动
|
||
sleep 60
|
||
|
||
# 健康检查
|
||
log "执行健康检查..."
|
||
HEALTH_CHECK_URL="https://aiedu.ireborn.com.cn/health"
|
||
|
||
# 尝试多次健康检查
|
||
RETRY_COUNT=0
|
||
MAX_RETRIES=5
|
||
|
||
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
|
||
if curl -f -s -k "$HEALTH_CHECK_URL" > /dev/null; then
|
||
log "✅ 健康检查通过,更新成功完成"
|
||
|
||
# 清理旧的备份(保留最近5个)
|
||
cd "$BACKUP_DIR"
|
||
ls -t backup_*_database.sql 2>/dev/null | tail -n +6 | xargs rm -f 2>/dev/null || true
|
||
|
||
log "=== 自动更新完成 ==="
|
||
exit 0
|
||
else
|
||
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||
log "健康检查失败,重试 $RETRY_COUNT/$MAX_RETRIES"
|
||
sleep 10
|
||
fi
|
||
done
|
||
|
||
log "❌ 健康检查失败,开始回滚..."
|
||
|
||
# 回滚代码
|
||
cd "$PROJECT_DIR"
|
||
git reset --hard "$LOCAL_COMMIT"
|
||
|
||
# 重新启动服务
|
||
docker compose down
|
||
docker compose up -d
|
||
|
||
log "回滚完成,请检查服务状态"
|
||
exit 1
|