chore: CI流程加固+Schema检查门禁
- deploy.sh: 提交纪律检查(本地未提交修改→中止) + 冒烟测试(健康/登录/KPI/BOT/Schema) - .woodpecker: 加前端typecheck+后端pytest测试步骤, backend-deploy加提交纪律检查 - 新增schema_check.py: ORM与数据库表结构一致性检查 - 修复budget_plans表缺3列(source_kpi_id/source_type/calc_logic) - 附带入库: budget测试+文档
This commit is contained in:
@@ -7,26 +7,38 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
echo "===== 管理会计OS 生产部署 ====="
|
||||
echo ""
|
||||
|
||||
# 0. 拉取最新代码
|
||||
echo "[0/4] 拉取最新代码..."
|
||||
# 0. 提交纪律检查:本地有未提交修改则中止,防止 git pull 覆盖丢失
|
||||
echo "[0/5] 提交纪律检查..."
|
||||
cd "$SCRIPT_DIR"
|
||||
DIRTY=$(git status --porcelain 2>/dev/null | grep -v "__pycache__" | head -20)
|
||||
if [ -n "$DIRTY" ]; then
|
||||
echo "❌ 检测到本地未提交的修改,中止部署(防止 git pull 覆盖丢失代码):"
|
||||
echo "$DIRTY"
|
||||
echo ""
|
||||
echo "请先提交代码: git add -A && git commit -m '...' && git push origin main"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ 工作区干净,无未提交修改"
|
||||
|
||||
# 1. 拉取最新代码
|
||||
echo "[1/5] 拉取最新代码..."
|
||||
git pull origin main
|
||||
echo " ✓ 代码已更新"
|
||||
|
||||
# 1. 构建前端
|
||||
echo "[1/4] 构建前端..."
|
||||
# 2. 构建前端
|
||||
echo "[2/5] 构建前端..."
|
||||
cd "$SCRIPT_DIR/frontend"
|
||||
pnpm build
|
||||
echo " ✓ 构建完成"
|
||||
|
||||
# 2. 部署前端到 Nginx
|
||||
echo "[2/4] 部署前端..."
|
||||
# 3. 部署前端到 Nginx
|
||||
echo "[3/5] 部署前端..."
|
||||
rm -rf /var/www/cma/assets/
|
||||
cp -r dist/* /var/www/cma/
|
||||
echo " ✓ 部署完成"
|
||||
|
||||
# 3. 更新后端依赖(失败不阻断 — 依赖已在系统Python中,避免PEP668中断部署)
|
||||
echo "[3/4] 更新后端依赖..."
|
||||
# 4. 更新后端依赖(失败不阻断 — 依赖已在系统Python中,避免PEP668中断部署)
|
||||
echo "[4/5] 更新后端依赖..."
|
||||
cd "$SCRIPT_DIR/backend"
|
||||
if [ -f venv/bin/activate ]; then
|
||||
source venv/bin/activate
|
||||
@@ -37,13 +49,56 @@ else
|
||||
fi
|
||||
echo " ✓ 依赖检查完成"
|
||||
|
||||
# 4. 重启后端服务
|
||||
echo "[4/4] 重启后端服务..."
|
||||
# 5. 重启后端服务
|
||||
echo "[5/5] 重启后端服务..."
|
||||
systemctl daemon-reload
|
||||
systemctl restart cma-backend
|
||||
systemctl reload nginx 2>/dev/null || nginx -s reload
|
||||
echo " ✓ 服务重启完成"
|
||||
|
||||
# ── 部署后冒烟测试 ──
|
||||
echo ""
|
||||
echo "===== 冒烟测试 ====="
|
||||
sleep 3
|
||||
SMOKE_FAIL=0
|
||||
if curl -sf http://127.0.0.1:8010/health > /dev/null 2>&1; then
|
||||
echo " ✅ 后端健康检查通过"
|
||||
else
|
||||
echo " ❌ 后端健康检查失败"; SMOKE_FAIL=1
|
||||
fi
|
||||
if curl -sf http://127.0.0.1:8010/api/cma/bot/ping > /dev/null 2>&1; then
|
||||
echo " ✅ BOT桥接API通过"
|
||||
else
|
||||
echo " ❌ BOT桥接API失败"; SMOKE_FAIL=1
|
||||
fi
|
||||
# Schema 一致性检查(数据库与ORM结构对齐)
|
||||
if /root/cma-management/backend/venv/bin/python3 /root/cma-management/backend/scripts/schema_check.py > /dev/null 2>&1; then
|
||||
echo " ✅ Schema一致性通过"
|
||||
else
|
||||
echo " ❌ Schema不一致,请检查: cd /root/cma-management/backend && venv/bin/python3 scripts/schema_check.py"
|
||||
SMOKE_FAIL=1
|
||||
fi
|
||||
TOKEN=$(curl -s -X POST http://127.0.0.1:8010/api/cma/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"admin","password":"admin123"}' | python3 -c "import sys,json; print(json.load(sys.stdin).get('token',''))" 2>/dev/null)
|
||||
if [ -n "$TOKEN" ]; then
|
||||
echo " ✅ 登录API通过"
|
||||
if curl -sf -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8010/api/cma/kpis > /dev/null 2>&1; then
|
||||
echo " ✅ KPI接口通过"
|
||||
else
|
||||
echo " ❌ KPI接口失败"; SMOKE_FAIL=1
|
||||
fi
|
||||
else
|
||||
echo " ❌ 登录API失败"; SMOKE_FAIL=1
|
||||
fi
|
||||
|
||||
if [ "$SMOKE_FAIL" -eq 1 ]; then
|
||||
echo ""
|
||||
echo "🚨 冒烟测试未全部通过!请检查后端日志: journalctl -u cma-backend -n 50"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✅ 全部冒烟测试通过"
|
||||
|
||||
echo ""
|
||||
echo "===== 部署完成 ====="
|
||||
echo " 前端: https://cma.sxbh.ltd"
|
||||
|
||||
Reference in New Issue
Block a user