feat(ai-code-review): 新增 AI 多角色 code review action(攻防審查、findings 保存、建問題模式)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
6a0573b7c0
commit
d08b97bd87
@@ -0,0 +1,111 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* 彙整本次 action 執行的上下文:讀取 runner 注入的 GITHUB_* 執行期環境變數、
|
||||
* INPUT_* 輸入參數與事件 payload 檔(GITHUB_EVENT_PATH),組出後續呼叫
|
||||
* Gitea API 與執行 AI review 所需的全部資訊。
|
||||
*
|
||||
* 事件 payload 不存在或 JSON 壞損時以空物件續行、不拋錯,
|
||||
* 由呼叫端檢查 prNumber 是否為 null 判斷是否處於 PR 情境。
|
||||
*
|
||||
* @returns {{
|
||||
* serverUrl: string,
|
||||
* repository: string,
|
||||
* owner: string,
|
||||
* repo: string,
|
||||
* apiBase: string,
|
||||
* token: string,
|
||||
* model: string,
|
||||
* createIssue: boolean,
|
||||
* event: Object,
|
||||
* pr: (Object|null),
|
||||
* prNumber: (number|null),
|
||||
* prTitle: string,
|
||||
* prBody: string,
|
||||
* baseRef: string,
|
||||
* headRef: string,
|
||||
* headSha: string,
|
||||
* runId: string,
|
||||
* runNumber: string,
|
||||
* workspace: string,
|
||||
* actionPath: string
|
||||
* }} 執行上下文物件:
|
||||
* - serverUrl:Gitea 伺服器網址(GITHUB_SERVER_URL,已去除尾端斜線)。
|
||||
* - repository:`owner/repo` 全名(GITHUB_REPOSITORY)。
|
||||
* - owner / repo:自 repository 拆出的擁有者與專案名,缺值時為空字串。
|
||||
* - apiBase:Gitea REST API 基底網址(`<serverUrl>/api/v1`)。
|
||||
* - token:action input `token`(INPUT_TOKEN),用於 API 認證,缺值時為空字串。
|
||||
* - model:action input `model`(INPUT_MODEL,已 trim),指定 AI 模型,缺值時為空字串。
|
||||
* - createIssue:action input `create-issue`(INPUT_CREATE-ISSUE),是否將問題建到
|
||||
* 存取庫的問題追蹤(建問題模式);trim + 小寫後與字串 'true' 嚴格比對,預設 false。
|
||||
* - event:事件 payload 解析後的完整物件;讀取失敗時為空物件。
|
||||
* - pr:payload 內的 pull_request 物件;非 PR 事件時為 null。
|
||||
* - prNumber:PR 編號,優先取 payload,退而從 GITHUB_REF(refs/pull/N/...)解析;皆無時為 null。
|
||||
* - prTitle / prBody:PR 標題與描述(缺省或非 PR 情境時為空字串);
|
||||
* 建問題模式下作為新 issue 的標題與本文素材。
|
||||
* - baseRef / headRef:PR 的目標/來源分支名;非 PR 情境時為空字串。
|
||||
* - headSha:來源分支最新 commit SHA,優先取 payload,退而 GITHUB_SHA。
|
||||
* - runId / runNumber:本次 workflow 執行識別(GITHUB_RUN_ID / GITHUB_RUN_NUMBER)。
|
||||
* - workspace:工作目錄(GITHUB_WORKSPACE,退而 process.cwd())。
|
||||
* - actionPath:action 根目錄(GITHUB_ACTION_PATH,退而以原始碼位置推算),
|
||||
* 用於定位 action 自帶檔案(如角色提示),不依賴呼叫端工作目錄。
|
||||
*
|
||||
* @remarks
|
||||
* 使用情境:action 主程式(src/index.js)啟動時最先呼叫一次,
|
||||
* 取得上下文後傳遞給後續各模組使用。前置條件:需在 Gitea / GitHub Actions
|
||||
* runner 環境下執行(GITHUB_* 環境變數已注入);於本機直接執行時所有欄位
|
||||
* 退回預設值(空字串 / null / process.cwd()),不會拋錯。呼叫端應先檢查
|
||||
* prNumber 與 token 是否有值再進行 PR review 流程。注意:若 payload 含
|
||||
* pull_request 但缺 base/head 結構,讀取 baseRef/headRef 時會拋 TypeError。
|
||||
*/
|
||||
function loadContext() {
|
||||
const serverUrl = (process.env.GITHUB_SERVER_URL || '').replace(/\/+$/, '');
|
||||
const repository = process.env.GITHUB_REPOSITORY || '';
|
||||
const [owner = '', repo = ''] = repository.split('/');
|
||||
|
||||
// 讀取事件 payload(pull_request 事件時含 PR 完整資訊)。
|
||||
let event = {};
|
||||
const eventPath = process.env.GITHUB_EVENT_PATH;
|
||||
if (eventPath && fs.existsSync(eventPath)) {
|
||||
try {
|
||||
event = JSON.parse(fs.readFileSync(eventPath, 'utf8'));
|
||||
} catch {
|
||||
event = {}; // payload 壞損時以空物件續行,由呼叫端檢查 prNumber
|
||||
}
|
||||
}
|
||||
const pr = event.pull_request || null;
|
||||
|
||||
// PR 編號:優先取 payload,退而從 GITHUB_REF(refs/pull/N/...)解析。
|
||||
const refMatch = /refs\/pull\/(\d+)\//.exec(process.env.GITHUB_REF || '');
|
||||
const prNumber = (pr && pr.number) || (refMatch ? Number(refMatch[1]) : null);
|
||||
|
||||
return {
|
||||
serverUrl,
|
||||
repository,
|
||||
owner,
|
||||
repo,
|
||||
apiBase: `${serverUrl}/api/v1`,
|
||||
token: process.env.INPUT_TOKEN || '',
|
||||
model: (process.env.INPUT_MODEL || '').trim(),
|
||||
// 是否將問題建到存取庫的問題追蹤(input: create-issue,字串 'true' 才啟用,預設否)。
|
||||
createIssue: (process.env['INPUT_CREATE-ISSUE'] || '').trim().toLowerCase() === 'true',
|
||||
event,
|
||||
pr,
|
||||
prNumber,
|
||||
prTitle: pr ? pr.title || '' : '',
|
||||
prBody: pr ? pr.body || '' : '',
|
||||
baseRef: pr ? pr.base.ref : '',
|
||||
headRef: pr ? pr.head.ref : '',
|
||||
headSha: (pr && pr.head.sha) || process.env.GITHUB_SHA || '',
|
||||
runId: process.env.GITHUB_RUN_ID || '',
|
||||
runNumber: process.env.GITHUB_RUN_NUMBER || '',
|
||||
workspace: process.env.GITHUB_WORKSPACE || process.cwd(),
|
||||
// action 自帶檔案(角色提示等)以 action 根目錄定位,不依賴呼叫端工作目錄。
|
||||
actionPath: process.env.GITHUB_ACTION_PATH || path.resolve(__dirname, '..', '..'),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { loadContext };
|
||||
Reference in New Issue
Block a user