Устаревшие зависимости — самый тихий и самый частый вектор supply-chain инцидентов: команда знает, что нужно обновляться, но ручной PR на каждый пакет никто не осилит, поэтому в бэклоге копятся сотни версий и одна закрытая CVE. Renovate решает это не заменой ручного труда на ручной труд, а автоматизацией всего цикла: сканирует манифесты, группирует апдейты по смыслу и часть из них вливает без участия человека.
Содержание
Открыть содержание
Почему «обновим перед аудитом» больше не работает
Классический процесс обновления зависимостей выглядит как разовая акция. Раз в квартал кто-то из команды садится и полдня разбирает npm outdated или pip list --outdated, открывает пачку PR, разбирается, что сломалось, и мержит то, что прошло тесты. Работает, пока обновлений мало, а версий, отставших от актуальных, — единицы.
Проблема в том, что к моменту такого «разбора» дистанция до актуальной версии уже измеряется десятками релизов, и в диффе между текущей и целевой версией легко потерять breaking change. А «обновим перед аудитом» или «перед релизом» — это ровно тот момент, когда меньше всего хочется чинить внезапно всплывшую несовместимость под дедлайн.
Dependabot частично закрыл проблему для GitHub — он открывает по PR на каждое обновление и умеет базовую группировку через groups в dependabot.yml. Но группировка там ограничена одним измерением за раз (обычно по экосистеме или по паттерну имени), без условий на тип апдейта, зависимость от результата CI или временную задержку после релиза. В активном проекте с полусотней зависимостей это всё равно означает десятки отдельных или полусгруппированных PR в неделю, каждый со своим прогоном CI. Смотреть на такое некому, и через месяц PR-ы просто закрывают пачкой не глядя — что окончательно убивает саму цель автоматизации.
Чем Renovate отличается по существу
Renovate — не просто «ещё один бот, который открывает PR». Ключевое отличие — конфигурируемость самого процесса и мультиплатформенность.
- Работает везде. GitHub, GitLab, Bitbucket, Azure DevOps, Gitea — единый инструмент вместо разных ботов под каждую платформу. Для команд, у которых часть репозиториев в GitLab, а часть в GitHub, это единственный вариант с одинаковым UX и одним конфигом.
- Группировка вместо потока PR. Правилами
packageRulesможно объединить все minor/patch апдейты одного семейства пакетов (все@types/*, весьaws-sdk) в один PR вместо десяти отдельных. - Расписание, а не «как только вышло». Апдейты копятся и открываются по
schedule— например, раз в неделю по понедельникам, а не каждый раз, когда апстрим зарелизился. - Dependency Dashboard. Отдельный issue со сводкой всех pending, awaiting и errored апдейтов — единая точка входа вместо поиска PR по вкладкам.
lockFileMaintenance. Отдельный периодический апдейт lock-файла (package-lock.json,poetry.lock) даже когда версии в манифесте не менялись — подтягивает транзитивные зависимости, которые иначе никто не трогает годами.- Merge Confidence. На PR подтягиваются бейджи по каждому апдейту — сколько проектов в open source уже используют новую версию и сколько времени она в проде без отката. Это не гарантия отсутствия проблем, но ориентир, отличающий «версия вышла вчера и её ещё никто не пробовал» от «версия неделями стоит у тысяч проектов».
Расшариваемые конфиги через extends — ещё одна деталь, которая экономит время на масштабе организации. Пресет config:recommended в примере ниже — это готовый набор разумных дефолтов от самого Renovate; свой пресет можно опубликовать отдельным репозиторием и подключать той же строкой во всех проектах компании, вместо копирования renovate.json вручную.
Сравнение в одной таблице
| Ручной апдейт | Dependabot | Renovate | |
|---|---|---|---|
| Платформы | — | GitHub | GitHub, GitLab, Bitbucket, Azure DevOps, self-hosted |
| Группировка апдейтов | вручную | ограниченная (groups) | гибкие packageRules, любые срезы |
| Расписание | нет | ограниченное | полноценный cron-подобный schedule |
| Automerge | нет | базовый | да, с условиями по типу апдейта и cooldown |
| Self-hosted | — | нет | да (renovate CLI или job в CI) |
| Сводка состояния | нет | вкладка PR | Dependency Dashboard issue |
Что нужно, чтобы включить Renovate в проекте
Минимально нужны три вещи: конфиг с правилами группировки и расписанием, доступ бота к репозиторию и — если платформа не GitHub — self-hosted запуск в CI. Начнём с конфига.
На GitHub Renovate ставится как обычное GitHub App — авторизуете приложение на репозиторий или организацию, и первым же прогоном оно открывает onboarding PR с предложенным renovate.json, который можно поправить перед мерджем. На self-hosted платформах (GitLab, Bitbucket, Azure DevOps) такого приложения нет — конфиг просто кладут в репозиторий заранее, а сам Renovate запускают из CI, как показано ниже.
renovate.json в корне репозитория:
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"timezone": "Europe/Moscow",
"schedule": ["before 6am on monday"],
"lockFileMaintenance": {
"enabled": true,
"schedule": ["before 6am on monday"]
},
"packageRules": [
{
"matchUpdateTypes": ["minor", "patch"],
"matchDepTypes": ["dependencies"],
"groupName": "minor and patch (prod)",
"automerge": false
},
{
"matchDepTypes": ["devDependencies"],
"matchUpdateTypes": ["minor", "patch"],
"groupName": "dev dependencies",
"automerge": true,
"automergeType": "branch",
"minimumReleaseAge": "3 days"
},
{
"matchUpdateTypes": ["major"],
"labels": ["breaking"],
"automerge": false
}
],
"vulnerabilityAlerts": {
"labels": ["security"],
"automerge": false
}
}
Три вещи в этом конфиге держат automerge безопасным, а не просто «включённым». Во-первых, автомердж разрешён только для devDependencies и только для minor/patch — прод-зависимости и любой major всегда идут через человека. Во-вторых, minimumReleaseAge (в старых версиях — stabilityDays) заставляет Renovate подождать несколько дней после публикации пакета, прежде чем предлагать его к автомерджу: свежевышедшая версия — самый частый вектор supply-chain атаки (вредоносный код заливают именно в новый релиз, компрометировав аккаунт мейнтейнера), и пара дней задержки почти всегда достаточна, чтобы такую версию успели отозвать. В-третьих, vulnerabilityAlerts выделены отдельно и намеренно не автомерджатся — патч безопасности стоит смотреть глазами, а не доверять слепому CI.
Для self-hosted платформ (GitLab, Bitbucket) Renovate запускается как job по расписанию, а не как внешнее GitHub App. Job в GitLab CI:
renovate:
stage: dependencies
image: renovate/renovate:latest
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
variables:
RENOVATE_PLATFORM: gitlab
RENOVATE_ENDPOINT: $CI_SERVER_URL/api/v4
RENOVATE_TOKEN: $RENOVATE_BOT_TOKEN
RENOVATE_AUTODISCOVER: "true"
RENOVATE_AUTODISCOVER_FILTER: "acme-group/*"
script:
- renovate
Пайплайн запускается по CI/CD Schedule (в GitLab это отдельная сущность в настройках проекта, обычный cron-выражение вроде 0 6 * * 1), а не постоянно живущим процессом. RENOVATE_TOKEN — токен бот-аккаунта с правами на Merge Requests и Repository в нужных проектах, RENOVATE_AUTODISCOVER_FILTER ограничивает, какие репозитории группы бот вообще увидит — без фильтра Renovate попытается открыть PR-ы во всём, до чего дотягивается токен, что почти никогда не то, что нужно.
Как проверить, что всё работает
После первого запуска в репозитории должен появиться issue Dependency Dashboard — по нему сразу видно, что Renovate нашёл, что сгруппировал и что отложил. Если issue не появился, а pipeline прошёл зелёным — почти всегда виноват RENOVATE_AUTODISCOVER_FILTER (репозиторий не попал под фильтр) или токен без прав на нужную группу.
Локально конфиг можно проверить без реального запуска:
LOG_LEVEL=debug npx renovate-config-validator renovate.json
А сухой прогон против настоящего репозитория, без создания PR:
RENOVATE_TOKEN=... LOG_LEVEL=debug npx renovate --dry-run=full acme-group/app
В выводе будет видно, какие пакеты найдены, как они сгруппированы packageRules и какие апдейты automerge взял бы себе, если бы не dry-run — это самый быстрый способ отладить конфиг до того, как он начнёт открывать PR в бою.
Частые грабли
- Automerge без
minimumReleaseAge. Без задержки бот способен влить в прод версию, которую вредоносный актор опубликовал час назад. Cooldown в несколько дней — минимальная защита, а не опциональная настройка. - Слишком широкие
packageRules. Правило"matchPackagePatterns": ["*"]с automerge сразу для всего превращает Renovate в инструмент, который сам решает, что попадёт в прод. Правила стоит сужать до конкретныхmatchDepTypesиmatchUpdateTypes. - Забытый
RENOVATE_AUTODISCOVER_FILTER. На self-hosted без фильтра бот пытается открыть PR-ы во всех репозиториях, куда дотягивается токен, — включая те, где Renovate никто не ждал. - Игнорируемый Dependency Dashboard. Если issue никто не открывает месяцами, накапливаются
erroredиawaitingапдейты, о которых команда не знает, — тот же эффект, что и с забытыми PR, просто в одном месте вместо десяти.
Итог
Renovate не убирает необходимость думать об обновлениях — он убирает необходимость делать это вручную и по одному пакету за раз. Группировка снижает шум до уровня, который реально ревьюят, расписание превращает случайные апдейты в предсказуемый еженедельный поток, а minimumReleaseAge и явная граница между dev- и прод-зависимостями держат automerge безопасным по умолчанию. Цена входа — один renovate.json и, для self-hosted, один job в CI. Для команды, которая до сих пор откладывает апдейты «на потом», это самый дешёвый способ сделать их фоновым процессом уже на этой неделе.