import { GITEA_REPOSITORY, PR_NUMBER, PR_HEAD_BRANCH, PR_BASE_BRANCH, getLLMConfig } from './config.js'; import { loadRoles, getRoleIntro } from './roles.js'; import { getPRDiff, postComment } from './gitea.js'; import { analyzeWithRole, loadOldFindings, mergeFindings, sortByLevel } from './findings.js'; const WORKSPACE = process.env.GITHUB_WORKSPACE || '/workspace'; async function main() { console.log('='.repeat(60)); console.log('🚀 Step1: Pipeline 啟動'); console.log(` repo=${GITEA_REPOSITORY} PR=#${PR_NUMBER}`); console.log(` ${PR_HEAD_BRANCH} -> ${PR_BASE_BRANCH}`); // 偵測 LLM const { provider, baseURL, model } = getLLMConfig(); if (!provider) { console.error('❌ 未設定任何 LLM API Key,請檢查 action inputs'); process.exit(1); } console.log(` LLM: provider=${provider} model=${model} base_url=${baseURL}`); // 載入角色 const roles = loadRoles(); console.log(` 已載入 ${roles.length} 個角色: [${roles.map(r => r.name).join(', ')}]`); // 取得 PR diff console.log('\n📋 Step1: 取得 PR Diff'); let diff; try { diff = await getPRDiff(); console.log(` diff 長度: ${diff.length} 字元`); } catch (e) { console.error(` ❌ 取得 diff 失敗: ${e.message}`); process.exit(1); } if (!diff.trim()) { console.log(' ⚠️ diff 為空,無需審查'); process.exit(0); } // 發布角色介紹 comment console.log('\n💬 Step1: 發布角色介紹 Comment'); try { const intro = getRoleIntro(roles) + `\n\n> 🔍 服務:${provider} 模型:${model}`; await postComment(intro); console.log(' ✅ 角色介紹 comment 發布成功'); } catch (e) { console.log(` ⚠️ comment 發布失敗(繼續執行): ${e.message}`); } // Step2: 各角色分析 diff 產生新 findings console.log('\n📊 Step2: Findings 產生'); const newFindings = []; for (const role of roles) { try { const found = await analyzeWithRole(role, diff); newFindings.push(...found); } catch (e) { console.log(` ⚠️ [${role.name}] 分析失敗(跳過): ${e.message}`); } } console.log(` Step2 完成: 新 findings 總計 ${newFindings.length} 筆`); // Step3: 讀取舊 findings,合併去重 console.log('\n🔀 Step3: Findings 合併'); const oldFindings = loadOldFindings(WORKSPACE); const mergedFindings = mergeFindings(oldFindings, newFindings); const sorted = sortByLevel(mergedFindings); console.log(` Step3 merged findings total=${sorted.length} (critical=${sorted.filter(f=>f.level==='critical').length} warning=${sorted.filter(f=>f.level==='warning').length} info=${sorted.filter(f=>f.level==='info').length})`); console.log('\n📝 Step4: Findings 寫入與 Comment 發布(待實作)'); console.log(' [stub] 寫入 findings.json,發布 comment...'); console.log('\n💾 Step5: 記憶區 Commit/Push(待實作)'); console.log(' [stub] commit & push findings.json...'); console.log('\n🚦 Step6: 嚴重問題檢查(待實作)'); console.log(' [stub] 檢查 critical findings...'); console.log('\n✅ Pipeline 完成'); console.log('='.repeat(60)); } main().catch(e => { console.error('❌ Runner failed:', e.message); process.exit(1); });