установка

Установка и запуск

Бот 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_URLURL инстанса GitLab, без /api/v4 и без хвостового слэшаhttps://gitlab.acme.com
GITLAB_TOKENтокен бота со scope apiglpat-…
GITLAB_WEBHOOK_SECRETсекрет вебхука; то же значение — в настройке вебхука проекта (≥ 8 символов)
GITLAB_TIMEOUT_MSтаймаут запроса к GitLab API15000

Вендор считается настроенным, если задан GITLAB_TOKEN. Бот работает с одним вендором или с обоими сразу — но хотя бы один должен быть настроен, иначе он не стартует.

Переменные: GitHub

Второй вендор хостинга: ревью Pull Request'ов на github.com. Настраивать его не обязательно — блок целиком опционален. Подключение к вендору описано отдельно: Подключение к GitHub.

переменнаяназначениепример / по умолчанию
GITHUB_WEBHOOK_SECRETключ HMAC-подписи вебхуков (X-Hub-Signature-256), ≥ 8 символов
GITHUB_APP_IDID 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 API15000
когда вендор включаетсяНужен 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порт Redis6379
REDIS_PASSWORDпароль Redis (если включён)
REVIEW_CONCURRENCYсколько ревью воркер ведёт параллельно (1–64). Поднимайте под нагрузку большой команды (пики МРов) — очередь разгребается во столько же раз быстрее; для локальной модели, наоборот, снижайте. Потолок в пределах диапазона задаёт не воркер, а пропускная способность LLM: см. заметку про локальную модель3

Переменные: LLM

Подробности и локальная LLM — в разделе «LLM и свой ключ».

переменнаяназначениепример / по умолчанию
LLM_PROVIDERпровайдер: anthropic · yandex · ollama · openai · openrouter · vllmanthropic
LLM_API_KEYключ провайдера (общее имя; ANTHROPIC_API_KEY — алиас). Без него бот поднимется, но ревью упадёт с понятной ошибкой
LLM_MODELмодель (общее имя; ANTHROPIC_MODEL — алиас); можно дешевлеclaude-opus-4-8
LLM_BASE_URLendpoint OpenAI-совместимого провайдера / шлюза (ANTHROPIC_BASE_URL — алиас; пусто = облако)
LLM_FOLDER_IDкаталог Yandex Cloud — обязателен при LLM_PROVIDER=yandex
LLM_DATA_LOGGINGлогировать запросы на стороне Yandex AI Studiofalse
LLM_PROXYCONNECT-прокси, чтобы дотянуться до провайдера (слепой туннель; пусто = напрямую)
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_MODEschema
LLM_EFFORTглубина рассуждений: low · medium · high · xhigh · maxhigh
LLM_MAX_TOKENSпотолок выходных токенов16000
LLM_CACHE_TTLTTL prompt-кэша системного промпта (только Anthropic): 1h · 5m · off; 1h экономит вход на потоке MR1h
LLM_DIFF_CHAR_BUDGETбюджет символов диффа в промпте (~100K токенов)400000
LLM_FULL_FILE_CONTEXTrecall: полные изменённые файлы + соседи генератору, не только дифф (opt-in)false
LLM_ENVIRONMENT_CONTEXTrecall: версии стека из манифестов в промпт (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.ymlfalse
REPLY_ENABLEDreply mode: бот отвечает на реплики в тредах своего ревью (вебхуку нужен триггер Comments) — дефолт инсталляции; per-repo переопределяется reply.enabled в config.ymlfalse

Переменные: Postgres (опционально)

Postgres нужен только для метрик ревью — по умолчанию выключен, без него бот полностью работает. Чтобы включить: раскомментируйте сервис postgres и строку DATABASE_URL в docker-compose.yml и задайте пароль в .env. В метриках — только счётчики и метаданные (сколько находок сгенерировано, оставлено, дропнуто судьёй; модели, токены) в вашей же БД, автоочистка через 90 дней — по ним удобно смотреть пользу бота и что дропает судья.

переменнаяназначениепример / по умолчанию
DATABASE_URLстрока подключения к Postgres; пусто = метрики выключены, бот работаетpostgres://reviewgate:password@postgres:5432/reviewgate
POSTGRES_PASSWORDпароль БД (в .env); подставляется в DATABASE_URL и в сервис postgresreviewgate

Переменные: лицензия

переменнаяназначениепример / по умолчанию
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.x
почему не по тегуТег в вашем docker-compose.yml показывает, что вы просили, а не то, что реально запущено: при latest он не меняется от обновления к обновлению, а при зеркалировании образа в свой registry тег назначаете вы сами. Поле version проставляется при сборке образа, поэтому переживает и то, и другое. Значение dev означает сборку из исходников, а не из опубликованного образа.

Версию стоит прикладывать к любому обращению в поддержку — с неё начинается разбор.