name: PR合并自动部署 on: pull_request: branches: - main types: - closed concurrency: group: production-deploy cancel-in-progress: false jobs: release-check: if: ${{ github.event.pull_request.merged == true }} runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: 检出 main env: REPOSITORY_URL: http://117.72.28.96:8765/Jacky/Hulumath-Web.git run: git clone --branch main --single-branch "$REPOSITORY_URL" . - name: 检查发布文件和脚本语法 run: | set -eu test -f requirements.txt test -f backend/manage.py test -f deploy/hulumath-web.service test -f scripts/deploy_production.sh test -f scripts/smoke_production.py bash -n scripts/deploy_production.sh python3 -m compileall -q backend scripts git diff-tree --check -m -r HEAD deploy: if: ${{ github.event.pull_request.merged == true }} needs: - release-check runs-on: ubuntu-latest timeout-minutes: 25 steps: - name: 配置 SSH 环境 env: DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} run: | set -eu mkdir -p ~/.ssh printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key timeout 10 ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts - name: 远程执行 Django 部署 env: DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} DEPLOY_USER: ${{ secrets.DEPLOY_USER }} run: | ssh -T -i ~/.ssh/deploy_key \ "$DEPLOY_USER@$DEPLOY_HOST" <<'EOF' set -Eeuo pipefail PROJECT="/www/wwwroot/Hulumath-Web" REPOSITORY_URL="http://117.72.28.96:8765/Jacky/Hulumath-Web.git" PYTHON_BIN="/www/server/pyporject_evn/versions/3.12.13/bin/python3" exec 9>/tmp/hulumath-production-deploy.lock if ! flock -n 9; then echo "已有部署正在执行,本次退出" exit 1 fi echo "========================================" echo "开始部署 Django 生产版" echo "项目目录: $PROJECT" echo "========================================" cd "$PROJECT" git config --global --add safe.directory "$PROJECT" || true if [ ! -d .git ]; then echo "当前目录不是 Git 仓库" exit 1 fi PREVIOUS_REVISION="$(git rev-parse HEAD)" echo "获取远程 main..." git remote set-url origin "$REPOSITORY_URL" git fetch origin main git reset --hard origin/main chmod +x scripts/deploy_production.sh PROJECT_DIR="$PROJECT" \ PYTHON_BIN="$PYTHON_BIN" \ PREVIOUS_REVISION="$PREVIOUS_REVISION" \ DEPLOY_SMOKE_BASE_URL="http://127.0.0.1:4321" \ DEPLOY_SMOKE_WS_URL="ws://127.0.0.1:4321/ws/health/" \ bash scripts/deploy_production.sh echo "========================================" echo "部署完成" echo "========================================" EOF - name: 从 Runner 验证 Nginx 健康状态 env: DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} DEPLOY_PUBLIC_HOST: 117.72.28.96 run: | curl --fail --silent --show-error \ --retry 5 \ --retry-delay 2 \ --header "Host: $DEPLOY_PUBLIC_HOST" \ "http://$DEPLOY_HOST:4321/health/" \ | grep -q '"status": "ok"'