fix(review-resolve): 支援 wrapper findings 並修正輸出格式
This commit is contained in:
+18
-25
@@ -2,6 +2,7 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { postComment, postPullReviewComment, postPullReview } from './gitea.js';
|
||||
import { FINDINGS_PATH } from './config.js';
|
||||
import { buildFindingsWrapper } from './json.js';
|
||||
import { ok, line, warn } from './log.js';
|
||||
|
||||
const LEVEL_EMOJI = { critical: '🔴', warning: '🟡', info: '🔵' };
|
||||
@@ -35,7 +36,8 @@ function findingRow(f) {
|
||||
* 使用情境:任何要把一批 findings 呈現成單一 Markdown 表格的地方,先篩好要顯示的子集合再呼叫本函式。
|
||||
*/
|
||||
function buildTable(findings) {
|
||||
const rows = findings.map(findingRow).join('\n');
|
||||
const list = Array.isArray(findings) ? findings : [];
|
||||
const rows = list.map(findingRow).join('\n');
|
||||
return `| 等級 | 審查員 | 位置 | 建議 |\n|------|--------|------|------|\n${rows}`;
|
||||
}
|
||||
|
||||
@@ -97,7 +99,7 @@ export function parseLocation(location) {
|
||||
* `location` 能被解析出具體行號時。
|
||||
*/
|
||||
function inlineCommentBody(f) {
|
||||
return `**等級**:${levelText(f)}\n**審查員**:${f.role}\n**建議**:${f.suggestion}`;
|
||||
return `**等級**:${levelText(f)}\n**審查員**:${f?.role || 'AI Review'}\n**建議**:${f?.suggestion || ''}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,9 +125,9 @@ function problemText(f) {
|
||||
function reviewCommentBody(f) {
|
||||
return [
|
||||
`**嚴重等級**:${levelText(f)}`,
|
||||
`**審查員**:${f.role}`,
|
||||
`**審查員**:${f?.role || 'AI Review'}`,
|
||||
`**問題**:${problemText(f)}`,
|
||||
`**建議**:${f.suggestion}`,
|
||||
`**建議**:${f?.suggestion || ''}`,
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
@@ -235,15 +237,10 @@ function toReviewComment(f) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 發布單一 Gitea review,必要時會先降級成 summary review,再降級成一般 comment。
|
||||
* 發布單一 Gitea review,必要時降級成 summary review 或一般 comment。
|
||||
*
|
||||
* @param {Array<object>} findings 審查 findings。
|
||||
* @param {object} [deps={}] 可注入的相依物件。
|
||||
* @param {Function} [deps.postReview=postPullReview] 發布整批 review 的函式。
|
||||
* @param {Function} [deps.postInline=postPullReviewComment] 發布單筆行內 comment 的函式。
|
||||
* @param {Function} [deps.postIssue=postComment] 發布一般 comment 的降級函式。
|
||||
* @param {Array<object>} [deps.summaryFindings=findings] 用於統計的 findings 子集合。
|
||||
* @param {Array<object>} [deps.commentFindings=findings] 用於建立 review comments 的 findings 子集合。
|
||||
* @param {string} [deps.usageSection=''] 附加的使用量區塊。
|
||||
* @returns {Promise<void>} 無回傳值。
|
||||
*/
|
||||
export async function postFindingsReview(findings, deps = {}) {
|
||||
@@ -282,11 +279,11 @@ export async function postFindingsReview(findings, deps = {}) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 將 findings 寫入 `findings.json`(同步阻塞 I/O)。
|
||||
* 將 findings 寫入新版 wrapper 格式的 `findings.json`(同步阻塞 I/O)。
|
||||
*
|
||||
* @param {string} workspace 主要輸出目錄;實際寫入路徑為 `path.join(workspace, FINDINGS_PATH)`。
|
||||
* @param {Array<object>} findings 要寫入的 findings 陣列;會以 `JSON.stringify(findings, null, 2)` 序列化,
|
||||
* 並在檔尾補一個換行字元。
|
||||
* @param {Array<object>} findings 要寫入的 findings 陣列;會包成包含 `generatedAt`/`commitSha`/
|
||||
* `prNumber`/`tool`/`findings`/`excluded` 的 wrapper,再以 2 空白縮排 JSON 序列化並補換行。
|
||||
* @param {?string} [mirrorDir=null] 額外鏡射輸出目錄(例如供後續 repo commit 使用);
|
||||
* 為 `null`/`undefined`,或與 `workspace` 相同時,只會寫入一份(不重複寫入同一路徑)。
|
||||
* @returns {void} 無回傳值;成功時每個目標各記錄一行 log。
|
||||
@@ -297,14 +294,15 @@ export async function postFindingsReview(findings, deps = {}) {
|
||||
* 若同時需要寫回 workspace 與 repo 兩個位置,傳入 `mirrorDir` 即可一次呼叫完成兩份寫入。
|
||||
*/
|
||||
export function saveFindings(workspace, findings, mirrorDir = null) {
|
||||
const wrapper = buildFindingsWrapper(findings, []);
|
||||
const targets = [workspace];
|
||||
if (mirrorDir && mirrorDir !== workspace) targets.push(mirrorDir);
|
||||
|
||||
for (const targetDir of targets) {
|
||||
const fullPath = path.join(targetDir, FINDINGS_PATH);
|
||||
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
||||
fs.writeFileSync(fullPath, JSON.stringify(findings, null, 2) + '\n', 'utf8');
|
||||
ok(`findings 寫入: ${fullPath} (${findings.length} 筆)`);
|
||||
fs.writeFileSync(fullPath, JSON.stringify(wrapper, null, 2) + '\n', 'utf8');
|
||||
ok(`findings 寫入: ${fullPath} (${wrapper.findings.length} 筆)`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,12 +310,9 @@ export function saveFindings(workspace, findings, mirrorDir = null) {
|
||||
* 發布所有舊問題的彙總 comment(一次性發布一則一般 comment,不含行內標註)。
|
||||
*
|
||||
* @param {Array<{ is_new?: boolean, level?: string }>} findings 審查問題陣列;
|
||||
* 本函式以 `!f.is_new` 篩選舊問題——`is_new` 為 `false`、`undefined` 或其他 falsy 值皆視為舊問題
|
||||
* (注意:此判定與 {@link newFindingsOnly} 的 `is_new !== false` 不同,`undefined` 在此處被視為
|
||||
* 「舊」而非「新」,是否為預期設計需人工確認)。
|
||||
* 本函式以 `!f.is_new` 篩選舊問題——`is_new` 為 `false`、`undefined` 或其他 falsy 值皆視為舊問題。
|
||||
* @returns {Promise<void>} 無回傳值;`old.length === 0` 時直接 return,不會呼叫 `postComment`。
|
||||
* @remarks 資料列**未依等級排序**,維持 `findings` 原始輸入順序輸出(與 {@link postFindingsReview}
|
||||
* 內部先用 `bySeverity` 排序的行為不同,請勿假設本函式輸出已排序)。
|
||||
* @remarks 資料列**未依等級排序**,維持 `findings` 原始輸入順序輸出。
|
||||
* 使用情境:每輪 AI Code Review 收斂新舊問題後,統一針對「仍未解決的舊問題」發一則彙總說明。
|
||||
*/
|
||||
export async function postOldFindingsComment(findings) {
|
||||
@@ -336,8 +331,7 @@ export async function postOldFindingsComment(findings) {
|
||||
*
|
||||
* @param {Array<{ is_new?: boolean, level?: string }>} findings 審查問題陣列;
|
||||
* 以 `f.is_new && f.level !== 'critical'` 篩選——`is_new` 須為 truthy(例如 `true`)才算新問題,
|
||||
* `undefined`/`false` 皆會被排除(注意:此判定比 {@link newFindingsOnly} 的
|
||||
* `is_new !== false` 更嚴格,兩者對 `undefined` 的處理方向相反,是否為預期設計需人工確認)。
|
||||
* `undefined`/`false` 皆會被排除。
|
||||
* `level !== 'critical'` 涵蓋 `warning`、`info` 及任何非 `'critical'` 的其他值(含未知等級字串)。
|
||||
* @returns {Promise<void>} 無回傳值;`items.length === 0` 時直接 return,不會呼叫 `postComment`。
|
||||
* @remarks 資料列未依等級排序,維持 `findings` 原始輸入順序輸出。
|
||||
@@ -360,8 +354,7 @@ export async function postNewNonCriticalComment(findings) {
|
||||
* (內容為等級/審查員/建議),無法定位或行內發布失敗時降級為一般 comment。
|
||||
*
|
||||
* @param {Array<{ is_new?: boolean, level?: string, location?: string, role?: string, suggestion?: string }>} findings
|
||||
* 審查問題陣列;以 `f.is_new && f.level === 'critical'` 篩選——`is_new` 須為 truthy 才算新問題
|
||||
* (與 {@link newFindingsOnly} 的寬鬆判定不同,`undefined` 會被排除,需人工確認是否為預期設計)。
|
||||
* 審查問題陣列;以 `f.is_new && f.level === 'critical'` 篩選——`is_new` 須為 truthy 才算新問題。
|
||||
* @param {object} [deps={}] 可覆寫的相依注入物件(主要供測試替換)。
|
||||
* @param {Function} [deps.postInline=postPullReviewComment] 發布單筆行內 review comment 的函式。
|
||||
* @param {Function} [deps.postIssue=postComment] 發布一般 comment 的降級函式。
|
||||
|
||||
Reference in New Issue
Block a user