Files
ai-app-database/.gitea/workflows/deploy-demo.yml
T
2026-04-23 12:58:11 +09:00

224 lines
9.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ═══════════════════════════════════════════════════════════════
# Demo 部署工作流 — CI 成功后自动部署 / 可手动触发
#
# 触发条件:
# 1. "CI — Docker Build & Push" 在 main/master 上成功完成后自动触发
# 2. workflow_dispatch 手动触发(可指定镜像标签)
#
# 运行环境:
# - self-hosted runner(与 Gitea 同一服务器)
# - Docker 部署,外置 MySQL & Caddy
#
# 前置配置(Gitea → 仓库 → 设置 → Secrets):
# REGISTRY_TOKEN — 具有 package:read 权限的 Gitea Access Token
# DEMO_SECRET_KEY — Flask SECRET_KEY(随机字符串,≥32位)
# DEMO_ADMIN_PASS — Demo 管理员密码(首次部署时设置)
#
# 服务器前置条件:
# - 已安装 Docker + docker compose(或 docker-compose
# - 已安装并运行 Caddy,配置了 sites 目录 include
# - runner 用户在 docker 组 或 使用 sudo(见下方 SUDO_DOCKER 变量)
# ═══════════════════════════════════════════════════════════════
name: Deploy — Demo Environment
on:
# CI 工作流在 main/master 完成后触发
workflow_run:
workflows:
- "CI — Docker Build & Push"
branches:
- main
- master
types:
- completed
# 手动触发,支持指定镜像标签
workflow_dispatch:
inputs:
image_tag:
description: '镜像标签(默认: latest'
required: false
default: 'latest'
env:
REGISTRY: git.hty1024.com
# Demo 部署目录(需与服务器实际路径一致)
DEPLOY_DIR: /opt/resource-library-demo
# Caddy 站点配置目录(需在 Caddyfile 中通过 import 引用)
CADDY_SITES_DIR: /etc/caddy/sites
# 应用对外端口(Caddy 反向代理到此端口)
APP_PORT: 5000
# Demo 域名
DOMAIN: prl.hty1024.com
# 外置 MySQL 连接串
DB_URL: mysql+pymysql://resource_library:BWRVzzCwzuuP_1Hj@pma.hty1024.com:31000/resource_library
jobs:
deploy-demo:
name: Deploy to Demo
runs-on: self-hosted
# workflow_run 触发时,仅在 CI 成功时继续
if: >
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
steps:
# ── 1. 检出代码(获取 compose 文件等) ──────────────────────
- name: 检出代码
uses: actions/checkout@v4
# ── 2. 确定目标镜像标签 ──────────────────────────────────────
- name: 确定镜像标签
id: image
run: |
REPO=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')
IMAGE_NAME="${{ env.REGISTRY }}/${REPO}"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG="${{ github.event.inputs.image_tag }}"
else
TAG="latest"
fi
echo "name=${IMAGE_NAME}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
echo "full=${IMAGE_NAME}:${TAG}" >> $GITHUB_OUTPUT
echo "镜像: ${IMAGE_NAME}:${TAG}"
# ── 3. 登录 Gitea 镜像仓库 ──────────────────────────────────
- name: 登录 Gitea 镜像仓库
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ gitea.actor }}
password: ${{ secrets.REGISTRY_TOKEN }}
# ── 4. 检测 Docker Compose 命令 ─────────────────────────────
- name: 检测 Compose 命令
run: |
if docker compose version &>/dev/null 2>&1; then
echo "COMPOSE_CMD=docker compose" >> $GITHUB_ENV
echo "使用: docker compose"
elif command -v docker-compose &>/dev/null; then
echo "COMPOSE_CMD=docker-compose" >> $GITHUB_ENV
echo "使用: docker-compose"
else
echo "错误:未找到 docker compose 或 docker-compose,请先安装"
exit 1
fi
# ── 5. 拉取最新镜像 ──────────────────────────────────────────
- name: 拉取镜像
run: |
docker pull ${{ steps.image.outputs.full }}
echo "镜像摘要: $(docker inspect ${{ steps.image.outputs.full }} --format='{{.Id}}')"
# ── 6. 创建部署目录 ──────────────────────────────────────────
- name: 准备部署目录
run: |
mkdir -p ${{ env.DEPLOY_DIR }}
# ── 7. 写入环境配置文件 ──────────────────────────────────────
- name: 写入 .env 文件
run: |
cat > ${{ env.DEPLOY_DIR }}/.env.demo << 'ENVEOF'
# 自动生成 — 请勿手动编辑,由 CI/CD 工作流维护
DATABASE_URL=${{ env.DB_URL }}
SECRET_KEY=${{ secrets.DEMO_SECRET_KEY }}
APP_PORT=${{ env.APP_PORT }}
FLASK_ENV=production
ENVEOF
chmod 600 ${{ env.DEPLOY_DIR }}/.env.demo
echo "env 文件已写入"
# ── 8. 复制 compose 文件到部署目录 ───────────────────────────
- name: 复制 Compose 文件
run: |
cp docker-compose.external-db.yml ${{ env.DEPLOY_DIR }}/docker-compose.yml
# ── 9. 更新 compose 文件中的镜像引用 ─────────────────────────
- name: 更新镜像标签
run: |
cd ${{ env.DEPLOY_DIR }}
# 将 compose 文件中的镜像替换为当前目标镜像
sed -i "s|image:.*resource-library.*|image: ${{ steps.image.outputs.full }}|g" docker-compose.yml
echo "已更新镜像引用为: ${{ steps.image.outputs.full }}"
# ── 10. 部署 / 更新容器 ──────────────────────────────────────
- name: 部署容器
run: |
cd ${{ env.DEPLOY_DIR }}
$COMPOSE_CMD \
--env-file .env.demo \
--project-name resource-library-demo \
up -d --remove-orphans --pull never
echo "容器已启动"
$COMPOSE_CMD --project-name resource-library-demo ps
# ── 11. 等待服务就绪 ─────────────────────────────────────────
- name: 健康检查
run: |
max_wait=90
elapsed=0
url="http://127.0.0.1:${{ env.APP_PORT }}/auth/login"
echo "等待服务就绪(最长 ${max_wait}s)…"
while [ "$elapsed" -lt "$max_wait" ]; do
if curl -fsSL --max-time 5 "$url" > /dev/null 2>&1; then
echo "服务健康!(${elapsed}s"
exit 0
fi
sleep 5
elapsed=$((elapsed + 5))
echo " 已等待 ${elapsed}s…"
done
echo "健康检查超时,查看日志:"
$COMPOSE_CMD \
--project-name resource-library-demo \
logs --tail 50 2>/dev/null || true
exit 1
# ── 12. 配置 Caddy 站点 ──────────────────────────────────────
- name: 配置 Caddy
run: |
# 确保 Caddy sites 目录存在
mkdir -p ${{ env.CADDY_SITES_DIR }}
# 写入站点配置(仅在文件内容变更时才重载)
CADDY_CONF="${{ env.CADDY_SITES_DIR }}/${{ env.DOMAIN }}.caddy"
NEW_CONF=$(cat docker/caddy/${{ env.DOMAIN }}.caddy)
OLD_CONF=$(cat "$CADDY_CONF" 2>/dev/null || echo "")
if [ "$NEW_CONF" != "$OLD_CONF" ]; then
cp docker/caddy/${{ env.DOMAIN }}.caddy "$CADDY_CONF"
echo "Caddy 配置已更新,重载…"
# 优先使用 systemctl,退而使用 caddy reload
if systemctl is-active --quiet caddy; then
systemctl reload caddy || caddy reload --config /etc/caddy/Caddyfile
elif caddy validate --config /etc/caddy/Caddyfile &>/dev/null; then
caddy reload --config /etc/caddy/Caddyfile
else
echo "警告:无法重载 Caddy,请手动执行 systemctl reload caddy"
fi
else
echo "Caddy 配置未变更,跳过重载"
fi
# ── 13. 输出部署摘要 ─────────────────────────────────────────
- name: 输出部署摘要
run: |
echo "## 🚀 Demo 环境部署成功" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| 项目 | 值 |" >> $GITHUB_STEP_SUMMARY
echo "|------|-----|" >> $GITHUB_STEP_SUMMARY
echo "| 访问地址 | https://${{ env.DOMAIN }} |" >> $GITHUB_STEP_SUMMARY
echo "| 镜像 | \`${{ steps.image.outputs.full }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| 触发方式 | ${{ github.event_name }} |" >> $GITHUB_STEP_SUMMARY
echo "| 部署时间 | $(date -u '+%Y-%m-%d %H:%M:%S UTC') |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Demo 地址:** https://${{ env.DOMAIN }}" >> $GITHUB_STEP_SUMMARY