Skip to main content
03 November 2026
Tags
Build

How we use Renovate to automate Drupal maintenance and keep sites secure

Because patch Wednesday is now every Wednesday
Profile picture for user Bill Seremetis
Bill Seremetis
Drupal Developer

Bill has been part of the Drupal community since 2008. He works on support, site security and performance for Annertech clients.

The Renovate logo is shown alongside three websites.

With security advisories landing every week, keeping Drupal sites up to date by hand simply doesn’t scale any more. Here is how we use Renovate to automate the heavy lifting – turning a relentless pile of updates into quick, stress-free code reviews.

There was a time when keeping a Drupal site up to date meant checking the security advisories on Wednesday evening to see if any were announced, running composer update on the handful of sites that needed it, and moving on.

We would get Core security advisories every 2-4 months and contrib security advisories that would actually affect sites (high usage modules) every couple of months.

That time is gone.

Every week now brings new security advisories, and lately they come by the dozen. Not because the code got worse overnight, but because finding vulnerabilities got cheap, and fast. AI-assisted tooling reads code faster and more patiently than any human reviewer, and it is pointed at everything: core, contrib, the PHP libraries underneath, the JavaScript on top. The people reporting issues use it. So do the people who do not report them.

Between March and September 2026
183
Drupal security advisories
2x
compared to the same period in 2025
13
Core advisories, up from 1
0
Weeks that were advisory-less

The result is a steady stream of releases you actually need to ship, and a window between “advisory published” and “exploit in the wild” that keeps getting shorter.

Contributed-project advisories in 2026 have reached 292 through October 28, already the most of any year. The previous high was 175 in 2015.

The number of contributed project security advisories spiked from 113 in 2025 to 290 in 2026 so far.
Contributed-project advisories in 2026 (to 28 October).

In just five months, from June through October 2026, Drupal published 256 security advisories. That five-month total exceeds the 250 advisories published across the previous 30 months combined. This is the result of the Drupal Security AI Initiative, and by all means it is a good thing!

Core shows a different picture. One could say there was a rise with Drupal 8 and 9 and a decline in Security Advisories when Core reached maturity levels, until the advent of AI agents.

Drupal Core advisories are currently sitting at 16 in 2026, up from 8 in 2025.
The number of Security Advisories for Drupal core from 2005 to 2026 (28 October).

Updating all your projects by hand does not scale. One developer, one project, one evening a week? Maybe. 

Twenty projects? What about more than 70 – with different hosts, different patches and different release cadences? You just can’t keep up. Updates slip, slipped updates pile up, and a pile of updates is exactly the kind of work nobody wants to pick up on a Friday – and you can’t wait until Monday anymore! With vulnerabilities being actively exploited even before the fix is made you just don’t have that luxury.

The answer to the problem isn’t exactly a breakthrough: let a bot open the merge requests, and let humans review them.

Why Renovate?

Renovate is an automated dependency update tool. We use it to check for Drupal Core, contrib and private module updates, pack them and prepare Merge Requests for our Managed Services team to test and rapidly deploy.

Renovate watches your dependency files, notices new releases, and opens merge requests with the changes. It understands Composer, runs on GitHub, GitLab, Bitbucket, Forgejo/Gitea and others, and can be self-hosted. It also keeps a dependency dashboard issue in each repo, so you can see at a glance what is pending, what is blocked, and what was skipped.

Out of the box it is a little too eager for Drupal. It took us weeks upon weeks to come up with a sensible set of defaults. Below is the config we ended up with for Annertech, after rolling it out across a set of Drupal projects, and the reasoning behind each choice.

The config

Centralised Config – Main Config

This is managed centrally and all projects inherit it and can extend it. Rolling out a new version happens automatically to all projects.

You can find all config files and their latest versions in GitHub

default.json, publicly hosted:

{
    "description": "Annertech shared Renovate preset for Drupal projects. Extend with local>anrt-tools/renovate",
    "extends": ["config:recommended"],
    "automerge": false,
    "fetchChangeLogs": "off",
    "branchPrefix": "renovate/",
    "labels": ["dependencies"],    "rangeStrategy": "update-lockfile",
    "timezone": "Etc/UTC",
    "enabledManagers": ["composer"],
    "prHeader": "**Automated dependency update.** Please test on the dev site before merging and **check for configuration changes on production site.**",
    "prConcurrentLimit": 3,
    "prHourlyLimit": 2,
    "major": { "enabled": false },
    "ignorePaths": [
        "**/node_modules/**",
        "**/bower_components/**",
        "**/vendor/**",
        "vendor/**",
        "**/drush/**",
        "drush/**",
        "**/examples/**",
        "**/__tests__/**",
        "**/test/**",
        "**/tests/**",
        "**/__fixtures__/**",
        "web/core/**",
        "web/modules/contrib/**",
        "web/themes/contrib/**",
        "web/profiles/contrib/**",
        "web/libraries/**",
        "docroot/core/**",
        "docroot/modules/contrib/**",
        "docroot/themes/contrib/**",
        "docroot/profiles/contrib/**",
        "docroot/libraries/**"
    ],
    "postUpgradeTasks": {
        "commands": ["composer install --no-interaction --no-progress"],
        "fileFilters": [
            "composer.json",
            "composer.lock",
            "composer-manifest.yaml",
            "vendor/**",
            "web/core/**",
            "web/modules/contrib/**",
            "web/themes/contrib/**"
        ],
        "executionMode": "branch"
    },
    "packageRules": [
        {
            "matchPackagePatterns": [".*"],
            "prBodyColumns": [
                "Package",
                "Update",
                "Type",
                "Change"
            ]
        },
        {
            "matchPackageNames": ["php"],
            "enabled": false
        },
        {
            "groupName": "Drupal dependencies",
            "groupSlug": "drupal-deps",
            "matchUpdateTypes": ["minor", "patch"]
        }
    ]
}

