Dependency updates
Vortex ships a Renovate configuration that keeps your project's dependencies current. Renovate opens pull requests for new releases of your PHP and JavaScript packages, container images, CI tools and GitHub Actions. Every group auto-merges by default. Most groups also wait 14 days before they propose a release, which gives a registry time to pull a compromised release before it reaches your project. A fix for a published security advisory skips that wait when Renovate can read your repository's advisories.
This page is for the lead or DevOps engineer who sets up Renovate for a
project and decides which updates merge on their own. It covers how updates
are grouped, delayed and merged, running Renovate in your own CI and the
settings in renovate.json. To check your dependencies for known
vulnerabilities, see Dependency audit.
How updates are organized
Renovate opens every pull request from a branch with the deps/ prefix and
labels it Dependencies. To have the pull requests assigned to someone, add
their GitHub usernames to the assignees field.
Update rules
The following table lists the update groups, with the schedule and the delay of each:
| Group | Packages | Update types | Schedule | Minimum release age |
|---|---|---|---|---|
| Drupal core | drupal/core-recommended, drupal/core-composer-scaffold, drupal/core-project-message and drupal/core-dev | Minor, patch | Daily before 2 AM UTC | None |
| Drupal contrib and PHP packages (non-core) | All Drupal contrib modules and non-Drupal Packagist packages | Minor, patch | Weekly, Sunday before 2 AM UTC | 14 days for Packagist packages |
| JS packages | All npm packages (root package.json only) | Minor, patch | Weekly, Sunday before 2 AM UTC | 14 days |
| Container images | Images in .docker/ and docker-compose.yml, and the images CI starts with docker run | Major, minor, patch | Daily before 3 AM UTC | 14 days for Docker Hub images |
| CI tools | npm packages that CI runs at a pinned version through npx | Major, minor, patch | Daily before 3 AM UTC | 14 days |
| Renovate image | The renovate/renovate image in .circleci/update-dependencies.yml | Major, minor, patch | Weekly, Sunday before 3 AM UTC | 14 days |
| GitHub Actions | All actions, and the container images that the jobs in .github/workflows/ run in, all pinned to digests | Major, minor, patch | Daily before 3 AM UTC | 14 days |
A schedule is a time window. Renovate creates a group's branches only during a run that falls inside the group's window. The schedule itself never starts a run.
Renovate publishes several releases a day, so the image that runs Renovate in CircleCI has a group of its own with a weekly schedule. In the daily CI tools group, the Renovate image would get a new pull request almost every day.
Auto-merge
Every group auto-merges by default: GitHub merges the PR as soon as it meets
the base branch's protection rules, such as required status checks and
reviews. Each group in renovate.json lists an explicit automerge flag,
so you can see and change the behavior per group. To merge a group's PRs
yourself, set its flag to false:
{
"groupName": "PHP - Drupal core - Minor and patch",
"groupSlug": "php-drupal-core-minor-patch",
...
"automerge": false
}
The installer's Auto-merge dependency updates prompt asks which groups
to auto-merge, with every group selected by default. It sets the flag to
true for the groups you select and to false for the other groups. The CI
tools choice covers the Renovate image group too. When you update
Vortex, the prompt preselects the groups whose flag is already true,
so your choices carry over.
Auto-merge requires 2 settings in the GitHub repository:
- Allow auto-merge, turned on in Settings > General, under Pull Requests.
- Require status checks to pass before merging, turned on in the base branch's protection rules, with at least 1 required status check selected. Without a required check, GitHub might merge a PR even when CI fails.
Every required status check must also report on deps/* branches. A check
that never reports, such as a CircleCI job that a branch filter excludes
from deps/* branches, keeps the PR blocked indefinitely. A GitHub Actions
job skipped by its if condition reports as skipped, which satisfies the
requirement.
Minimum release age
In every group except Drupal core, Renovate holds back a new release until it's 14 days old, on registries that record release dates. A compromised release is often detected and pulled from its registry within days. Nobody reviews an auto-merged update, so the delay keeps such a release out of your project. Renovate recommends 14 days when you auto-merge third-party dependencies.
Each delayed group sets minimumReleaseAge next to its automerge flag:
{
"groupName": "JavaScript - All packages - Minor and patch",
"groupSlug": "js-all-minor-patch",
...
"minimumReleaseAge": "14 days",
"automerge": true
}
The top-level "internalChecksFilter": "strict" setting makes Renovate
wait to create the branch and the PR until a release reaches that age. When
the newest release is too young, Renovate proposes the newest release that's
old enough. A grouped PR leaves out the packages with no release old enough
yet. Because the PR only exists after the delay has passed, GitHub's
auto-merge can't merge a release early.
The delay adds to each group's schedule. A weekly group proposes a release 14 to 21 days after it's published. A daily group proposes it 14 to 15 days after.
Drupal core
Drupal core has no delay, so a core security release is proposed on the next
daily run. Its rule in renovate.json carries a description that says so.
Registries without release dates
Renovate can only hold back a release when its registry records when the release was published. 2 of the registries Vortex uses don't record release dates, so their updates arrive without the delay:
- Drupal.org, for Drupal contrib modules
- GitHub Container Registry, for the Gitleaks image
The top-level "minimumReleaseAgeBehaviour": "timestamp-optional" setting
lets these updates through. Without it, Renovate would hold them back
indefinitely. The logLevelRemap entry stops Renovate from reporting them
as a repository problem on the Dependency Dashboard.
Docker Hub records release dates, but Renovate can't read them for an image
with more than 1,000 tags. The Renovate image has tens of thousands of tags,
so Vortex looks its versions up in the renovate npm package instead.
The package uses the same version numbers and records a date for every
release.
GitHub Actions are aged by the date of the commit that a tag points to. The action's publisher controls that date, so for actions the delay is a weaker safeguard than for packages from a registry.
Change the delay
To change the delay for a group, edit its minimumReleaseAge. To remove the
delay, delete the key. Turning auto-merge off for a group keeps its delay,
so to get those PRs as soon as a release is published, delete the key too.
The delay applies to routine updates only: a
security fix skips it.
The Dependency Dashboard lists the updates waiting for the minimum age under
Pending Status Checks, where you can request an update early. The
self-hosted service turns the dashboard off by default: to see it, set
RENOVATE_DEPENDENCY_DASHBOARD to true.
Security fixes
Renovate raises a PR for a published security advisory on its next run after it reads the advisory. The PR skips the minimum release age, the group's schedule and the limit on open PRs. It updates the affected dependency to the lowest release that fixes the advisory.
Advisory PRs carry the Dependencies and Security labels, so they stand
apart from routine updates. The vulnerabilityAlerts setting in
renovate.json sets the labels:
"vulnerabilityAlerts": {
"labels": [
"Dependencies",
"Security"
]
},
Let Renovate read advisories
On GitHub, Renovate reads advisories from the repository's Dependabot alerts. Turn on these 2 settings in Settings > Advanced Security:
- Dependency graph
- Dependabot alerts
Both settings are free on every GitHub plan, for private repositories too.
Renovate raises advisory PRs only for the packages listed in
composer.json and package.json and the actions in your workflow files.
Update an indirect dependency that an alert flags yourself.
Dependabot alerts only list advisories in the repository's Security
tab. Dependabot opens PRs through 2 separate features: Dependabot
security updates and version updates from a .github/dependabot.yml
file. Leave both off, so Renovate stays the only bot that opens dependency
PRs.
Renovate also needs permission to read the alerts:
- Renovate GitHub app: read access to Dependabot alerts. Check the app's permissions under Settings > GitHub Apps.
- Self-hosted service: a
RENOVATE_TOKENthat reads Dependabot alerts. A classic token'sreposcope includes that access. A fine-grained token needs the Dependabot alerts repository permission set to Read-only.
Without that access, Renovate gets no advisories. Each security fix then waits like a routine update.
Read advisories from OSV
If your organization blocks Dependabot alerts, Renovate can read
advisories from the OSV database instead. Add
"osvVulnerabilityAlerts": true to renovate.json. Renovate marks the
option as
experimental.
It checks only the dependencies listed in composer.json and
package.json. The self-hosted service downloads the OSV database on
every run.
When Renovate reads no advisories, a security fix arrives as a routine update and waits like any other update. Apply a fix that needs a new major version yourself, because Renovate skips major updates of PHP and JS packages. The dependency audit still reports the advisory in CI. To apply any other fix sooner, update the dependency yourself or request the pending update from the Dependency Dashboard.
Batch security fixes with routine updates
To have security fixes wait for their group's schedule and minimum release age, turn the fast path off:
"vulnerabilityAlerts": {
"enabled": false
},
Leave osvVulnerabilityAlerts off with this setting. With both set,
Renovate skips the dependencies that OSV flags.
Continuous integration
Renovate can run as the hosted GitHub app or as a self-hosted service in CircleCI or GitHub Actions. A self-hosted service suits projects that restrict third-party access to their repositories. The installer's Dependency updates provider prompt offers 3 options:
- Renovate GitHub app, the default: the installer removes the self-hosted CI configuration, which the app doesn't need.
- Renovate self-hosted in CI: the installer keeps the self-hosted job.
- None: the installer removes
renovate.jsonand.circleci/update-dependencies.yml.
With either of the last 2 options, the installer keeps
.github/workflows/update-dependencies.yml, even in a CircleCI project.
When GitHub Actions doesn't run Renovate for your project, delete that
workflow by hand.
If the job is configured but a required variable is missing, the job still
runs and skips the Renovate run without failing the build. Its log shows a
Skipping job. message that names the missing variable. On GitHub Actions,
the required variables are RENOVATE_TOKEN and RENOVATE_GIT_AUTHOR.
CircleCI also requires RENOVATE_REPOSITORIES, because it has no repository
to default to.
Set up the self-hosted service
On both CI providers, the job checks renovate.json with Renovate's
configuration validator before the update run starts. Pick your CI provider
for its setup:
- GitHub Actions
- CircleCI
Create the following required variables in the GitHub repository settings, in Settings > Secrets and variables > Actions:
RENOVATE_TOKEN: A GitHub personal access token, created as a repository secret. A classic token needs thereposcope, plus theworkflowscope so Renovate can update the actions in your workflow files. A fine-grained token also needs read access to Dependabot alerts for security fixes. For its other permissions, see the Renovate GitHub platform documentation.RENOVATE_GIT_AUTHOR: The author of Renovate commits in the formatName <email@example.com>, such asRenovate Bot <renovate@example.com>, created as a repository variable.
The following optional variables are repository variables too. Each one has a default:
RENOVATE_REPOSITORIES: Repository to run Renovate on in the formatyourorg/repo(default: the current repository).RENOVATE_DRY_RUN: Set totrueto test runs without making changes (default:false).RENOVATE_DEPENDENCY_DASHBOARD: Set totrueto enable the dependency dashboard (default:false).
The workflow runs on a schedule at 11:45 and 23:45 UTC every day. Both
times fall outside the schedule windows in renovate.json, which all end
by 3 AM UTC, so a scheduled run opens no PRs for the update groups. To get
PRs from scheduled runs, move the cron times in
.github/workflows/update-dependencies.yml into the windows, or widen the
windows.
Manual trigger: run the workflow from the Actions tab with the
workflow dispatch feature. A manual run ignores the schedules,
prHourlyLimit and branchConcurrentLimit. renovate.json doesn't set
branchConcurrentLimit, so it otherwise takes the prConcurrentLimit value
of 10. A manual run can therefore create more than 10 branches. It still
opens at most 10 PRs and waits for the
minimum release age. Select its
preserve_schedules option to keep the schedules and skip the updates that
aren't due, the way a scheduled run does.
Debug logging: enabled by default with LOG_LEVEL: 'debug'.
Create the following required variables in the CircleCI project settings:
RENOVATE_TOKEN: A GitHub personal access token. A classic token needs thereposcope, plus theworkflowscope so Renovate can update the actions in your workflow files. A fine-grained token also needs read access to Dependabot alerts for security fixes. For its other permissions, see the Renovate GitHub platform documentation.RENOVATE_REPOSITORIES: Repository to run Renovate on in the formatyourorg/repo.RENOVATE_GIT_AUTHOR: The author of Renovate commits in the formatName <email@example.com>, such asRenovate Bot <renovate@example.com>.
The following optional variables each have a default:
RENOVATE_DRY_RUN: Set totrueto test runs without making changes (default:false).RENOVATE_DEPENDENCY_DASHBOARD: Set totrueto enable the dependency dashboard (default:false).
Manual trigger: trigger a pipeline from the CircleCI UI with the
run_update_dependencies pipeline parameter set to true. The manual run
uses the same job and settings as a scheduled run, with no override, so it
keeps the schedules and limits.
Scheduled trigger: add a scheduled trigger under
Project Settings > Triggers with config source update-dependencies.yml
and branch develop. Name it update-dependencies: the workflow runs only
for a scheduled pipeline with that name. The configuration file suggests
11:05 and 23:05 UTC every day. Those times fall outside the schedule windows
in renovate.json too, so to get PRs from scheduled runs, pick times inside
the windows.
Renovate version: the job runs a pinned renovate/renovate image, which
Renovate keeps up to date through the Renovate image group.
Renovate tracks the image only while its tag is a full version such as
44.176.2. It doesn't track a digest or a floating tag such as 44.
Debug logging: enabled by default with LOG_LEVEL: 'debug'.
The self-hosted service runs only on its schedule or when you start it, so a request you tick on the Dependency Dashboard waits for the next run.
Confirm that the job's Run Renovate step ran and that no step printed a
Skipping job. message.
Dependency dashboard
The Renovate Dependency Dashboard is a GitHub issue that tracks the updates Renovate has found. It groups them under headings such as these:
- Awaiting Schedule: updates waiting for their group's schedule window
- Pending Status Checks: updates waiting for their release to reach the minimum release age
- Rate-Limited: updates held back by the limit on open PRs
- Errored: updates that failed and that Renovate retries
- Open: updates that already have a PR
To request an update early, tick its checkbox on the dashboard.
In self-hosted mode, the issue title names the CI provider that runs Renovate:
- On GitHub Actions: "Renovate Dependency Dashboard (self-hosted) by GitHub Actions"
- On CircleCI: "Renovate Dependency Dashboard (self-hosted) by CircleCI"
Configuration
The configuration lives in
renovate.json.
It extends Renovate's config:recommended preset. Its Drupal core and
contrib groups follow the Renovate configuration for automated Drupal
dependency updates project.
Renovate reads only the files that the managers in enabledManagers cover:
composerforcomposer.jsonnpmfor thepackage.jsonfilesdockerfilefor the Dockerfiles in.docker/docker-composefordocker-compose.ymlgithub-actionsfor the workflows in.github/workflows/custom.regexfor 4 custom managers: theIMAGEbuild argument indocker-compose.yml, thedocker runandnpx --yeslines in.circleci/config.ymland.github/workflows/, and therenovate/renovateimage in.circleci/update-dependencies.yml
Renovate leaves the other image references in .circleci/config.yml
untracked, such as the drevops/ci-runner image that the jobs run in.
Renovate raises the version constraint in composer.json and package.json
to each new release ("rangeStrategy": "bump"), the same way Composer's
bump-after-update setting does. Constraints that
end in @dev, @alpha, @beta, @RC or @stable are the exception. A
rule that works around a
Renovate bug gives
them update-lockfile, so Renovate updates only the lock file while the new
release fits the constraint. The rule matches the flags in that exact case,
so a lowercase @rc still gets bump.
Because configMigration is on, Renovate also raises a pull request when it
needs to migrate renovate.json to a newer configuration format.
PR throughput and presentation
The following settings control how many PRs Renovate opens and how they look:
- Concurrent PR limit:
prConcurrentLimit: 10- at most 10 open PRs across all groups at any time. - Hourly PR limit:
prHourlyLimit: 0- no hourly cap, because the schedules in the update rules limit the rate. - Commit body table:
commitBodyTable: true- every update commit carries a table of its updates in the commit message body. - Dashboard labels: the Renovate dependency dashboard issue is labeled
Dependencies(dependencyDashboardLabels).
Disabled updates
Renovate skips these updates on purpose, so you apply them by hand. The following table lists each disabled rule:
| Group | What's skipped | Why |
|---|---|---|
| PHP major | All Packagist packages in composer.json, including Drupal core and contrib | Major version upgrades might introduce breaking changes |
| JS major | All npm packages in the root package.json | Major version upgrades might introduce breaking changes |
| PHP language version | php constraint in composer.json | The constraint stays in line with config.platform.php and the PHP version of the container images |
| JS language versions | node, npm in package.json | The constraints stay in line with the Node.js and npm versions in the cli container, where npm runs |
| JS non-root packages | Any package.json not at the root | Theme dependencies are managed separately |