Перейти к содержимому
Hogin Hogin
Назад

Renovate: автообновление зависимостей, которое не бесит

7 мин чтения

Устаревшие зависимости — самый тихий и самый частый вектор supply-chain инцидентов: команда знает, что нужно обновляться, но ручной PR на каждый пакет никто не осилит, поэтому в бэклоге копятся сотни версий и одна закрытая CVE. Renovate решает это не заменой ручного труда на ручной труд, а автоматизацией всего цикла: сканирует манифесты, группирует апдейты по смыслу и часть из них вливает без участия человека.

Содержание

Открыть содержание

Почему «обновим перед аудитом» больше не работает

Классический процесс обновления зависимостей выглядит как разовая акция. Раз в квартал кто-то из команды садится и полдня разбирает npm outdated или pip list --outdated, открывает пачку PR, разбирается, что сломалось, и мержит то, что прошло тесты. Работает, пока обновлений мало, а версий, отставших от актуальных, — единицы.

Проблема в том, что к моменту такого «разбора» дистанция до актуальной версии уже измеряется десятками релизов, и в диффе между текущей и целевой версией легко потерять breaking change. А «обновим перед аудитом» или «перед релизом» — это ровно тот момент, когда меньше всего хочется чинить внезапно всплывшую несовместимость под дедлайн.

Dependabot частично закрыл проблему для GitHub — он открывает по PR на каждое обновление и умеет базовую группировку через groups в dependabot.yml. Но группировка там ограничена одним измерением за раз (обычно по экосистеме или по паттерну имени), без условий на тип апдейта, зависимость от результата CI или временную задержку после релиза. В активном проекте с полусотней зависимостей это всё равно означает десятки отдельных или полусгруппированных PR в неделю, каждый со своим прогоном CI. Смотреть на такое некому, и через месяц PR-ы просто закрывают пачкой не глядя — что окончательно убивает саму цель автоматизации.

Поток отдельных PR против группировки апдейтов

Чем Renovate отличается по существу

Renovate — не просто «ещё один бот, который открывает PR». Ключевое отличие — конфигурируемость самого процесса и мультиплатформенность.

Расшариваемые конфиги через extends — ещё одна деталь, которая экономит время на масштабе организации. Пресет config:recommended в примере ниже — это готовый набор разумных дефолтов от самого Renovate; свой пресет можно опубликовать отдельным репозиторием и подключать той же строкой во всех проектах компании, вместо копирования renovate.json вручную.

Renovate: расписание, сканирование манифестов, группировка, PR или automerge

Сравнение в одной таблице

Ручной апдейтDependabotRenovate
ПлатформыGitHubGitHub, GitLab, Bitbucket, Azure DevOps, self-hosted
Группировка апдейтоввручнуюограниченная (groups)гибкие packageRules, любые срезы
Расписаниенетограниченноеполноценный cron-подобный schedule
Automergeнетбазовыйда, с условиями по типу апдейта и cooldown
Self-hostedнетда (renovate CLI или job в CI)
Сводка состояниянетвкладка PRDependency 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 в бою.

Частые грабли

Итог

Renovate не убирает необходимость думать об обновлениях — он убирает необходимость делать это вручную и по одному пакету за раз. Группировка снижает шум до уровня, который реально ревьюят, расписание превращает случайные апдейты в предсказуемый еженедельный поток, а minimumReleaseAge и явная граница между dev- и прод-зависимостями держат automerge безопасным по умолчанию. Цена входа — один renovate.json и, для self-hosted, один job в CI. Для команды, которая до сих пор откладывает апдейты «на потом», это самый дешёвый способ сделать их фоновым процессом уже на этой неделе.


Поделиться:

Следующая статья
KEDA: автоскейлинг по событиям и до нуля