Per Project config

In the repository root add a renovate.json file with a link to the above default.json:

{
    "extends": ["https://publicly.hosted/default.json"]
}

You can add more directives if you want, like:

    "assignees": ["bserem"],

What it does, and why

One merge request, not 40

All minor and patch updates, core and contrib, land in a single grouped merge request (MR). Drupal projects have a lot of dependencies. One MR per package means your merge request list becomes the new pile of work nobody wants to touch. One combined MR is one review, one pipeline, one deploy.

Build artifacts stay consistent

Many Drupal projects commit vendor/ and the contrib code under web/. Regardless of how you feel about it, this keeps the project ready to deploy at all times, minimises deployment time and simplifies deployment pipelines (no build step). It is quite neat for projects that have reached their adolescence and are not undergoing rapid development.

postUpgradeTasks does exactly that: runs real composer install in the codebase and then Renovate commits whatever composer wrote.

Don’t want to commit contributed code? We've got your back.

If you do not commit build artifacts, drop the postUpgradeTasks block and let the lock file be the only change.

That is the lockfile-only setup, and it is simpler on every front. Each MR contains a single changed file, composer.lock, so reviews are short and easy to read. Your pipeline runs composer install at build time, which means the lock file is the exact recipe for what ends up on the server. It also works on the hosted Mend app, since there is no hook to skip. The only requirement is that the runner can execute Composer, see below.

Majors stay with humans

major.enabled: false

A Drupal core major, a contrib 2.x to 3.x jump, a Symfony component major: these need someone to read the release notes, check for deprecated APIs and run the upgrade path. A bot should not be guessing.

Anything outside Composer (npm, Docker images, CI templates) is off too, by keeping enabledManagers to composer. Start narrow, widen later.

Nothing is automerged

Every MR gets a human review and a green pipeline before it lands. Renovate does the tedious part, which is noticing and preparing. People do the part that needs judgment.

The idea is simple: The dev wakes up in the morning, makes their coffee, opens their Gitlab dashboards and acts on them. Their job shifts from hammering composer update commands to reviewing Renovate's merge requests.

Thanks to containerized environments every MR has an environment ready for client QA too if deemed necessary.

If a project has full test coverage then you will know in your pipeline if the update is ready to merge without the need to self-test.

No grace period, on purpose

Renovate can hold back fresh releases with minimumReleaseAge, which protects you from the occasional broken release or compromised package. This also holds back security releases, which is the exact opposite of what you want when an advisory went out this morning.

Right now security fixes arrive in the same MR as everything else, so fresh beats delayed. Once security updates are handled on a separate track, adding a grace period for regular updates becomes a sensible next step.

We experimented a lot with having two different tracks, one for security and one for everything else, but it quickly became painful. Our tests coincided with Symfony security updates and it was clear that under mixed circumstances you can end up with composer (not renovate) refusing to update packages because sub-dependencies were marked as insecure. One track for everything solves that.

Things to know up front

You need a self-hosted runner for postUpgradeTasks

Running arbitrary commands is an admin-level setting. composer install has to be allow-listed on the runner, for example:

RENOVATE_ALLOWED_COMMANDS='["^composer install"]'

On the hosted Mend app the hook is silently skipped and you get MRs with a stale vendor/. If that is where you run Renovate, use a lock-file-only setup.

The runner needs PHP and Composer

With update-lockfile, the only change is a regenerated composer.lock. If Composer cannot run, you get an MR with a nice description and no commits. Use the full renovate/renovate image (or RENOVATE_BINARY_SOURCE=install), and look for an "Artifact update problem" block in the MR body.

Validate before you ship config changes

npx --package renovate renovate-config-validator renovate.json

And do a local dry run against a real project before pushing it to a whole fleet:

LOG_LEVEL=debug GITHUB_COM_TOKEN=ghp_... \
  npx renovate --platform=local --dry-run=full

The GitHub token is only there so Renovate can read release notes without hitting rate limits.

What’s next?

This setup is deliberately conservative. The obvious next steps are:

  • A separate, faster track for security advisories, so you don't pack regular updates on a security merge request
  • A track for major updates, not necessarily in a ready to merge state, but mostly as a visual representation of where things stand, to identify patches that would become incompatible as other conflicts.

Conclusion

Security advisories are not going to slow down any time soon. As automated tooling continues to uncover vulnerabilities at a rapid clip, relying on manual maintenance schedules will only leave your sites exposed and your development team overwhelmed.

By putting Renovate to work, we have shifted the burden of dependency management from human effort to automated pipelines. Instead of spending hours hunting down updates and wrestling with Composer commands, our team can focus on what really matters: reviewing clean, pre-made merge requests and keeping client sites rock-solid.

This conservative setup is just the beginning of our automated maintenance journey. As we continue to refine our processes, the goal remains the same: Making sure that no matter how fast patch Wednesday arrives, applying updates remains an easy part of our week.

Profile picture for user Bill Seremetis
Bill Seremetis
Drupal Developer

Bill has been part of the Drupal community since 2008. He works on support, site security and performance for Annertech clients.

Ready to automate your Drupal maintenance?

Patch Wednesday does not have to mean late-night headaches. Get in touch with our team to see how we can bring automated updates and rock-solid security to your organisation’s digital estate.

large-cta