This is part 2 of a series on having CI pipelines for your Drupal site, and building Drupal Deploy Confidence. In this part of our series, we’re looking at another low-hanging fruit: composer validate
. It's quick to set up and can save your team from subtle but frustrating dependency issues.
What does composer validate actually do?
According to the official Composer documentation, this command:
...checks if your composer.json is valid. If a composer.lock exists, it will also check if it is up to date with the composer.json.
That might sound trivial, but in practice it solves a common and annoying problem: when the lock file is out of sync with composer.json.
You’ve probably seen this warning:
Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.
In a CI context, composer validate
will fail with a non-zero exit code if this mismatch is found. That’s a good thing - it prevents developers from merging code that might lead to confusion, instability, or surprise dependency changes.
Why you should care
Here’s why we make composer validate
a standard in CI pipelines:
1. It prevents outdated or unexpected dependencies
When the lock file is behind composer.json, your project might not actually install the packages you think it will. That’s a recipe for bugs that are hard to trace, especially in production.
Failing early in CI ensures that your dependencies are exactly what you committed to - nothing more, nothing less.
2. It avoids misleading advice
The warning suggests you can simply run composer update
to fix the mismatch. But unless you're deliberately updating all your dependencies, this is often bad advice.
Running composer update
without constraints may introduce unintended package upgrades, which might either break other parts of the system, introduce regressions or complicate debugging.
By enforcing a clean lock file, you avoid needing to deal with this situation altogether.
Optional strictness
By default composer validate
will also check things like requiring a name or description in your composer.json. This is particularly useful for packages intended for public reuse. For regular web projects, we usually skip these extra rules - they don’t add much value in a project context. In practice, that means the validate of our CI pipeline runs this command:
composer validate --no-check-version --no-check-publish
To make sure this is in fact literally the same on all platforms, we add a wrapper script to composer.json, so we can simply run
composer ci:validate
Conclusion
If you have followed the parts so far, you should now have 2 CI jobs in your pipeline. Please see the below links for both jobs in all 3 major version control providers:
Direct link to pipeline for Bitbucket: https://bitbucket.org/eirikmorland/drupal-confidence/src/part-2/bitbucket-pipelines.yml
Direct link to pipeline for GitLab: https://gitlab.com/eiriksm/drupal-confidence/-/blob/part-2/.gitlab-ci.yml?ref_type=heads
Direct link to pipeline for GitHub: https://github.com/eiriksm/drupal-confidence/blob/part-2/.github/workflows/test.yml
Do you want to comment?
This article uses github for commenting. To comment, you can visit https://github.com/eiriksm/eiriksm.dev-comments/issues/26.