Automating Dependency Updates with Renovate

Permalink to "Automating Dependency Updates with Renovate"

Part of Continuous Dependency Monitoring, this page gives a production renovate.json and its Dependabot equivalent for turning dependency drift and security advisories into reviewable pull requests automatically.

Quick Reference

Permalink to "Quick Reference"
Property Value
Config file location renovate.json (repo root) — also .github/renovate.json, .renovaterc.json, or renovate key in package.json
Schema https://docs.renovatebot.com/renovate-schema.json
Base preset extends: ["config:recommended"]
Routine schedule schedule: ["before 6am on monday"]
Security fix schedule vulnerabilityAlerts.schedule: ["at any time"]
Version strategy rangeStrategy: "pin" (applications)
Lockfile refresh lockFileMaintenance: { enabled: true }
Patch automerge packageRules[].automerge: true on matchUpdateTypes: ["patch"]
Status surface Dependency Dashboard issue + per-PR checks

Keep one configuration file per repository. Renovate reads it on every run and reconciles open pull requests against it, so the file is the single source of truth for update behaviour.

How Renovate Automates the Update Feed

Permalink to "How Renovate Automates the Update Feed"

Renovate runs as a hosted GitHub App (or a self-hosted job), scans your manifests and lockfile against the registry, and opens a pull request for every dependency that has a newer version — with the lockfile already regenerated and a changelog in the description. It runs in two modes from one config: a slow, batched cadence governed by schedule for routine upkeep, and an immediate, out-of-band pull request driven by vulnerabilityAlerts when an update closes a known advisory. This is the remediation half of a monitoring loop — the detection half (advisory feeds and CI audit gates) and the triage flow that decides what to do with each finding are covered in the parent workflow.

Renovate Update Flow Diagram showing renovate.json and the lockfile feeding the Renovate app, which emits routine version-bump pull requests on a weekly schedule and security pull requests immediately. renovate.json config lockfile resolved deps Renovate scan + resolve Routine PR weekly window Security PR at any time schedule advisory

Canonical Implementation

Permalink to "Canonical Implementation"

The following renovate.json is a complete, production-ready configuration for a deployed application. Commit it to the repository root.

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:recommended",
    ":dependencyDashboard",
    ":semanticCommits"
  ],
  "timezone": "UTC",
  "schedule": ["before 6am on monday"],
  "prConcurrentLimit": 5,
  "prHourlyLimit": 2,
  "rangeStrategy": "pin",
  "rebaseWhen": "conflicted",
  "labels": ["dependencies"],
  "lockFileMaintenance": {
    "enabled": true,
    "schedule": ["before 6am on monday"]
  },
  "vulnerabilityAlerts": {
    "labels": ["security", "dependencies"],
    "schedule": ["at any time"],
    "prPriority": 10
  },
  "packageRules": [
    {
      "description": "Automerge patch updates once CI is green",
      "matchUpdateTypes": ["patch", "pin", "digest"],
      "automerge": true,
      "automergeType": "pr",
      "platformAutomerge": true
    },
    {
      "description": "Group all non-major dev tooling into one PR",
      "matchDepTypes": ["devDependencies"],
      "matchUpdateTypes": ["minor", "patch"],
      "groupName": "dev dependencies"
    },
    {
      "description": "Require manual review for major bumps",
      "matchUpdateTypes": ["major"],
      "automerge": false,
      "addLabels": ["breaking"]
    }
  ]
}

The vulnerabilityAlerts.schedule of "at any time" is what makes security fixes bypass the Monday window; prPriority: 10 floats them above routine pull requests when the concurrency limit is reached. rangeStrategy: "pin" rewrites "^5.4.0" to an exact "5.4.10" so every install is reproducible.

Variant Examples

Permalink to "Variant Examples"

Dependabot equivalent (dependabot.yml)

Permalink to "Dependabot equivalent (dependabot.yml)"

If you prefer GitHub’s native bot, the closest equivalent lives at .github/dependabot.yml. Dependabot has no direct analogue to rangeStrategy: pin (it respects your manifest ranges) or lockFileMaintenance, but it covers scheduling and grouping:

version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      time: "06:00"
      timezone: "UTC"
    open-pull-requests-limit: 5
    labels: ["dependencies"]
    groups:
      dev-dependencies:
        dependency-type: "development"
        update-types: ["minor", "patch"]

