docs(workflow 階段): 將前置驗證改為 Step2
This commit is contained in:
+1
-1
@@ -141,7 +141,7 @@ export async function commitAndPush(workspace, repoDir, _spawnSync = spawnSync,
|
||||
run(['push', remoteUrl, PR_HEAD_BRANCH], repoDir, credEnv);
|
||||
ok(`persisted findings commit=${commitHash} push=${PR_HEAD_BRANCH} review_outcome=${reviewOutcome}`);
|
||||
} catch (pushErr) {
|
||||
warn(`Step7 commit 成功但 push 失敗: commit=${commitHash} push=${PR_HEAD_BRANCH} review_outcome=${reviewOutcome} error=${pushErr.message}`);
|
||||
warn(`Step8 commit 成功但 push 失敗: commit=${commitHash} push=${PR_HEAD_BRANCH} review_outcome=${reviewOutcome} error=${pushErr.message}`);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
+1
-1
@@ -193,7 +193,7 @@ describe('commitAndPush', () => {
|
||||
console.warn = originalWarn;
|
||||
}
|
||||
|
||||
assert.ok(logs.some(line => line.includes('Step7 commit 成功但 push 失敗')));
|
||||
assert.ok(logs.some(line => line.includes('Step8 commit 成功但 push 失敗')));
|
||||
assert.ok(logs.some(line => line.includes('pre-receive hook declined')));
|
||||
});
|
||||
});
|
||||
|
||||
+12
-12
@@ -71,7 +71,7 @@ async function main() {
|
||||
warn(`comment 發布失敗(繼續執行): ${e.message}`);
|
||||
}
|
||||
|
||||
step('Step2', 'Findings 產生');
|
||||
step('Step3', 'Findings 產生');
|
||||
const results = await Promise.allSettled(roles.map(role => analyzeWithRole(role, diff)));
|
||||
const newFindings = [];
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
@@ -81,9 +81,9 @@ async function main() {
|
||||
warn(`[${roles[i].name}] 分析失敗(跳過): ${results[i].reason?.message}`);
|
||||
}
|
||||
}
|
||||
ok(`Step2 完成: 新 findings 總計 ${newFindings.length} 筆`);
|
||||
ok(`Step3 完成: 新 findings 總計 ${newFindings.length} 筆`);
|
||||
|
||||
step('Step3', 'Findings 合併與語意去重');
|
||||
step('Step4', 'Findings 合併與語意去重');
|
||||
let repoDir;
|
||||
try {
|
||||
repoDir = cloneRepo(WORKSPACE);
|
||||
@@ -96,28 +96,28 @@ async function main() {
|
||||
}
|
||||
const oldFindings = loadOldFindings(repoDir || WORKSPACE);
|
||||
const mergedFindings = mergeFindings(oldFindings, newFindings);
|
||||
ok(`Step3 merged findings total=${mergedFindings.length}`);
|
||||
ok(`Step4 merged findings total=${mergedFindings.length}`);
|
||||
const deduped = await deduplicateWithAI(mergedFindings);
|
||||
const sorted = sortByLevel(deduped);
|
||||
ok(`Step3 去重完成: ${mergedFindings.length} -> ${sorted.length} 筆 (critical=${sorted.filter(f=>f.level==='critical').length} warning=${sorted.filter(f=>f.level==='warning').length} info=${sorted.filter(f=>f.level==='info').length})`);
|
||||
ok(`Step4 去重完成: ${mergedFindings.length} -> ${sorted.length} 筆 (critical=${sorted.filter(f=>f.level==='critical').length} warning=${sorted.filter(f=>f.level==='warning').length} info=${sorted.filter(f=>f.level==='info').length})`);
|
||||
|
||||
step('Step4', 'AI 排除問題過濾');
|
||||
step('Step5', 'AI 排除問題過濾');
|
||||
const exclusions = loadExclusions(repoDir || WORKSPACE, repoState, WORKSPACE);
|
||||
const ruleFiltered = applyExclusions(sorted, exclusions);
|
||||
const filtered = await filterFalsePositivesWithAI(ruleFiltered, exclusions);
|
||||
ok(`Step4 完成: findings total=${filtered.length}`);
|
||||
ok(`Step5 完成: findings total=${filtered.length}`);
|
||||
|
||||
step('Step5', 'Findings 寫入與 Review 發布');
|
||||
step('Step6', 'Findings 寫入與 Review 發布');
|
||||
const reviewDir = repoDir || WORKSPACE;
|
||||
saveFindings(WORKSPACE, filtered, reviewDir);
|
||||
try {
|
||||
await postFindingsReview(filtered);
|
||||
ok('Step5 完成');
|
||||
ok('Step6 完成');
|
||||
} catch (e) {
|
||||
warn(`review 發布失敗(繼續執行): ${e.message}`);
|
||||
}
|
||||
|
||||
step('Step6', 'JSON 格式驗證');
|
||||
step('Step7', 'JSON 格式驗證');
|
||||
const missingPaths = [];
|
||||
for (const relPath of [FINDINGS_PATH, EXCLUSIONS_PATH]) {
|
||||
const fullPath = path.join(reviewDir, relPath);
|
||||
@@ -133,12 +133,12 @@ async function main() {
|
||||
ensureJSONArrayFileExists(fullPath, relPath);
|
||||
}
|
||||
|
||||
step('Step7', '記憶區 Commit/Push');
|
||||
step('Step8', '記憶區 Commit/Push');
|
||||
const reviewOutcome = filtered.some(f => f.level === 'critical') ? 'failure' : 'success';
|
||||
line(`review outcome=${reviewOutcome}`);
|
||||
await commitAndPush(WORKSPACE, repoDir || WORKSPACE, undefined, undefined, reviewOutcome);
|
||||
|
||||
step('Step8', '嚴重問題檢查');
|
||||
step('Step9', '嚴重問題檢查');
|
||||
const criticalCount = filtered.filter(f => f.level === 'critical').length;
|
||||
if (criticalCount > 0) {
|
||||
error(`發現 ${criticalCount} 個嚴重問題,workflow 結束(exit 1)`);
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ export async function runPreflight(workspace = process.env.GITHUB_WORKSPACE || '
|
||||
verifyRemote = verifyRemoteAccess,
|
||||
verifyLLMFn = verifyLLM,
|
||||
} = deps;
|
||||
step('Step1.5', '前置驗證(驗證相關設定)');
|
||||
step('Step2', '前置驗證(驗證相關設定)');
|
||||
|
||||
const env = checkEnv();
|
||||
if (!env.ok) {
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ function readRoleFiles() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 載入攻擊方角色(Step2 產生 findings 用),依檔名排序。
|
||||
* 載入攻擊方角色(Step3 產生 findings 用),依檔名排序。
|
||||
* 防守方(如 Paladin)不在此列,裁決邏輯由去重/誤報過濾流程承擔。
|
||||
*/
|
||||
export function loadRoles() {
|
||||
|
||||
Reference in New Issue
Block a user