Managing environments with Composer
This guest post comes to us from our eZ Partner, Netmaking.
Composer greatly simplifies handling dependencies for PHP applications. In this blog post, we'll have a look at how to use Composer to manage your dependencies when your different environments call for different versions of the libraries you use.
When is this useful? Imagine that your application depends on a library that you're developing. Your composer.json might look like this:
Every time you make a change to your library, you merge it into the library's master branch. Then, in your app, you run composer update your-namespace/your-library, and you have the latest version of your library.
Your development process for a new feature may look like this:
- Develop in your development environment (on a feature branch)
- Merge your feature branch into master
- Deploy to production
A more robust development process
But - as you may know - deploying directly from your development environment to your production environment means that more errors will go unnoticed. You'd like a testing environment - which is as similar as possible to your production environment, but with a separate database - as a step between your development and production environments.
Your new development process contains a few extra steps:
- Develop in your development environment (on a feature branch)
- Merge your feature branch into your testing branch
- Deploy to testing
- Someone else on your team and/or on your client's team tests and approves of the change
- Merge your feature branch into master
- Deploy to production
This is a more robust process and will - if you're like me - lead to less fear of failure on deployment to production.
Making changes to your library
But what if your new feature requires making changes to your library? You'd make a new feature branch in your library, and develop it there. But how can you deploy that feature to testing?
You don't want to merge it into your library's master branch before it's ready to be deployed to production. (If you did this, and someone else on your team ran composer update and deployed to production, the new version of your library would end up in production before it was fully tested and approved.)
Another possibility is to - in your app's testing branch - update the library's reference in composer.lock to point to the exact commit that you want to use in your testing environment. But this reference may be overwritten, for example if this reference is changed manually at a later point in time, or master is merged into testing.
You then risk that your library's new feature no longer exists in your testing environment. If this happens before your client and/or team member has tested the new feature, confusion and frustration will ensue.
Composer environment variables
We can avoid this problem using Composer's environment variables. They let us specify different dependencies for different environments, meaning that your app will depend on a different version of your library depending on the environment.
In your library, you can - just like in your app - have a testing branch. You can merge your changes into this branch, and only when they've been tested and approved merge them into your library's master branch - just like in the app itself.
If this is all a bit confusing at this point, don't worry. Let me walk you through an example.
Step-by-step
We'll start in your application's root and make copies of your Composer-files. In your terminal:
Now, we're ready to change your composer-testing.json to require your library'stesting branch:
Notice how it now says dev-testing rather than dev-master.
Next, we'll use the environment variable COMPOSER to let your package manager know that you want it to use a different set of files than default, allowing us to get the latest changes to your library's testing branch:
Assuming that your library's testing branch contains one commit that your library's master branch lacks, the output should look approximately like this:
Using Capistrano
If you use Capistrano to automate your deployments, you can use the following line to set the appropriate environment in your testing deployment script:
To learn more about Capistrano, you can visit their documentation overview.
There are also other options:
1. Deployer
Example of usage: https://www.sitepoint.com/deploying-php-applications-with-deployer/
2. Rocketeer
Example of usage: https://semaphoreci.com/community/tutorials/deploying-php-applications-with-rocketeer-and-docker
eZ also has a page on using Composer: https://doc.ez.no/display/DEVELOPER/Using+Composer
Summary
By using Composer's COMPOSER environment variable, you have a robust way of varying your dependencies between your different environments, such as testing and production.
Further Reading
eZ Platform is now Ibexa DXP
Ibexa DXP was announced in October 2020. It replaces the eZ Platform brand name, but behind the scenes it is an evolution of the technology. Read the Ibexa DXP v3.2 announcement blog post to learn all about our new product family: Ibexa Content, Ibexa Experience and Ibexa Commerce