ci: Gitea Actions 流水线 — push 自动部署 test / 手动触发晋升 prod
deploy-test / build-and-deploy-test (push) Failing after 1m4s

- 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(避免重启生产容器), 晋升走镜像文件传输
This commit is contained in:
abcv7
2026-08-26 09:58:15 +08:00
parent dbe9b58b0c
commit 236ff19413
2 changed files with 212 additions and 0 deletions
+105
View File
@@ -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"
+107
View File
@@ -0,0 +1,107 @@
# =============================================================================
# TIANAI CAPTCHA PLATFORM — 生产环境晋升(手动触发器)
# 触发:Gitea Actions 页面手动 workflow_dispatchconfirm 必须输入 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 后重建容器"