From 236ff1941327a3e279701b55fa66dda1feefd8a9 Mon Sep 17 00:00:00 2001 From: abcv7 Date: Wed, 26 Aug 2026 09:58:15 +0800 Subject: [PATCH] =?UTF-8?q?ci:=20Gitea=20Actions=20=E6=B5=81=E6=B0=B4?= =?UTF-8?q?=E7=BA=BF=20=E2=80=94=20push=20=E8=87=AA=E5=8A=A8=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=20test=20/=20=E6=89=8B=E5=8A=A8=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=E6=99=8B=E5=8D=87=20prod?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - deploy-test.yml: push master → Maven容器构建 → 推 Registry :test/:sha-x → SSH重建test容器 → 健康检查 - promote-prod.yml: workflow_dispatch(confirm=yes) → test镜像 save/scp/load 到 prod1 → 备份旧镜像 → 重建 → 健康检查 - prod1 daemon 未配 insecure-registries(避免重启生产容器), 晋升走镜像文件传输 --- .gitea/workflows/deploy-test.yml | 105 +++++++++++++++++++++++++++++ .gitea/workflows/promote-prod.yml | 107 ++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 .gitea/workflows/deploy-test.yml create mode 100644 .gitea/workflows/promote-prod.yml diff --git a/.gitea/workflows/deploy-test.yml b/.gitea/workflows/deploy-test.yml new file mode 100644 index 0000000..a890f32 --- /dev/null +++ b/.gitea/workflows/deploy-test.yml @@ -0,0 +1,105 @@ +# ============================================================================= +# TIANAI CAPTCHA PLATFORM — 测试环境自动部署 +# 触发:push 到 master(或手动 workflow_dispatch) +# 流程:checkout → Maven 容器构建 jar → docker build → 推 Registry(:test + :sha-x) +# → SSH 到测试机(156.233.226.86) 重建容器 → 健康检查 +# 架构参考:perler-lab deploy-test.yml +# ============================================================================= +name: deploy-test + +on: + push: + branches: [master] + workflow_dispatch: + +concurrency: + group: deploy-test-master + cancel-in-progress: false + +env: + REGISTRY: 156.233.226.46:5000 + IMAGE: 156.233.226.46:5000/tianai-captcha-platform + +jobs: + build-and-deploy-test: + runs-on: ubuntu-latest + steps: + - name: Checkout master + uses: actions/checkout@v4 + with: + ref: master + + - name: Setup SSH key (from secrets) + run: | + mkdir -p ~/.ssh + printf '%s\n' "${{ secrets.CAPTCHA_DEPLOY_KEY }}" > ~/.ssh/id_ed25519_deploy + chmod 600 ~/.ssh/id_ed25519_deploy + ssh-keyscan -H ${{ secrets.CAPTCHA_TEST_HOST }} >> ~/.ssh/known_hosts 2>/dev/null + ssh-keyscan -H ${{ secrets.CAPTCHA_PROD_HOST }} >> ~/.ssh/known_hosts 2>/dev/null + echo "SSH 密钥就绪" + + - name: Build jar (Maven + JDK21 in docker, 带依赖缓存卷) + run: | + set -e + docker volume create tianai-maven-cache >/dev/null 2>&1 || true + docker run --rm -v "$PWD":/ws -v tianai-maven-cache:/root/.m2 -w /ws \ + maven:3.9-eclipse-temurin-21 mvn -q package -DskipTests + ls -la tianai-captcha-platform/target/*.jar + + - name: Build & push image + run: | + set -e + SHA=$(echo "$GITHUB_SHA" | cut -c1-8) + # Dockerfile 约定 jar 在构建上下文根目录 + cp tianai-captcha-platform/target/tianai-captcha-platform-*.jar \ + tianai-captcha-platform/tianai-captcha-platform-2.0.0-SNAPSHOT.jar + docker build -t $IMAGE:test -t $IMAGE:sha-$SHA tianai-captcha-platform + docker push $IMAGE:test + docker push $IMAGE:sha-$SHA + echo "已推送 $IMAGE:test 和 $IMAGE:sha-$SHA" + + - name: Deploy to test env + run: | + set -e + SSH_CMD="ssh -i $HOME/.ssh/id_ed25519_deploy root@${{ secrets.CAPTCHA_TEST_HOST }}" + $SSH_CMD ' + set -e + echo "===== 拉取镜像 =====" + docker pull 156.233.226.46:5000/tianai-captcha-platform:test + echo "===== 重建容器 =====" + docker rm -f tianai-captcha 2>/dev/null || true + docker run -d --name tianai-captcha \ + --network mw \ + --restart unless-stopped \ + -p 127.0.0.1:18200:18200 \ + -v /opt/tianai/config:/app/config \ + 156.233.226.46:5000/tianai-captcha-platform:test + sleep 15 + docker ps --filter name=tianai-captcha --format "{{.Names}} {{.Status}}" + docker logs tianai-captcha 2>&1 | tail -3 + ' + + - name: Health check (generate API) + run: | + set -e + SSH_CMD="ssh -i $HOME/.ssh/id_ed25519_deploy root@${{ secrets.CAPTCHA_TEST_HOST }}" + OK=0 + CODE=000 + for i in $(seq 1 24); do + CODE=$($SSH_CMD 'curl -s -o /dev/null -w "%{http_code}" -X POST "http://127.0.0.1:18200/api/challenge/generate" -H "X-Site-Key: 6a062b70-c0b3-428e-8f1b-cca402e67ddb"' || echo 000) + if [ "$CODE" = "200" ]; then OK=1; break; fi + sleep 5 + done + if [ "$OK" != "1" ]; then + echo "健康检查失败 (code=$CODE)" + $SSH_CMD 'docker logs tianai-captcha --tail 30' || true + exit 1 + fi + echo "测试环境健康检查 OK (HTTP $CODE)" + + - name: Deployment summary + if: always() + run: | + echo "commit: $GITHUB_SHA" + echo "test 访问: test 机 127.0.0.1:18200 (mw 网络: tianai-captcha:18200)" + echo "晋升生产: Gitea → 仓库 → Actions → promote-prod → 输入 yes" diff --git a/.gitea/workflows/promote-prod.yml b/.gitea/workflows/promote-prod.yml new file mode 100644 index 0000000..9088fdd --- /dev/null +++ b/.gitea/workflows/promote-prod.yml @@ -0,0 +1,107 @@ +# ============================================================================= +# TIANAI CAPTCHA PLATFORM — 生产环境晋升(手动触发器) +# 触发:Gitea Actions 页面手动 workflow_dispatch,confirm 必须输入 yes +# 流程:从测试机导出当前 :test 镜像 → scp 到 prod1 → docker load +# → 备份旧镜像 → 重建容器 → 健康检查 +# 说明:prod1 的 docker daemon 未配置 insecure-registries(改它需要重启 daemon +# = 重启全部生产容器),因此不走 registry pull,用 save/scp/load 传递镜像。 +# ============================================================================= +name: promote-prod + +on: + workflow_dispatch: + inputs: + confirm: + description: '确认部署到生产环境(prod1)? 输入 yes' + required: true + default: 'no' + +env: + IMAGE: 156.233.226.46:5000/tianai-captcha-platform + +jobs: + promote-prod: + runs-on: ubuntu-latest + if: github.event.inputs.confirm == 'yes' + steps: + - name: Setup SSH key (from secrets) + run: | + mkdir -p ~/.ssh + printf '%s\n' "${{ secrets.CAPTCHA_DEPLOY_KEY }}" > ~/.ssh/id_ed25519_deploy + chmod 600 ~/.ssh/id_ed25519_deploy + ssh-keyscan -H ${{ secrets.CAPTCHA_TEST_HOST }} >> ~/.ssh/known_hosts 2>/dev/null + ssh-keyscan -H ${{ secrets.CAPTCHA_PROD_HOST }} >> ~/.ssh/known_hosts 2>/dev/null + echo "SSH 密钥就绪" + + - name: Export test image (test → runner) + run: | + set -e + SSH_KEY="$HOME/.ssh/id_ed25519_deploy" + TEST=${{ secrets.CAPTCHA_TEST_HOST }} + ssh -i $SSH_KEY root@$TEST \ + "docker pull $IMAGE:test >/dev/null && docker save $IMAGE:test | gzip > /tmp/tianai-promote.tar.gz && ls -la /tmp/tianai-promote.tar.gz" + scp -i $SSH_KEY root@$TEST:/tmp/tianai-promote.tar.gz /tmp/tianai-promote.tar.gz + echo "镜像已下载到 runner" + + - name: Transfer to prod1 (runner → prod1) + run: | + set -e + SSH_KEY="$HOME/.ssh/id_ed25519_deploy" + PROD=${{ secrets.CAPTCHA_PROD_HOST }} + scp -i $SSH_KEY /tmp/tianai-promote.tar.gz root@$PROD:/tmp/ + ssh -i $SSH_KEY root@$TEST 'rm -f /tmp/tianai-promote.tar.gz' + rm -f /tmp/tianai-promote.tar.gz + echo "镜像已传输到 prod1" + + - name: Load & restart container on prod1 + run: | + set -e + SSH_KEY="$HOME/.ssh/id_ed25519_deploy" + PROD=${{ secrets.CAPTCHA_PROD_HOST }} + ssh -i $SSH_KEY root@$PROD ' + set -e + echo "===== 备份当前生产镜像 =====" + docker tag tianai-captcha-platform:latest tianai-captcha-platform:backup-$(date +%Y%m%d-%H%M) 2>/dev/null \ + && echo "已备份" || echo "无旧镜像可备份" + echo "===== 加载新镜像 =====" + docker load < /tmp/tianai-promote.tar.gz + docker tag '"$IMAGE"':test tianai-captcha-platform:latest + rm -f /tmp/tianai-promote.tar.gz + echo "===== 重建容器 =====" + docker rm -f tianai-captcha 2>/dev/null || true + docker run -d --name tianai-captcha \ + --network middleware \ + --restart unless-stopped \ + -p 18200:18200 \ + -v /opt/tianai/config:/app/config \ + tianai-captcha-platform:latest + sleep 15 + docker ps --filter name=tianai-captcha --format "{{.Names}} {{.Status}}" + docker logs tianai-captcha 2>&1 | tail -3 + ' + + - name: Health check prod (generate + secondary-verify 探针) + run: | + set -e + SSH_KEY="$HOME/.ssh/id_ed25519_deploy" + PROD=${{ secrets.CAPTCHA_PROD_HOST }} + OK=0 + CODE=000 + for i in $(seq 1 24); do + CODE=$(ssh -i $SSH_KEY root@$PROD 'curl -s -o /dev/null -w "%{http_code}" -X POST "http://127.0.0.1:18200/api/challenge/generate" -H "X-Site-Key: 6796bad8-4369-492f-a4d7-643a93bb07f3"' || echo 000) + if [ "$CODE" = "200" ]; then OK=1; break; fi + sleep 5 + done + if [ "$OK" != "1" ]; then + echo "生产健康检查失败 (code=$CODE)" + ssh -i $SSH_KEY root@$PROD 'docker logs tianai-captcha --tail 30' || true + echo "如需回滚: ssh prod1 后执行 docker rm -f tianai-captcha 并用 backup-xxx 标签重建容器" + exit 1 + fi + echo "生产环境健康检查 OK (HTTP $CODE)" + + - name: Promotion summary + if: always() + run: | + echo "生产访问: prod1 :18200 (middleware 网络: tianai-captcha:18200)" + echo "回滚方式: prod1 上 docker tag tianai-captcha-platform:backup-YYYYMMDD-HHMM tianai-captcha-platform:latest 后重建容器"