Skip to content

WassimAkkacha/code-review-bot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Code Review Bot

A multi-agent PR code review system built with Google ADK (Agent Development Kit) and Gemini 2.5 Flash. It analyzes Git diffs and produces structured, actionable code review reports covering bugs, style violations, security vulnerabilities, and improvement suggestions — all in parallel.


How It Works

The bot implements a Fan-Out / Fan-In multi-agent pipeline:

User Input (raw git diff)
        │
        ▼
┌─────────────────────────────────────────────┐
│         SequentialAgent: CodeReviewPipeline  │
│                                             │
│  Step 1 ── DiffParser (LlmAgent)            │
│             calls parse_github_diff()        │
│             → state["parsed_diff"]           │
│                                             │
│  Step 2 ── ReviewerPanel (ParallelAgent)    │
│             ├── BugDetector     ──────────┐  │
│             ├── StyleChecker    ──────────┤  │
│             ├── SuggestionAgent ──────────┤  │
│             └── SecurityScanner ──────────┘  │
│               (all run simultaneously)       │
│                                             │
│  Step 3 ── Synthesizer (LlmAgent)           │
│             merges all reports              │
│             → structured JSON output        │
└─────────────────────────────────────────────┘
        │
        ▼
ReviewOutput (Pydantic-validated JSON)

Each specialist agent focuses on a single concern and writes to its own state key. The Synthesizer reads all four reports, deduplicates findings, and produces a final ReviewOutput with:

  • An executive summary
  • All findings sorted by severity (critical → warning → info)
  • An approval recommendation (APPROVE / REQUEST_CHANGES / COMMENT)
  • Finding counts by severity

Project Structure

code_review_bot/
├── agent.py                    # ADK entry point — defines root_agent
├── run.py                      # Standalone async runner (for CI/CD or scripting)
├── __init__.py
│
├── agents/
│   ├── bug_detector.py         # Finds logic errors, crashes, resource leaks
│   ├── style_checker.py        # Enforces naming, formatting, PEP 8, etc.
│   ├── suggestion_agent.py     # Proposes idiomatic improvements and DRY fixes
│   ├── security_scanner.py     # Detects SQLi, XSS, hardcoded secrets, OWASP Top 10
│   └── synthesizer.py          # Merges all reports into structured ReviewOutput
│
├── tools/
│   ├── diff_parser.py          # Pure-function git diff parser (no LLM)
│   └── github_client.py        # GitHub API integration (fetch live PR diffs)
│
├── schemas/
│   └── review_models.py        # Pydantic models: ReviewOutput, ReviewFinding, etc.
│
├── callbacks/
│   └── guardrails.py           # Input validation (rejects diffs > 5000 lines)
│
├── tests/
│   ├── test_diff_parser.py     # Unit tests for the diff parser
│   ├── test_agents.py          # Smoke tests for agent wiring and schemas
│   └── fixtures/
│       └── sample_diff.txt     # Sample diff with intentional vulnerabilities
│
├── .env                        # GOOGLE_API_KEY (not committed)
└── pyproject.toml

Prerequisites


Local Setup

1. Clone the repo

git clone https://github.com/your-username/code_review_bot.git
cd code_review_bot

2. Create and activate a virtual environment

python -m venv .venv
source .venv/bin/activate      # macOS/Linux
.venv\Scripts\activate         # Windows

3. Install dependencies

pip install google-adk pydantic python-dotenv requests

4. Add your API key

echo 'GOOGLE_API_KEY=your-gemini-api-key-here' > .env

Get a free key at https://aistudio.google.com/apikey.


Running Locally

Option A — Interactive Web UI (recommended for development)

# From the PARENT directory of code_review_bot/
cd ..
adk web .

Open http://127.0.0.1:8000, select code_review_bot from the dropdown, paste a git diff into the chat, and send.

The UI shows the full agent trace: tool calls, each specialist's response, and the final structured JSON — all in real time.

Option B — CLI (one-shot)

# From inside code_review_bot/
python run.py                    # uses built-in sample diff
python run.py path/to/diff.txt   # review any diff file

Running Tests

# From inside code_review_bot/
python -m pytest tests/ -v
tests/test_diff_parser.py::test_parse_simple_diff       PASSED
tests/test_diff_parser.py::test_parse_multi_file_diff   PASSED
tests/test_diff_parser.py::test_parse_empty_diff        PASSED
tests/test_diff_parser.py::test_parse_language_detection PASSED
tests/test_diff_parser.py::test_parse_unknown_language  PASSED
tests/test_diff_parser.py::test_parse_hunk_lines        PASSED
tests/test_agents.py::test_agent_imports                PASSED
tests/test_agents.py::test_root_agent_wiring            PASSED
tests/test_agents.py::test_diff_parser_has_tool         PASSED
tests/test_agents.py::test_output_keys                  PASSED
tests/test_agents.py::test_review_output_schema         PASSED

Example Output

Input — a diff with SQL injection and a hardcoded secret:

{
  "summary": "This PR introduces two critical security vulnerabilities in the authentication layer: a SQL injection in the login query and a hardcoded JWT secret. Changes should not be merged until both issues are resolved.",
  "findings": [
    {
      "file": "src/auth/login.py",
      "line": 18,
      "severity": "critical",
      "category": "security",
      "title": "SQL Injection (CWE-89)",
      "description": "User input is directly interpolated into a SQL query string. An attacker can manipulate the username field to execute arbitrary SQL.",
      "suggestion": "Use parameterized queries: db.execute('SELECT * FROM users WHERE username = ?', (username,))"
    },
    {
      "file": "src/auth/login.py",
      "line": 20,
      "severity": "critical",
      "category": "security",
      "title": "Hardcoded JWT Secret",
      "description": "The string 'secret123' is used as the JWT signing key. Anyone with access to the source code can forge valid tokens.",
      "suggestion": "Load the secret from an environment variable: os.environ['JWT_SECRET']"
    }
  ],
  "approval_recommendation": "REQUEST_CHANGES",
  "stats": { "critical": 2, "warning": 0, "info": 0 }
}

Key Design Decisions

Decision Rationale
Multi-agent fan-out Each specialist focuses on one concern — better results than one big prompt
Parallel reviewers BugDetector, StyleChecker, SuggestionAgent, SecurityScanner run simultaneously, reducing wall-clock time by ~4x
Deterministic diff parser Parsing is a pure function — no LLM tokens wasted on what regex solves
Pydantic output_schema Guarantees valid, typed JSON from the Synthesizer — no brittle string parsing
output_key as state bus Agents communicate through session.state — no shared globals, no coupling
Guardrail callback Rejects diffs > 5000 lines before any LLM call, capping token usage

Tech Stack

  • Google ADK — multi-agent orchestration (SequentialAgent, ParallelAgent, LlmAgent)
  • Gemini 2.5 Flash — LLM for all agents (fast, cost-efficient)
  • Pydantic v2 — structured output schema and data validation
  • Python 3.11+

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages