From 5ae0549453f66ff4cc4cdfea719381cdc9118295 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Mon, 11 May 2026 09:49:07 +0000 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E9=9A=8E=E6=AE=B5=E4=BA=94?= =?UTF-8?q?=E5=85=AD=20-=20findings=20commit/push=20=E5=88=B0=E4=BE=86?= =?UTF-8?q?=E6=BA=90=E5=88=86=E6=94=AF=EF=BC=8Ccritical=20=E5=95=8F?= =?UTF-8?q?=E9=A1=8C=20exit=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/git.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ app/main.js | 17 +++++++++++++---- 2 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 app/git.js diff --git a/app/git.js b/app/git.js new file mode 100644 index 0000000..7634ffb --- /dev/null +++ b/app/git.js @@ -0,0 +1,44 @@ +import { execSync } from 'child_process'; +import { GITEA_SERVER_URL, GITEA_REPOSITORY, GITEA_TOKEN, PR_HEAD_BRANCH, FINDINGS_PATH } from './config.js'; + +function exec(cmd, cwd) { + return execSync(cmd, { cwd, stdio: 'pipe' }).toString().trim(); +} + +/** + * Commit findings.json 並 push 到 PR 來源分支 + */ +export function commitAndPush(workspace) { + const repoDir = `${workspace}/${GITEA_REPOSITORY}`; + const remoteUrl = `${GITEA_SERVER_URL.replace(/\/$/, '')}/${GITEA_REPOSITORY}.git` + .replace('https://', `https://${GITEA_TOKEN}@`); + + try { + // 設定 git 身份 + exec('git config user.email "ai-review[bot]@gitea"', repoDir); + exec('git config user.name "AI Review Bot"', repoDir); + + // 切換到來源分支 + exec(`git fetch origin ${PR_HEAD_BRANCH}`, repoDir); + exec(`git checkout ${PR_HEAD_BRANCH}`, repoDir); + + // 確認 findings.json 存在 + exec(`git add ${FINDINGS_PATH}`, repoDir); + + // 檢查是否有變更 + const status = exec('git status --porcelain', repoDir); + if (!status) { + console.log(' findings.json 無變更,跳過 commit'); + return; + } + + const commitMsg = 'chore: update ai-review findings [skip ci]'; + const commitHash = exec(`git commit -m "${commitMsg}"`, repoDir) + .match(/\[.+ ([a-f0-9]+)\]/)?.[1] || 'unknown'; + + exec(`git push ${remoteUrl} ${PR_HEAD_BRANCH}`, repoDir); + console.log(` ✅ persisted findings commit=${commitHash} push=${PR_HEAD_BRANCH}`); + } catch (e) { + console.log(` ⚠️ Runner failed: commit/push 失敗: ${e.message}`); + } +} diff --git a/app/main.js b/app/main.js index de466f7..4e6f88c 100644 --- a/app/main.js +++ b/app/main.js @@ -3,6 +3,7 @@ import { loadRoles, getRoleIntro } from './roles.js'; import { getPRDiff, postComment } from './gitea.js'; import { analyzeWithRole, loadOldFindings, mergeFindings, sortByLevel, deduplicateWithAI } from './findings.js'; import { saveFindings, postOldFindingsComment, postNewNonCriticalComment, postNewCriticalComments } from './comments.js'; +import { commitAndPush } from './git.js'; const WORKSPACE = process.env.GITHUB_WORKSPACE || '/workspace'; @@ -88,11 +89,19 @@ async function main() { console.log(` ⚠️ comment 發布失敗(繼續執行): ${e.message}`); } - console.log('\n💾 Step5: 記憶區 Commit/Push(待實作)'); - console.log(' [stub] commit & push findings.json...'); + // Step5: commit/push findings.json 到來源分支 + console.log('\n💾 Step5: 記憶區 Commit/Push'); + commitAndPush(WORKSPACE); - console.log('\n🚦 Step6: 嚴重問題檢查(待實作)'); - console.log(' [stub] 檢查 critical findings...'); + // Step6: 有 critical 問題則 exit 1 + console.log('\n🚦 Step6: 嚴重問題檢查'); + const criticalCount = sorted.filter(f => f.level === 'critical').length; + if (criticalCount > 0) { + console.log(` ❌ 發現 ${criticalCount} 個嚴重問題,workflow 結束(exit 1)`); + console.log('='.repeat(60)); + process.exit(1); + } + console.log(' ✅ 無嚴重問題'); console.log('\n✅ Pipeline 完成'); console.log('='.repeat(60)); From 519e04691d2ce0f888b3592d5c21f41869fc3e05 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Mon, 11 May 2026 09:51:28 +0000 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20git.js=20=E6=94=B9=E7=94=A8=20spawnS?= =?UTF-8?q?ync=20=E7=9B=B4=E6=8E=A5=E5=91=BC=E5=8F=AB=20git=20binary?= =?UTF-8?q?=EF=BC=88=E9=81=BF=E5=85=8D=20/bin/sh=20ENOENT=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/git.js | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/app/git.js b/app/git.js index 7634ffb..ed80d20 100644 --- a/app/git.js +++ b/app/git.js @@ -1,8 +1,11 @@ -import { execSync } from 'child_process'; +import { spawnSync } from 'child_process'; import { GITEA_SERVER_URL, GITEA_REPOSITORY, GITEA_TOKEN, PR_HEAD_BRANCH, FINDINGS_PATH } from './config.js'; -function exec(cmd, cwd) { - return execSync(cmd, { cwd, stdio: 'pipe' }).toString().trim(); +function git(args, cwd) { + const result = spawnSync('git', args, { cwd, encoding: 'utf8' }); + if (result.error) throw result.error; + if (result.status !== 0) throw new Error(result.stderr || result.stdout); + return (result.stdout || '').trim(); } /** @@ -10,33 +13,24 @@ function exec(cmd, cwd) { */ export function commitAndPush(workspace) { const repoDir = `${workspace}/${GITEA_REPOSITORY}`; - const remoteUrl = `${GITEA_SERVER_URL.replace(/\/$/, '')}/${GITEA_REPOSITORY}.git` - .replace('https://', `https://${GITEA_TOKEN}@`); + const remoteUrl = GITEA_SERVER_URL.replace(/\/$/, '').replace('https://', `https://${GITEA_TOKEN}@`) + `/${GITEA_REPOSITORY}.git`; try { - // 設定 git 身份 - exec('git config user.email "ai-review[bot]@gitea"', repoDir); - exec('git config user.name "AI Review Bot"', repoDir); + git(['config', 'user.email', 'ai-review[bot]@gitea'], repoDir); + git(['config', 'user.name', 'AI Review Bot'], repoDir); + git(['fetch', 'origin', PR_HEAD_BRANCH], repoDir); + git(['checkout', PR_HEAD_BRANCH], repoDir); + git(['add', FINDINGS_PATH], repoDir); - // 切換到來源分支 - exec(`git fetch origin ${PR_HEAD_BRANCH}`, repoDir); - exec(`git checkout ${PR_HEAD_BRANCH}`, repoDir); - - // 確認 findings.json 存在 - exec(`git add ${FINDINGS_PATH}`, repoDir); - - // 檢查是否有變更 - const status = exec('git status --porcelain', repoDir); + const status = git(['status', '--porcelain'], repoDir); if (!status) { console.log(' findings.json 無變更,跳過 commit'); return; } - const commitMsg = 'chore: update ai-review findings [skip ci]'; - const commitHash = exec(`git commit -m "${commitMsg}"`, repoDir) - .match(/\[.+ ([a-f0-9]+)\]/)?.[1] || 'unknown'; - - exec(`git push ${remoteUrl} ${PR_HEAD_BRANCH}`, repoDir); + const out = git(['commit', '-m', 'chore: update ai-review findings [skip ci]'], repoDir); + const commitHash = out.match(/\[.+ ([a-f0-9]+)\]/)?.[1] || 'unknown'; + git(['push', remoteUrl, PR_HEAD_BRANCH], repoDir); console.log(` ✅ persisted findings commit=${commitHash} push=${PR_HEAD_BRANCH}`); } catch (e) { console.log(` ⚠️ Runner failed: commit/push 失敗: ${e.message}`);