Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français
Lire en français

Renovate: automate dependency updates

29 min read
Improve this page

Logo Renovate

Renovate automates the updates of your software dependencies by creating testable, traceable and mergeable Pull Requests. This guide teaches you how to install, configure and secure it. You will be able to adapt the update strategies to your project (scheduling, automerge, grouping) and harden your installation against supply chain attacks. Prerequisites: Node.js 24.11+ installed and access to a Git repository (GitHub, GitLab, Bitbucket or other).

What you will learn

  • Install Renovate and run a first local dry-run.
  • Configure presets, scheduling and automerge.
  • Customize updates with packageRules, custom managers and grouping.
  • Secure a self-hosted installation against supply chain attacks.
  • Run Renovate in CI/CD (GitHub Actions, GitLab CI).

What is Renovate?

Renovate continuously watches the libraries of your project, checks whether newer versions are available, and prepares an automatically tested update, ready to merge.

Renovate is an open source tool (AGPL license) maintained by Mend.io. It analyzes your dependency files (package.json, Dockerfile, docker-compose.yml, requirements.txt, go.mod, pom.xml, Terraform files, Ansible playbooks, GitHub Actions, and many more), detects outdated versions, and automatically creates Pull Requests (PRs) with the matching updates.

Without RenovateWith Renovate
Manual version checksAutomatic update detection
Risk of forgetting dependenciesCoverage of all recognized dependency files
No traceability of decisionsFull history in the PRs
Vulnerabilities that stay undetected for a long timeUpdate proposed as soon as a fixed version is published

Renovate supports a very large number of package managers (called managers, the full list is in the documentation): JavaScript (npm, Yarn, pnpm), Python (pip, Poetry, Pipenv), Java (Maven, Gradle), Go, Rust, Ruby, .NET, PHP, Helm, Terraform, Ansible, Docker, GitHub Actions, and many more.

Prerequisites

Before starting, check that you have:

  • Node.js 24.11 or higher: Renovate is installed through npm. Check with node -v.
  • A Git repository hosted on GitHub, GitLab, Bitbucket, Azure DevOps, Forgejo or Gitea.
  • A Personal Access Token (PAT) with the necessary rights on your platform (detailed below).
  • Basic Git knowledge: knowing what a branch and a Pull Request are.

How Renovate works

Understanding how Renovate works internally helps you configure it better. On each run, Renovate goes through five phases:

Phase 1, Initialization. Renovate clones the repository, reads the configuration (renovate.json) and resolves the extended presets. It checks whether the repository is already onboarded (that is, whether it has a configuration file).

Phase 2, Dependency extraction. The managers go through the files of the project to identify all the declared dependencies. Each manager knows how to read a specific format: the npm manager reads package.json, the dockerfile manager reads FROM instructions, the terraform manager reads the required_providers blocks, and so on.

Phase 3, Update lookup. For each extracted dependency, Renovate queries the matching datasource (the npm registry, Docker Hub, PyPI, etc.) to find the available versions. It compares the current version with the published versions and determines the applicable updates.

Phase 4, Writing the updates. Renovate generates the necessary changes: it creates branches, updates the dependency files (including the lock files), and opens the Pull Requests on the platform.

Phase 5, Finalization. Renovate updates the Dependency Dashboard (if enabled), handles the automerge of the PRs that passed the tests, and cleans up the stale branches.

The diagram shows these five phases in the order of a run. The highlighted phase, lookup, is the one that queries the registries: it decides which updates apply.

A Renovate run in five phases: initialization, dependency extraction by the managers, version lookup through the datasources, writing branches and PRs, then finalization with the Dependency Dashboard and automerge.Initializationclone · renovate.json · presetsExtractionmanagers: package.json, FROM…Lookupdatasources: npm, Docker Hub…Writingbranches, lock files, PRsFinalizationDependency Dashboard, automerge
Source · SVG
Esc to close, + and − to zoom, scroll to move around. 100 %

