docs(ai-code-review): 補齊各模組 JSDoc、指令檔逐行註解並重建 README
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
303104bb20
commit
1378f03595
+86
-8
@@ -13,24 +13,72 @@ import { verifyRemoteAccess } from './git.js';
|
||||
import { step, line, ok, error, result } from './log.js';
|
||||
|
||||
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
||||
/**
|
||||
* 組出 Gitea REST API v1 的完整網址。
|
||||
*
|
||||
* 會將模組層級的 GITEA_SERVER_URL 尾端斜線去除後串接 `/api/v1` 與傳入路徑。
|
||||
* @param {string} path - 以 `/` 開頭的 API 子路徑,例如 `/repos/owner/name`。
|
||||
* @returns {string} 完整可請求的 API URL。
|
||||
* @remarks 依賴模組層級常數 GITEA_SERVER_URL;若該值為空會丟出 TypeError。
|
||||
*/
|
||||
const api = (path) => `${GITEA_SERVER_URL.replace(/\/$/, '')}/api/v1${path}`;
|
||||
/**
|
||||
* 產生呼叫 Gitea API 用的 HTTP headers。
|
||||
*
|
||||
* Authorization 採 Gitea 的 `token <token>` 認證格式。
|
||||
* @param {string} token - Gitea 個人存取權杖(personal access token)。
|
||||
* @returns {{Authorization: string, 'Content-Type': string}} 可直接交給 axios 的 headers 物件。
|
||||
*/
|
||||
const giteaHeaders = (token) => ({ Authorization: `token ${token}`, 'Content-Type': 'application/json' });
|
||||
/**
|
||||
* 將模型字串解析為 OpenCode 的 providerID 與 modelID。
|
||||
*
|
||||
* 若 model 含 `/` 則以斜線拆分為 provider/model;否則 provider 取
|
||||
* 環境變數 OPENCODE_PROVIDER(預設 `google`),model 即原字串。
|
||||
* @param {string} model - 模型識別字串,例如 `google/gemini-2.0` 或 `gemini-2.0`。
|
||||
* @returns {{providerID: string, modelID: string}} 解析後的 provider 與 model 識別碼。
|
||||
* @remarks 讀取 process.env.OPENCODE_PROVIDER;split 上限為 2 段,多餘段落會被忽略。
|
||||
*/
|
||||
const opencodeModelConfig = (model) => {
|
||||
const [providerID, modelID] = model.includes('/') ? model.split('/', 2) : [process.env.OPENCODE_PROVIDER || 'google', model];
|
||||
return { providerID, modelID };
|
||||
};
|
||||
/**
|
||||
* 組出呼叫 OpenCode server 用的 axios 請求設定。
|
||||
*
|
||||
* 固定 30 秒逾時,並套用 config.js 的 getOpenCodeHttpsAgent() 作為 httpsAgent。
|
||||
* @param {object} headers - 要套用的 HTTP headers 物件。
|
||||
* @returns {{headers: object, timeout: number, httpsAgent: import('https').Agent}} axios 設定物件。
|
||||
* @remarks 每次呼叫都會執行 getOpenCodeHttpsAgent() 取得 agent。
|
||||
*/
|
||||
const opencodeAxiosOptions = (headers) => ({
|
||||
headers,
|
||||
timeout: 30000,
|
||||
httpsAgent: getOpenCodeHttpsAgent(),
|
||||
});
|
||||
|
||||
/**
|
||||
* 將(axios)錯誤格式化為易讀的訊息字串。
|
||||
*
|
||||
* 有 HTTP 回應狀態碼時輸出 `HTTP <status> <message>`,否則僅輸出 message。
|
||||
* @param {Error & {response?: {status?: number}, message: string}} e - 捕捉到的錯誤物件。
|
||||
* @returns {string} 格式化後的錯誤描述。
|
||||
*/
|
||||
function giteaErr(e) {
|
||||
const status = e.response?.status;
|
||||
return status ? `HTTP ${status} ${e.message}` : e.message;
|
||||
}
|
||||
|
||||
/** 檢查必要環境變數是否齊全;可傳入覆寫值供測試使用 */
|
||||
/**
|
||||
* 檢查 code review 所需的必要環境變數是否齊全。
|
||||
*
|
||||
* 用法:preflight 第一關,缺任何一項即視為不通過並列出缺少項目。
|
||||
* @param {object} [opts] - 覆寫值,供測試注入;省略時各欄取模組層級常數預設值。
|
||||
* @param {string} [opts.token=GITEA_TOKEN] - Gitea token。
|
||||
* @param {string} [opts.repo=GITEA_REPOSITORY] - `owner/name` 形式的 repo。
|
||||
* @param {string|number} [opts.pr=PR_NUMBER] - PR 編號。
|
||||
* @returns {{ok: boolean, missing: string[]}} ok 表是否全部齊全;missing 列出缺少的環境變數名稱。
|
||||
*/
|
||||
export function checkRequiredEnv({ token = GITEA_TOKEN, repo = GITEA_REPOSITORY, pr = PR_NUMBER } = {}) {
|
||||
const missing = [];
|
||||
if (!token) missing.push('GITEA_TOKEN');
|
||||
@@ -39,7 +87,15 @@ export function checkRequiredEnv({ token = GITEA_TOKEN, repo = GITEA_REPOSITORY,
|
||||
return { ok: missing.length === 0, missing };
|
||||
}
|
||||
|
||||
/** 用 GITEA_TOKEN 讀取此 repo,同時驗證 token 有效與有讀取權限 */
|
||||
/**
|
||||
* 驗證 Gitea token 有效且對指定 repo 有讀取權限。
|
||||
*
|
||||
* 透過唯讀的 `GET /repos/{repo}` 探測;任何錯誤都被攔截並轉為回傳值,不會 throw。
|
||||
* 採用 rejectUnauthorized:false 的 httpsAgent(不驗證 TLS 憑證)。
|
||||
* @param {string} [token=GITEA_TOKEN] - Gitea token,可注入供測試。
|
||||
* @param {string} [repo=GITEA_REPOSITORY] - `owner/name` 形式的 repo,可注入供測試。
|
||||
* @returns {Promise<{ok: true}|{ok: false, error: string}>} 成功僅含 ok;失敗含格式化錯誤訊息。
|
||||
*/
|
||||
export async function verifyGiteaToken(token = GITEA_TOKEN, repo = GITEA_REPOSITORY) {
|
||||
try {
|
||||
await axios.get(api(`/repos/${repo}`), { headers: giteaHeaders(token), timeout: 30000, httpsAgent });
|
||||
@@ -49,7 +105,14 @@ export async function verifyGiteaToken(token = GITEA_TOKEN, repo = GITEA_REPOSIT
|
||||
}
|
||||
}
|
||||
|
||||
/** 若有提供 comment token,用它呼叫 /user 驗證可用;沒提供則略過 */
|
||||
/**
|
||||
* 驗證選用的 comment token(GITEA_COMMENT_TOKEN)是否可用。
|
||||
*
|
||||
* 未提供 token 時直接視為通過並標記 skipped:true(之後 comment 會沿用主 token);
|
||||
* 有提供則以 `GET /user` 探測。錯誤被攔截轉為回傳值,不會 throw。
|
||||
* @param {string} [token=GITEA_COMMENT_TOKEN] - 專用於發布 comment 的 token,可注入供測試。
|
||||
* @returns {Promise<{ok: true, skipped?: true}|{ok: false, error: string}>} skipped 表示未提供而略過。
|
||||
*/
|
||||
export async function verifyCommentToken(token = GITEA_COMMENT_TOKEN) {
|
||||
if (!token) return { ok: true, skipped: true };
|
||||
try {
|
||||
@@ -61,9 +124,13 @@ export async function verifyCommentToken(token = GITEA_COMMENT_TOKEN) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 驗證 LLM 設定可用:
|
||||
* - 僅支援 OpenCode server
|
||||
* - 檢查 OpenCode base URL 是否可連線,並確認 provider/model 已設定
|
||||
* 驗證 LLM(OpenCode server)設定可用。
|
||||
*
|
||||
* 依序確認:已設定 provider、有 base URL、health 端點可連線、OpenCode 已設定
|
||||
* 對應 provider 且其列出指定 model。任一不符回傳對應錯誤;錯誤被攔截不會 throw。
|
||||
* @returns {Promise<{ok: true, provider: string}|{ok: false, provider?: string, error: string}>}
|
||||
* 通過時含 provider;未設定 provider 的失敗分支不含 provider 欄位。
|
||||
* @remarks 設定來源為 config.js 的 getLLMConfig();provider/model 鍵的比對使用 opencodeModelConfig 解析後的 providerID/modelID。
|
||||
*/
|
||||
export async function verifyLLM() {
|
||||
const { provider, baseURL, model } = getLLMConfig();
|
||||
@@ -87,8 +154,19 @@ export async function verifyLLM() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 集中執行所有驗證相關設定的前置檢查;全部通過回傳 true,任一失敗回傳 false。
|
||||
* 僅做唯讀的認證/連線確認,不發布任何 comment。
|
||||
* 執行所有前置驗證(Step2):環境變數、Gitea token、comment token、git 遠端、LLM。
|
||||
*
|
||||
* 全程唯讀,不發布任何 comment;任一檢查失敗即記錄錯誤並回傳 false。
|
||||
* 各檢查可經 deps 注入覆寫,方便單元測試。
|
||||
* @param {string} [workspace=process.env.GITHUB_WORKSPACE||'/workspace'] - git 遠端驗證用的工作目錄。
|
||||
* @param {object} [deps] - 依賴注入,覆寫各檢查函式(預設為本模組/ git.js 的實作)。
|
||||
* @param {Function} [deps.checkEnv=checkRequiredEnv] - 環境變數檢查。
|
||||
* @param {Function} [deps.verifyToken=verifyGiteaToken] - Gitea token / repo 讀取驗證。
|
||||
* @param {Function} [deps.verifyComment=verifyCommentToken] - comment token 驗證。
|
||||
* @param {Function} [deps.verifyRemote=verifyRemoteAccess] - git 遠端(ls-remote)認證驗證。
|
||||
* @param {Function} [deps.verifyLLMFn=verifyLLM] - LLM(OpenCode)連線驗證。
|
||||
* @returns {Promise<boolean>} 全部通過為 true,任一失敗為 false。
|
||||
* @remarks 透過 log.js 輸出 step/ok/line/error/result 記錄;不會 throw(前提是注入的檢查函式皆自行攔截錯誤)。
|
||||
*/
|
||||
export async function runPreflight(workspace = process.env.GITHUB_WORKSPACE || '/workspace', deps = {}) {
|
||||
const {
|
||||
|
||||
Reference in New Issue
Block a user