name: ai-review

# AI 自动 review，按目标分支选择 review 模式
# - PR → develop (L2): 硬规则 block + 软规则评论
# - PR → staging (L3): 批次审，输出本批次合并风险摘要
# - PR → production (L4): 发布风险审，关注回滚预案 / 灰度策略 / 不可逆改动
#
# 实现：scripts/ops/ai-review-runner.sh，调用 Claude Code CLI（不直接走 API，免 SDK 依赖）
# 详细 review 模式定义见 .agents/skills/code-review/SKILL.md
#
# ⚠️ 启用前置条件：
#   1. Runner 镜像已安装 claude CLI 且已登录（act_runner 用户 HOME=/var/lib/act_runner）
#   2. Gitea secret AI_REVIEW_GITEA_TOKEN 已配置——值为 AIBot 账号 PAT
#      （scope: read:repository + write:issue + write:status；详见 docs/ops/automation-accounts.md）
#   3. 预算/速率限制由 CLI 自己的配额管控，无需额外控制
#
# 当前阶段：已转正（2026-05-11，auto-eval 综合分 72.5% ≥ 70%；#171 关闭）
#   - 正常写 Gitea 评论 + 更 commit status
#   - 如需临时回退，将 `AI_REVIEW_DRY_RUN: '1'` 加回下方 `Run AI review` step 的 env
#
# 触发策略：
#   - pull_request opened/synchronize/ready_for_review/reopened：PR 进入可 review 或新增 commit 时跑
#   - issue_comment 含 `/ai-review`：手动触发（注意：用 default branch 的 workflow + code，
#     不会拿到 PR head 的最新 yaml/runner——靠 push 自然触发优于评论）
#   - workflow_dispatch：手动 trigger（不写 commit status，不能用来满足 required check）
#
# 重复 review 控制（替代 #259 删 synchronize 的方案）：
#   - runner 用 PR diff hash 做幂等：当前 diff hash == 上轮 state header 里的 diff hash
#     则跳过 claude CLI 调用，秒级 success exit。详见 scripts/ops/ai-review-runner.sh
#   - 优点：merge develop 进 PR / rebase / 无内容 force-push 都自动跳过 claude，
#     真改了 diff 才跑全量 review

permissions:
  contents: read
  pull-requests: write
  statuses: write

on:
  pull_request:
    types: [opened, synchronize, ready_for_review, reopened]
    branches:
      - develop
      - staging
      - production
  issue_comment:
    types: [created]
  workflow_dispatch:
    inputs:
      pr_number:
        description: 'PR number to review'
        required: true

jobs:
  ai-review:
    # 三种触发方式按 if 收敛到同一 job；issue_comment 必须含 `/ai-review` 且在 PR 上
    # 防自触发循环（PR #380 修）：
    #   1. startsWith 而非 contains —— contains 子串匹配会把 AIBot 自己评论中的
    #      文件路径（scripts/ops/ai-review-runner.sh / .gitea/workflows/ai-review.yml）
    #      误识别为 `/ai-review` 命令，造成 bot 自评论触发自己跑下一轮
    #   2. 排除 AIBot 自己的评论 —— 防御深度，未来加新的 bot 也不会撞同一坑
    if: |
      github.event_name == 'pull_request' ||
      github.event_name == 'workflow_dispatch' ||
      (github.event_name == 'issue_comment' &&
       github.event.issue.pull_request != null &&
       github.event.comment.user.login != 'AIBot' &&
       startsWith(github.event.comment.body, '/ai-review'))
    runs-on: ubuntu-latest
    # Pull/agent 模式：claude 自己 git diff / Read 文件多轮探查
    # 单次 review 2-5 min；timeout 留 20 min 给大 PR + 多次探查上下文
    timeout-minutes: 20
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Resolve PR number and base branch
        id: pr
        env:
          GITEA_API_TOKEN: ${{ secrets.AI_REVIEW_GITEA_TOKEN }}
        run: |
          set -euo pipefail
          PR_NUMBER="${{ github.event.pull_request.number || github.event.issue.number || inputs.pr_number }}"
          if [ -z "$PR_NUMBER" ]; then
            echo "❌ 无法解析 PR_NUMBER"; exit 1
          fi
          # issue_comment / workflow_dispatch 没有 GITHUB_BASE_REF，统一走 API 拿 base.ref
          BASE_REF=$(curl -fsS -H "Authorization: token $GITEA_API_TOKEN" \
            "http://43.130.59.228/api/v1/repos/${{ github.repository }}/pulls/$PR_NUMBER" \
            | jq -r .base.ref)
          if [ -z "$BASE_REF" ] || [ "$BASE_REF" = "null" ]; then
            echo "❌ 无法从 API 拿到 base ref（PR #$PR_NUMBER）"; exit 1
          fi
          case "$BASE_REF" in
            develop)    MODE="hard-rules-block" ;;
            staging)    MODE="batch-summary" ;;
            production) MODE="release-risk" ;;
            *)          MODE="hard-rules-block" ;;
          esac
          {
            echo "pr_number=$PR_NUMBER"
            echo "base_ref=$BASE_REF"
            echo "mode=$MODE"
          } >> $GITHUB_OUTPUT
          echo "PR #$PR_NUMBER → $BASE_REF (mode=$MODE)"

      - name: Verify claude CLI is available
        run: command -v claude && claude --version

      - name: Run AI review
        env:
          AI_REVIEW_MODE: ${{ steps.pr.outputs.mode }}
          GITEA_API_TOKEN: ${{ secrets.AI_REVIEW_GITEA_TOKEN }}
          PR_NUMBER: ${{ steps.pr.outputs.pr_number }}
        run: bash scripts/ops/ai-review-runner.sh