Installation and first run

  1. Install Renovate globally

    Open a terminal and install the npm package:

    Terminal window
    npm install -g renovate

    Check: run renovate --version. You should see a version number (for example 43.278.5).

  2. Create the Personal Access Tokens

    Renovate needs two tokens to work:

    • RENOVATE_GITHUB_COM_TOKEN: a classic PAT on github.com with the public_repo scope. It is used to fetch changelogs and avoid API limits.
    • RENOVATE_TOKEN: a PAT with the repo and workflow scopes on the target repository.

    Export the tokens in your terminal:

    Terminal window
    export RENOVATE_GITHUB_COM_TOKEN="ghp_your_github_token"
    export RENOVATE_TOKEN="your_platform_token"

    You will still come across the old name GITHUB_COM_TOKEN in existing configurations. The Renovate documentation declares it deprecated, and it will be removed in an upcoming major version. It is still read in the meantime, and it takes precedence over the new name if both are defined: delete it when you switch to RENOVATE_GITHUB_COM_TOKEN, otherwise the old token is the one used.

  3. Create the configuration file

    At the root of your repository, create a renovate.json file:

    {
    "$schema": "https://docs.renovatebot.com/renovate-schema.json",
    "extends": ["config:recommended"]
    }

    The config:recommended preset enables the settings recommended by the Renovate team: grouping of non-major updates by monorepo, a limit on concurrent PRs, and activation of the Dependency Dashboard.

  4. Run a local dry-run

    Before running Renovate on a real repository, test it in local mode to see what it detects without creating any branches or PRs:

    Terminal window
    LOG_LEVEL=debug renovate --platform=local --dry-run=lookup

    This mode analyzes the current directory, identifies the dependencies and the available updates, then stops without modifying anything. Browse the logs to check that Renovate detects your files properly.

  5. Run Renovate on a remote repository

    Once you are happy with the dry-run, run Renovate on a real repository:

    Terminal window
    renovate --platform=github your-org/your-repo

    Or for GitLab:

    Terminal window
    renovate --platform=gitlab --endpoint=https://gitlab.com/api/v4 your-org/your-repo

    On the first run, Renovate creates an onboarding PR that proposes a renovate.json file. Merge this PR to enable Renovate on your repository.

Basic configuration

The configuration files

Renovate looks for its configuration in one of these files, in order of priority:

FileFormat
renovate.jsonStandard JSON
renovate.json5JSON5 (comments allowed)
.renovatercJSON or JSON5
.renovaterc.jsonJSON
renovate section in package.jsonJSON

In practice, renovate.json is the most common choice. If you prefer to add comments to document your configuration, use the JSON5 format with renovate.json5.

Understanding presets

Presets are reusable configurations. Instead of configuring everything by hand, you extend an existing preset: you start from a consistent base and only override what differs.

The most common built-in presets:

PresetRole
config:recommendedRecommended base configuration
config:best-practicesStronger recommendations (includes minimumReleaseAge for npm)
:dependencyDashboardEnables the dependency dashboard (included in config:recommended)
schedule:nonOfficeHoursLimits updates to outside office hours
group:allNonMajorGroups all minor and patch updates into a single PR
:automergeDigestAutomerges Docker digest updates

Here is an example combining several presets:

{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
"schedule:nonOfficeHours",
":automergeDigest"
]
}

Update strategies

Semantic versioning (SemVer)

Most ecosystems follow the SemVer convention: MAJOR.MINOR.PATCH. Each type of update carries a different risk:

  • Patch (e.g. 1.2.3 → 1.2.4): bug fixes. Very low risk.
  • Minor (e.g. 1.2.3 → 1.3.0): new backward-compatible features. Low risk.
  • Major (e.g. 1.2.3 → 2.0.0): changes that may break backward compatibility. High risk.

Renovate distinguishes these three types and lets you configure a different behavior for each. The config:recommended preset automatically separates major updates from the others.

Adapting the strategy by update type

Here is a typical configuration that automatically merges patches and minors while keeping majors for a manual review:

{
"extends": ["config:recommended"],
"packageRules": [
{
"description": "Automerge patches and minors (excluding v0.x)",
"matchUpdateTypes": ["minor", "patch"],
"matchCurrentVersion": "!/^0/",
"automerge": true
}
]
}

