Skip to content

Commit 50b651d

Browse files
nadavisclaude
andcommitted
feat: add Gemini AI code review on PRs to main
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4b4e142 commit 50b651d

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

.github/workflows/ai-review.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: AI Code Review
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
jobs:
8+
review:
9+
name: Gemini Code Review
10+
runs-on: ubuntu-latest
11+
# Skip if the PR was opened by the bot itself
12+
if: github.actor != 'github-actions[bot]'
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Install dependencies
18+
run: npm install @google/generative-ai @octokit/rest
19+
20+
- name: Run AI Review
21+
env:
22+
GITHUB_TOKEN: ${{ secrets.AUTO_PR_TOKEN }}
23+
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
24+
PR_NUMBER: ${{ github.event.pull_request.number }}
25+
run: node scripts/ai-review.mjs

scripts/ai-review.mjs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { GoogleGenerativeAI } from "@google/generative-ai";
2+
import { Octokit } from "@octokit/rest";
3+
4+
const prNumber = parseInt(process.env.PR_NUMBER);
5+
const githubToken = process.env.GITHUB_TOKEN;
6+
const [repoOwner, repoName] = (process.env.GITHUB_REPOSITORY || "").split("/");
7+
8+
const octokit = new Octokit({ auth: githubToken });
9+
10+
async function runReview() {
11+
try {
12+
console.log(`Fetching diff for PR #${prNumber}...`);
13+
const { data: prDiff } = await octokit.pulls.get({
14+
owner: repoOwner,
15+
repo: repoName,
16+
pull_number: prNumber,
17+
mediaType: { format: "diff" },
18+
});
19+
20+
if (!prDiff || prDiff.trim().length === 0) {
21+
console.log("Empty diff, skipping review.");
22+
return;
23+
}
24+
25+
const prompt = `You are a senior Python engineer reviewing a pull request for the Node9 Python SDK.
26+
Node9 is an execution security library — a @protect decorator that intercepts AI agent tool calls and asks for human approval before running them.
27+
28+
Review the following git diff and provide concise, actionable feedback. Focus on:
29+
- Correctness and edge cases
30+
- Security issues (this is a security library — be strict)
31+
- API design and usability for developers integrating with LangChain, CrewAI, etc.
32+
- Test coverage gaps
33+
- Anything that could break the daemon HTTP communication
34+
35+
If the changes look good with no issues, say so briefly.
36+
Do NOT rewrite the code. Just review it.
37+
Keep your review under 400 words.
38+
39+
## Git Diff:
40+
${prDiff}`;
41+
42+
console.log("Sending diff to Gemini for review...");
43+
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
44+
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
45+
const result = await model.generateContent([prompt]);
46+
const review = result.response.text();
47+
48+
console.log("Posting review comment...");
49+
await octokit.issues.createComment({
50+
owner: repoOwner,
51+
repo: repoName,
52+
issue_number: prNumber,
53+
body: `## 🤖 Gemini Code Review\n\n${review}\n\n---\n*Automated review by Gemini 2.5 Flash*`,
54+
});
55+
56+
console.log("Review posted successfully.");
57+
} catch (error) {
58+
console.error("Error:", error.message);
59+
process.exit(1);
60+
}
61+
}
62+
63+
runReview();

0 commit comments

Comments
 (0)