feat: AI Pull Request action — opencode 自動產生 PR 並通過 AI review #2

Open
jiantw83 wants to merge 24 commits from ai-review-resolve/develop-20260626-114117 into develop
Showing only changes of commit f7e6f1c64e - Show all commits
+18 -15
View File
1
@@ -97,25 +97,28 @@ export class Git {
* @returns {{ hasConflict: boolean, files: string[] }}
*/
detectConflict(target, source) {
// 建立暫時的本地 target 分支,嘗試以 --no-commit 合併 source
const tmp = `__conflict_check_${target}`;
// 建立暫時的本地 target 分支,嘗試以 --no-commit 合併 source
// 名稱帶 PID,避免並行或前次殘留造成命名衝突。
const tmp = `__conflict_check_${target}_${process.pid}`;
this._git(['checkout', '-B', tmp, `refs/remotes/pr/${target}`]);
const merge = this._git(['merge', '--no-commit', '--no-ff', `refs/remotes/pr/${source}`]);
let hasConflict = merge.status !== 0;
let files = [];
try {
const merge = this._git(['merge', '--no-commit', '--no-ff', `refs/remotes/pr/${source}`]);
const hasConflict = merge.status !== 0;
let files = [];
if (hasConflict) {
const unmerged = this._git(['diff', '--name-only', '--diff-filter=U']);
files = unmerged.stdout.split('\n').map((s) => s.trim()).filter(Boolean);
if (hasConflict) {
const unmerged = this._git(['diff', '--name-only', '--diff-filter=U']);
files = unmerged.stdout.split('\n').map((s) => s.trim()).filter(Boolean);
}
return { hasConflict, files };
} finally {
// 無論成敗都還原工作區並清除暫存分支
this._git(['merge', '--abort']);
this._git(['checkout', '--detach']);
this._git(['branch', '-D', tmp]);
}
// 還原工作區
this._git(['merge', '--abort']);
this._git(['checkout', '--detach']);
this._git(['branch', '-D', tmp]);
return { hasConflict, files };
}
/**