Are your dependencies old enough to go to school? Do you have that one big-ticket that haunts you in the backlog, which aims to upgrade PHP, a Composer package, or the framework’s version? Keep on reading – we’ve got you covered. We faced these challenges as well and, thanks to that, we managed to come up with a solution: developing a tool that makes the upgrade process automatic, continuous, and fun!
As a developer, it’s essential to keep up with the latest tools and technologies and apply them to your projects. With software development constantly evolving (faster and faster lately), it’s natural to have new solutions emerging regularly. By staying up-to-date with these advancements, you can enhance your skills and knowledge, improve your workflow, and ultimately produce better-quality software. In today’s digital age, where cybersecurity threats are becoming increasingly sophisticated, it’s crucial to use the latest tools and technologies to ensure the security of your applications. As you most probably already know, outdated distributions may have vulnerabilities that hackers can exploit. This exposes the software and the users to various threats such as data breaches, malware, and ransomware attacks.
By using up-to-date versions, you (and developers in general) can achieve the following:
- Take advantage of the latest security features and updates and ensure the software’s security against cyber threats, giving users peace of mind and preventing potential damage to an organization’s reputation;
- Work more efficiently, reduce development time, and deliver more features and functionality to the users;
- Prove a commitment to personal and professional growth, which can help you stand out in a competitive job market.
Here at Evozon, we understand the need to constantly improve ourselves and our projects and to deliver high-quality software built on top of the most recent technologies. Consequently, we set a goal to automate the upgrade process, and we’ve created a tool that enables us to keep our projects up-to-date.
World, meet Future!
Future offers an automatic, pipeline-based, and efficient way of upgrading projects, saving developers time and effort. How? By splitting the whole process into three distinct phases. Each one focuses on a specific aspect of the upgrade process: the platform, the dependencies, and the codebase. Now, it’s important to also note that each phase is optional and fully configurable. Moreover, all the changes Future applies are made in an isolated environment, without affecting your project.
Let’s Dive Deeper into The Process
Phase 1: Upgrading the platform
The first phase involves upgrading the platform that your project runs on. This is essential, as running your project on an outdated platform can result in compatibility issues and security vulnerabilities. Future automates this process by creating a fully configurable Docker container, built using the most recent versions of your platform-related dependencies (such as PHP, databases, etc.). Later, you will use it to run your project’s test suite. Thus, it eases the upgrade process, without worrying about compatibility issues or breaking your app’s functionality. If the upgrade fails, Future provides detailed information about the failure’s reason and proposes the next steps to overcome it.
Phase 2: Upgrading existing Composer dependencies to the latest version
Once you have upgraded the platform, the next step is to upgrade all Composer dependencies to their latest version. Future checks your composer.json file and updates each package to its latest version. If the process fails, you’ll receive detailed information about the not-updated package(s) and what you have to do next to address the situation. Thus, we offer a step-by-step approach that allows you to upgrade your project’s dependencies in small, non-scary iterations.
Phase 3: Upgrading the code to the latest standards automatically
The final phase of the upgrade process involves upgrading your codebase to the latest standards. Future achieves this through the use of Rector, a powerful tool that automates the process of upgrading your codebase by applying a configurable set of refactoring rules. This includes using features added in the latest PHP versions, removing deprecated code, applying modern coding standards, or creating custom refactoring rules.
If all the phases have been successfully executed, Future runs your project’s test suite inside the created Docker container, making sure that the upgrade has not broken your app’s functionality. Throughout each step of the way, Future provides useful feedback on what has been performed. Also, if necessary, detailed information about the error that occurred. This way, you can take the proper actions: apply the upgrade or address the reported issues.
How to upgrade your PHP project using Future
Getting started with Future is really easy. However, it requires two important prerequisites:
- CI pipeline;
- Test suite.
We believe all projects should have these. Also, we strongly encourage you to add them to your project in case they are missing. Not only for using Future, but for the sake of developing high-quality and robust software.
After managing to meet the prerequisites, all you need to do is:
- Install the package;
- Add Future as a new and independent step in your pipeline;
- Configure the step in order to meet the needs of your project;
- Run the pipeline;
- Go through the provided summary and apply the suggested changes;
- Go to 4.
Future can be installed as a development-only package in any Composer-based PHP project. For more information, check our GitHub repository. Once installed, you need to create a new step in your CI flow that will create an up-to-date environment in the form of a Docker container. That’s where your project’s test suite will be run after updating all the Composer dependencies and applying the Rector-related refactoring rules. Future provides templates for the main web-based Git repositories, which you can use and configure to match your project’s needs (see the code snippet below).
future-proofing: stage: future allow_failure: true needs:  image: php:fpm-alpine #replace this with the platform you target for the upgrade #services:define the services required to run your test suite #variables: define the variables required to run your test suite before_script #performall the necessary steps required to run your project's test suite - composer install --no-interaction --no-scripts --prefer-dist script - vendor/bin/future bump-php - vendor/bin/future bump-deps - composer update -W --no-interaction --no-scripts - vendor/bin/rector init #register rector rule sets - vendor/bin/future add-ruleset \\Rector\\Set\\ValueObject\\SetList::CODE_QUALITY #register rector rules - vendor/bin/future add-rule \\Rector\\Restoration\\Rector\\Class_\\RemoveFinalFromEntityRector::class #exclude rector rules - vendor/bin/future skip \\Rector\\CodingStyle\\Rector\\ClassConst\\VarConstantCommentRector::class - vendor/bin/rector process src --no-progress-bar --no-diffs #run your project's test suite - vendor/bin/phpunit --no-interaction --colors=never
Continuous Integration Job Template for Implementing Future
To avoid affecting the workflow of your team, you must allow this step to fail. If something went wrong, Future will collect and provide useful feedback as output which you can use to take action. To facilitate this, create a corresponding ticket that addresses each failure one by one. Once all the failures have been addressed and the Future-related step has passed, you can apply the upgrades Future has made in the isolated container to the main repository through the use of the binary provided by Future (see the section below). Then, you can remove the allow_failure: true option. At the same time, it’s essential to make the job a part of the definition of done of your project, ensuring that any future merge request will be future-proof. One important aspect to keep in mind: once you get to the latest versions, you stay there!
Demo: Watch Future in action
To better understand the process and highlight Future’s power and simplicity, we created a short demo where we upgrade an application using the binary. Join us as we enhance our app’s platform, Composer dependencies, and codebase and address the challenges we face! The process we present below is just a fraction of what Future can do. It reflects the steps that you should automate in your project’s pipeline when defining the CI step. We recommend using the binary locally only when committing the changes to the repository when the job passes.
Future is an open-source tool that automates the upgrade process of Composer-based PHP projects and provides the resources to make upgrades a step in the workflow of your projects. Therefore, it allows you to stay up-to-date with greater ease. We welcome any contribution and feedback and look forward to your thoughts about Future.
Article written by Ioan Ovidiu Enache