AI Code Reviewer Template
WorkflowReady-to-deploy AI code reviewer with GitHub Actions integration.
AI Code Reviewer Template
Overview
This template provides a ready-to-deploy AI code reviewer that integrates with GitHub Actions. It automatically reviews pull requests, identifies potential issues, and provides actionable feedback.
The AI Code Reviewer combines static analysis, code quality checks, and security scanning to provide comprehensive code review feedback. It helps catch issues early and maintains code quality standards.
Prerequisites
- GitHub repository with pull requests
- Claude API key or OpenAI API key
- Basic GitHub Actions knowledge
Features
- Automated PR Reviews: Runs on every pull request
- Multi-Dimensional Analysis: Style, bugs, security, performance
- Actionable Feedback: Specific line-level suggestions
- Configurable Rules: Customize what to check
- Comment Integration: Posts reviews directly on PRs
Project Structure
ai-code-reviewer/
├── .github/
│ └── workflows/
│ └── code-review.yml # GitHub Actions workflow
├── reviewer/
│ ├── __init__.py
│ ├── analyzer.py # Code analysis logic
│ ├── security.py # Security checks
│ ├── style.py # Style checks
│ └── reporter.py # Report generation
├── config/
│ └── rules.yaml # Review rules configuration
├── requirements.txt
└── README.md
GitHub Actions Workflow
.github/workflows/code-review.yml:
name: AI Code Review
on:
pull_request:
types: [opened, synchronize, reopened]
pull_request_review_comment:
types: [created]
permissions:
contents: read
pull-requests: write
jobs:
code-review:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install openai PyGithub
- name: Run AI Code Review
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
python reviewer/main.py
- name: Post Review Comments
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python reviewer/post_comments.py
Core Reviewer Implementation
Main Entry Point
reviewer/main.py:
import os
import subprocess
import json
from openai import OpenAI
from github import Github
class AICodeReviewer:
def __init__(self):
self.client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
self.github = Github(os.environ["GITHUB_TOKEN"])
self.repo = self.github.get_repo(os.environ["REPO"])
self.pr_number = int(os.environ["PR_NUMBER"])
def get_pr_diff(self):
"""Get the diff of the PR."""
pr = self.repo.get_pull(self.pr_number)
files = pr.get_files()
diff = []
for file in files:
if file.status != 'removed':
diff.append({
'filename': file.filename,
'patch': file.patch,
'additions': file.additions,
'deletions': file.deletions,
})
return diff
def analyze_file(self, filename: str, diff: str, language: str):
"""Analyze a single file for issues."""
prompt = f"""You are an expert code reviewer. Analyze the following code changes and identify issues.
File: {filename}
Language: {language}
Changes:
```diff
{diff}
Please analyze and report:
- Bugs: Logic errors, edge cases, potential crashes
- Security: Vulnerabilities, unsafe patterns
- Performance: Inefficiencies, optimization opportunities
- Style: Code style violations, readability issues
- Best Practices: Missing error handling, poor abstractions
For each issue, provide:
- Line number (approximate)
- Severity (high/medium/low)
- Description
- Suggested fix
Format your response as JSON:
{{
"issues": [
{{
"line": <number>,
"severity": "high|medium|low",
"category": "bug|security|performance|style|best-practice",
"description": "<description>",
"suggestion": "<suggested fix>"
}}
]
}}
```"""
response = self.client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are an expert code reviewer."},
{"role": "user", "content": prompt},
],
response_format={"type": "json_object"},
)
return json.loads(response.choices[0].message.content)
def run_review(self):
"""Run the full review process."""
diff = self.get_pr_diff()
all_issues = []
for file in diff:
# Detect language
language = self.detect_language(file['filename'])
# Analyze file
result = self.analyze_file(
file['filename'],
file['patch'],
language
)
# Add filename to issues
for issue in result.get('issues', []):
issue['filename'] = file['filename']
all_issues.append(issue)
return all_issues
def detect_language(self, filename: str):
"""Detect programming language from filename."""
ext = filename.split('.')[-1].lower()
lang_map = {
'py': 'Python',
'js': 'JavaScript',
'ts': 'TypeScript',
'jsx': 'JavaScript/React',
'tsx': 'TypeScript/React',
'go': 'Go',
'rs': 'Rust',
'java': 'Java',
'cpp': 'C++',
'c': 'C',
'rb': 'Ruby',
'php': 'PHP',
'sql': 'SQL',
'html': 'HTML',
'css': 'CSS',
'md': 'Markdown',
'yaml': 'YAML',
'json': 'JSON',
}
return lang_map.get(ext, 'Unknown')
def generate_summary(self, issues: list):
"""Generate a summary of the review."""
high = len([i for i in issues if i['severity'] == 'high'])
medium = len([i for i in issues if i['severity'] == 'medium'])
low = len([i for i in issues if i['severity'] == 'low'])
categories = {}
for issue in issues:
cat = issue['category']
categories[cat] = categories.get(cat, 0) + 1
return {
'total_issues': len(issues),
'high': high,
'medium': medium,
'low': low,
'by_category': categories,
}
if __name__ == "__main__":
reviewer = AICodeReviewer()
issues = reviewer.run_review()
summary = reviewer.generate_summary(issues)
# Save results
with open('review_results.json', 'w') as f:
json.dump({'issues': issues, 'summary': summary}, f, indent=2)
print(f"Found {len(issues)} issues")
print(f"High: {summary['high']}, Medium: {summary['medium']}, Low: {summary['low']}")
Post Comments to PR
reviewer/post_comments.py:
import os
import json
from github import Github
def post_review_comments():
github = Github(os.environ["GITHUB_TOKEN"])
repo = github.get_repo(os.environ["REPO"])
pr_number = int(os.environ["PR_NUMBER"])
pr = repo.get_pull(pr_number)
# Load review results
with open('review_results.json', 'r') as f:
results = json.load(f)
issues = results['issues']
summary = results['summary']
# Post summary comment
summary_body = f"""## 🤖 AI Code Review Summary
**Total Issues Found:** {summary['total_issues']}
| Severity | Count |
|----------|-------|
| 🔴 High | {summary['high']} |
| 🟡 Medium | {summary['medium']} |
| 🟢 Low | {summary['low']} |
### Issues by Category
| Category | Count |
|----------|-------|
"""
for cat, count in summary['by_category'].items():
summary_body += f"| {cat} | {count} |\n"
summary_body += """
---
*This review was generated automatically by AI. Please verify all suggestions before applying.*
"""
pr.create_issue_comment(summary_body)
# Post individual comments on lines
for issue in issues:
if issue['severity'] == 'high':
pr.create_issue_comment(
f"**🔴 {issue['category'].upper()} in `{issue['filename']}`**\n\n"
f"{issue['description']}\n\n"
f"**Suggestion:** {issue['suggestion']}"
)
if __name__ == "__main__":
post_review_comments()
Configuration
config/rules.yaml:
# AI Code Reviewer Configuration
rules:
# Bug detection
bugs:
enabled: true
severity: high
checks:
- null_pointer_dereference
- off_by_one
- unhandled_exceptions
- race_conditions
# Security checks
security:
enabled: true
severity: high
checks:
- sql_injection
- xss
- command_injection
- hardcoded_secrets
- insecure_dependencies
# Performance
performance:
enabled: true
severity: medium
checks:
- n_plus_one_queries
- inefficient_loops
- missing_indexes
- large_allocations
# Style
style:
enabled: true
severity: low
checks:
- naming_conventions
- code_organization
- documentation
- complexity
# Best practices
best_practices:
enabled: true
severity: medium
checks:
- error_handling
- resource_cleanup
- type_safety
- immutability
# Language-specific rules
languages:
python:
additional_checks:
- pep8_compliance
- type_hints
- docstrings
typescript:
additional_checks:
- strict_mode
- interface_usage
- null_checks
# Ignored files
ignore:
- "*.test.*"
- "*.spec.*"
- "node_modules/**"
- "dist/**"
- "build/**"
- "*.min.js"
Setup
1. Add Secrets to GitHub
Go to your repository Settings → Secrets and variables → Actions:
OPENAI_API_KEY: Your OpenAI API key- Or
ANTHROPIC_API_KEY: Your Anthropic API key
2. Install Dependencies
pip install openai PyGithub pyyaml
3. Run Locally (Testing)
# Set environment variables
export OPENAI_API_KEY="sk-..."
export GITHUB_TOKEN="ghp_..."
export PR_NUMBER="123"
export REPO="owner/repo"
# Run review
python reviewer/main.py
# Post comments
python reviewer/post_comments.py
Customization
Add Custom Checks
Edit reviewer/analyzer.py to add custom analysis logic:
def check_custom_pattern(code: str) -> list:
"""Add your custom checks here."""
issues = []
# Example: Check for deprecated API usage
if "deprecated_function()" in code:
issues.append({
"line": 1,
"severity": "medium",
"category": "best-practice",
"description": "Using deprecated function",
"suggestion": "Use new_function() instead",
})
return issues
Adjust Review Aggressiveness
Edit config/rules.yaml to enable/disable specific checks or adjust severity levels.
