In this article we will learn how to dual boot any composer app (like a Yii2 app) in a local environment and continuous integration (CI) service. This can be used to upgrade the version of Composer, PHP, or even maybe Yii, along the way with normal development, even if it's a process that spans many weeks or months.
This is inspired by Jordan Raine's talk about Clio's process to upgrade Rails over the years (You can watch it over here: Ten Years of Yii Upgrades), this post by Ernesto Tagwerker, and my own experiences about doing this on the Kantox B2B Forex Fintech platform.
First, we need to initialize the composer-next.json
file like this:
$ cd path/to/project
$ cp composer.json composer-next.json
Now, in composer-next.json
, we just need to change Yii to the new version:
- In
composer.json
:
"yiisoft/yii2": "2.0.22",
- In
composer-next.json
:
"yiisoft/yii2": "2.0.23",
Now I can install my current dependencies with composer install
and my future dependencies with COMPOSER=composer-next.json composer install
using the COMPOSER
env var.
After running COMPOSER=composer-next.json composer update
, I have a brand new composer-next.lock
file. That means that my dependencies are ready to run my test suite. So I can run them like this:
$ COMPOSER=composer-next.json composer run-script test
There are many advantages to using dual booting in your composer application. In no particular order:
- You can run your test suite with two different versions of Yii. Running
composer run-script test
still works thanks to having anothercomposer.json
file. - You can run your application in development with two different versions of Yii with
composer run-script [command-to-run-server]
. - You can even run your application in staging using the next version of Yii. Simply make sure that you set this environment variable:
COMPOSER
and usecomposer run-script
. - You can quickly debug issues between your current version of Yii and the next one.
Now, the last step is to fix the issues that the update might have uncovered. The way to do it to build up compatibilty with the new version of Yii is:
-
Identify an error (through a test or the UI)
-
Fix the source of the incompatibility on the new version of Yii
-
Fix the error
-
If the fix solves the error in both the old and the new version of Yii, you're done!
-
Otherwise, split the fix in two parts as follows:
if(getenv('COMPOSER') === 'composer-next.json'){ // fix for the new version } else { // existing code that works in the old version }
Once compatibility with the new version is fully accomplished, the cleanup is just searching in all the project for
if(getenv('COMPOSER') === 'composer-next.json')
and deleting all the old code ✨
The next step would be to setup 2 different builds in CI:
- One that users
composer.json
- One that users
composer-next.json
: this one will only run the tests that run the code that has been fixed. As more code is fixed, more tests are run in this build, until all the tests run.
This is done so that no developer breaks the new version of the code, even if they only develop using the old version.
The setup depends on the specific CI service, but it shouldn't be too hard: it's basically C&Ping the configuration to a new build and replacing composer run-script x
with COMPOSER=composer-next.json composer run-script x
.