Do you need to set environment variables for Composer scripts to work? Here’s how.
But first, a little story.
Recently, I was working through a PR to upgrade oauth2-keycloak to use PHPUnit 9; no, not to version 10 for a couple of reasons.
After making the required changes to the package, I went to run the test suite and noticed that there wasn’t a scripts property in the project’s composer.json file.
This seemed a little odd to me, as the scripts property has been common on numerous projects that I’ve worked with in the past.
Why? Because they help automate so many aspects of common functionality, such as running tests, under a unified command interface.
Laravel, for example, has an excellent post-install script, and Mezzio projects generated with the Skeleton Installer come with the following scripts configuration:
{
"scripts": {
"post-create-project-cmd": [
"@development-enable"
],
"development-disable": "laminas-development-mode disable",
"development-enable": "laminas-development-mode enable",
"development-status": "laminas-development-mode status",
"mezzio": "mezzio --ansi",
"check": [
"@cs-check",
"@test"
],
"clear-config-cache": "php bin/clear-config-cache.php",
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"serve": "php -S 0.0.0.0:8080 -t public/",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
}
}
You can see that there are scripts for managing Mezzio’s development mode, running tests, and starting the application, among others.
Sadly, this project didn’t have one.
So, as part of upgrading the package to PHPUnit 9, I wanted to make running its test suite a little easier and added the following section to composer.json:
{
"scripts": {
"test": "phpunit --colors=always"
}
}
By doing this, running tests would only require running the following command:
Sure, running the underlying command (./vendor/bin/phpunit --colors=always
) isn’t much longer.
However, scripts remove the need to remember a plethora of various options, arguments, and values, such as those supported by PHPUnit.
With the change made, I thought my work was done.
Sadly, on running the command, I encountered the following warning.
Warning: XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set
This was because I’d enabled code coverage reporting in phpunit.xml.dist yet hadn’t set XDEBUG_MODE
appropriately.
At this moment, I found myself a little stuck, as I couldn’t assume anything about a user’s environment, when they were working with the package.
I needed to ensure that the environment variable, XDEBUG_MODE
, was set to coverage
before the script was run.
However, I couldn’t see an obvious, Composer-specific, way to do so.
Sure, I could set the environment variable when running the command, as in the example below.
XDEBUG_MODE=coverage composer test
However, that leaves room for mistakes to happen.
For example, the same error will occur if the environment variable’s not set before or on running the command.
Plus, it would only work for me, not any future users of the package.
Then, I tried to set the environment variable with the following configuration in phpunit.xml.dist.
<php>
<ini name="xdebug.mode" value="coverage"/>
</php>
Unfortunately, that didn’t solve the problem.
I did a little digging into the Composer manual and found that it environment variables can be set in scripts.
To do this, the script’s value needs to be an array of steps, where the environment variable is set with @putenv
, before the command is called, as you can see in the example below.
{
"scripts": {
"install-phpstan": [
"@putenv COMPOSER=phpstan-composer.json",
"composer install --prefer-dist"
]
}
}
With that change made, the test suite ran successfully — with no broken tests as a result of the changes I’d made to upgrade to PHPUnit 9!
What’s more, the script also provided an extra bit of project documentation.
That’s how to set environment variables in Composer scripts
If you find yourself in the same situation as I did, now you can set environment variables as part of your Composer scripts, and your scripts will work as expected.
The Composer logo is copyright the Composer project.
Join the discussion
comments powered by Disqus