AI Code Reviewer Template

Workflow

Ready-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:

  1. Bugs: Logic errors, edge cases, potential crashes
  2. Security: Vulnerabilities, unsafe patterns
  3. Performance: Inefficiencies, optimization opportunities
  4. Style: Code style violations, readability issues
  5. 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.

Resources

View on GitHub

Related Templates