Testing your composer dependencies with prefer-lowest
A few days ago, a new feature landed in composer, the --prefer-lowest
argument.
Normally, for any dependency, composer will attempt to always install the latest possible version.
For instance, if your composer.json looks like this:
"require" : {
"vendor/package" : "~1.2.1"
}
Then you are telling composer effectively that it should install any version after 1.2.1, but before 1.3.
If version 1.2.5 is the latest, composer will always grab that version.
With the new --prefer-lowest
setting, you can tell composer to install the
oldest possible version of a package that still matches your requirement.
So if we run:
composer update --prefer-lowest
We should get version 1.2.1 for vendor/package
and all its dependencies.
Why is this useful?
In some projects, there may be packages lying around that are not the latest version. This could be because it introduced some BC break, or introduced a bug.
If other packages also use the package that’s being held back, they may get an older version as a dependency.
So for package maintainers, they will want to find out if their package correctly works with the oldest package they claim to support.
So for us to test this, we can simply run:
composer update --prefer-lowest
./bin/phpunit
If our unittests break with older dependencies, we know that we either need to increase the oldest supported version, or implement a workaround so it still works.
Automating this with Travis
If you are using Travis for automated testing, you can also tell travis to test with the oldest possible dependencies.
Travis allows you to add new lines to the build matrix with the env:
setting,
which makes this super easy to do.
If for instance your .travis.yml
looks a bit like this:
language: php
php:
- 5.4
- 5.5
- 5.6
- hhmv
before_script:
- composer update --prefer-source
script:
- ./bin/phpunit
You can modify it to this, to allow Travis to do 1 build for the latest, and one build for the oldest possible depdendencies:
language: php
php:
- 5.4
- 5.5
- 5.6
- hhmv
env:
matrix:
- PREFER_LOWEST="--prefer-lowest"
- PREFER_LOWEST=""
before_script:
- composer update --prefer-source $PREFER_LOWEST
script:
- ./bin/phpunit
This would result in a total of 8 builds.
Depend on a wide range of versions
While you should always recommend anyone to run the latest versions of your dependencies, it’s a good idea to support a wide range of versions including older ones.
In a large applications a lot of packages may be installed together, and if there’s a package out there that depends on a specific version, and another on a different specific version of that same package, this would result in a situation where these two packages cannot be installed together.
To give your users the smoothest experience possible, it’s therefore best to try to nail down the oldest possible dependencies your package can still work with, and only increase that minimum version if you’re depending on the latest introduced feature, or to get around an major bug.
Comments
mnapoli •
--prefer-lowest rather than --prefer-oldest :)
Evert •
Fixed!
Jordi Boggiano •
Also worth noting that combining --prefer-lowest with --prefer-stable might be worth it to avoid testing against early alpha/beta/RCs of dependencies. It's unlikely someone would rely on them anyway and it is likely to make you waste time figuring out what's wrong if you hit a pre-release bug in one of the dependencies.
Anton •
Really cool! Will use in in Deployer.
> --prefer-lowest with --prefer-stable