test: 補齊 runPreflight 測試並 triage preflight findings
triage 6 筆 review findings:1 筆修正、5 筆移入 exclusions。 修正(Maya, warning):runPreflight 僅測過 env 缺失早退,缺成功路徑與 各失敗點覆蓋。將其驗證步驟改為可注入的 deps 參數(預設沿用原函式, 行為不變),並補上完整成功、comment 略過、各失敗點早停、workspace 傳遞共 8 個測試。 移入 exclusions(誤報,保留原文): - Rex critical:GITEA_SKIP_TLS_VERIFY 為預設開啟驗證的 opt-in 設定, 與既有 gitea.js 排除一致,非漏洞 - Leo warning:verifyLLM 內聚清楚,拆分屬主觀重構 - Zara warning:每把 key 30s timeout 為刻意的可靠性下限,僅失敗時累積 - Rex info:axios 錯誤訊息不含認證標頭/內容 - Aria info:預設參數引用 config 常數為刻意且利於測試的 pattern findings.json 清空(全部已修正或排除)。app/ 測試 112 pass。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+13
-6
@@ -93,24 +93,31 @@ export async function verifyLLM() {
|
||||
* 集中執行所有驗證相關設定的前置檢查;全部通過回傳 true,任一失敗回傳 false。
|
||||
* 僅做唯讀的認證/連線確認,不發布任何 comment。
|
||||
*/
|
||||
export async function runPreflight(workspace = process.env.GITHUB_WORKSPACE || '/workspace') {
|
||||
export async function runPreflight(workspace = process.env.GITHUB_WORKSPACE || '/workspace', deps = {}) {
|
||||
const {
|
||||
checkEnv = checkRequiredEnv,
|
||||
verifyToken = verifyGiteaToken,
|
||||
verifyComment = verifyCommentToken,
|
||||
verifyRemote = verifyRemoteAccess,
|
||||
verifyLLMFn = verifyLLM,
|
||||
} = deps;
|
||||
step('Step1.5', '前置驗證(驗證相關設定)');
|
||||
|
||||
const env = checkRequiredEnv();
|
||||
const env = checkEnv();
|
||||
if (!env.ok) {
|
||||
error(`缺少必要環境變數: ${env.missing.join(', ')}`);
|
||||
return false;
|
||||
}
|
||||
ok('必要環境變數齊全 (GITEA_TOKEN, GITEA_REPOSITORY, PR_NUMBER)');
|
||||
|
||||
const gitea = await verifyGiteaToken();
|
||||
const gitea = await verifyToken();
|
||||
if (!gitea.ok) {
|
||||
error(`GITEA_TOKEN 驗證失敗(無法讀取 repo ${GITEA_REPOSITORY}): ${gitea.error}`);
|
||||
return false;
|
||||
}
|
||||
ok(`GITEA_TOKEN 可讀取 repo ${GITEA_REPOSITORY}`);
|
||||
|
||||
const comment = await verifyCommentToken();
|
||||
const comment = await verifyComment();
|
||||
if (!comment.ok) {
|
||||
error(`GITEA_COMMENT_TOKEN 驗證失敗: ${comment.error}`);
|
||||
return false;
|
||||
@@ -118,14 +125,14 @@ export async function runPreflight(workspace = process.env.GITHUB_WORKSPACE || '
|
||||
if (comment.skipped) line('未提供 GITEA_COMMENT_TOKEN,comment 將沿用 GITEA_TOKEN');
|
||||
else ok('GITEA_COMMENT_TOKEN 可用');
|
||||
|
||||
const remote = verifyRemoteAccess(workspace);
|
||||
const remote = verifyRemote(workspace);
|
||||
if (!remote.ok) {
|
||||
error(`git push 認證/連線驗證失敗(ls-remote): ${remote.error}`);
|
||||
return false;
|
||||
}
|
||||
ok('git remote 認證可用(ls-remote 成功)');
|
||||
|
||||
const llm = await verifyLLM();
|
||||
const llm = await verifyLLMFn();
|
||||
if (!llm.ok) {
|
||||
error(`LLM 驗證失敗: ${llm.error}`);
|
||||
return false;
|
||||
|
||||
@@ -188,10 +188,76 @@ describe('verifyLLM', () => {
|
||||
});
|
||||
|
||||
describe('runPreflight', () => {
|
||||
// Stub deps that all succeed; individual tests override one to fail.
|
||||
function makeDeps(overrides = {}) {
|
||||
return {
|
||||
checkEnv: () => ({ ok: true, missing: [] }),
|
||||
verifyToken: async () => ({ ok: true }),
|
||||
verifyComment: async () => ({ ok: true }),
|
||||
verifyRemote: () => ({ ok: true }),
|
||||
verifyLLMFn: async () => ({ ok: true, provider: 'openai', keyIndex: 1, total: 1 }),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
it('returns false and stops early when required env is missing', async () => {
|
||||
// Config constants default to empty in the test environment, so the
|
||||
// required-env check fails before any network call is attempted.
|
||||
const result = await runPreflight();
|
||||
assert.equal(result, false);
|
||||
});
|
||||
|
||||
it('returns true when every verification step succeeds', async () => {
|
||||
const result = await runPreflight('/ws', makeDeps());
|
||||
assert.equal(result, true);
|
||||
});
|
||||
|
||||
it('returns true when the comment token check is skipped', async () => {
|
||||
const result = await runPreflight('/ws', makeDeps({
|
||||
verifyComment: async () => ({ ok: true, skipped: true }),
|
||||
}));
|
||||
assert.equal(result, true);
|
||||
});
|
||||
|
||||
it('returns false when the Gitea token check fails', async () => {
|
||||
let remoteCalled = false;
|
||||
const result = await runPreflight('/ws', makeDeps({
|
||||
verifyToken: async () => ({ ok: false, error: 'HTTP 401' }),
|
||||
verifyRemote: () => { remoteCalled = true; return { ok: true }; },
|
||||
}));
|
||||
assert.equal(result, false);
|
||||
assert.equal(remoteCalled, false, 'should stop before later checks');
|
||||
});
|
||||
|
||||
it('returns false when the comment token check fails', async () => {
|
||||
const result = await runPreflight('/ws', makeDeps({
|
||||
verifyComment: async () => ({ ok: false, error: 'HTTP 401' }),
|
||||
}));
|
||||
assert.equal(result, false);
|
||||
});
|
||||
|
||||
it('returns false when git remote access fails', async () => {
|
||||
let llmCalled = false;
|
||||
const result = await runPreflight('/ws', makeDeps({
|
||||
verifyRemote: () => ({ ok: false, error: 'auth failed' }),
|
||||
verifyLLMFn: async () => { llmCalled = true; return { ok: true }; },
|
||||
}));
|
||||
assert.equal(result, false);
|
||||
assert.equal(llmCalled, false, 'should stop before the LLM check');
|
||||
});
|
||||
|
||||
it('returns false when LLM verification fails', async () => {
|
||||
const result = await runPreflight('/ws', makeDeps({
|
||||
verifyLLMFn: async () => ({ ok: false, error: '所有 key 驗證失敗' }),
|
||||
}));
|
||||
assert.equal(result, false);
|
||||
});
|
||||
|
||||
it('passes the workspace through to the remote-access check', async () => {
|
||||
let captured;
|
||||
await runPreflight('/custom/ws', makeDeps({
|
||||
verifyRemote: (ws) => { captured = ws; return { ok: true }; },
|
||||
}));
|
||||
assert.equal(captured, '/custom/ws');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user