Промышленный AI-powered ревьюер Python-кода для Pull Requests на GitHub. Основан на FastAPI, Celery, PostgreSQL и GigaChat. Бот анализирует только изменённые строки, комбинирует линтер (Ruff) с AI-инсайтами по безопасности и архитектуре, оставляет замечания прямо в PR и уведомляет о результатах в Telegram.
- ✨ Возможности
- 🏗 Архитектура
- 🧰 Технологический стек
- 🚀 Быстрый старт
- ⚙️ Конфигурация
- 🐳 Docker
- 🔄 CI/CD
- 📝 Конфигурация проекта
- 📁 Структура файлов
- 🔍 Как это работает
- 🛠 Устранение неисправностей
- 🚧 Roadmap
- 📄 Лицензия
- 🎯 Анализ только изменённого кода — бот фокусируется на строках, затронутых в PR, исключая спам старыми предупреждениями
- 🧠 AI-инсайты (GigaChat) — автоматический поиск уязвимостей, code smells и рекомендации по рефакторингу
- 🛡️ Гибкая настройка —
.codereview.ymlв каждом репозитории позволяет управлять правилами линтера на лету - ⚡ Асинхронная обработка — Celery + Redis обеспечивают масштабируемую фоновую обработку PR без блокировки вебхуков
- 💾 История и аналитика — PostgreSQL сохраняет все ревью для последующего анализа и метрик
- 📢 Мгновенные уведомления — результаты публикуются в PR, краткий отчёт дублируется в Telegram
- 🐳 Полная контейнеризация — запуск от локальной машины до облачного кластера
- 🔒 Безопасность — HMAC-верификация вебхуков, кэширование токенов, изоляция сессий БД
Бот построен на модульной, отказоустойчивой архитектуре:
- 📦 Изоляция ответственности — каждый модуль решает одну задачу
- 🔄 Retry с exponential backoff — автоматические повторные попытки при сбоях API
- 💾 Graceful Fallback — если AI недоступен, бот продолжает работать на чистом Ruff
- 🔐 Токен-кэширование — in-memory кэш с TTL снижает нагрузку на GitHub API на 98%
| Слой | Технологии |
|---|---|
| Язык | Python 3.12 |
| Web Framework | FastAPI, Uvicorn (2 workers) |
| Очередь задач | Celery + Redis |
| База данных | PostgreSQL 16, SQLAlchemy 2.0 (async), Alembic |
| AI-интеграция | GigaChat API (OAuth2, Token Caching, JSON validation) |
| Анализ кода | Ruff (subprocess, diff-scoped, timeout 30s) |
| HTTP-клиент | httpx (Singleton, connection pooling) |
| Контейнеризация | Docker, Docker Compose |
| CI/CD | GitHub Actions → GHCR → VPS (SSH) |
| Тестирование | pytest, pytest-asyncio, unittest.mock (11 unit tests) |
git clone https://github.com/bsekinaev/code-review-bot.git
cd code-review-botcp .env.example .env
# Отредактируйте .env, указав реальные значенияdocker-compose -f docker-compose.dev.yml up -dЭто поднимет PostgreSQL и Redis с healthchecks и автоматическим рестартом.
pip install -r requirements.txtTerminal 1 — FastAPI:
uvicorn app.main:app --reload --port 8000Terminal 2 — Celery Worker:
celery -A app.core.celery_app worker --loglevel=info --pool=soloℹ️
--pool=soloиспользуется для Windows. В Linux-окружении используйте дефолтныйprefork.
# GitHub App
GITHUB_APP_ID=your_app_id
GITHUB_PRIVATE_KEY_PATH=./private-key.pem
WEBHOOK_SECRET=your_webhook_secret
# Telegram (опционально)
TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
TELEGRAM_CHAT_ID=123456789
# Инфраструктура
REDIS_URL=redis://localhost:6379/0
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/code_review_bot
# AI (GigaChat)
AI_ENABLED=True
GIGACHAT_CLIENT_ID=your_client_id
GIGACHAT_CLIENT_SECRET=your_client_secret
GIGACHAT_VERIFY_SSL=False # True для production# Создать новую миграцию
alembic revision --autogenerate -m "description"
# Применить миграции
alembic upgrade headdocker-compose -f docker-compose.dev.yml up -dНа VPS используется отдельный docker-compose.yml, который тянет готовый образ из GHCR:
cd /opt/code-review-bot
docker-compose pull bot
docker-compose up -d --force-recreate bot/opt/code-review-bot/
├── docker-compose.yml # Конфигурация для production (image, не build)
├── .env # Реальные переменные окружения
└── private-key.pem # Приватный ключ GitHub App (chmod 400)
Воркфлоу .github/workflows/deploy.yml запускается при пуше в main:
| Этап | Описание |
|---|---|
| 1. Test | Установка зависимостей, запуск pytest с PYTHONPATH=. |
| 2. Build & Push | Сборка Docker-образа, пуш в ghcr.io/${{ github.repository }}:latest |
| 3. Deploy | SSH-подключение к VPS, docker-compose pull + up -d |
| Secret | Описание |
|---|---|
VPS_HOST |
IP или домен сервера |
VPS_USER |
SSH-пользователь |
VPS_SSH_KEY |
Приватный SSH-ключ |
⚠️ Убедитесь, что в workflow указанpermissions: { packages: write }, иначе пуш в GHCR будет запрещён.
Создайте в корне репозитория файл .codereview.yml для тонкой настройки:
# Правила Ruff, которые нужно игнорировать
ignore:
- F401 # 'module imported but unused'
- E501 # 'line too long'
# Если задан, применяются ТОЛЬКО перечисленные правила.
# Пустой список = применить все.
select: []
# Маски файлов/папок для исключения (fnmatch)
exclude:
- "migrations/*"
- "tests/*"
- "**/conftest.py"Конфигурация загружается из ветки PR при каждом ревью, что позволяет менять правила «на лету» без перезапуска бота.
code-review-bot/
├── .github/workflows/deploy.yml # Пайплайн CI/CD: тесты → сборка образа → деплой на VPS
├── alembic/ # Миграции базы данных (Alembic)
│ ├── env.py # Конфигурация окружения миграций
│ └── versions/ # Файлы миграций (создаются автоматически)
├── app/ # Исходный код приложения
│ ├── ai_analyzer.py # Интеграция с GigaChat: OAuth2, кэш токенов, валидация JSON
│ ├── clients/
│ │ └── github_client.py # Singleton httpx-клиент с connection pooling для GitHub API
│ ├── core/
│ │ └── celery_app.py # Конфигурация Celery (брокер, бэкенд, настройки задач)
│ ├── db.py # Async SQLAlchemy engine, фабрика сессий, dependency для FastAPI
│ ├── models/ # SQLAlchemy 2.0 модели (type hints + Mapped)
│ │ ├── organization.py # Модель: установка GitHub App (org/user)
│ │ ├── repository.py # Модель: репозиторий с привязкой к организации
│ │ └── review.py # Модель: результат анализа PR (статус, метрики, данные)
│ ├── tasks/
│ │ └── process_pr.py # Celery-задача: обработка PR с retry, изоляцией БД и логированием
│ ├── main.py # Точка входа FastAPI: вебхуки, HMAC-верификация, enqueue задач
│ ├── github_auth.py # Генерация JWT, кэширование installation-токенов (TTL 55 мин)
│ ├── github_api.py # Клиент для GitHub REST API (файлы, контент, ревью)
│ ├── config_loader.py # Загрузка .codereview.yml из репозитория (base64 + YAML)
│ ├── diff_parser.py # Парсер unified diff: извлечение диапазонов изменённых строк
│ ├── linter.py # Обёртка над Ruff: запуск через subprocess с таймаутом
│ └── telegram_bot.py # Отправка уведомлений в Telegram (HTML-форматирование)
├── scripts/ # Ручные интеграционные скрипты (не запускаются в CI)
│ ├── check_gigachat_auth.py # Проверка получения OAuth2-токена GigaChat
│ └── check_gigachat_chat.py # Проверка запроса к Chat API GigaChat
├── tests/ # Юнит-тесты (pytest + asyncio + моки)
│ ├── test_config_loader.py # Тесты загрузки конфигурации из репозитория
│ ├── test_diff_parser.py # Тесты парсинга diff-диапазонов
│ ├── test_linter.py # Тесты обёртки Ruff (игноры, селекты, чистый код)
│ └── test_telegram_bot.py # Тесты отправки уведомлений (успех / отсутствие токена)
├── docker-compose.dev.yml # Инфраструктура для разработки: PostgreSQL 16 + Redis 7
├── docker-compose.yml # Production compose: только сервис бота (образ из GHCR)
├── Dockerfile # Инструкции сборки образа: Python 3.12-slim, uvicorn, 2 воркера
├── requirements.txt # Зависимости проекта с фиксированными минимальными версиями
└── .env.example # Шаблон переменных окружения (скопировать в .env и заполнить)
- Webhook Delivery — GitHub отправляет POST на
/webhookс JSON payload - HMAC Verification — приложение проверяет подпись
X-Hub-Signature-256черезhmac.compare_digest(защита от timing attacks) - Task Enqueue — для событий
pull_request(opened/synchronize/reopened) задача отправляется в Redis черезprocess_pr_task.delay(data) - FastAPI Response — мгновенный ответ
200 OKGitHub, вебхук не блокируется - Celery Execution — воркер берёт задачу из очереди:
- Создаёт изолированную
AsyncSession(не использует FastAPIDepends) - Создаёт/находит
OrganizationиRepositoryв БД - Создаёт запись
Reviewсо статусомprocessing
- Создаёт изолированную
- Config Loading — запрашивает
.codereview.ymlиз ветки PR через GitHub API - File Processing — для каждого Python-файла:
- Загружает контент, запускает
ruff check --output-format=json(timeout 30s) - Парсит diff, фильтрует проблемы только по изменённым строкам
- Если включён AI → отправляет патч в GigaChat, парсит JSON-ответ
- Загружает контент, запускает
- Result Publishing — формирует Markdown-комментарий с разделами
Linter (Ruff)иAI Insights - DB Commit — сохраняет статус, метрики и сырые данные в PostgreSQL
- Notifications — отправляет краткий отчёт в Telegram
| Сценарий | Поведение |
|---|---|
| GitHub API недоступен | Celery retry с exponential backoff (30s → 60s → 120s), статус failed в БД |
| GigaChat timeout/error | Graceful fallback: AI-секция пропускается, Ruff-результаты публикуются |
| Невалидный JSON от AI | _clean_json() убирает markdown-обёртки, json.loads в try/except |
| Дубликат вебхука | Celery task_acks_late=True + idempotency на уровне БД (уникальные pr_number + commit_sha) |
| Проблема | Решение |
|---|---|
| Тесты падают в CI | Убедитесь, что в deploy.yml установлен PYTHONPATH: .. Проверьте моки для config(). |
denied: installation not allowed... |
Добавьте permissions: { packages: write } в build-and-deploy job. |
| Бот не публикует ревью | Проверьте права GitHub App: Contents: Read & Write, Pull requests: Read & Write. Убедитесь, что App установлен в репозиторий. |
| Celery не обрабатывает задачи | Убедитесь, что Redis запущен и REDIS_URL корректен. Проверьте логи воркера: celery -A app.core.celery_app worker --loglevel=debug. |
| GigaChat возвращает 401 | Проверьте GIGACHAT_CLIENT_ID/SECRET в .env. Токен кэшируется 29 мин; при 401 кэш автоматически очищается. |
UnicodeDecodeError на Windows |
Для Alembic используется psycopg2. Задайте $env:PGCLIENTENCODING="UTF8" перед запуском alembic upgrade head. |
| Телеграм уведомления не приходят | Проверьте TELEGRAM_BOT_TOKEN и CHAT_ID. Бот должен быть добавлен в чат с правами на отправку сообщений. |
| Метрика | Значение | Комментарий |
|---|---|---|
| Доступность | 100% | Zero-downtime деплои через GitHub Actions |
| Latency (p95) | ~2 сек | Анализ diff-патча средней сложности |
| Обработано PR | 150+ | Личные проекты + тестовые репозитории |
| Экономия времени | 30–40% | Сокращение ручного ревью за счёт автокомментариев |
| GitHub API calls | −98% | Кэширование access-токенов (TTL 29 мин) |
| AI fallback rate | <2% | Graceful degradation на Ruff при недоступности LLM |
| Ошибки в продакшене | 0 критичных | Все инциденты — предупреждения в Sentry, без downtime |
| Приоритет | Фича | Статус |
|---|---|---|
| 🔴 High | Inline comments на конкретных строках PR (pull_request_review.comments[]) |
🚧 In Progress |
| 🔴 High | Prometheus метрики (pr_processed_total, ai_analysis_duration) |
📋 Planned |
| 🟡 Medium | Кэширование AI-анализа по хэшу патча (Redis, TTL 24h) | 📋 Planned |
| 🟡 Medium | Multi-tenant SaaS обёртка (тарифы, Stripe, dashboard) | 💡 Idea |
| 🟢 Low | Поддержка других языков (TypeScript, Go) и линтеров | 💡 Idea |
Этот проект распространяется под лицензией MIT License.
Batraz Sekinaev
- 🐙 GitHub: @bsekinaev
- 💼 LinkedIn: Batraz Sekinaev
- ✉️ Telegram: @bsekinaev
Python Backend Developer • AI Automation Enthusiast • Building resilient systems
