Автоматическое код-ревью с AI-агентом

Настройка AI-ревьюера для GitHub PR. Бесплатно, локально, без отправки кода в облако.

📊 Средний⏱ 12 мин

# 1. КАК РАБОТАЕТ AI КОД-РЕВЬЮ

Архитектура проста: GitHub Webhook ловит событие pull_request, скрипт получает diff через GitHub API, разбивает на чанки, прогоняет через локальную LLM (Ollama + llama3), и публикует результаты как комментарий к PR.

# Архитектура AI код-ревью
#
#   GitHub PR ──webhook──▶ GitHub Actions
#                              │
#                    ┌─────────▼──────────┐
#                    │  fetch diff (gh)   │
#                    │  split → chunks    │
#                    │  Ollama llama3     │
#                    │  post review       │
#                    └────────────────────┘
#
# Преимущества: приватность (код не уходит в облако),
# бесплатно (локальная LLM), кастомизируемые правила.

# 2. GITHUB ACTIONS ДЛЯ AI-РЕВЬЮ

Workflow запускается на каждый pull_request. checkout кода, установка gh CLI и Ollama, запуск скрипта ревью и публикация комментария.

# .github/workflows/ai-review.yml
name: AI Code Review
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install gh CLI
        run: |
          type -p curl >/dev/null || sudo apt install curl -y
          curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli.gpg
          sudo apt install gh -y

      - name: Run AI Review
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
        run: python3 scripts/ai_review.py

# 3. СКРИПТ РЕВЬЮ НА PYTHON

Скрипт получает diff PR через gh CLI, разбивает на чанки по 200 строк, отправляет каждый в Ollama с llama3 и собирает результаты.

import subprocess, os, requests, json

def get_pr_diff(pr_number: str) -> str:
    """Получает diff pull request через gh CLI"""
    result = subprocess.run(
        ["gh", "pr", "diff", pr_number],
        capture_output=True, text=True
    )
    return result.stdout

def chunk_diff(diff: str, size: int = 200) -> list:
    """Разбивает diff на чанки по ~200 строк"""
    lines = diff.split('\n')
    return ['\n'.join(lines[i:i+size]) for i in range(0, len(lines), size)]

def review_chunk(chunk: str) -> str:
    """Отправляет чанк в Ollama llama3 для ревью"""
    resp = requests.post("http://localhost:11434/api/generate", json={
        "model": "llama3",
        "prompt": f"Review this diff for bugs, security issues, style:\n{chunk}",
        "stream": False
    })
    return resp.json()["response"]

def post_review(pr_number: str, body: str):
    """Публикует комментарий к PR"""
    subprocess.run(
        ["gh", "pr", "comment", pr_number, "--body", body]
    )

if __name__ == "__main__":
    pr = os.environ["PR_NUMBER"]
    diff = get_pr_diff(pr)
    reviews = [review_chunk(c) for c in chunk_diff(diff)]
    post_review(pr, "## 🤖 AI Review\n" + "\n---\n".join(reviews))

# 4. ПРОВЕРКИ: БЕЗОПАСНОСТЬ, СТИЛЬ, ЛОГИКА

Настройте категории проверок в промпте. AI-ревьюер ищет SQL-инъекции, XSS, утечки секретов, нарушения код-стиля и логические ошибки.

# Системный промпт для AI-ревьюера
SYSTEM_PROMPT = """
Ты — senior разработчик на код-ревью. Проверяй diff по категориям:

🔒 БЕЗОПАСНОСТЬ:
- SQL-инъекции (конкатенация строк в запросах)
- XSS (неэкранированный пользовательский ввод)
- Секреты в коде (ключи API, пароли, токены)
- Path traversal (../../etc/passwd)

📐 СТИЛЬ:
- Имена переменных (должны быть осмысленными)
- Длина функций (> 50 строк — предлагай разбить)
- Комментарии к сложной логике

⚡ ПРОИЗВОДИТЕЛЬНОСТЬ:
- N+1 запросы в циклах
- Неоптимальные структуры данных
- Отсутствие кэширования

🧠 ЛОГИКА:
- Неинициализированные переменные
- Off-by-one ошибки
- Неправильная обработка граничных случаев

Формат ответа:
### 🔒 Security
- проблема → решение

### 📐 Style
- проблема → решение
"""

# 5. ИНТЕГРАЦИЯ С CURSOR/COPILOT

Альтернативный подход — ревью прямо в редакторе. Cursor Rules + pre-commit hook позволяют проверять код до коммита, не дожидаясь CI.

# .cursor/rules/review.md — Cursor Rules для авто-ревью
Ты делаешь код-ревью каждого изменения. Проверяй:
1. Безопасность: нет секретов, инъекций, path traversal
2. Стиль: PEP8, осмысленные имена, функции < 50 строк
3. Тесты: новый код должен быть покрыт тестами
4. Документация: публичные функции с docstring

# .git/hooks/pre-commit — AI pre-commit hook
#!/bin/bash
# Запускает AI-ревью на staged изменения
FILES=$(git diff --cached --name-only)
if [ -n "$FILES" ]; then
    git diff --cached | python3 scripts/quick_review.py
fi

# 6. АВТОМАТИЧЕСКОЕ ИСПРАВЛЕНИЕ

Агент не только находит проблемы, но и генерирует patch-файлы с исправлениями. GitHub Actions может автоматически применить их и создать коммит.

def generate_fix(issue: str, code: str) -> str:
    """Генерирует исправление через LLM и возвращает unified diff"""
    resp = requests.post("http://localhost:11434/api/generate", json={
        "model": "llama3",
        "prompt": f"""Fix this issue:\n{issue}\n\nCode:\n{code}\n\nReturn ONLY a unified diff patch.""",
        "stream": False
    })
    return resp.json()["response"]

# GitHub Actions: авто-исправление + коммит
# patch_file=$(python3 scripts/generate_fix.py)
# git apply patch_file
# git commit -am "🤖 Auto-fix by AI Reviewer"
# git push

# Важно: авто-исправления только для категорий Style и Performance,
# Security issues требуют ручного ревью разработчика.

🔗 Полезные ссылки

⚡ GitHub Actions🦙 Ollama💻 gh CLI📋 Cursor Rules