持续集成流水线:强化最终自动部署流水线、测试门禁与生产冒烟自检
This commit is contained in:
1 parent
6762189093
commit
f2122997d7
2 files changed
+103
-10
No files matched your search
+37
-5
@@ -16,6 +16,7 @@ build_backend:
|
||||
- railway-deploy
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
script:
|
||||
- echo "=== 开始编译后端 RuoYi-Vue ==="
|
||||
- export JAVA_HOME=/data2/wzb/tools/jdk8
|
||||
@@ -24,7 +25,9 @@ build_backend:
|
||||
- bash scripts/bootstrap/check-kingbase-jdbc.sh
|
||||
- cd RuoYi-Vue
|
||||
- mvn clean package
|
||||
- echo "=== 后端编译成功 ==="
|
||||
- |
|
||||
python3 -c 'import glob, re; runs = [int(m.group(1)) for f in glob.glob("ruoyi-*/target/surefire-reports/*.txt") for m in re.finditer(r"Tests run:\s*(\d+)", open(f, errors="ignore").read())]; print("=== 后端测试执行统计: Tests run: %d ===" % sum(runs))'
|
||||
- echo "=== 后端测试与构建成功 ==="
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
@@ -37,6 +40,7 @@ build_frontend:
|
||||
- railway-deploy
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
script:
|
||||
- echo "=== 开始编译前端 build_ui ==="
|
||||
- export NODE_OPTIONS="--openssl-legacy-provider --dns-result-order=ipv4first"
|
||||
@@ -46,7 +50,11 @@ build_frontend:
|
||||
ln -sfn /data2/wzb/tools/frontend-cache/node_modules ./node_modules;
|
||||
fi
|
||||
- npm run build:prod
|
||||
- echo "=== 前端编译成功 ==="
|
||||
- if [ ! -d "dist" ] || [ ! -f "dist/index.html" ]; then
|
||||
echo "错误:前端构建产物 build_ui/dist/index.html 不存在,构建失败";
|
||||
exit 1;
|
||||
fi
|
||||
- echo "=== 前端编译成功,build_ui/dist/index.html 校验通过 ==="
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
@@ -59,13 +67,37 @@ deploy_production:
|
||||
- railway-deploy
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH == "feat/cicd-pipeline"'
|
||||
- when: never
|
||||
script:
|
||||
- echo "=== 开始部署应用 ==="
|
||||
# 部署前端静态资源到发布目录
|
||||
- echo "=== 0. 验证部署运行时环境配置 ==="
|
||||
- if [ -z "${TRAIN_STUDENT_IDENTITY_ENCRYPTION_KEY:-}" ] || [ -z "${TRAIN_STUDENT_IDENTITY_HASH_KEY:-}" ] || [ -z "${SPRING_REDIS_PASSWORD:-}" ]; then
|
||||
echo "错误:缺少必需的运行时配置";
|
||||
exit 1;
|
||||
fi
|
||||
- echo "required runtime configuration present."
|
||||
- echo "=== 1. 执行部署备份 (Rollback 兜底) ==="
|
||||
- if [ -d "/data2/wzb/deploy/frontend" ] && [ "$(ls -A /data2/wzb/deploy/frontend 2>/dev/null)" ]; then
|
||||
echo "备份现有前端资源到 /data2/wzb/deploy/frontend.bak ...";
|
||||
mkdir -p /data2/wzb/deploy/frontend.bak;
|
||||
cp -a /data2/wzb/deploy/frontend/. /data2/wzb/deploy/frontend.bak/;
|
||||
fi
|
||||
- if [ -f "/data2/wzb/deploy/backend/ruoyi-admin.jar" ]; then
|
||||
echo "备份现有后端 Jar 到 /data2/wzb/deploy/backend/ruoyi-admin.jar.bak ...";
|
||||
cp -p /data2/wzb/deploy/backend/ruoyi-admin.jar /data2/wzb/deploy/backend/ruoyi-admin.jar.bak;
|
||||
fi
|
||||
- echo "=== 2. 部署前端静态资源与文档中心 ==="
|
||||
- mkdir -p /data2/wzb/deploy/frontend
|
||||
- rm -rf /data2/wzb/deploy/frontend/*
|
||||
- cp -r build_ui/dist/* /data2/wzb/deploy/frontend/
|
||||
# 部署后端 Jar 包并执行平滑重启
|
||||
- mkdir -p /data2/wzb/deploy/frontend/docs
|
||||
- cp -r docs/* /data2/wzb/deploy/frontend/docs/
|
||||
- echo "=== 3. 部署后端 Jar 包 ==="
|
||||
- mkdir -p /data2/wzb/deploy/backend
|
||||
- cp RuoYi-Vue/ruoyi-admin/target/ruoyi-admin.jar /data2/wzb/deploy/backend/
|
||||
- echo "=== 4. 执行平滑重启与生产自检 ==="
|
||||
- chmod +x deploy/restart-all.sh
|
||||
- bash deploy/restart-all.sh
|
||||
- echo "=== 5. 输出访问地址 ==="
|
||||
- echo "APPLICATION_URL=http://192.168.139.230:8082/"
|
||||
- echo "DOCUMENTATION_URL=http://192.168.139.230:8082/docs/visual/index.html"
|
||||
- echo "=== 部署与自检成功完成! ==="
|
||||
+66
-5
@@ -21,22 +21,28 @@ mkdir -p "$BACKEND_DIR" "$FRONTEND_DIR" "$LOG_DIR"
|
||||
|
||||
echo "=== 0. 检查运行时安全配置 ==="
|
||||
|
||||
MISSING_CONFIG=0
|
||||
if [ -z "${TRAIN_STUDENT_IDENTITY_ENCRYPTION_KEY:-}" ]; then
|
||||
echo "错误:缺少 TRAIN_STUDENT_IDENTITY_ENCRYPTION_KEY"
|
||||
exit 1
|
||||
MISSING_CONFIG=1
|
||||
fi
|
||||
|
||||
if [ -z "${TRAIN_STUDENT_IDENTITY_HASH_KEY:-}" ]; then
|
||||
echo "错误:缺少 TRAIN_STUDENT_IDENTITY_HASH_KEY"
|
||||
exit 1
|
||||
MISSING_CONFIG=1
|
||||
fi
|
||||
|
||||
if [ -z "${SPRING_REDIS_PASSWORD:-}" ]; then
|
||||
echo "错误:缺少 SPRING_REDIS_PASSWORD"
|
||||
MISSING_CONFIG=1
|
||||
fi
|
||||
|
||||
if [ "$MISSING_CONFIG" -ne 0 ]; then
|
||||
echo "运行时安全配置检查失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "运行时安全配置存在性检查通过"
|
||||
echo "required runtime configuration present."
|
||||
|
||||
echo "=== 1. 检查并停止当前用户的旧后端进程 ==="
|
||||
TARGET_PID=""
|
||||
@@ -100,8 +106,8 @@ for i in {1..35}; do
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if [ "$HEALTH_OK" -ne 1 ]; then
|
||||
echo "错误:后端健康检查超时,请检查 $LOG_PATH"
|
||||
if [ "$HEALTH_OK" != "1" ]; then
|
||||
echo "Backend health check failed: 后端健康检查失败或超时,请检查 $LOG_PATH"
|
||||
|
||||
if kill -0 "$NEW_PID" 2>/dev/null; then
|
||||
kill -15 "$NEW_PID" 2>/dev/null || true
|
||||
@@ -167,6 +173,12 @@ http {
|
||||
NGINX_EOF
|
||||
fi
|
||||
|
||||
echo "验证 Nginx 配置文件 (Nginx Gate)..."
|
||||
if ! /usr/sbin/nginx -t -c "$NGINX_CONF"; then
|
||||
echo "错误:Nginx 配置文件测试失败,禁止启动或重载"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if pgrep -u "$(whoami)" -f "nginx: master" >/dev/null; then
|
||||
echo "平滑重载前端 Nginx 服务..."
|
||||
|
||||
@@ -183,4 +195,53 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "=== 4. 执行生产环境自动化冒烟测试 (Production Smoke Gate) ==="
|
||||
SMOKE_PASS=1
|
||||
|
||||
# A. 验证前端应用首页
|
||||
HTTP_STATUS_A=$(curl -o /dev/null -s -w "%{http_code}" "http://127.0.0.1:8082/")
|
||||
if [ "$HTTP_STATUS_A" = "200" ]; then
|
||||
echo "[Smoke PASS] A: http://127.0.0.1:8082/ -> HTTP $HTTP_STATUS_A"
|
||||
else
|
||||
echo "[Smoke FAIL] A: http://127.0.0.1:8082/ -> HTTP $HTTP_STATUS_A (预期 200)"
|
||||
SMOKE_PASS=0
|
||||
fi
|
||||
|
||||
# B. 验证后端 API 反向代理及业务状态
|
||||
RES_B=$(curl -s "http://127.0.0.1:8082/prod-api/captchaImage" 2>/dev/null)
|
||||
HTTP_STATUS_B=$(curl -o /dev/null -s -w "%{http_code}" "http://127.0.0.1:8082/prod-api/captchaImage")
|
||||
if [ "$HTTP_STATUS_B" = "200" ] && echo "$RES_B" | grep -q '"code":200'; then
|
||||
echo "[Smoke PASS] B: http://127.0.0.1:8082/prod-api/captchaImage -> HTTP $HTTP_STATUS_B 且 code:200"
|
||||
else
|
||||
echo "[Smoke FAIL] B: http://127.0.0.1:8082/prod-api/captchaImage -> HTTP $HTTP_STATUS_B 业务响应异常"
|
||||
SMOKE_PASS=0
|
||||
fi
|
||||
|
||||
# C. 验证 Human Documentation Portal 首页
|
||||
HTTP_STATUS_C=$(curl -o /dev/null -s -w "%{http_code}" "http://127.0.0.1:8082/docs/visual/index.html")
|
||||
if [ "$HTTP_STATUS_C" = "200" ]; then
|
||||
echo "[Smoke PASS] C: http://127.0.0.1:8082/docs/visual/index.html -> HTTP $HTTP_STATUS_C"
|
||||
else
|
||||
echo "[Smoke FAIL] C: http://127.0.0.1:8082/docs/visual/index.html -> HTTP $HTTP_STATUS_C (预期 200)"
|
||||
SMOKE_PASS=0
|
||||
fi
|
||||
|
||||
# D. 验证文档静态资源 docs.css 与 docs.js
|
||||
HTTP_STATUS_CSS=$(curl -o /dev/null -s -w "%{http_code}" "http://127.0.0.1:8082/docs/visual/assets/docs.css")
|
||||
HTTP_STATUS_JS=$(curl -o /dev/null -s -w "%{http_code}" "http://127.0.0.1:8082/docs/visual/assets/docs.js")
|
||||
if [ "$HTTP_STATUS_CSS" = "200" ] && [ "$HTTP_STATUS_JS" = "200" ]; then
|
||||
echo "[Smoke PASS] D: docs.css (HTTP $HTTP_STATUS_CSS) & docs.js (HTTP $HTTP_JS) -> HTTP 200"
|
||||
else
|
||||
echo "[Smoke FAIL] D: docs.css (HTTP $HTTP_STATUS_CSS), docs.js (HTTP $HTTP_JS) (预期 200)"
|
||||
SMOKE_PASS=0
|
||||
fi
|
||||
|
||||
if [ "$SMOKE_PASS" != "1" ]; then
|
||||
echo "错误:生产环境冒烟测试未全部通过,部署失败!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== 生产环境冒烟测试全部通过 (Production Smoke Gate PASSED) ==="
|
||||
echo "APPLICATION_URL=http://192.168.139.230:8082/"
|
||||
echo "DOCUMENTATION_URL=http://192.168.139.230:8082/docs/visual/index.html"
|
||||
echo "=== 部署全部就绪!前端访问地址: http://192.168.139.230:8082 ==="
|
||||
Reference in new issue
Block a user