From Drupal 7 to standard PHP development

The pain

In the past we used a Drupal 7 multi-site powering at least 3 different sites at the same time with all our business logic bundled inside of various massive custom modules shared along all the sites and some of them with dependencies of external modules (like Message Broker) and each site was using a different version of these modules.

We were restricted to deploying the work of a large team every one or two weeks. When something broke because of the number of changes we’d just deployed together with everything, we were unable to immediately know the source of the issue and sometimes we had to wait till the next scheduled deployment in order to fix the problem.

We needed to undertake a sanity test of the whole site on every deployment because a simple core update could shut down the whole site or one change in the javascript could break all the apps in one go. Every time we felt like we were delivering a Pandora’s box.

The Dream

We still wanted a Drupal 8 site that deals with the content and users, and the other functionality is decoupled into small services with the most appropriate technology/framework for that service. This means that if a service becomes unavailable the other services will still be working and it is easier to spot the bug because the project is smaller. Obviously we’d rather nothing went wrong but inevitably it will, so being able to isolate an issue and possibly take one service down to fix is much better than having no site or apps available at all.

We wanted to deploy automatically more often and create less work and get instant feedback once our work is done.

We are moving parts of our workflow/apps to other services so we can focus on improving our expertise in CI/CD, using tools like platforms.sh, travis CI, Concourse CI, etc. and get experience from the PHP world and their best practices and try to apply them in our big apps, so we can improve our workflow.

Our way

Drupal profiles

We decided to create a profile that powers a basic config and modules to all our sites so in this way is easier to maintain/update all the sites

Continuous Delivery

Our last project was a symfony 3 app, for which we started implementing our new standard pipeline that looks like this on Concourse CI:

Basically on each pull request (PR) we run all the unit tests to make sure that everything looks “fine”. Once the PR gets merge it tries to deploy to a test environment and it does a full sanity test in order to guarantee that nothing breaks and then we repeat the same process to the staging environment. We usually let it deploy to production then too unless we are expecting an event that would, for instance, substantially increase traffic and in that case we have the control to delay and push it when we are ready.

All the way to production can be done in less than an hour and I’d dare to say that the release is ready in the exact moment you press the merge button.

Container ecosystem

All our projects have a docker-compose file with the same image as our site so everyone has the same environment no matter what operating system are they using. We also added all the necessary commands grouped by utility as composer scripts so it is easier to remember and we don’t need to create bin/bash files

TDD

We prefer to do TDD because our tests are like the specification of the task, so when it passes, it is done. In a non-TDD environment, the goal is usually not very clear and changes can be hard to understand and test.

For covering that we decided to experiment with PHPSpec, which is a great developer-friendly testing tool that encourages Test Driven Development and also creates the initial code structure for the functionality.

Conclusion

I think everyone in the team is happy with this new way of doing things because it gives us more security, flexibility, and the freedom to learn and refactor things without fear. We have improved our deployment timescale from weeks to minutes, which is a huge achievement.