Security fixes are handled separately by Dependabot’s own security-updates feature, which is enabled at the repository level rather than in this file and always runs immediately.

Grouping monorepo packages

Permalink to "Grouping monorepo packages"

In a monorepo, collapse related ecosystem updates into a single pull request so reviewers see one coherent change instead of a dozen:

{
  "packageRules": [
    {
      "description": "One PR for the whole ESLint toolchain",
      "matchPackageNames": ["eslint"],
      "matchPackagePrefixes": ["@typescript-eslint/", "eslint-config-", "eslint-plugin-"],
      "groupName": "eslint"
    }
  ]
}

Automerge only patch, hold minor and major

Permalink to "Automerge only patch, hold minor and major"

To automerge patch updates while still requiring review for anything that could change behaviour, scope automerge narrowly and disable it explicitly for the wider types:

{
  "packageRules": [
    { "matchUpdateTypes": ["patch"], "automerge": true },
    { "matchUpdateTypes": ["minor", "major"], "automerge": false, "dependencyDashboardApproval": true }
  ]
}

dependencyDashboardApproval: true holds minor and major updates in the Dependency Dashboard until you tick a checkbox, so they never open unsolicited.

Gotchas and Edge Cases

Permalink to "Gotchas and Edge Cases"
  • Automerge is only as safe as your test suite. platformAutomerge will merge a green pull request with no human in the loop. If CI does not exercise the updated code path, a broken — or maliciously republished — patch reaches the default branch unreviewed. Restrict automerge to patch/pin/digest, keep a required status check, and never automerge minor or major.

  • rangeStrategy: pin changes the meaning of your manifest. Pinning rewrites caret and tilde ranges to exact versions, so your package.json becomes a list of frozen versions and Renovate itself becomes the only path to an upgrade. That is the intent for a deployed application, but it is the wrong default for a published library, where consumers need range flexibility — use bump or widen there instead.

  • lockFileMaintenance is noisy if left on a tight schedule. It refreshes the entire lockfile — every transitive pin — on its cadence, which can produce a large, hard-to-review diff. Keep it on the same weekly window as routine updates, not "at any time", or it will open a sprawling pull request whenever any transitive dependency ships a release.

  • Security fixes silently wait if vulnerabilityAlerts is unset. Without an explicit vulnerabilityAlerts block, advisory fixes are subject to your routine schedule and can sit unopened until the next window — up to a week of avoidable exposure. Always give it "schedule": ["at any time"]. The block also requires that Dependabot alerts are enabled on the repository, since Renovate reads that feed to know a package is vulnerable.

  • Concurrency limits can starve the security queue. With prConcurrentLimit reached by routine bumps, a new security pull request may not open until a slot frees. Setting prPriority high on vulnerabilityAlerts (as in the canonical config) ensures the security fix jumps ahead rather than queueing behind cosmetic updates.

Verification Steps

Permalink to "Verification Steps"

1. Dry-run the configuration locally

Permalink to "1. Dry-run the configuration locally"

Before relying on the hosted app, run Renovate in dry-run mode to see exactly which pull requests it would open without creating any:

LOG_LEVEL=debug npx renovate --dry-run=full --platform=github \
  --token="$RENOVATE_TOKEN" OWNER/REPO

Expected output — the log lists each detected update and the branch it would create, and confirms no writes occurred:

INFO: Dependency extraction complete {"deps": 42}
INFO: DRY-RUN: Would create PR: Update dependency vite to v5.4.10
INFO: DRY-RUN: Would automerge PR after checks
INFO: Renovate is exiting with a success code

2. Validate the config file schema

Permalink to "2. Validate the config file schema"

Catch a malformed renovate.json before it reaches a run:

npx --package renovate -c renovate-config-validator

Expected output on a valid file:

 INFO: Validating renovate.json
 INFO: Config validated successfully

3. Confirm behaviour on the Dependency Dashboard

Permalink to "3. Confirm behaviour on the Dependency Dashboard"

After the first real run, open the Dependency Dashboard issue Renovate creates. It lists open pull requests, pending scheduled updates, and any awaiting-approval items. A security fix should appear under Open immediately with the security label, while routine bumps sit under Pending with their next scheduled time. If a security fix is stuck under Pending, the vulnerabilityAlerts block is missing or Dependabot alerts are not enabled on the repository.


Permalink to "Related"
Continuous Dependency Monitoring Supply Chain Auditing & Depend…