Upgrading to Composer 2 using Ansible
A week ago I looked at upgrading to Composer 2 on a couple of machines. The process wasn't as simple as I was hoping, or as what was documented. After that, I was worried about updating it for my Ansible configuration. Afterall, if something doesn't quite work, I lose the ability to deploy my application to the relevant environments.
My Ansible role prior to Composer version 2 was as follows:
--- - name: Check if composer exists stat: path: /usr/local/bin/composer register: composer_file - name: Download Composer get_url: url: https://getcomposer.org/installer dest: /root/composer-setup.php when: composer_file.stat.isreg is not defined or not composer_file.stat.isreg - name: Add composer command: php /root/composer-setup.php --install-dir=/usr/local/bin --filename=composer when: composer_file.stat.isreg is not defined or not composer_file.stat.isreg
Basically, that's check if Composer exists. If it doesn't, download it an install it. Anyone familiar with Ansible and Composer will realise that this won't ensure that all versions of Composer are the same. That could lead to some interesting behaviour (and is hugely bad practice).
The same role can be easily modified to ensure the same version of Composer is used on each server
--- - name: Check if composer exists stat: path: /usr/local/bin/composer checksum_algorithm: sha256 register: composer_file - name: Download Composer get_url: url: https://getcomposer.org/installer dest: /root/composer-setup.php when: > composer_file.stat.isreg is not defined or not composer_file.stat.isreg or composer_file.stat.checksum != 'c3b2bc477429c923c69f7f9b137e06b2a93c6a1e192d40ffad1741ee5d54760d' - name: Add composer command: php /root/composer-setup.php --version=2.0.4 --install-dir=/usr/local/bin --filename=composer when: > composer_file.stat.isreg is not defined or not composer_file.stat.isreg or composer_file.stat.checksum != 'c3b2bc477429c923c69f7f9b137e06b2a93c6a1e192d40ffad1741ee5d54760d'
Because the Composer project provides the checksum for the version on the download page, it's a simple case of specifying the version to install, and checking the version being used matches the expected checksum. If it doesn't, install specified version.
With the servers updated with the latest version of Composer, it was time to test the deployment task. It's all well and good having the latest release of a product there, but if it doesn't work when you need it to, it's no good. Set the task running, loads of success and then...
TASK [Install/update requirements from composer.json] *************************
Nothing beyond that. Maybe there's lots going on. A few minutes later...still nothing. Eventually the process timed out. It worked fine before, it's not now. Composer is there (I checked). It's the right version (I checked again). Will it run manually? No!
Disclaimer: Bad practice alert! The servers are within DigitalOcean, and by default the user account is
root. Ansible therefore connects as
root, and doesn't do any
sudo work to get escalated privileges. It's always been bad practice to run Composer as root. But Composer 2.0 waits for an explicit input to confirm you want to run as root.
Fortunately, there's a way around this. Actually, two if you count creating a new user and not running as
root. Composer nicely provides a
--no-interaction flag which can be passed. The task for the install is now:
- name: Install/update requirements from composer.json command: composer install --no-dev --no-interaction -d /var/www/html/project when: true
Upgrading Composer on Ansible was actually easier than when I did it on my local machine. Any issues I came across were simply down to my bad practices rather than an issue with Composer itself. Even then, there's ways around it.
I'll be rolling the change to Composer 2 out to all my servers, but also adding a technical debt issue to stop using root.