Skip to main content
Version: v2

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. Every group except Drupal core also waits 14 days before it proposes a release, which keeps a freshly compromised release out of your project.

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 explains how the updates are grouped, delayed, and merged, how to run Renovate in your own CI, and what renovate.json sets. To check your dependencies for known vulnerabilities instead, 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:

GroupPackagesUpdate typesScheduleMinimum release age
Drupal coredrupal/core-recommended, drupal/core-composer-scaffold, drupal/core-project-message, and drupal/core-devMinor, patchDaily before 2 AM UTCNone
Drupal contrib and PHP packages (non-core)All Drupal contrib modules and non-Drupal Packagist packagesMinor, patchWeekly, Sunday before 2 AM UTC14 days for Packagist packages
JS packagesAll npm packages (root package.json only)Minor, patchWeekly, Sunday before 2 AM UTC14 days
Container imagesImages in .docker/ and docker-compose.yml, and the images CI starts with docker runMajor, minor, patchDaily before 3 AM UTC14 days for Docker Hub images
CI toolsnpm packages that CI runs at a pinned version through npxMajor, minor, patchDaily before 3 AM UTC14 days
Renovate imageThe renovate/renovate image in .circleci/update-dependencies.ymlMajor, minor, patchWeekly, Sunday before 3 AM UTC14 days
GitHub ActionsAll actions, pinned to digestsMajor, minor, patchDaily before 3 AM UTC14 days

A schedule is a window, not a start time. Renovate creates a group's branches only during a run that falls inside the group's window, and the schedule never starts a run on its own.

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, it 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 passing required status checks and any required 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 Vortex CLI asks which groups to auto-merge in its Auto-merge dependency updates prompt, with every group selected by default. It sets the flag to true for the groups you select and to false for the rest. The CI tools choice covers the Renovate image group too. When you update Vortex, the CLI 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​

Renovate holds back a new release until it's 14 days old in every group except Drupal core. 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
}

Renovate creates the branch and the PR only after a release reaches that age, and the top-level "internalChecksFilter": "strict" setting enforces this. When the newest release is too young, Renovate proposes the newest release that's old enough. A grouped PR leaves out the packages that have no release old enough yet. The PR exists only after the delay has passed, so 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, and a daily group 14 to 15 days after.

Drupal core​

Drupal core has no delay, so Renovate proposes a core security release on the next daily run. The core rule in renovate.json carries a description that says so.

Registries without release dates​

Renovate can hold back a release only when its registry records the publication date. Of the registries Vortex uses, 2 record no dates: Drupal.org (Drupal contrib modules) and GitHub Container Registry (the Gitleaks image). Their updates arrive without the delay. The top-level "minimumReleaseAgeBehaviour": "timestamp-optional" setting lets these updates through; without it, Renovate holds 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.

Renovate ages a GitHub Action by the date of the commit its tag points to. The action's publisher controls that date, so the delay is a weaker safeguard for actions than for registry packages.

Security fixes​

When Renovate can read your repository's Dependabot alerts, it raises a fix for a published advisory straight away, skipping the delay and the schedule. Otherwise, a security fix arrives as a routine update and waits like any other. To apply a fix sooner, update the dependency yourself or request the pending update from the Dependency Dashboard.

Changing the delay​

To change a group's delay, edit its minimumReleaseAge. To remove the delay, delete the key. A group with auto-merge turned off keeps its delay, so delete the key too if you want those PRs as soon as a release is published.

The Dependency Dashboard lists updates waiting for the minimum age under Pending Status Checks, where you can also request 1 early. The self-hosted service turns the dashboard off by default: set RENOVATE_DEPENDENCY_DASHBOARD to true to see them.

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 Vortex CLI's Dependency updates provider prompt offers 3 options:

  • Renovate GitHub app, the default: the CLI removes the self-hosted CI configuration, which the app doesn't need.
  • Renovate self-hosted in CI: the CLI keeps the self-hosted job.
  • None: the CLI removes renovate.json.

With either of the last 2 options, the CLI keeps .github/workflows/update-dependencies.yml, even in a CircleCI project. Delete that workflow by hand when GitHub Actions doesn't run Renovate for your project.

note

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, since it has no repository to default to.

Setting up the self-hosted service​

Both versions check renovate.json with Renovate's configuration validator before the update run starts. Pick your CI provider for its setup:

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 the repo scope, plus the workflow scope so Renovate can update the actions in your workflow files. For the permissions of a fine-grained token, see the Renovate GitHub platform documentation.
  • RENOVATE_GIT_AUTHOR: Author for Renovate commits in the format Name <email@example.com> (for example, Renovate Bot <renovate@example.com>), created as a repository variable.

The following optional variables are repository variables too, and their defaults apply when you don't set them:

  • RENOVATE_REPOSITORIES: Repository to run Renovate on in the format yourorg/repo (default: the current repository).
  • RENOVATE_DRY_RUN: Set to true to test runs without making changes (default: false).
  • RENOVATE_DEPENDENCY_DASHBOARD: Set to true to 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 them 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 using 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, but it still opens at most 10 PRs and still 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'.

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.

When you turn it on in self-hosted mode, the issue title names the CI provider that runs Renovate. On GitHub Actions it's "Renovate Dependency Dashboard (self-hosted) by GitHub Actions", and on CircleCI the title ends in "by CircleCI" instead.

Configuration​

The configuration lives in renovate.json. It extends Renovate's config:recommended preset, and 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:

  • composer for composer.json
  • npm for the package.json files
  • dockerfile for the Dockerfiles in .docker/
  • docker-compose for docker-compose.yml
  • github-actions for the workflows in .github/workflows/
  • custom.regex for 4 custom managers: the IMAGE build argument in docker-compose.yml, the docker run and npx --yes lines in .circleci/config.yml and .github/workflows/, and the renovate/renovate image in .circleci/update-dependencies.yml

Other image references in .circleci/config.yml, such as the CircleCI PHP images that the jobs run in, aren't tracked.

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 instead, 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; the schedules in the update rules provide the throttling.
  • 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:

GroupWhat's skippedWhy
PHP majorAll Packagist packages in composer.json, including Drupal core and contribMajor version upgrades might introduce breaking changes
JS majorAll npm packages in the root package.jsonMajor version upgrades might introduce breaking changes
PHP language versionphp constraint in composer.jsonThe constraint stays in line with config.platform.php and the PHP version of the container images
JS language versionsnode, npm in package.jsonThe constraints stay in line with the Node.js and npm versions in the cli container, where npm runs
JS non-root packagesAny package.json not at the rootTheme dependencies are managed separately