Skip to main content

Restrict Composer dependency updates to only patch releases

Published on

I was doing website maintenance and checked for outdated dependencies with composer outdated. I usually filter with -D for checking direct dependencies and -p for packages with patch releases. These are typically easy pickings. I saw I was on 2.1.3 of the Honeypot module and 2.1.4 was available. So I ran composer update drupal/honeypot. I noticed the module was updated to 2.2.0, because my Composer constraint is drupal/honeypot: ^2.0, allowing minor updates. I figured that was fine enough. Turns out it wasn't.

I have a continuous integration job that takes my main branch and tests the pull request against running drush updb. It failed because of missing schema changes. I was really confused, until I found this issue in its issue queue: https://www.drupal.org/project/honeypot/issues/3468450. It turns out that the maintainer removed update hooks between minor versions, which is usually a major version type of change. At least, that's how Drupal Core works.

You jumped versions and didn't update your database to account for the change made between 2.1.3 and 2.1.4. Update to 2.1.4 first and make sure you do a database update.

Luckily I have this CI check for dependency updates. Generally, it is to catch magical configuration changes made in update hooks that I didn't know needed to be re-exported. This time it caught an expected/unexpected usage of hook_update_last_removed

In Composer 2.8.0 a new flag was added to the update command called --patch-only. When using this flag, the requested dependency update will always be to a patch version regardless of the version constraint in your composer.json. Using the following command I was able to get updated from 2.1.3 to 2.1.4 without modifying my composer.json.

composer update drupal/honeypot --patch-only

However, I am probably going to go through my composer.json and fix all of my ^MAJOR_VERSION constraints for Drupal modules and change them to ~ and pin to a specific major and minor, allowing only patch updates. Unfortunately the ^ and MAJOR_VERSION constraints are due to the legacy versioning of Drupal modules and themes. Take the Token module release 8.x-1.15. The major version is 1, and the minor version is 15. The legacy release format does not provide patch releases; it's always a minor release. Modules that have moved to semantic versioning actually have patch releases.

If you're not testing your Drupal site's update process you should read my Verifying your Drupal site's configuration against changes from dependency updates blog post.