I’ve had some issues recently (due to the recent release of BLT 12.5+) due to some systems actively supporting Composer 2 and some not. BLT now requires Composer 2 which is fine on systems that I have full control of. I can composer self-update all over the place. At least I can on systems I own. What about build containers on continuous integration platforms?
Remember that fundamentally when you’re linking up the composer binary you’re typically doing this at a fairly high level of system resources (e.g. /usr/local/bin) and for security purposes build containers might not let you change that.
So now we have a problem: how do you install composer 2 into a container that doesn’t let you install composer 2?
Let’s work around it!
Installing a Local Composer Binary
Many CI scripts will let you do basic things, like run commands that might download a file. So, looking at the Composer download instructions, you’ll see something like:
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
- php composer-setup.php
- php -r "unlink('composer-setup.php');"
Once this is done, you can run composer.phar and you should see composer 2 (whatever version is current). The problem (at least on BLT builds) is that BLT assumes your composer binary is not composer.phar, but composer.
As I describe in my recent blog post, you can totally have multiple composer binaries installed! But when you’re using a scripting tool (like BLT) you need to be entirely certain that the proper binary is called in the proper place (and BLT does not support configurable composer binaries). So getting composer 2 installed as composer.phar is a step in the right direction, but it’s not everything you need to do.
The next step is to alias composer and essentially overwrite the stock functionality. This can be done like this:
alias composer="path/to/composer.phar"
On Acquia’s Pipelines server this is:
alias composer="/mnt/tmp/local.prod/source/composer.phar"
The result then is if you run composer you’ll get the aliased composer.phar binary and not the globally installed composer binary. In my case, composer is now composer 2 and not composer 1.
A working Example
If you check out the GovCon repository you can see our pipelines file there with this example in place. One further note (as you can see from our PR) you’ll have to .gitignore your composer.phar file as it will get created during the build and cause BLT to fail its check for dirty (or modified) files.
So that’s it! Just manually install the composer.phar and alias it to composer and you’re good to go with composer 2, even in a container where you can’t rewrite the global binaries.
Dependency trees can be massive, and with the upcoming Drupal 10 release PHP 8.1 could have a significant impact on your project.