The matchCurrentVersion: "!/^0/" condition excludes packages in 0.x versions, because SemVer allows breaking changes on any update before version 1.0.0. The /^0/ pattern is a regular expression that designates versions starting with 0, and the leading ! inverts it.

The range strategy

The rangeStrategy option controls how Renovate modifies the version constraints in your files. The possible values are:

StrategyBehaviorTypical use
bumpRaises the lower bound (^1.2.3 → ^1.3.0)Applications with a lock file
replaceWidens the range if possible (^1.2.3 → ^1.3.0 if compatible)Published libraries
pinPins the version exactly (^1.2.3 → 1.3.0)Maximum reproducibility
widenWidens the range (^1.2.3 → ^1.2.3 || ^2.0.0)Libraries supporting several majors
autoLets Renovate decide depending on the contextDefault value

For an application project (not published as a library), the bump strategy is generally the best choice because it makes updates explicit in the lock file.

Scheduling updates

By default, Renovate is "always on": it creates PRs as soon as it finds an update. This can become noisy on projects with many dependencies. The schedule option lets you control the execution windows.

Setting a time zone

Renovate uses UTC by default. To use your local time, configure the time zone with an IANA identifier:

{
"timezone": "Europe/Paris"
}

Scheduling examples

Renovate recommends the cron syntax (5 fields) for schedules. The asterisk * is mandatory for the minutes because Renovate does not support minute granularity:

{
"extends": ["config:recommended"],
"timezone": "Europe/Paris",
"schedule": ["* 0-4 * * 1-5", "* * * * 0,6"]
}

This configuration means: run the updates on weekdays between midnight and 5 a.m., and at any time on weekends.

Other common examples:

NeedCronEquivalent preset
Outside office hours* 0-4,22-23 * * 1-5 + * * * * 0,6schedule:nonOfficeHours
Weekends only* * * * 0,6schedule:weekends
Monday morning before 6 a.m.* 0-5 * * 1none
Quarterly, on the 1st of the month* * 1 */3 *none

Limiting the frequency for a specific package

Some libraries publish very often (AWS SDK, TypeScript types...). You can apply a dedicated schedule to them to reduce the noise:

{
"packageRules": [
{
"description": "AWS SDK: weekly updates only",
"matchPackageNames": ["@aws-sdk/**"],
"schedule": ["* 21-23 * * 0"]
}
]
}

Automerge: merging automatically

Automerge lets Renovate merge a PR without human intervention as soon as the CI tests pass. This feature is ideal for low-risk updates: devDependencies patches, lock file updates, or Docker digests.

When to enable automerge

The Renovate team recommends enabling automerge for any update that you would systematically merge anyway. In practice, this often covers:

  • devDependencies (linters, test tools, formatters)
  • Minor and patch updates on well-tested projects
  • Lock file maintenance (refresh with no change of the declared version)
  • Docker digests (hash update with no tag change)

Automerge configuration examples

Automerge of linter devDependencies:

{
"packageRules": [
{
"description": "Automerge dev tools",
"matchDepTypes": ["devDependencies"],
"matchPackageNames": ["eslint", "prettier", "vitest"],
"automerge": true
}
]
}

Automerge of all non-major updates:

{
"packageRules": [
{
"description": "Automerge non-major excluding v0.x",
"matchUpdateTypes": ["minor", "patch"],
"matchCurrentVersion": "!/^0/",
"automerge": true
}
]
}

Automerge of lock file maintenance:

{
"lockFileMaintenance": {
"enabled": true,
"automerge": true,
"schedule": ["* * * * 0"]
}
}

Branch automerge vs PR automerge

By default, Renovate creates a PR and then merges it through the platform (platformAutomerge). You can configure a quieter mode with automergeType: "branch": Renovate only creates a branch, and if the tests pass, it pushes the commit directly to the target branch without creating a PR. If the tests fail, it then creates a PR so that you can investigate.

{
"automergeType": "branch"
}

Dependency Dashboard

The Dependency Dashboard is an issue that Renovate creates in your repository. It serves as a centralized dashboard showing the state of all the updates: in progress, pending, closed or ignored.

The config:recommended preset enables the Dashboard by default. If you want to enable it manually:

