name: 🔎 校验

on:
  workflow_run:
    workflows: ["🧰 准备环境"]
    types:
      - completed

concurrency:
  group: checks-${{ github.repository }}-${{ github.event.workflow_run.head_sha }}
  cancel-in-progress: true

# ==========================================
# 🔧 配置区域 - 校验参数
# ==========================================
env:
  # Prepare 完成后经 workflow_run 触发；Prepare 已装工具 + fetch 到共享 bare 仓库。
  # 本 workflow 只做只读校验（lint + 测试），不推任何分支，故 token 仅用于
  # 极端情况下补取缺失提交（正常路径 Prepare 已 fetch 到位）。
  #
  # 安全：ACCESS_TOKEN 不放在 workflow 级 env。lint/test 步骤会执行上游提交
  # （PR 场景为不受信输入）的脚本，其环境里不应出现 token；仅下放到
  # prepare_worktree 步骤。
  WORKSPACE_ROOT: "/data/workspace"
  SOURCE_BRANCH: ${{ github.event.workflow_run.head_branch }}
  SOURCE_SHA: ${{ github.event.workflow_run.head_sha }}
  SOURCE_EVENT: ${{ github.event.workflow_run.event }}
  COMMIT_LINT_REQUIRE_EMOJI: "1"

jobs:
  checks:
    # 仅在 Prepare 成功后触发。Prepare 覆盖 push(main) / pull_request /
    # schedule / dispatch，故 checks 在这些场景均会运行。
    # lint 与 test 合并为单 job：共用一个临时 worktree，准备一次，顺序执行
    # （lint 在前 fail-fast，失败即不跑 test）。二者跑同一 SOURCE_SHA、皆只读、
    # 无依赖，无需拆分为并行 job（那会重复整段 worktree 准备逻辑 + 多一个 worktree）。
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    name: 🔎 规范检查 + 全量测试
    runs-on: standard-ubuntu-22
    permissions:
      contents: read

    steps:
      - name: 📥 准备临时 Worktree
        id: prepare_worktree
        shell: bash
        env:
          ACCESS_TOKEN: ${{ secrets.WORKFLOW }}
        run: |
          set -euo pipefail

          REPO_NAME="${{ github.event.repository.name }}"
          HEAD_SHA="${SOURCE_SHA}"
          REPOSITORY_DIR="${WORKSPACE_ROOT}/${REPO_NAME}/repository.git"
          WORKTREE_DIR="${WORKSPACE_ROOT}/${REPO_NAME}/worktrees/checks-${{ github.run_id }}-${{ github.run_attempt }}"
          WORKTREE_LOCK="${WORKSPACE_ROOT}/${REPO_NAME}/worktree-admin.lock"

          case "$HEAD_SHA" in
            ''|*[!0-9a-fA-F]*)
              echo "无效的上游提交 SHA: $HEAD_SHA" >&2
              exit 1
              ;;
          esac
          if [ ! -d "$REPOSITORY_DIR" ] || \
             [ "$(git --git-dir="$REPOSITORY_DIR" rev-parse --is-bare-repository 2>/dev/null)" != "true" ]; then
            echo "Prepare 未创建有效共享 bare 仓库: $REPOSITORY_DIR" >&2
            exit 1
          fi

          # 正常路径 Prepare 已把上游提交 fetch 到位；极端情况下（bare 仓库被清理
          # 重建、或 Prepare 与本 run 之间发生 prune）补取一次，token 仅用于此。
          if ! git --git-dir="$REPOSITORY_DIR" cat-file -e "${HEAD_SHA}^{commit}" 2>/dev/null; then
            git \
              -c credential.helper= \
              -c 'credential.helper=!f() { test "$1" = get || exit 0; printf "%s\n" username=oauth2; printf "%s\n" "password=${ACCESS_TOKEN}"; }; f' \
              -c credential.interactive=never \
              --git-dir="$REPOSITORY_DIR" fetch --prune --force origin \
              '+refs/heads/*:refs/remotes/origin/*' || true
          fi
          if ! git --git-dir="$REPOSITORY_DIR" cat-file -e "${HEAD_SHA}^{commit}"; then
            echo "共享仓库中不存在上游提交: $HEAD_SHA（事件: $SOURCE_EVENT）" >&2
            exit 1
          fi

          exec 9>"$WORKTREE_LOCK"
          flock 9
          # 回收陈旧临时 worktree（超过 24h 的 checks-* 目录）。worktree prune 只清理
          # 指向已消失目录的 metadata，不删仍存在的陈旧目录，故按 mtime 主动回收。
          worktrees_root="$(dirname "$WORKTREE_DIR")"
          if [ -d "$worktrees_root" ]; then
            find "$worktrees_root" -mindepth 1 -maxdepth 1 -type d -name 'checks-*' \
              -mmin +1440 -print 2>/dev/null | while IFS= read -r stale; do
              [ "$stale" = "$WORKTREE_DIR" ] && continue
              git --git-dir="$REPOSITORY_DIR" worktree remove --force "$stale" 2>/dev/null || rm -rf "$stale"
            done
          fi
          git --git-dir="$REPOSITORY_DIR" worktree prune
          if [ -e "$WORKTREE_DIR" ]; then
            git --git-dir="$REPOSITORY_DIR" worktree remove --force "$WORKTREE_DIR" 2>/dev/null || rm -rf "$WORKTREE_DIR"
          fi
          mkdir -p "$(dirname "$WORKTREE_DIR")"
          git --git-dir="$REPOSITORY_DIR" worktree add --detach "$WORKTREE_DIR" "$HEAD_SHA"
          flock -u 9

          git -C "$WORKTREE_DIR" reset --hard "$HEAD_SHA"
          git -C "$WORKTREE_DIR" clean -ffdx

          echo "REPOSITORY_DIR=$REPOSITORY_DIR" >> "$GITHUB_ENV"
          echo "REPO_DIR=$WORKTREE_DIR" >> "$GITHUB_ENV"
          echo "✅ Worktree 就绪: $WORKTREE_DIR @ $HEAD_SHA"

      - name: 🔍 校验提交信息
        shell: bash
        run: |
          set -euo pipefail
          cd "$REPO_DIR"
          # 注：经 workflow_run 触发，事件 payload 为 workflow_run，不含 PR title；
          # lint 脚本会回落到 head commit message 校验（PR 标题本身不再校验）。
          echo "🔍 检查 commit message 规范（上游事件: $SOURCE_EVENT）..."
          python3 .gitea/ci/commit_message_lint.py
          echo "✅ Lint 检查通过"

      - name: 🧪 运行全量测试
        shell: bash
        run: |
          set -euo pipefail

          echo "========================================"
          echo "🐍 Python 测试（上游事件: $SOURCE_EVENT）"
          echo "========================================"

          cd "$REPO_DIR"
          echo "📋 覆盖：CLI、subtree/snapshot 部署路线、模板同步、文档一致性"
          python3 -m unittest discover -s test -p "test_*.py" -v
          echo "✅ Python 测试通过"

          echo "========================================"
          echo "🔗 文档链接检查"
          echo "========================================"

          python3 test/integration/check_doc_links.py
          echo "✅ 文档链接检查通过"
          echo "🎉 所有测试完成"

      - name: 🧹 清理临时 Worktree
        if: always()
        shell: bash
        run: |
          set -uo pipefail
          [ -n "${REPOSITORY_DIR:-}" ] || exit 0
          [ -n "${REPO_DIR:-}" ] || exit 0
          WORKTREE_LOCK="$(dirname "$REPOSITORY_DIR")/worktree-admin.lock"
          exec 9>"$WORKTREE_LOCK"
          flock 9
          git --git-dir="$REPOSITORY_DIR" worktree remove --force "$REPO_DIR" 2>/dev/null || rm -rf "$REPO_DIR"
          git --git-dir="$REPOSITORY_DIR" worktree prune
          flock -u 9
