Установка и запуск
Бот ReviewGate поставляется одним Docker-образом. Рядом поднимается Redis (очередь ревью); PostgreSQL — опционален, только для метрик ревью. Всё — в вашем контуре. Вторая поверхность — CLI для машины разработчика — поставляется отдельным исполняемым файлом, без Docker и Node: CLI, хук и MCP.
app — сам бот · redis — очередь BullMQ (обязателен: вебхук только кладёт задачу, всю работу делает воркер) · postgres — опционален, только для метрик ревью (по умолчанию выключен; без него бот полностью работает). Код и дифф клиента не хранятся никогда.Запуск
Скачайте готовый клиентский docker-compose.yml (бот + Redis, опционально Postgres), заполните рядом .env (см. справочник ниже) и поднимите контур:
curl -O https://reviewgate.dev/docker-compose.yml
docker compose up -d
docker compose ps # every service healthy
docker compose logs -f appПроверьте, что бот отвечает:
curl http://localhost:3000/api/health
# {"status":"ok","ts":...,"version":"0.1.x",
# "capacity":{"total":3,"cli":1,"mrReserve":2,
# "inFlight":{"mr":0,"cli":0},"waiting":0}}capacity — как настроена пропускная способность ревью; её видно снаружи, без захода на машину за стартовым логом: total — сколько ревью воркер ведёт параллельно (REVIEW_CONCURRENCY), cli — сколько из этих слотов могут занять локальные прогоны через сервер ревью, mrReserve — слоты, которые они занять не могут никогда (гарантия, что ревью MR/PR стартует сразу), а inFlight/waiting — что происходит прямо сейчас. Обратите внимание, чего ответ не говорит: он собирается без обращения к Redis и к базе, поэтому зелёный ответ означает, что процесс жив, а не что очередь доступна.
docker compose logs app.Переменные: GitLab
| переменная | назначение | пример / по умолчанию |
|---|---|---|
| GITLAB_BASE_URL | URL инстанса GitLab, без /api/v4 и без хвостового слэша | https://gitlab.acme.com |
| GITLAB_TOKEN | токен бота со scope api | glpat-… |
| GITLAB_WEBHOOK_SECRET | секрет вебхука; то же значение — в настройке вебхука проекта (≥ 8 символов) | — |
| GITLAB_TIMEOUT_MS | таймаут запроса к GitLab API | 15000 |
Вендор считается настроенным, если задан GITLAB_TOKEN. Бот работает с одним вендором или с обоими сразу — но хотя бы один должен быть настроен, иначе он не стартует.
Переменные: GitHub
Второй вендор хостинга: ревью Pull Request'ов на github.com. Настраивать его не обязательно — блок целиком опционален. Подключение к вендору описано отдельно: Подключение к GitHub.
| переменная | назначение | пример / по умолчанию |
|---|---|---|
| GITHUB_WEBHOOK_SECRET | ключ HMAC-подписи вебхуков (X-Hub-Signature-256), ≥ 8 символов | — |
| GITHUB_APP_ID | ID GitHub App — рекомендуемый режим | — |
| GITHUB_APP_PRIVATE_KEY_B64 | приватный ключ App, base64 одной строкой (base64 -w0 key.pem) | — |
| GITHUB_TOKEN | альтернатива App: personal access token (быстрый старт) | — |
| GITHUB_BASE_URL | адрес инсталляции | https://github.com |
| GITHUB_TIMEOUT_MS | таймаут запроса к GitHub API | 15000 |
GITHUB_WEBHOOK_SECRET и аутентификация — пара GITHUB_APP_ID + GITHUB_APP_PRIVATE_KEY_B64 либо GITHUB_TOKEN. Одиночный GITHUB_TOKEN вендора не включает осознанно: это самая «фоновая» переменная экосистемы (её экспортируют gh CLI и Actions), и иначе GitLab-инсталляция на чужой машине падала бы на старте из-за чужого токена.Переменные: Redis и очередь
| переменная | назначение | пример / по умолчанию |
|---|---|---|
| REDIS_HOST | хост Redis (в docker-compose — имя сервиса) | redis |
| REDIS_PORT | порт Redis | 6379 |
| REDIS_PASSWORD | пароль Redis (если включён) | — |
| REVIEW_CONCURRENCY | сколько ревью воркер ведёт параллельно (1–64). Поднимайте под нагрузку большой команды (пики МРов) — очередь разгребается во столько же раз быстрее; для локальной модели, наоборот, снижайте. Потолок в пределах диапазона задаёт не воркер, а пропускная способность LLM: см. заметку про локальную модель | 3 |
Переменные: LLM
Подробности и локальная LLM — в разделе «LLM и свой ключ».
| переменная | назначение | пример / по умолчанию |
|---|---|---|
| LLM_PROVIDER | провайдер: anthropic · yandex · ollama · openai · openrouter · vllm | anthropic |
| LLM_API_KEY | ключ провайдера (общее имя; ANTHROPIC_API_KEY — алиас). Без него бот поднимется, но ревью упадёт с понятной ошибкой | — |
| LLM_MODEL | модель (общее имя; ANTHROPIC_MODEL — алиас); можно дешевле | claude-opus-4-8 |
| LLM_BASE_URL | endpoint OpenAI-совместимого провайдера / шлюза (ANTHROPIC_BASE_URL — алиас; пусто = облако) | — |
| LLM_FOLDER_ID | каталог Yandex Cloud — обязателен при LLM_PROVIDER=yandex | — |
| LLM_DATA_LOGGING | логировать запросы на стороне Yandex AI Studio | false |
| LLM_PROXY | CONNECT-прокси, чтобы дотянуться до провайдера (слепой туннель; пусто = напрямую) | — |
| LLM_TIMEOUT_MS | таймаут запроса к LLM, мс (локальные модели отвечают медленно) | 600000 |
| LLM_JSON_MODE | как просить у OpenAI-совместимого провайдера структурированный ответ: schema (json_schema) · object (json_object) · none (форму держат промпт и парсер). DeepSeek: none — json_schema он отвергает, а json_object на реальном ревью-прогоне (длинный промпт) отдаёт пустой ответ. Для отдельного бэкенда — LLM_BACKEND_<ИМЯ>_JSON_MODE | schema |
| LLM_EFFORT | глубина рассуждений: low · medium · high · xhigh · max | high |
| LLM_MAX_TOKENS | потолок выходных токенов | 16000 |
| LLM_CACHE_TTL | TTL prompt-кэша системного промпта (только Anthropic): 1h · 5m · off; 1h экономит вход на потоке MR | 1h |
| LLM_DIFF_CHAR_BUDGET | бюджет символов диффа в промпте (~100K токенов) | 400000 |
| LLM_FULL_FILE_CONTEXT | recall: полные изменённые файлы + соседи генератору, не только дифф (opt-in) | false |
| LLM_ENVIRONMENT_CONTEXT | recall: версии стека из манифестов в промпт (opt-in) | false |
| LLM_GENERATORS | роли-генераторы инсталляции по умолчанию, через запятую: [бэкенд:]модель[@effort] (первый — основной; default — основной провайдер). Per-repo переопределяется llm.generators целиком | — |
| LLM_JUDGES | панель судей по умолчанию (тот же синтаксис, не больше 2); per-repo — llm.judges | — |
| LLM_ARBITER | арбитр-председатель по умолчанию (одна роль); per-repo — llm.arbiter | — |
| LLM_BUDGET_TOKENS | потолок трат: бюджет токенов ПРОГОНА для основного провайдера (вход+выход+кэш). Барьеры фиксированные и не настраиваются: 80% — нотис в сводке, 100% — громкий нотис (ревью выполняется целиком), 300% — стоп прогона с публикацией собранного. Лимиты других вендоров — LLM_BACKEND_<ИМЯ>_BUDGET_TOKENS; без переменной бэкенд не лимитирован | — |
| DIAGNOSTICS | блок 🔬 диагностики прогона в сводке — дефолт инсталляции; per-repo переопределяется diagnostics в config.yml | false |
| REPLY_ENABLED | reply mode: бот отвечает на реплики в тредах своего ревью (вебхуку нужен триггер Comments) — дефолт инсталляции; per-repo переопределяется reply.enabled в config.yml | false |
Переменные: Postgres (опционально)
Postgres нужен только для метрик ревью — по умолчанию выключен, без него бот полностью работает. Чтобы включить: раскомментируйте сервис postgres и строку DATABASE_URL в docker-compose.yml и задайте пароль в .env. В метриках — только счётчики и метаданные (сколько находок сгенерировано, оставлено, дропнуто судьёй; модели, токены) в вашей же БД, автоочистка через 90 дней — по ним удобно смотреть пользу бота и что дропает судья.
| переменная | назначение | пример / по умолчанию |
|---|---|---|
| DATABASE_URL | строка подключения к Postgres; пусто = метрики выключены, бот работает | postgres://reviewgate:password@postgres:5432/reviewgate |
| POSTGRES_PASSWORD | пароль БД (в .env); подставляется в DATABASE_URL и в сервис postgres | reviewgate |
Переменные: лицензия
| переменная | назначение | пример / по умолчанию |
|---|---|---|
| REVIEWGATE_LICENSE | ранее выданный JWT-ключ (опционально); без него бот работает со статусом «Лицензия: Community» в сводке (язык этой строки — ключ language конфига; по умолчанию он английский) | — |
| REVIEWGATE_LICENSE_PUBLIC_KEY | переопределение вшитого публичного ключа (обычно не нужно) | — |
Переменные: логи (опционально)
Рецепт подключения к Graylog/ELK/Loki — на странице «Логи и мониторинг».
| переменная | назначение | пример / по умолчанию |
|---|---|---|
| LOG_FORMAT | формат логов: text · json (одна JSON-строка на запись, атрибуция джобы полями project_path/mr_iid/head_sha/vendor — для лог-стека; строго нижний регистр) | text |
Откуда берётся образ
При docker compose up -d образ скачивается сам — отдельные команды нужны только если вы забираете его вручную: в закрытый контур, во внутренний реестр или для проверки перед установкой.
| адрес | роль |
|---|---|
registry.reviewgate.dev/reviewgate-bot | основной; docker login не нужен — чтение открыто |
novohudonossor/reviewgate-bot | зеркало на Docker Hub, тот же образ (совпадает по digest) |
Какие версии опубликованы — спросите у самого реестра:
curl -s https://registry.reviewgate.dev/v2/reviewgate-bot/tags/listСкачать вручную и проверить, что получили именно тот образ (digest должен совпасть с зеркалом — образ собирается один раз и публикуется в оба реестра):
docker pull registry.reviewgate.dev/reviewgate-bot:latest
# the digest must match the mirror:
docker buildx imagetools inspect registry.reviewgate.dev/reviewgate-bot:latest | grep Digest
docker buildx imagetools inspect novohudonossor/reviewgate-bot:latest | grep DigestЗакрытый контур (без интернета)
На машине с доступом в интернет сохраните образ в файл, перенесите его любым разрешённым у вас способом и загрузите на целевом сервере. Образ собран под linux/amd64 — указывайте платформу явно, если качаете с ARM-машины (например с Mac):
VERSION=latest # or a specific tag from the list above
# 1) on a machine with internet access
docker pull --platform linux/amd64 registry.reviewgate.dev/reviewgate-bot:$VERSION
docker save registry.reviewgate.dev/reviewgate-bot:$VERSION | gzip > reviewgate-bot-$VERSION.tar.gz
# 2) move the file to the target server, then there:
gunzip -c reviewgate-bot-$VERSION.tar.gz | docker load
docker image ls | grep reviewgate-botПосле docker load пропишите в docker-compose.yml тот же тег, который загрузили, — тогда up -d возьмёт локальный образ и в сеть не пойдёт.
Обновление
Бот распространяется публичным образом с реестра registry.reviewgate.dev (зеркало — Docker Hub, см. «Образ не скачивается») — рекомендуем закрепить конкретный тег версии. Обновление — обычный pull и перезапуск:
docker compose pull app
docker compose up -d appЕсли тег закреплён (не latest), сначала укажите в docker-compose.yml новый — иначе pull перетянет тот же образ и up -d ничего не пересоздаст. Список опубликованных версий — командой из раздела «Откуда берётся образ».
Какая версия у вас работает
Версия сборки вшита в образ и видна в ответе /api/health, в строке 🚀 ReviewGate bot … стартового лога и в выводе diagnose.sh.
curl -s http://localhost:3000/api/health
# {"status":"ok","ts":...,"version":"0.1.x","capacity":{...}}
# ↑ the version of the running image
docker compose logs app | grep 🚀
# 🚀 ReviewGate bot 0.1.x listening on http://0.0.0.0:3000/apiЕсли бот вообще не стартует (например, из-за ошибки в .env), версия всё равно читается — она вшита в образ, а не выдаётся приложением:
docker compose run --rm --no-deps app printenv REVIEWGATE_VERSION
# 0.1.xdocker-compose.yml показывает, что вы просили, а не то, что реально запущено: при latest он не меняется от обновления к обновлению, а при зеркалировании образа в свой registry тег назначаете вы сами. Поле version проставляется при сборке образа, поэтому переживает и то, и другое. Значение dev означает сборку из исходников, а не из опубликованного образа.Версию стоит прикладывать к любому обращению в поддержку — с неё начинается разбор.