{
"dependencyDashboard": true
}

The Dashboard provides three features that are particularly useful in a team context.

Visibility of ignored updates. If someone closes a Renovate PR without merging it, the update appears in the "Closed/Ignored" section of the Dashboard. You can relaunch it with one click by ticking the matching checkbox.

Approval workflow. For sensitive updates, you can ask Renovate to wait for an explicit approval before creating the PR. This approval is given by ticking a checkbox in the Dashboard:

{
"major": {
"dependencyDashboardApproval": true
}
}

With this configuration, major updates appear only in the Dashboard. Renovate only creates the PR when you tick the matching checkbox. Minor and patch updates continue as usual.

Abandonment detection. The config:best-practices preset includes abandonments:recommended, which flags packages that have not published any update for more than a year. These warnings appear at the top of the Dashboard to alert you to potentially abandoned dependencies.

Advanced configuration

The packageRules

The packageRules are the central mechanism to customize Renovate's behavior per dependency, group of dependencies, update type or any other criterion. Each rule is an object with matchers (selection criteria) and options to apply.

The main matchers:

MatcherRoleExample
matchPackageNamesPackage name (glob or regex)["react", "@types/**"]
matchDepTypesDependency type["devDependencies"]
matchUpdateTypesUpdate type["major", "minor", "patch"]
matchDatasourcesData source["docker", "npm"]
matchFileNamesSource file["docker-compose*.yml"]
matchManagersPackage manager["dockerfile", "helm-values"]
matchCurrentVersionCurrent version (regex)"!/^0/"

Here is a complete example combining several rules:

{
"extends": ["config:recommended"],
"packageRules": [
{
"description": "Group the React packages",
"matchPackageNames": ["react", "react-dom", "@types/react"],
"groupName": "react monorepo"
},
{
"description": "Automerge lint tools",
"matchPackageNames": ["eslint*", "prettier"],
"matchUpdateTypes": ["minor", "patch"],
"automerge": true
},
{
"description": "Block Node.js 22+ updates",
"matchPackageNames": ["node"],
"matchUpdateTypes": ["major"],
"enabled": false
},
{
"description": "Limit Terraform providers to the weekend",
"matchManagers": ["terraform"],
"matchDatasources": ["terraform-provider"],
"schedule": ["* * * * 0,6"]
}
]
}

The rules are evaluated in order: the last rule that matches a dependency takes priority for each option it defines.

Custom Managers

The customManagers let Renovate detect dependencies in files with a non-standard format. Renovate supports two types of custom managers: regex and jsonata.

The regex type is the most common. You write a regular expression (in French) that captures the necessary information: depName, currentValue, and datasource.

Let us take a concrete example: you have a shell script that downloads an Ubuntu cloud image, and you want Renovate to detect and update the version automatically.

In your download-ubuntu.sh script:

Terminal window
# renovate: datasource=github-releases depName=canonical/cloud-init
CLOUD_INIT_VERSION="24.4"

In renovate.json:

{
"customManagers": [
{
"customType": "regex",
"managerFilePatterns": ["/\\.sh$/"],
"matchStrings": [
"#\\s*renovate:\\s*datasource=(?<datasource>.*?)\\s+depName=(?<depName>.*?)\\n.*?VERSION=\"(?<currentValue>.*?)\""
]
}
]
}

The structured comment # renovate: datasource=... depName=... in the source file provides the context the regex needs. This convention makes any file "renovatable" without changing its format.

