feat(ai-code-review): 建問題模式導向 issue,並整併流程調整、文件與 CI #5
@@ -81,12 +81,12 @@ flowchart TD
|
||||
| [log.taipeiFromIso](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/log.js#L60) | [將 ISO 時間字串轉為台北時區顯示字串](#logtaipeifromiso) |
|
||||
| [log.log](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/log.js#L83) | [以統一格式輸出一行日誌](#loglog) |
|
||||
| [context.loadContext](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/context.js#L64) | [彙整 runner 環境變數與事件 payload 為執行上下文](#contextloadcontext) |
|
||||
| [gitrepo.latestCommitSubject](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L60) | [取得最新 commit 的訊息標題](#gitrepolatestcommitsubject) |
|
||||
| [gitrepo.resolveMergeBase](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L81) | [解析 base 分支與 HEAD 的 merge-base](#gitreporesolvemergebase) |
|
||||
| [gitrepo.changedFiles](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L104) | [列出 base 與 HEAD 之間有變更的檔案](#gitrepochangedfiles) |
|
||||
| [gitrepo.fileDiff](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L125) | [取得單一檔案的 git diff 內容](#gitrepofilediff) |
|
||||
| [gitrepo.fileLastUpdatedIso](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L143) | [取得檔案最後一次 commit 的 ISO 時間](#gitrepofilelastupdatediso) |
|
||||
| [gitrepo.commitAndPushFindings](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L181) | [以 bot 身分 commit 結果檔並 push 回 PR 來源分支](#gitrepocommitandpushfindings) |
|
||||
| [gitrepo.latestCommitSubject](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L79) | [取得最新 commit 的訊息標題](#gitrepolatestcommitsubject) |
|
||||
| [gitrepo.resolveMergeBase](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L100) | [解析 base 分支與 HEAD 的 merge-base](#gitreporesolvemergebase) |
|
||||
| [gitrepo.changedFiles](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L136) | [列出 base 與 HEAD 之間有變更的檔案](#gitrepochangedfiles) |
|
||||
| [gitrepo.fileDiff](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L157) | [取得單一檔案的 git diff 內容](#gitrepofilediff) |
|
||||
| [gitrepo.fileLastUpdatedIso](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L175) | [取得檔案最後一次 commit 的 ISO 時間](#gitrepofilelastupdatediso) |
|
||||
| [gitrepo.commitAndPushFindings](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitrepo.js#L213) | [以 bot 身分 commit 結果檔並 push 回 PR 來源分支](#gitrepocommitandpushfindings) |
|
||||
| [gitea.whoAmI](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitea.js#L87) | [取得 token 對應的使用者(bot 身分)](#giteawhoami) |
|
||||
| [gitea.createCommentOnIssue](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitea.js#L106) | [對指定編號 issue/PR 新增一般留言](#giteacreatecommentonissue) |
|
||||
| [gitea.createIssueComment](https://gitea.jsc.idv.tw/node-actions/ai-code-review/src/branch/develop/src/lib/gitea.js#L124) | [對本次 PR 新增一般留言](#giteacreateissuecomment) |
|
||||
|
||||
+40
-8
@@ -44,6 +44,25 @@ function gitTrim(cwd, ...args) {
|
||||
return git(cwd, ...args).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 嘗試同步執行 git 指令,失敗時回傳 false,成功時回傳 true。
|
||||
*
|
||||
* @param {string} cwd - git 工作目錄(repo 的 checkout 路徑)。
|
||||
* @param {...string} args - 傳給 git 的參數。
|
||||
* @returns {boolean} git 指令是否成功結束。
|
||||
* @remarks
|
||||
* 使用情境:修復淺層 checkout 的歷史不足時,部分 fetch 策略可能因 runner
|
||||
* 或遠端版本不同而失敗;呼叫端可依序嘗試多種策略,不讓第一個失敗中斷流程。
|
||||
*/
|
||||
function tryGit(cwd, ...args) {
|
||||
try {
|
||||
git(cwd, ...args);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得目前 HEAD 最新一筆 commit 的訊息標題(commit message 第一行)。
|
||||
*
|
||||
@@ -64,14 +83,14 @@ function latestCommitSubject(cwd) {
|
||||
/**
|
||||
* 解析 PR base 分支與目前 HEAD 的 merge-base commit SHA。
|
||||
*
|
||||
* 先嘗試 `git fetch origin <baseRef>` 更新 base 分支資料(失敗時靜默忽略,
|
||||
* 因 fetch-depth: 0 的 checkout 通常已含 base 分支,可直接沿用本地資料),
|
||||
* 再以 `git merge-base origin/<baseRef> HEAD` 取得共同祖先。
|
||||
* 先以 refspec 明確更新 `origin/<baseRef>`,再以 `git merge-base origin/<baseRef> HEAD`
|
||||
* 取得共同祖先。若 checkout 是淺層歷史而導致 merge-base 失敗,會補抓完整或更深的
|
||||
* base/head 歷史後重試,避免 PR workflow 因 checkout 預設深度不足而中斷。
|
||||
*
|
||||
* @param {string} cwd - git 工作目錄(repo 的 checkout 路徑)。
|
||||
* @param {string} baseRef - PR 目標(base)分支名稱,例如 'master' 或 'develop';不含 'origin/' 前綴。
|
||||
* @returns {string} merge-base 的 commit SHA(40 碼十六進位字串)。
|
||||
* @throws {Error} 本地不存在 origin/<baseRef>、或兩者無共同祖先時,`git merge-base` 失敗並拋出(fetch 失敗不會拋出)。
|
||||
* @throws {Error} 補抓歷史後仍無法取得共同祖先時,丟出含 baseRef 的明確錯誤。
|
||||
* @remarks
|
||||
* 使用情境:AI code review 以此結果作為 diff 比較基準——
|
||||
* 先 `resolveMergeBase(cwd, pr.base.ref)` 取得基準 SHA,
|
||||
@@ -79,12 +98,25 @@ function latestCommitSubject(cwd) {
|
||||
* 避免把 base 分支後續演進誤算進 diff。
|
||||
*/
|
||||
function resolveMergeBase(cwd, baseRef) {
|
||||
const remoteBase = `origin/${baseRef}`;
|
||||
tryGit(cwd, 'fetch', '--no-tags', 'origin', `+refs/heads/${baseRef}:refs/remotes/${remoteBase}`);
|
||||
try {
|
||||
git(cwd, 'fetch', 'origin', baseRef);
|
||||
} catch {
|
||||
// fetch-depth: 0 的 checkout 通常已含 base 分支,抓不到時直接沿用本地資料。
|
||||
return gitTrim(cwd, 'merge-base', remoteBase, 'HEAD');
|
||||
} catch (firstError) {
|
||||
const isShallow = gitTrim(cwd, 'rev-parse', '--is-shallow-repository') === 'true';
|
||||
if (isShallow) {
|
||||
tryGit(cwd, 'fetch', '--no-tags', '--unshallow', 'origin');
|
||||
}
|
||||
tryGit(cwd, 'fetch', '--no-tags', '--deepen=1000', 'origin', `+refs/heads/${baseRef}:refs/remotes/${remoteBase}`);
|
||||
tryGit(cwd, 'fetch', '--no-tags', '--deepen=1000', 'origin', 'HEAD');
|
||||
try {
|
||||
return gitTrim(cwd, 'merge-base', remoteBase, 'HEAD');
|
||||
} catch {
|
||||
const error = new Error(`無法解析 origin/${baseRef} 與 HEAD 的 merge-base;請確認 checkout 有足夠歷史,或設定 checkout fetch-depth: 0。`);
|
||||
error.cause = firstError;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return gitTrim(cwd, 'merge-base', `origin/${baseRef}`, 'HEAD');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user