From 73c53e11de34fa6afb80259a167c30c469157c15 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Fri, 26 Jun 2026 13:58:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(ai-pull-request):=20=E9=81=AE=E8=94=BD?= =?UTF-8?q?=E9=8C=AF=E8=AA=A4=E8=A8=8A=E6=81=AF=20token=E3=80=81=E6=B8=85?= =?UTF-8?q?=E7=90=86=E6=9A=AB=E5=AD=98=E8=A8=AD=E5=AE=9A=E3=80=81=E6=88=AA?= =?UTF-8?q?=E6=96=B7=E5=88=86=E6=94=AF=E5=90=8D=E7=A8=B1=E4=B8=A6=E6=94=B9?= =?UTF-8?q?=E7=94=A8=20homedir?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/index.js | 10 +++++--- app/lib/opencode.js | 57 ++++++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/app/index.js b/app/index.js index 81b4c3d..d67a4f0 100644 --- a/app/index.js +++ b/app/index.js @@ -2,7 +2,7 @@ import { loadInputs, logInputs } from './lib/inputs.js'; import { Git } from './lib/git.js'; import { GiteaClient } from './lib/gitea.js'; import { OpenCode } from './lib/opencode.js'; -import { log } from './lib/util.js'; +import { log, maskSecrets } from './lib/util.js'; async function main() { const inputs = loadInputs(); @@ -143,7 +143,9 @@ function buildResolveBranchName(target, source) { const runId = process.env.GITHUB_RUN_NUMBER || process.env.GITHUB_RUN_ID || ''; const safe = (s) => s.replace(/[^a-zA-Z0-9._/-]/g, '-'); const suffix = runId ? `-${runId}` : ''; - return `resolve-conflict/${safe(target)}-into-${safe(source)}${suffix}`; + // 截斷主體長度,避免 target/source 過長使分支名稱超出 Git 限制 + const stem = `${safe(target)}-into-${safe(source)}`.slice(0, 180); + return `resolve-conflict/${stem}${suffix}`; } /** 解衝突 PR 的描述。 */ @@ -180,6 +182,8 @@ function reportPull(pull, created) { } main().catch((err) => { - log.error(err?.stack || err?.message || String(err)); + const detail = err?.stack || err?.message || String(err); + // 錯誤訊息/stack 可能夾帶 token,輸出到 CI 日誌前先遮蔽 + log.error(maskSecrets(detail, [process.env.GITEA_TOKEN])); process.exit(1); }); diff --git a/app/lib/opencode.js b/app/lib/opencode.js index 1190790..0d3870f 100644 --- a/app/lib/opencode.js +++ b/app/lib/opencode.js @@ -1,6 +1,6 @@ -import { writeFileSync, mkdtempSync } from 'node:fs'; -import { tmpdir } from 'node:os'; -import { join } from 'node:path'; +import { writeFileSync, mkdtempSync, rmSync } from 'node:fs'; +import { tmpdir, homedir } from 'node:os'; +import { join, dirname } from 'node:path'; import { run, log, maskSecrets } from './util.js'; /** @@ -74,33 +74,38 @@ export class OpenCode { const configPath = this._writeConfig(); const prompt = buildPrompt({ ...ctx, language: this.language }); - log.info(`呼叫 opencode(${this.provider}/${this.model})分析 diff...`); - const result = run( - 'opencode', - ['run', '--model', `${this.provider}/${this.model}`, prompt], - { - cwd: tmpdir(), - env: { - ...process.env, - OPENCODE_CONFIG: configPath, - // 確保 opencode 有可寫的 HOME / 設定目錄 - HOME: process.env.HOME || '/root', + try { + log.info(`呼叫 opencode(${this.provider}/${this.model})分析 diff...`); + const result = run( + 'opencode', + ['run', '--model', `${this.provider}/${this.model}`, prompt], + { + cwd: tmpdir(), + env: { + ...process.env, + OPENCODE_CONFIG: configPath, + // 確保 opencode 有可寫的 HOME / 設定目錄 + HOME: process.env.HOME || homedir(), + }, + timeout: 5 * 60 * 1000, }, - timeout: 5 * 60 * 1000, - }, - ); + ); - if (result.status !== 0) { - log.warn(`opencode 執行失敗 (${result.status}):${maskSecrets(result.stderr).slice(0, 500)}`); - return null; - } + if (result.status !== 0) { + log.warn(`opencode 執行失敗 (${result.status}):${maskSecrets(result.stderr).slice(0, 500)}`); + return null; + } - const parsed = extractResult(result.stdout); - if (!parsed) { - log.warn('無法從 opencode 輸出解析出標題/描述'); - return null; + const parsed = extractResult(result.stdout); + if (!parsed) { + log.warn('無法從 opencode 輸出解析出標題/描述'); + return null; + } + return parsed; + } finally { + // 清理 _writeConfig 建立的暫存設定目錄,避免堆積 + rmSync(dirname(configPath), { recursive: true, force: true }); } - return parsed; } }