The pattern reads in three parts: the comment (#\s*renovate:\s*datasource=, where \s* accepts spaces), the values captured by named groups ((?<datasource>.*?) and (?<depName>.*?), where .*? takes as few characters as possible), then, on the next line, VERSION="...", whose content becomes currentValue. In the JSON, each backslash is doubled (\\s for \s), because the backslash is already the escape character of JSON. The basic syntax is the one from the lesson Regular expressions in Python (in French), with one difference: a group name is written here (?<name>...), there (?P<name>...).

The managerFilePatterns field lists the files to analyze. A regular expression is written there between slashes ("/\\.sh$/"); without them, the value is read as a glob ("**/*.sh"). It replaces fileMatch: managerFilePatterns is available from 40.2.0 (May 2025), fileMatch has no longer been a documented option since Renovate 41.0.0, and an old configuration is migrated automatically. The datasource can also come from a datasourceTemplate field instead of the comment.

Custom Datasources

When the versions of a tool are not published on a classic registry (npm, PyPI, Docker Hub...), you can create a customDatasource that queries a custom URL:

{
"customDatasources": {
"UbuntuCloudImages": {
"defaultRegistryUrlTemplate": "https://cloud-images.ubuntu.com/releases/24.04/",
"format": "html"
}
},
"packageRules": [
{
"matchDatasources": ["custom.UbuntuCloudImages"],
"extractVersion": "^release-(?<version>\\d+)/$"
}
]
}

The supported formats are json, plain, html and yaml. The extractVersion field uses a regex to extract the version number from the returned content.

Grouping updates

By default, Renovate creates a separate PR per dependency. On a large project, this can generate dozens of PRs. Grouping (groupName) gathers several dependencies into a single PR:

{
"packageRules": [
{
"description": "Group all AWS SDK dependencies",
"matchPackageNames": ["@aws-sdk/**"],
"groupName": "AWS SDK"
},
{
"description": "Group all non-major updates into one PR",
"matchUpdateTypes": ["minor", "patch"],
"groupName": "all non-major dependencies",
"groupSlug": "all-minor-patch"
}
]
}

The group:allNonMajor preset does exactly this, concisely:

{
"extends": ["config:recommended", "group:allNonMajor"]
}

Limiting the number of PRs

To avoid overload, Renovate offers several limiters:

OptionRoleDefault value
prConcurrentLimitMax number of PRs open in parallel10
prHourlyLimitMax number of PRs created per hour2
branchConcurrentLimitMax number of active branches10
{
"prConcurrentLimit": 5,
"prHourlyLimit": 1
}

Securing Renovate

Renovate runs code coming from your repositories (install scripts, post- upgrade tasks). On a self-hosted installation shared between several teams, a bad configuration can turn Renovate into a supply chain attack vector. This section details the risks and the countermeasures.

Risk 1, Autodiscovery without a filter

When autodiscover: true is enabled without restriction, Renovate will process all the repositories the bot has access to. On GitLab, an attacker can invite the bot into a booby-trapped repository (on GitLab, accepting an invitation is automatic), and on the next run, Renovate clones the malicious repository and runs its scripts.

For example, a booby-trapped Gradle repository with a modified gradlew will run arbitrary code during the dependency resolution phase, because Renovate invokes the language's native manager.

Countermeasure: always restrict autodiscovery with an explicit filter:

{
"autodiscover": true,
"autodiscoverFilter": ["my-org/frontend-*", "my-org/backend-*"]
}

Or better, use a fixed list of repositories in your self-hosted global configuration:

{
"repositories": ["my-org/web-app", "my-org/backend-api"]
}

Risk 2, Install scripts and environment variables

Two self-hosted options are particularly dangerous if they are badly configured:

  • allowScripts: true lets repositories run the postinstall, prepare, etc. scripts during npm install. A malicious package can place arbitrary code there.
  • exposeAllEnv: true passes all the environment variables of the Renovate process on to the subprocesses. The RENOVATE_TOKEN token can be exfiltrated through a crafted commit message.

Countermeasure: keep the default values and explicitly configure what you need:

{
"allowScripts": false,
"exposeAllEnv": false,
"ignoreScripts": true,
"allowedCommands": []
}

If you need a specific post-upgrade script, restrict it with a strict regex in allowedCommands:

{
"allowedCommands": ["^npm run lint:fix$", "^go mod tidy$"]
}

Risk 3, Automerge without a security delay

If automerge is enabled without a cooldown period, a compromised npm package can be published and merged into your project within minutes, before anyone detects the problem. This is called the golden hour of the supply chain attack.

Countermeasure: enable minimumReleaseAge to impose a delay between the publication of a version and its adoption by Renovate:

{
"extends": ["config:best-practices"],
"minimumReleaseAge": "3 days"
}

The config:best-practices preset already includes a minimumReleaseAge of 3 days for the npm ecosystem. You can adjust it per dependency through the packageRules.

Risk 4, Race condition on automerge (GitLab)

On GitLab, a malicious developer with a developer role can add a commit to the branch of a Renovate MR before the bot enables automerge. If the timing is right, the unreviewed commit is automatically merged into the protected branch, bypassing the four-eyes review principle.

Countermeasure: configure GitLab to allow automerge only if the CI pipeline has been rerun after the last commit:

Complete hardened self-hosted configuration

For a secure self-hosted installation, combine all the countermeasures in your global configuration (a config.js file or environment variables):

// config.js - hardened self-hosted global configuration
module.exports = {
platform: 'gitlab',
endpoint: 'https://gitlab.example.com/api/v4',
token: process.env.RENOVATE_TOKEN,
// Restrict the repositories processed
autodiscover: true,
autodiscoverFilter: ['my-org/frontend-*', 'my-org/backend-*'],
// Block the execution of arbitrary code
allowScripts: false,
exposeAllEnv: false,
allowedCommands: ['^npm run lint:fix$'],
// Security delay
extends: ['config:best-practices'],
// Audit the actions
repositoryCache: 'enabled',
};

Running Renovate in CI/CD

In production, Renovate is rarely launched by hand. It is integrated into a CI/CD pipeline that runs it at regular intervals (typically every hour or every night).

Use the official action renovatebot/github-action:

.github/workflows/renovate.yml
name: Renovate
on:
schedule:
- cron: '0 */2 * * *' # Every 2 hours
workflow_dispatch:
permissions: {}
jobs:
renovate:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: renovatebot/github-action@3064367f740a1a91cca218698a63902689cce200 # v46.1.20
with:
configurationFile: renovate.json
token: ${{ secrets.RENOVATE_TOKEN }}
env:
RENOVATE_GITHUB_COM_TOKEN: ${{ secrets.RENOVATE_GITHUB_COM_TOKEN }}

Troubleshooting

SymptomLikely causeSolution
Renovate creates no PRRepository not yet onboardedMerge the onboarding PR, or check that renovate.json exists
Automerge does not workProtected branch with mandatory reviewsSet platformAutomerge: true and add the bot as an authorized author
"Automerge: Disabled by config" in the PRIncorrect automerge configurationCheck the packageRules: the last matching rule takes priority
PRs created then closed immediatelyRate limit reached or lock file in conflictCheck the logs with LOG_LEVEL=debug, check prConcurrentLimit
Lock file not updatedPackage manager not foundIn self-hosted, check binarySource and that the tools are installed
Dependency Dashboard not createdFeature not supported by the platformThe Dashboard requires Markdown issues (not supported on Bitbucket Server)
"Cannot find manager" in the logsFile format not recognizedCheck the file name or create a customManager
A customManager detects nothingPattern refused by RE2 (lookaround assertion, backreference) or managerFilePatterns without slashes read as a globRemove (?=...), (?<=...) and \1 from the pattern; write "/\\.sh$/" for a regex
Too many PRsNo schedule or limit configuredAdd schedule, prConcurrentLimit and consider group:allNonMajor

Key takeaways

  1. Renovate automates the creation of PRs to update your dependencies, covering a very large number of package managers.
  2. Presets (config:recommended, config:best-practices) offer a solid base without complex manual configuration.
  3. Automerge reduces the workload for low-risk updates (patches, devDependencies, lock files), but always require passing CI tests.
  4. The Dependency Dashboard centralizes visibility on all the updates and allows an approval workflow for sensitive changes.
  5. minimumReleaseAge is a first protection against supply chain attacks: impose a delay before adopting a new version.
  6. In self-hosted mode, never enable autodiscover without a filter, nor allowScripts or exposeAllEnv without an explicit reason.
  7. The packageRules allow granular control: group, schedule, automerge or block per dependency, manager or update type.
  8. The customManagers detect versions in non-standard files: files are declared with managerFilePatterns (regex between /…/, otherwise glob), and patterns run with RE2, without lookaround assertions or backreferences.

Next steps

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn