From 47b5b7ea5c1953df04712c7148dbbdda12876b9a Mon Sep 17 00:00:00 2001 From: Jeffery Date: Mon, 22 Jun 2026 15:48:19 +0000 Subject: [PATCH] =?UTF-8?q?fix(Step9):=20=E9=82=84=E5=8E=9F=E5=9A=B4?= =?UTF-8?q?=E9=87=8D=E5=95=8F=E9=A1=8C=E5=A4=B1=E6=95=97=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- app/gitea.js | 17 ----------------- app/gitea.test.js | 27 +-------------------------- app/main.js | 13 ++----------- 4 files changed, 4 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 6e9649f..f984556 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ 6. 將 PR 問題表格寫入 `.gitea/ai-review/findings.json`,並發布一個 Gitea Review:Review 本文只統計本次新發現的問題,使用「嚴重/警告/建議」三欄呈現各等級數量;之後將可找出檔案與行數的問題依照嚴重等級排序後加入 Review Comments 內,每個 Comment 包含嚴重等級/審查員/問題/建議,其中「問題」是審查員判斷該處有問題的原因,不是檔案路徑或行號 7. 驗證來源分支中的 `findings.json` 與 `exclusions.json` 是否為合法 JSON array;格式錯誤時先嘗試透過 AI 修正內容,再重新驗證;修正後仍不合法才 exit 1;檔案不存在則建立並寫入 `[]` 8. Commit 問題檔案,只將 workspace 中實際存在的 `.gitea/ai-review/findings.json` 與 `.gitea/ai-review/exclusions.json` 覆蓋到記憶區;workspace 沒有的問題檔就略過。自動提交的 commit message 會帶上 `[ai-review-bot]`,供 workflow 判斷是否要跳過重跑 -9. 如果 PR 問題表格中有嚴重問題,先嘗試透過 Gitea API 對 PR head commit 建立 failure status 來阻擋 PR 合併;若 API 阻擋失敗,才改用原本的 workflow failure 處理(`exit 1`) +9. 如果 PR 問題表格中有嚴重問題,則不要讓 workflow 執行成功(exit 1) # 設計 diff --git a/app/gitea.js b/app/gitea.js index aa6e400..24cccbc 100644 --- a/app/gitea.js +++ b/app/gitea.js @@ -118,23 +118,6 @@ export async function postComment(body) { return resp.data; } -export async function blockPRMergeWithStatus({ sha = PR_HEAD_SHA || process.env.GITHUB_SHA, criticalCount = 0 } = {}) { - if (!sha) throw new Error('缺少 PR head commit sha,無法建立 Gitea status'); - - const countText = criticalCount > 0 ? `${criticalCount} 個` : ''; - const resp = await axios.post( - api(`/repos/${GITEA_REPOSITORY}/statuses/${encodeURIComponent(sha)}`), - { - state: 'failure', - target_url: `${GITEA_SERVER_URL.replace(/\/$/, '')}/${GITEA_REPOSITORY}/pulls/${PR_NUMBER}`, - description: `AI Code Review 發現${countText}嚴重問題,請修復後再合併。`, - context: 'ai-code-review/critical', - }, - { headers: headers(), timeout: 30000, httpsAgent }, - ); - return resp.data; -} - /** * 在 PR 指定檔案的指定行數發布行內 review comment(標註程式碼位置)。 * 透過 Gitea 的 pull reviews API,以 new_position 對應新版檔案的行號。 diff --git a/app/gitea.test.js b/app/gitea.test.js index 3839342..de76d51 100644 --- a/app/gitea.test.js +++ b/app/gitea.test.js @@ -1,7 +1,7 @@ import { describe, it, afterEach, mock } from 'node:test'; import assert from 'node:assert/strict'; import axios from 'axios'; -import { getPRDiff, filterDiff, postComment, postPullReviewComment, postPullReview, getCommitMessageBySha, getBranchHeadCommitMessage, shouldSkipBotCommit, getBotReviewOutcome, blockPRMergeWithStatus } from './gitea.js'; +import { getPRDiff, filterDiff, postComment, postPullReviewComment, postPullReview, getCommitMessageBySha, getBranchHeadCommitMessage, shouldSkipBotCommit, getBotReviewOutcome } from './gitea.js'; afterEach(() => mock.restoreAll()); @@ -57,31 +57,6 @@ describe('gitea', () => { await assert.rejects(() => postComment('test'), /api error/); }); - it('blockPRMergeWithStatus creates a failure commit status on the PR head sha', async () => { - let capturedUrl, capturedBody, capturedOpts; - mock.method(axios, 'post', async (url, body, opts) => { - capturedUrl = url; - capturedBody = body; - capturedOpts = opts; - return { data: { id: 12 } }; - }); - - const result = await blockPRMergeWithStatus({ sha: 'abc/123', criticalCount: 3 }); - - assert.deepEqual(result, { id: 12 }); - assert.ok(capturedUrl.includes('/api/v1/repos/')); - assert.ok(capturedUrl.endsWith('/statuses/abc%2F123')); - assert.equal(capturedBody.state, 'failure'); - assert.equal(capturedBody.context, 'ai-code-review/critical'); - assert.ok(capturedBody.description.includes('3 個嚴重問題')); - assert.ok(capturedBody.target_url.includes('/pulls/')); - assert.ok(capturedOpts.headers['Authorization'].startsWith('token ')); - }); - - it('blockPRMergeWithStatus rejects when commit sha is missing', async () => { - await assert.rejects(() => blockPRMergeWithStatus({ sha: '', criticalCount: 1 }), /缺少 PR head commit sha/); - }); - it('postPullReviewComment posts an inline review comment to the pulls reviews API', async () => { let capturedUrl, capturedBody, capturedOpts; mock.method(axios, 'post', async (url, body, opts) => { diff --git a/app/main.js b/app/main.js index e519818..eb87469 100644 --- a/app/main.js +++ b/app/main.js @@ -1,7 +1,7 @@ import path from 'path'; import { GITEA_REPOSITORY, PR_NUMBER, PR_HEAD_BRANCH, PR_BASE_BRANCH, getLLMConfig, FINDINGS_PATH, EXCLUSIONS_PATH } from './config.js'; import { loadRoles, getRoleIntro } from './roles.js'; -import { getPRDiff, postComment, getCommitMessageBySha, getBotReviewOutcome, shouldSkipBotCommit, blockPRMergeWithStatus } from './gitea.js'; +import { getPRDiff, postComment, getCommitMessageBySha, getBotReviewOutcome, shouldSkipBotCommit } from './gitea.js'; import { analyzeWithRole, loadOldFindings, mergeFindings, sortByLevel, deduplicateWithAI, loadExclusions, applyExclusions, filterFalsePositivesWithAI } from './findings.js'; import { saveFindings, postFindingsReview } from './comments.js'; import { cloneRepo, commitAndPush, getRepoState } from './git.js'; @@ -145,16 +145,7 @@ async function main() { step('Step9', '嚴重問題檢查'); const criticalCount = filtered.filter(f => f.level === 'critical').length; if (criticalCount > 0) { - error(`發現 ${criticalCount} 個嚴重問題`); - try { - await blockPRMergeWithStatus({ sha: headSha, criticalCount }); - ok('已透過 Gitea API 建立 failure status 阻擋 PR 合併'); - section('Pipeline 結束'); - process.exit(0); - } catch (e) { - warn(`透過 Gitea API 阻擋 PR 合併失敗,改用原本 workflow failure 處理: ${e.message}`); - } - error('workflow 結束(exit 1)'); + error(`發現 ${criticalCount} 個嚴重問題,workflow 結束(exit 1)`); section('Pipeline 結束'); process.exit(1); } -- 2.53.0