Skip to content

Update ai-review.yml #2

Update ai-review.yml

Update ai-review.yml #2

Workflow file for this run

name: ExpTechAI
on:
pull_request:
types: [opened, synchronize, reopened]
issue_comment:
types: [created]
jobs:
ai-review:
if: |
github.event_name == 'pull_request' ||
(
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
(
contains(github.event.comment.body, '/review') ||
contains(github.event.comment.body, '@ExpTechAI')
) &&
(
github.event.comment.author_association == 'OWNER' ||
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR'
)
)
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
steps:
- name: Get PR ref
id: pr
uses: actions/github-script@v7
with:
github-token: ${{ secrets.PAT_TOKEN }}
script: |
if (context.eventName === 'pull_request') {
return {
sha: context.payload.pull_request.head.sha,
number: context.payload.pull_request.number
};
}
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.issue.number
});
return { sha: pr.head.sha, number: pr.number };
- name: React to comment
if: github.event_name == 'issue_comment'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.PAT_TOKEN }}
script: |
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: 'eyes'
});
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ fromJSON(steps.pr.outputs.result).sha }}
fetch-depth: 0
- name: Run AI Code Review
id: review
uses: zxcloli666/AI-Code-Review@v1.3.0
env:
PR_NUMBER: ${{ fromJSON(steps.pr.outputs.result).number }}
with:
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
OPENAI_API_KEY: ${{ secrets.VLLM_API_KEY }}
OPENAI_API_BASE_URL: ${{ secrets.VLLM_BASE_URL }}
OPENAI_API_MODEL: "auto"
REVIEW_LANGUAGE: "zh"
MAX_CHUNK_SIZE: "60000"
SEVERITY_THRESHOLD: "error"
SILENT_MODE: "false"
ENABLE_LINTERS: "true"
ENABLE_AST: "true"
ENABLE_DEPENDENCY_ANALYSIS: "true"
- name: Enforce strict review
if: always()
uses: actions/github-script@v7
with:
github-token: ${{ secrets.PAT_TOKEN }}
script: |
const { owner, repo } = context.repo;
const pr_number = ${{ fromJSON(steps.pr.outputs.result).number }};
const { data: comments } = await github.rest.issues.listComments({
owner, repo, issue_number: pr_number, per_page: 100
});
const aiComments = comments
.filter(c => c.user.type === 'Bot' || c.user.login.includes('github-actions'))
.filter(c => c.body.includes('AI CODE REVIEW') || c.body.includes('AI Code Review'))
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
if (aiComments.length === 0) {
core.setFailed('❌ 找不到 AI Review 結果留言 —— AI 審查可能沒跑完或 vLLM 連線失敗');
return;
}
const latest = aiComments[0].body;
core.info('=== 最新 AI Review 留言節錄 ===');
core.info(latest.slice(0, 500));
const blockers = [];
if (/❌\s*REJECTED|❌\s*BLOCKED|Verdict.*REJECTED|verdict.*reject/i.test(latest)) {
blockers.push('AI 給出 REJECTED 判定');
}
const critMatch = latest.match(/Critical[^0-9]*?(\d+)/i);
if (critMatch && parseInt(critMatch[1]) > 0) {
blockers.push(`發現 ${critMatch[1]} 個 Critical 問題`);
}
const scoreMatch = latest.match(/Quality Score[^\d]*(\d+)\s*\/\s*100/i);
if (scoreMatch && parseInt(scoreMatch[1]) < 60) {
blockers.push(`Quality Score 過低: ${scoreMatch[1]}/100(門檻 60)`);
}
if (blockers.length > 0) {
const msg = '🚫 嚴格模式擋 PR:\n' + blockers.map(b => ` - ${b}`).join('\n');
core.setFailed(msg);
await github.rest.issues.createComment({
owner, repo, issue_number: pr_number,
body: `## 🚫 嚴格模式:此 PR 被擋下\n\n${blockers.map(b => `- ${b}`).join('\n')}\n\n請依照上方 AI Review 建議修正後重新 push。`
});
} else {
core.info('✅ 嚴格模式通過,沒有發現 blocker');
}