feat(ai-code-review): 建問題模式導向 issue,並整併流程調整、文件與 CI #6
+13
-11
@@ -18,8 +18,8 @@ const TOTAL_DIFF_LIMIT = 160_000;
|
||||
*
|
||||
* 處理順序:換行與控制字元一律壓成單一空白(避免注入假日誌行)→ 遮蔽
|
||||
* `Authorization` 標頭、`token=`/`token:` 型憑證、URL 內嵌帳密、以及常見長金鑰/
|
||||
* 長 hex/`ghp_` 等 token 樣式。屬「盡力遮罩」——無法窮舉所有機密格式,故僅在
|
||||
* 明確開啟除錯輸出時作為第二道防線使用(見 {@link agentFailureDetail})。
|
||||
* 長 hex/`ghp_` 等 token 樣式。屬「盡力遮罩」——無法窮舉所有機密格式,作為輸出
|
||||
* CLI 診斷片段前的防線使用(見 {@link agentFailureDetail})。
|
||||
*
|
||||
* @param {*} text - 待遮罩的原始文字(非字串會先以 `String()` 轉型)。
|
||||
* @returns {string} 已去控制字元並遮蔽常見機密樣式的單行文字。
|
||||
@@ -40,10 +40,11 @@ function redactSecrets(text) {
|
||||
* 從 `runAgent` 的失敗結果組出可診斷的一行摘要:退出碼/訊號為主,原始輸出預設隱藏。
|
||||
*
|
||||
* 安全考量:AI CLI 失敗時可能在 stderr/stdout 回顯提示內容、環境資訊、token、PII 或
|
||||
* 原始碼祕密,這些會被長期保存並供多人讀取的 CI log 收錄。故本函式**預設只輸出**
|
||||
* exit code/signal/killed 等不含機密的分類資訊;**僅在明確開啟 Actions step debug**
|
||||
* (環境變數 `ACTIONS_STEP_DEBUG=true`)時,才附上經 {@link redactSecrets} 遮罩且去除
|
||||
* 控制字元的 stderr/stdout 片段(各截前 500 字)作為診斷第二選擇。純函式、不拋例外。
|
||||
* 原始碼祕密,這些會被長期保存並供多人讀取的 CI log 收錄。權衡「可除錯性」後:本函式
|
||||
* 於失敗時**預設**附上經 {@link redactSecrets} 遮罩且去除控制字元的 **stderr** 片段
|
||||
* (先截去過長輸入再取前 500 字)——只印 exit code 幾乎無從判斷 CLI
|
||||
* 為何失敗;**另在明確開啟 Actions step debug**(環境變數 `ACTIONS_STEP_DEBUG=true`)時,
|
||||
* 再附上同樣遮罩的 **stdout** 片段作為第二診斷來源。純函式、不拋例外。
|
||||
*
|
||||
* @param {{error: (Error & {code?: number|string, signal?: string, killed?: boolean})|null, stderr?: string, output?: string}} res
|
||||
* `runAgent` 的回傳物件。
|
||||
@@ -63,20 +64,21 @@ function agentFailureDetail(res) {
|
||||
else if (err.code) parts.push(`code ${err.code}`);
|
||||
else if (err.signal) parts.push(`signal ${err.signal}`);
|
||||
}
|
||||
// 預設不輸出 AI CLI 原始 stderr/stdout(可能含 token、PII 或原始碼祕密);
|
||||
// 僅在明確開啟 Actions step debug 時,附上「已遮罩+去控制字元」的片段作為診斷。
|
||||
const verbose = String(process.env.ACTIONS_STEP_DEBUG || '').trim().toLowerCase() === 'true';
|
||||
if (verbose) {
|
||||
// 先截去過長輸入再遮罩,避免對數 MB 的失敗輸出跑整份 O(k×n) 正規掃描;
|
||||
// 2000 字上限已足以涵蓋跨界機密樣式,最終仍截為 500 字。
|
||||
const DEBUG_INPUT_LIMIT = 2_000;
|
||||
// 預設即附上「經 redactSecrets 遮罩+去控制字元+限長」的 stderr 片段——CLI 失敗時若只印
|
||||
// exit code 幾乎無從除錯(見 test-claude 秒失敗案例);遮罩為盡力防線,仍以此權衡可除錯性。
|
||||
const stderr = redactSecrets(String((res && res.stderr) || '').slice(0, DEBUG_INPUT_LIMIT));
|
||||
if (stderr) parts.push(`stderr:${stderr.slice(0, 500)}`);
|
||||
// 明確開啟 Actions step debug 時,再附上 stdout 片段作為第二診斷來源。
|
||||
const verbose = String(process.env.ACTIONS_STEP_DEBUG || '').trim().toLowerCase() === 'true';
|
||||
if (verbose) {
|
||||
const stdout = redactSecrets(String((res && res.output) || '').slice(0, DEBUG_INPUT_LIMIT));
|
||||
if (stdout) parts.push(`stdout:${stdout.slice(0, 500)}`);
|
||||
}
|
||||
if (parts.length === 0) {
|
||||
parts.push((err && err.message && redactSecrets(err.message)) || 'AI CLI 執行失敗(詳細輸出已隱藏)');
|
||||
parts.push((err && err.message && redactSecrets(err.message)) || 'AI CLI 執行失敗(無診斷輸出)');
|
||||
}
|
||||
return parts.join('|');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user