Микросервис для автоматического назначения ревьюеров на Pull Request'ы.
Сервис автоматически назначает до 2 ревьюеров из команды автора PR, поддерживает переназначение ревьюеров и управление командами.
Основной функционал:
- Автоматическое назначение ревьюеров из команды автора
- Переназначение ревьюеров с учётом активности
- Управление командами и пользователями
- Отслеживание статусов PR (OPEN/MERGED)
- Идемпотентные операции слияния
- Статистика по PR и пользователям
# Клонировать репозиторий
git clone https://github.com/KruglovEgor/ReviewService.git
cd ReviewService
# Запустить приложение и БД
docker-compose up --build -d
# Проверить статус
docker-compose psСервис доступен на http://localhost:8080
Swagger UI: http://localhost:8080/swagger/
Unit-тесты:
go test -v ./internal/...Integration-тесты (E2E):
# Запустить тесты в изолированной БД
docker-compose -f docker-compose.test.yml up --build --abort-on-container-exit
# Очистка после тестов
docker-compose -f docker-compose.test.yml down -vИнтеграционные тесты автоматически:
- Создают чистую тестовую БД
- Применяют миграции
- Запускают все E2E сценарии
- Работают на любой ОС без настройки
# Остановить и удалить контейнеры
docker-compose down
# Остановить и удалить контейнеры + volumes (полная очистка БД)
docker-compose down -vПроект следует принципам Clean Architecture:
internal/
├── domain/ # Доменные модели и интерфейсы репозиториев
├── repository/ # Реализация работы с PostgreSQL
├── service/ # Бизнес-логика
├── handler/ # HTTP обработчики
├── config/ # Конфигурация
└── testutil/ # Утилиты для тестирования
Слои:
- Domain - модели данных, бизнес-правила, интерфейсы
- Repository - работа с БД через pgx/v5
- Service - бизнес-логика (назначение ревьюеров, валидация)
- Handler - HTTP API через chi/v5
Полная документация доступна в Swagger UI по адресу /swagger/
Команды:
POST /team/add- создать командуGET /team/get?team_name={name}- получить командуPOST /team/deactivate- массово деактивировать команду
Пользователи:
POST /users/setIsActive- изменить статус активностиGET /users/getReview?user_id={id}- получить PR пользователя
Pull Requests:
POST /pullRequest/create- создать PR (автоназначение ревьюеров)POST /pullRequest/merge- слияние PR (идемпотентно)POST /pullRequest/reassign- переназначить ревьювераGET /pullRequest/list?status={OPEN|MERGED}- список PR
Статистика:
GET /stats- общая статистика сервиса
Схема:
teams - команды
users - пользователи (связь с командой)
pull_requests - PR'ы
pr_reviewers - связь PR-ревьюверИндексы добавлены для оптимизации запросов:
users(team_name, is_active)- поиск активных участников командыpr_reviewers(user_id)- поиск PR'ов пользователяpull_requests(status)- фильтрация по статусу
Миграции применяются автоматически при запуске приложения.
Сервис настраивается через переменные окружения. Все значения имеют defaults - файл .env не обязателен для запуска.
Docker Compose использует defaults, указанные в формате ${VAR:-default}. Это значит:
- Если переменная не задана → используется default значение
- Для изменения настроек можно создать
.envфайл (см..env.example)
Основные переменные:
# База данных
DB_HOST=postgres
DB_PORT=5432
DB_USER=reviewservice
DB_PASSWORD=password
DB_NAME=reviewservice
# Сервер
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
# Приложение
LOG_LEVEL=info
APP_ENV=developmentСоздание .env файла (опционально):
# Скопируйте шаблон
cp .env.example .env
# Отредактируйте значения при необходимости
# Файл .env в .gitignore и не будет закоммиченПолный список переменных с defaults смотрите в docker-compose.yml
go test -v ./internal/...Покрытие кода:
# Запуск с покрытием (только service layer где есть тесты)
go test ./internal/service/... -coverprofile=coverage.out
# Генерация HTML отчёта
go tool cover -html=coverage.out -o coverage.html
# Просмотр в консоли
go tool cover -func=coverage.outТекущее покрытие:
- Service layer: 67.7%
- Handler layer: 48.8%
- Всего: 98 тестов
Через Docker Compose (рекомендуется):
# Запускает изолированную тестовую БД и выполняет E2E тесты
docker-compose -f docker-compose.test.yml up --build --abort-on-container-exit
# Очистка после тестов
docker-compose -f docker-compose.test.yml down -vЭтот метод:
- ✅ Работает на любой ОС из коробки
- ✅ Изолированная тестовая БД (не влияет на dev окружение)
- ✅ Автоматически применяет миграции
- ✅ Не требует установки PostgreSQL локально
Что происходит внутри:
- Создаётся контейнер
postgres_testс чистой БД - Собирается тестовый образ из
Dockerfile.test - Запускаются тесты из
./tests/integration/... - После завершения контейнеры останавливаются
Результат: Все тесты должны пройти успешно при первом запуске после клонирования репозитория.
Для запуска приложения:
- Docker & Docker Compose
- Свободные порты: 8080 (API), 5432 (PostgreSQL)
Для локальной разработки:
- Go 1.23+
- Docker (для запуска PostgreSQL)
Важно: Проект готов к запуску из коробки - .env файл не требуется, все defaults настроены в docker-compose.yml.
Используется алгоритм Fisher-Yates shuffle для честного случайного выбора из активных участников команды.
Повторный вызов POST /pullRequest/merge для уже слитого PR возвращает 200 OK с текущим состоянием.
При деактивации пользователя его открытые PR автоматически переназначаются по приоритету:
- Команда деактивируемого - сначала ищем замену в его команде
- Команда автора PR - если в первой команде нет активных
- Другие команды - если и в команде автора нет
- Удаление без замены - если вообще нет активных пользователей
Это обеспечивает сохранение ревьюверов даже при массовой деактивации команды.
Пользователи с is_active = false:
- Не назначаются на новые PR
- Не участвуют в переназначении
- Остаются в существующих PR до явного переназначения
Критичные операции выполняются в транзакциях для консистентности данных:
- CreateTeam - атомарное создание команды + множественное создание/обновление пользователей
- AssignReviewers - атомарное назначение нескольких ревьюеров
- ReassignReviewer - атомарная замена ревьювера
BulkDeactivateTeam:
- Деактивация пользователей команды выполняется атомарно (один SQL запрос)
- Переназначение открытых PR происходит последовательно (best-effort подход)
- Частичные ошибки переназначения логируются и возвращаются в результате
Сервер корректно завершает активные соединения при получении SIGTERM/SIGINT (30 сек таймаут).
GET /stats возвращает:
- Общую статистику PR (total, open, merged, среднее число ревьюеров)
- Статистику по каждому пользователю
POST /team/deactivate:
- Деактивирует всех членов команды
- Автоматически переназначает их открытые PR
- Возвращает детальный отчёт
E2E тесты с реальной PostgreSQL в tests/integration/:
- Полный жизненный цикл (команда → PR → merge → статистика)
- Массовая деактивация с переназначением
Настроен golangci-lint с 15+ линтерами (см. .golangci.yml)
- Go 1.23
- PostgreSQL 16 + pgx/v5
- chi/v5 - HTTP router
- zap - структурированное логирование
- golang-migrate - миграции БД
- Docker & Docker Compose
- RPS: 5+ (согласно требованиям)
- Response Time: <300ms (p95)
- Connection Pool: 25 max open, 5 max idle
- Timeouts: Read 10s, Write 10s, Idle 60s
.
├── cmd/api/ # Точка входа
├── internal/ # Приватный код приложения
│ ├── domain/ # Модели и интерфейсы
│ ├── repository/ # Работа с БД
│ ├── service/ # Бизнес-логика
│ ├── handler/ # HTTP handlers
│ ├── config/ # Конфигурация
│ └── testutil/ # Тестовые утилиты
├── migrations/ # SQL миграции
├── tests/integration/ # E2E тесты
├── docker-compose.yml # Docker окружение
├── Dockerfile # Production образ
├── .golangci.yml # Конфигурация линтера
└── openapi.yml # OpenAPI спецификация