Модуль 2.9 · Урок 2
Урок 2: Code Review с агентом
Содержание
- Чему вы научитесь
- Проблема: человеческие ревьюеры переутомлены
- Готовые AI-инструменты для code review (2025-2026)
- Часть 1: Что может проверять агент
- Таблица: AI vs Human
- Что НЕ может агент
- Часть 2: Настройка автоматического pre-review
- Вариант 1: Git Hook (локально)
- Вариант 2: GitHub Actions (в CI)
- Часть 3: Эффективные промпты для review
- Шаблон базовый
- Шаблон с контекстом (лучше)
- Пример: Реальный код с проблемами
- Баги
- [!] Data Leakage
- [+] Что хорошо
- Рекомендации
- Checklist для интеграции
- Антипаттерн: Слепое доверие к AI
- Попробуйте сами
- Ключевые выводы
- Следующий урок
Чему вы научитесь
- Использовать AI для автоматического pre-review PR
- Определять, что может проверять агент, а что — только человек
- Настраивать git hooks для автоматического ревью перед коммитом
- Создавать эффективные промпты для code review
- Интегрировать AI review в CI/CD pipeline
Проблема: человеческие ревьюеры переутомлены
Типичный день ревьюера:
- 20 PR в очереди
- Каждый PR — 200-500 строк кода
- Нужно искать баги, уязвимости, нарушения стиля, проблемы производительности
- Результат: поверхностный ревью, баги проходят в продакшн
Решение: AI pre-review находит 70-80% проблем до human review. Ревьюер может сосредоточиться на архитектуре и бизнес-логике.
Готовые AI-инструменты для code review (2025-2026)
| Инструмент | Тип | Что умеет |
|---|---|---|
| CodeRabbit | GitHub/GitLab app | Авто-ревью PR, walkthrough summary, line-by-line suggestions. Бесплатный тир есть (с лимитами). |
| Sourcery | GitHub app / VS Code | Focused code review, меньше шума, on-prem вариант |
| Claude Code | CLI | Встроенный ревью через pre-commit hooks или вручную |
| GitHub Copilot | IDE + GitHub | Inline suggestions и agent-powered code review для PR. |
Команды сообщают о значительном снижении времени на ручное ревью при использовании CodeRabbit.
Ниже показано, как настроить собственный AI-ревью через Claude Code (без внешних сервисов).
graph LR
A["Разработчик<br/>открывает PR"] -->|git push| B["[AI] Claude AI<br/>pre-review"]
B -->|находит 70% проблем| C["Комментарий с<br/>проблемами"]
C -->|dev исправляет| D["Human reviewer<br/>проверяет<br/>архитектуру"]
D -->|[+] одобрено| E["Merge to main"]
Часть 1: Что может проверять агент
Таблица: AI vs Human
| Категория | AI может | Human проверяет | Примечание |
|---|---|---|---|
| Синтаксис/нарушения стиля | [+] 100% | — | Автоматически находит все |
| Потенциальные баги | [+] 80% | [+] Финальная проверка | Может пропустить edge cases |
| Уязвимости безопасности | [+] 70% | [+] Обязательно | SQL injection, XSS, etc. |
| Производительность O(n) | [+] 90% | [+] Обсуждение | Может предложить улучшение |
| Мёртвый код | [+] 95% | [+] Иногда | Unused imports, переменные |
| Тесты достаточны | [+] 60% | [+] Критично | Может не понять coverage intent |
| Бизнес-логика верна | [-] 0% | [+] 100% | Требует контекста продакта |
| Архитектурное решение | [-] 10% | [+] 100% | Нужна история проекта |
| API согласованность | [+] 85% | [+] Иногда | Может найти breaking changes |
| Документация полна | [+] 80% | [+] Финально | Может предложить дополнения |
Что НЕ может агент
- Бизнес-требования: “Эта функция решает задачу X продакта?” — только человек
- Архитектурные решения: “Должна ли это быть microservice?” — только человек
- Trade-off’ы: “Скорость vs надёжность” — только человек с контекстом
- Историческое знание: “Почему мы не используем Y?” — нужна память проекта
- UX/DX интеграция: “Будет ли это удобно для фронтенда?” — нужно обсуждение
Часть 2: Настройка автоматического pre-review
Вариант 1: Git Hook (локально)
Файл .git/hooks/pre-commit:
#!/bin/bash
# pre-commit hook для автоматического review перед коммитом
echo "[AI] Запуск AI-review перед коммитом..."
# Получаем список изменённых файлов
CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
if [ -z "$CHANGED_FILES" ]; then
echo "[-] Нет файлов для коммита"
exit 1
fi
# Создаём diff для review
DIFF=$(git diff --cached)
# Вызываем Claude Code для review
claude "Проведи code review для следующего diff:
$DIFF
Проверь на:
1. Синтаксические ошибки
2. Потенциальные баги (null checks, edge cases)
3. Уязвимости безопасности (injection, XSS)
4. Нарушения стиля (PEP8, ESLint)
5. Мёртвый код (unused imports, variables)
6. Проблемы производительности (N+1 queries, O(n²))
Формат ответа:
## Баги найдены: [ДА/НЕТ]
[список с line numbers]
## Уязвимости: [ВЫСОКИЙ/СРЕДНИЙ/НИЗ/НЕТ]
[список]
## [+] Хороший код: [1-3 примера]
## Рекомендации: [1-3 пункта]" > /tmp/review.txt
# Показываем результат
cat /tmp/review.txt
# Если нашлись критические проблемы, останавливаем commit
if grep -q "ВЫСОКИЙ" /tmp/review.txt; then
echo ""
echo "[!] Найдены проблемы безопасности ВЫСОКОГО уровня."
echo "Исправьте перед коммитом или используйте --no-verify для пропуска."
exit 1
fi
exit 0
Установка:
chmod +x .git/hooks/pre-commit
Вариант 2: GitHub Actions (в CI)
Файл .github/workflows/ai-review.yml:
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
ai-review:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get PR diff
id: diff
run: |
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr-branch
git diff origin/main...pr-branch > /tmp/pr.diff
- name: Run Claude AI Review
env:
CLAUDE_API_KEY: ${{ secrets.CLAUDE_API_KEY }}
run: |
# Здесь вызов Claude через API или CLI
claude "Проверь этот PR diff на баги, уязвимости, стиль..." > /tmp/review.md
- name: Post review as comment
uses: actions/github-script@v9
with:
script: |
const fs = require('fs');
const review = fs.readFileSync('/tmp/review.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## [AI] AI Code Review\n\n${review}`
});
Часть 3: Эффективные промпты для review
Шаблон базовый
Проведи code review для этого фрагмента кода:
[КОД]
Фокусируйся на:
1. Безопасность
2. Производительность
3. Читаемость
4. Тестируемость
Формат:
- Баги: [список или "не найдено"]
- Уязвимости: [или "не найдено"]
- Производительность: [или "окей"]
- [+] Что хорошо: [1-2 примера]
Шаблон с контекстом (лучше)
Код ревью для PR #123: "Добавить кэширование в getUserData"
КОНТЕКСТ:
- Это legacy REST API, мигрируем на GraphQL
- Пики трафика: 10k req/sec в часы пик
- DB response time: 200ms в среднем
- Кэш TTL: 5 минут
КОД:
[КОД]
Проверь на:
1. Race conditions (кэш vs DB)
2. Cache invalidation правильность
3. Memory leak'и при большом кэше
4. Security (утечка приватных данных через кэш)
Приоритет: безопасность > производительность > чистота кода
Пример: Реальный код с проблемами
Файл user_service.py:
# Плохой код для review
user_cache = {}
def get_user(user_id):
"""Получить пользователя по ID"""
# BUG #1: нет проверки user_id на валидность
if user_id in user_cache:
return user_cache[user_id]
# BUG #2: нет обработки ошибок DB
db = Database()
user = db.query(f"SELECT * FROM users WHERE id = {user_id}")
# BUG #3: SQL injection!
# BUG #4: неограниченный рост кэша (memory leak)
user_cache[user_id] = user
# BUG #5: возвращаем весь объект, включая пароль
return user
def update_user(user_id, data):
"""Обновить пользователя"""
# BUG #6: не инвалидируем кэш после обновления
db = Database()
db.query(f"UPDATE users SET ... WHERE id = {user_id}")
Хороший ревью от Claude:
## [AI] AI Code Review
### Уязвимости: КРИТИЧЕСКИЙ
1. **SQL Injection (строка 13)** — прямое подставление user_id в SQL
```python
# [-] ОПАСНО
user = db.query(f"SELECT * FROM users WHERE id = {user_id}")
# [+] ИСПРАВИТЬ
user = db.query("SELECT * FROM users WHERE id = ?", (user_id,))
Баги
-
Memory leak в кэше — неограниченный рост
user_cache# [-] НЕПРАВИЛЬНО user_cache[user_id] = user # Растёт бесконечно # [+] ИСПРАВИТЬ - используй LRU cache from functools import lru_cache @lru_cache(maxsize=10000) def get_user(user_id): ... -
Несогласованность кэша — при update_user кэш не инвалидируется
# РАНЬШЕ: update_user не чистит кэш # ТЕПЕРЬ: после обновления нужно user_cache.pop(user_id, None) -
Нет проверки валидности — user_id может быть None или string
# [+] ДОБАВИТЬ if not isinstance(user_id, int) or user_id <= 0: raise ValueError(f"Invalid user_id: {user_id}")
[!] Data Leakage
На строке 20 возвращаем весь объект user, включая пароль:
# [-] НЕПРАВИЛЬНО
return user # Содержит user['password']!
# [+] ИСПРАВИТЬ
return {k: v for k, v in user.items() if k != 'password'}
[+] Что хорошо
- Попытка использовать кэш (идея правильная)
- Отдельные функции для get и update (разделение ответственности)
Рекомендации
- Перевести на
lru_cacheизfunctools - Использовать parameterized queries везде
- Добавить логирование при cache miss (для мониторинга)
- Написать unit-тесты для cache invalidation
## Часть 4: Интеграция в workflow команды
### Сценарий: день ревьюера с AI
```mermaid
flowchart LR
A["09:00 PR"] --> B["09:01 AI-review"]
B --> C["09:03 Исправления"]
C --> D["09:05 Re-check"]
D --> E["09:30 Human review"]
E --> F["09:35 Merge"]
09:00 - Dev открывает PR #250
↓
09:01 - CI запускает AI-review (1 сек)
↓
09:02 - Claude оставляет комментарий:
"Найдена уязвимость: SQL injection на строке 45"
↓
09:03 - Dev видит комментарий, исправляет код
↓
09:05 - Dev пушит изменения, AI-review запускается снова
↓
09:06 - AI: "[+] SQL injection исправлена. Осталось добавить тесты."
↓
09:30 - Human reviewer смотрит PR:
- Синтаксис? [+] (проверил AI)
- Безопасность? [+] (проверил AI)
- Бизнес-логика? [+] (проверяет human)
- Архитектура? [+] (проверяет human)
↓
09:35 - Одобрено и merged
Checklist для интеграции
- Установлен git hook
pre-commitили GitHub Actions - Настроены критические уровни (CRITICAL, HIGH) для блокировки
- AI-review комментарии не скрывают human-comments
- Ревьюеры обучены: AI находит баги, они решают — архитектура
- Метрики отслеживаются: % PR с AI-comments, % issues найденных AI
Антипаттерн: Слепое доверие к AI
[-] Неправильно:
# AI сказал "всё ок" → merge without human review
if ai_review == "no issues":
merge_to_main() # ОПАСНО!
[+] Правильно:
AI-review находит тактические проблемы (баги, уязвимости)
Human-review проверяет стратегические проблемы (архитектура, бизнес)
Попробуйте сами
Задача: Настроить AI-review для своего репозитория.
-
Вариант 1 (быстро): Установить git hook:
chmod +x .git/hooks/pre-commit git add -A && git commit -m "test: trigger AI review" # Посмотреть результат в терминале -
Вариант 2 (production): GitHub Actions:
- Скопировать
.github/workflows/ai-review.yml - Push в main
- Открыть PR, посмотреть AI-comment
- Скопировать
-
Тестирование: Добавить намеренный баг:
# Плохой код sql_query = f"SELECT * FROM users WHERE id = {user_input}"Запустить AI-review → должна найти SQL injection
Ключевые выводы
- AI для тактики: Баги, уязвимости, стиль — это работа AI
- Human для стратегии: Архитектура, бизнес-логика, trade-off’ы — это работа человека
- 70% проблем: AI находит легко, 30% требуют контекста
- Faster feedback: Pre-review происходит за 1-2 сек вместо часов ожидания
- Лучше код: Разработчик получает feedback до human-review, код приходит в лучшем виде
Следующий урок
В уроке 3 мы разберём мультиагентные workflow: как использовать несколько AI-агентов для разных задач одновременно, DevSquad паттерн, и когда это действительно нужно.