feat: add JSON format validation for findings and exclusions after processing
This commit is contained in:
@@ -149,6 +149,11 @@
|
||||
"location": "app/llm.test.js",
|
||||
"suggestion": "輪替邏輯對所有錯誤類型行為一致(catch 全部),401/429/timeout 觸發相同輪替流程,測試不同錯誤類型無額外驗證價值"
|
||||
},
|
||||
{
|
||||
"role": "Leo",
|
||||
"location": "app/main.js",
|
||||
"suggestion": "main.js 中的 Step 標題註解為 pipeline 流程說明,非待整理的 TODO,不需要轉換為具體任務"
|
||||
},
|
||||
{
|
||||
"role": "Rex",
|
||||
"location": "app/package.json",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
5. 將提示詞放到 ./app/prompts 內供程式讀取
|
||||
6. API Key 支援逗號分隔傳入多個,隨機順序各嘗試一次,全部失敗則 exit 1
|
||||
7. 讀取 Git Diff 時排除 `.gitea/` 資料夾內的所有檔案,避免 AI 分析 workflow 設定等非業務程式碼
|
||||
8. 階段五完成後驗證 `findings.json` 與 `exclusions.json` 是否為合法 JSON 格式,驗證失敗則 exit 1
|
||||
|
||||
# 使用說明
|
||||
|
||||
@@ -30,6 +31,8 @@
|
||||
2. 在 `.gitea/workflows` 資料夾中建立 `ai-review.yaml'
|
||||
3. 在 `ai-review.yaml` 中填入以下內容(選擇一個使用):
|
||||
|
||||
> **權限說明**:此 Action 需要 `contents: write`(寫入 findings.json)、`pull-requests: write`(發佈 PR comment)、`issues: write`(發佈 issue comment)三項權限,為正常運作所必要,無法縮減。
|
||||
|
||||
### 1. OpenAI
|
||||
```yaml
|
||||
name: AI
|
||||
|
||||
@@ -45,6 +45,11 @@
|
||||
- 驗收:PR 中有 `.gitea/` 路徑的變更時,diff 內容不包含該路徑的區塊,AI 分析結果不含 `.gitea/` 相關問題。
|
||||
- 完成
|
||||
|
||||
## 階段十:階段五後驗證 JSON 格式
|
||||
- 目標:階段五完成後驗證 `findings.json` 與 `exclusions.json` 是否為合法 JSON 格式,驗證失敗則 exit 1。
|
||||
- 驗收:log 中能看到兩個檔案的驗證結果(成功或失敗),格式錯誤時有明確錯誤訊息且 workflow 狀態為失敗。
|
||||
- 完成
|
||||
|
||||
---
|
||||
|
||||
所有階段驗收通過。
|
||||
|
||||
@@ -11,6 +11,10 @@ export async function getPRDiff() {
|
||||
return filterDiff(resp.data, ['.gitea/']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 過濾 diff 內容,移除路徑符合 excludePrefixes 的區塊。
|
||||
* 每個區塊以 "diff --git a/<prefix>" 開頭判斷,使用 startsWith 精確比對前綴。
|
||||
*/
|
||||
function filterDiff(diff, excludePrefixes) {
|
||||
return diff.split(/(?=^diff --git )/m)
|
||||
.filter(block => !excludePrefixes.some(p => block.startsWith(`diff --git a/${p}`)))
|
||||
|
||||
+22
-1
@@ -1,4 +1,6 @@
|
||||
import { GITEA_REPOSITORY, PR_NUMBER, PR_HEAD_BRANCH, PR_BASE_BRANCH, getLLMConfig } from './config.js';
|
||||
import fs from 'fs';
|
||||
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 } from './gitea.js';
|
||||
import { analyzeWithRole, loadOldFindings, mergeFindings, sortByLevel, deduplicateWithAI, loadExclusions, applyExclusions, filterFalsePositivesWithAI } from './findings.js';
|
||||
@@ -60,6 +62,7 @@ async function main() {
|
||||
|
||||
// Step3: 讀取舊 findings,合併去重(含 AI 語意去重)
|
||||
console.log('\n🔀 Step3: Findings 合併');
|
||||
// Clone repo 以讀取舊 findings 與排除清單
|
||||
let repoDir;
|
||||
try {
|
||||
repoDir = cloneRepo(WORKSPACE);
|
||||
@@ -77,6 +80,7 @@ async function main() {
|
||||
|
||||
// Step4: 讀取排除問題檔案,過濾 PR 問題表格,並請 AI 判斷誤報
|
||||
console.log('\n🚫 Step4: AI 排除問題過濾');
|
||||
// 輸入至 findings 用於 AI 誤報過濾,exclusions 同時作為已知誤報參考
|
||||
const exclusions = loadExclusions(repoDir || WORKSPACE);
|
||||
const ruleFiltered = applyExclusions(sorted, exclusions);
|
||||
const filtered = await filterFalsePositivesWithAI(ruleFiltered, exclusions);
|
||||
@@ -94,6 +98,23 @@ async function main() {
|
||||
console.log(` ⚠️ comment 發布失敗(繼續執行): ${e.message}`);
|
||||
}
|
||||
|
||||
// Step5b: 驗證 findings.json 與 exclusions.json 為合法 JSON
|
||||
console.log('\n🔎 Step5b: JSON 格式驗證');
|
||||
for (const relPath of [FINDINGS_PATH, EXCLUSIONS_PATH]) {
|
||||
const fullPath = path.join(repoDir || WORKSPACE, relPath);
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
console.log(` ⚠️ ${relPath} 不存在,跳過驗證`);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
JSON.parse(fs.readFileSync(fullPath, 'utf8'));
|
||||
console.log(` ✅ ${relPath} JSON 格式正確`);
|
||||
} catch (e) {
|
||||
console.error(` ❌ ${relPath} JSON 格式錯誤: ${e.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Step6: commit/push findings.json 到來源分支
|
||||
console.log('\n💾 Step6: 記憶區 Commit/Push');
|
||||
await commitAndPush(WORKSPACE);
|
||||
|
||||
Reference in New Issue
Block a user