diff --git a/action.yml b/action.yml index da3749a..4bbcddc 100644 --- a/action.yml +++ b/action.yml @@ -6,6 +6,9 @@ inputs: repository: description: 'Repository name with owner. For example, actions/checkout' default: ${{ github.repository }} + REVIEW_PULL_REQUEST: + description: 'Whether to compare the records from the beginning of the commit to the latest one; false indicates that only the most recent commit will be reviewed. 是否比对提交开始到最新的记录,false表示只审核最新一次提交审核' + default: false BASE_REF: description: 'github event pull_request base ref' default: ${{ github.event.pull_request.base.ref }} diff --git a/dist/index.js b/dist/index.js index 47949ce..239389f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -10,6 +10,7 @@ const reviewers_prompt = (process.env.INPUT_REVIEWERS_PROMPT || ""); useChinese = language.toLowerCase() === "chinese"; const include_files = (0, utils_1.split_message)(process.env.INPUT_INCLUDE_FILES || ""); const exclude_files = (0, utils_1.split_message)(process.env.INPUT_EXCLUDE_FILES || ""); +const review_pull_request = (!process.env.INPUT_REVIEW_PULL_REQUEST) ? false : (process.env.INPUT_REVIEW_PULL_REQUEST.toLowerCase() === "true"); const system_prompt = reviewers_prompt || (0, prompt_1.take_system_prompt)(prompt_genre, language); // 获取输入参数 const url = process.env.INPUT_HOST; // INPUT_HOST 是从 action.yml 中定义的输入 @@ -53,7 +54,8 @@ async function aiGenerate({ host, token, prompt, model, system }) { header: { 'Authorization': token ? `Bearer ${token}` : "", } }); } -async function aiCheckDiffContext() { +async function getPrDiffContext() { + let items = []; const BASE_REF = process.env.INPUT_BASE_REF; try { (0, node_child_process_1.execSync)(`git fetch origin ${BASE_REF}`, { encoding: 'utf-8' }); @@ -61,9 +63,9 @@ async function aiCheckDiffContext() { const diffOutput = (0, node_child_process_1.execSync)(`git diff --name-only origin/${BASE_REF}...HEAD`, { encoding: 'utf-8' }); let files = diffOutput.trim().split("\n"); for (let key in files) { + // noinspection DuplicatedCode if (!files[key]) continue; - console.log("check diff context:", files[key]); if ((include_files.length > 0) && (!(0, utils_1.doesAnyPatternMatch)(include_files, files[key]))) { console.log("exclude(include):", files[key]); continue; @@ -73,12 +75,61 @@ async function aiCheckDiffContext() { continue; } const fileDiffOutput = (0, node_child_process_1.execSync)(`git diff origin/${BASE_REF}...HEAD -- "${files[key]}"`, { encoding: 'utf-8' }); + items.push({ + path: files[key], + context: fileDiffOutput, + }); + } + } + catch (error) { + console.error('Error executing git diff:', error); + } + return items; +} +async function getHeadDiffContext() { + let items = []; + try { + // exec git diff get diff files + const diffOutput = (0, node_child_process_1.execSync)(`git diff --name-only HEAD^`, { encoding: 'utf-8' }); + let files = diffOutput.trim().split("\n"); + for (let key in files) { + // noinspection DuplicatedCode + if (!files[key]) + continue; + if ((include_files.length > 0) && (!(0, utils_1.doesAnyPatternMatch)(include_files, files[key]))) { + console.log("exclude(include):", files[key]); + continue; + } + else if ((exclude_files.length > 0) && ((0, utils_1.doesAnyPatternMatch)(exclude_files, files[key]))) { + console.log("exclude(exclude):", files[key]); + continue; + } + const fileDiffOutput = (0, node_child_process_1.execSync)(`git diff HEAD^ -- "${files[key]}"`, { encoding: 'utf-8' }); + items.push({ + path: files[key], + context: fileDiffOutput, + }); + } + } + catch (error) { + console.error('Error executing git diff:', error); + } + return items; +} +async function aiCheckDiffContext() { + try { + let commit_sha_url = `${process.env.GITHUB_SERVER_URL}/${process.env.INPUT_REPOSITORY}/src/commit/${process.env.GITHUB_SHA}`; + let items = review_pull_request ? await getPrDiffContext() : await getHeadDiffContext(); + for (let key in items) { + if (!items[key]) + continue; + let item = items[key]; // ai generate try { let response = await aiGenerate({ host: url, token: process.env.INPUT_AI_TOKEN, - prompt: fileDiffOutput, + prompt: item.context, model: model, system: process.env.INPUT_REVIEW_PROMPT }); @@ -96,7 +147,7 @@ async function aiCheckDiffContext() { commit = commit.substring(0, commit.length - 3); } } - let comments = `# ${Review} \r\n${process.env.GITHUB_SERVER_URL}/${process.env.INPUT_REPOSITORY}/src/commit/${process.env.GITHUB_SHA}/${files[key]} \r\n\r\n\r\n${commit}`; + let comments = `# ${Review} \r\n${commit_sha_url}/${item.path} \r\n\r\n\r\n${commit}`; let resp = await pushComments(comments); if (!resp.id) { // noinspection ExceptionCaughtLocallyJS diff --git a/src/index.ts b/src/index.ts index 94530ca..a009656 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ const reviewers_prompt = (process.env.INPUT_REVIEWERS_PROMPT || ""); useChinese = language.toLowerCase() === "chinese" const include_files = split_message(process.env.INPUT_INCLUDE_FILES || ""); const exclude_files = split_message(process.env.INPUT_EXCLUDE_FILES || ""); +const review_pull_request = (!process.env.INPUT_REVIEW_PULL_REQUEST) ? false : (process.env.INPUT_REVIEW_PULL_REQUEST.toLowerCase() === "true") const system_prompt = reviewers_prompt || take_system_prompt(prompt_genre, language); @@ -58,7 +59,8 @@ async function aiGenerate({host, token, prompt, model, system}: any): Promise 0) && (!doesAnyPatternMatch(include_files, files[key]))) { console.log("exclude(include):", files[key]) continue; @@ -77,12 +79,59 @@ async function aiCheckDiffContext() { } const fileDiffOutput = execSync(`git diff origin/${BASE_REF}...HEAD -- "${files[key]}"`, {encoding: 'utf-8'}); + items.push({ + path: files[key], + context: fileDiffOutput, + }) + } + } catch (error) { + console.error('Error executing git diff:', error); + } + return items; +} + +async function getHeadDiffContext() { + let items = []; + try { + // exec git diff get diff files + const diffOutput = execSync(`git diff --name-only HEAD^`, {encoding: 'utf-8'}); + let files = diffOutput.trim().split("\n"); + for (let key in files) { + // noinspection DuplicatedCode + if (!files[key]) continue; + if ((include_files.length > 0) && (!doesAnyPatternMatch(include_files, files[key]))) { + console.log("exclude(include):", files[key]) + continue; + } else if ((exclude_files.length > 0) && (doesAnyPatternMatch(exclude_files, files[key]))) { + console.log("exclude(exclude):", files[key]) + continue; + } + + const fileDiffOutput = execSync(`git diff HEAD^ -- "${files[key]}"`, {encoding: 'utf-8'}); + items.push({ + path: files[key], + context: fileDiffOutput, + }) + } + } catch (error) { + console.error('Error executing git diff:', error); + } + return items; +} + +async function aiCheckDiffContext() { + try { + let commit_sha_url = `${process.env.GITHUB_SERVER_URL}/${process.env.INPUT_REPOSITORY}/src/commit/${process.env.GITHUB_SHA}`; + let items: Array = review_pull_request ? await getPrDiffContext() : await getHeadDiffContext(); + for (let key in items) { + if (!items[key]) continue; + let item = items[key]; // ai generate try { let response = await aiGenerate({ host: url, token: process.env.INPUT_AI_TOKEN, - prompt: fileDiffOutput, + prompt: item.context, model: model, system: process.env.INPUT_REVIEW_PROMPT }) @@ -100,7 +149,7 @@ async function aiCheckDiffContext() { commit = commit.substring(0, commit.length - 3); } } - let comments = `# ${Review} \r\n${process.env.GITHUB_SERVER_URL}/${process.env.INPUT_REPOSITORY}/src/commit/${process.env.GITHUB_SHA}/${files[key]} \r\n\r\n\r\n${commit}` + let comments = `# ${Review} \r\n${commit_sha_url}/${item.path} \r\n\r\n\r\n${commit}` let resp = await pushComments(comments); if (!resp.id) { // noinspection ExceptionCaughtLocallyJS