Add a limit for file number, improve the C# handling

This commit is contained in:
Alejandro Ramirez 2024-11-25 12:43:31 -05:00
parent a9a064dfa1
commit 9c6f0593c9
4 changed files with 90 additions and 15 deletions

View file

@ -20,6 +20,7 @@
"ts-node": "^10.9.1"
},
"devDependencies": {
"@types/minimatch": "^5.1.2",
"@types/node": "^18.15.5",
"@vercel/ncc": "^0.36.1",
"prettier": "^2.8.6",

View file

@ -2,12 +2,13 @@ import { readFileSync } from "fs";
import * as core from "@actions/core";
import OpenAI from "openai";
import { Octokit } from "@octokit/rest";
import parseDiff, { Chunk, File } from "parse-diff";
import parseDiff, { Chunk, File, Change } from "parse-diff";
import minimatch from "minimatch";
const GITHUB_TOKEN: string = core.getInput("GITHUB_TOKEN");
const OPENAI_API_KEY: string = core.getInput("OPENAI_API_KEY");
const OPENAI_API_MODEL: string = core.getInput("OPENAI_API_MODEL");
const MAX_FILES: number = 25;
const octokit = new Octokit({ auth: GITHUB_TOKEN });
@ -46,14 +47,36 @@ async function getDiff(
repo: string,
pull_number: number
): Promise<string | null> {
const response = await octokit.pulls.get({
owner,
repo,
pull_number,
mediaType: { format: "diff" },
});
// @ts-expect-error - response.data is a string
return response.data;
try {
const response = await octokit.request('GET /repos/{owner}/{repo}/pulls/{pull_number}', {
owner,
repo,
pull_number,
mediaType: {
format: 'diff',
},
});
return response.data as unknown as string;
} catch (error) {
console.error('Error fetching diff:', error);
return null;
}
}
function getLanguageContext(filename: string): string {
if (filename.endsWith('.cs')) {
return `This is a C# file using .NET 8 features. Consider the following when reviewing:
- C# 12 features like primary constructors, collection expressions, and inline arrays
- .NET 8 features including native AOT compilation considerations
- Performance implications and best practices
- Dependency injection patterns
- Async/await usage
- SOLID principles
- Nullable reference types
- Record types and pattern matching
- Memory management and disposable resources`;
}
return '';
}
async function analyzeCode(
@ -62,7 +85,16 @@ async function analyzeCode(
): Promise<Array<{ body: string; path: string; line: number }>> {
const comments: Array<{ body: string; path: string; line: number }> = [];
for (const file of parsedDiff) {
// If there are more than MAX_FILES, only process the first MAX_FILES
const filesToProcess = parsedDiff.length > MAX_FILES
? parsedDiff.slice(0, MAX_FILES)
: parsedDiff;
if (parsedDiff.length > MAX_FILES) {
console.log(`Pull request contains ${parsedDiff.length} files. Processing only the first ${MAX_FILES} files.`);
}
for (const file of filesToProcess) {
if (file.to === "/dev/null") continue; // Ignore deleted files
for (const chunk of file.chunks) {
const prompt = createPrompt(file, chunk, prDetails);
@ -79,6 +111,8 @@ async function analyzeCode(
}
function createPrompt(file: File, chunk: Chunk, prDetails: PRDetails): string {
const languageContext = getLanguageContext(file.to || '');
return `Your task is to review pull requests. Instructions:
- Provide the response in following JSON format: {"reviews": [{"lineNumber": <line_number>, "reviewComment": "<review comment>"}]}
- Do not give positive comments or compliments.
@ -87,6 +121,8 @@ function createPrompt(file: File, chunk: Chunk, prDetails: PRDetails): string {
- Use the given description only for the overall context and only comment the code.
- IMPORTANT: NEVER suggest adding comments to the code.
${languageContext}
Review the following code diff in the file "${
file.to
}" and take the pull request title and description into account when writing the response.
@ -103,8 +139,7 @@ Git diff to review:
\`\`\`diff
${chunk.content}
${chunk.changes
// @ts-expect-error - ln and ln2 exists where needed
.map((c) => `${c.ln ? c.ln : c.ln2} ${c.content}`)
.map((c: Change) => `${c.ln ? c.ln : c.ln2} ${c.content}`)
.join("\n")}
\`\`\`
`;
@ -224,10 +259,10 @@ async function main() {
const excludePatterns = core
.getInput("exclude")
.split(",")
.map((s) => s.trim());
.map((s: string) => s.trim());
const filteredDiff = parsedDiff.filter((file) => {
return !excludePatterns.some((pattern) =>
const filteredDiff = parsedDiff.filter((file: File) => {
return !excludePatterns.some((pattern: string) =>
minimatch(file.to ?? "", pattern)
);
});

34
src/types/parse-diff.d.ts vendored Normal file
View file

@ -0,0 +1,34 @@
declare module 'parse-diff' {
export interface Change {
type: string;
content: string;
ln?: number;
ln2?: number;
normal?: boolean;
add?: boolean;
del?: boolean;
}
export interface Chunk {
content: string;
changes: Change[];
oldStart: number;
oldLines: number;
newStart: number;
newLines: number;
}
export interface File {
chunks: Chunk[];
deletions: number;
additions: number;
from: string;
to: string;
index: string[];
binary?: boolean;
new?: boolean;
deleted?: boolean;
}
export default function parseDiff(diff: string): File[];
}

View file

@ -163,6 +163,11 @@
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e"
integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==
"@types/minimatch@^5.1.2":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
"@types/node-fetch@^2.6.4":
version "2.6.9"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.9.tgz#15f529d247f1ede1824f7e7acdaa192d5f28071e"