Continuous Delivery with Symfony

Sunday, February 7, 2016 21:11

Most of the Symfony based applications use Capifony for creating a continuous delivery pipeline but sometimes it’s not flexible enough. Because of this reason I’ve decided to create a different approach (which can be seem a bit old-looking but it’s easy, trust me).

First, let’s take a look at the process:

Development/Testing pipeline

Continuous Delivery Testing/Development pipeline

Okay, we want to make sure that no bug can get through our pipeline. For this reason we try to set up as many traps as we can for bad code. Here is my pipeline for this job (for web applications):

  1. Creating code
    Developers commit code on feature branches. After the Code Review, the code can be merged back to the develop branch.
  2. Starting the pipeline
    At a fixed time (somewhere in the morning) the pipeline starts and pulls the latest code from develop branch.
  3. Static analysis
    First step is to make a static analysis on the code to detect possible defects and bad design, typos, etc.
  4. Unit testing
    This step should be no longer than a few minutes. It’ll test our business logic without any dependencies (database, message queues, caching servers, etc.).
  5. Functional testing
    The code is tested in this step completely. It is the longest step as it uses all of the other services, like: database, message queues, etc.
  6. Manual testing
    Simultaneously with the previous steps a manual testing server can be set up for manual testing. As we’re in Continuous Delivery this server should be used for usability testing and not functional testing!
  7. Pushing changes to master
    If everything is fine, we can push our tested code into master branch. This branch represents the stable code and will be released onto the production servers.

Production pipeline

Continuous Delivery Production (Release) pipeline

This is the easy part. You have a fully tested code, you just have to make sure that everything goes into production without any issues. The following steps are needed:

  1. Getting out the server from production
    This step can be done by either putting out a “Maintenance in progress” page or by reconfiguring HAProxy/Nginx proxy/etc. to redirect traffic elsewhere.
  2. Backing up database
    We want to make sure that if anything happens during the upgrade process, we won’t lose any data. Our worst scenario is to roll back everything to the previous state.
  3. Upgrading the codebase/database
  4. Putting back the server into production
    If everything went fine, we can redirect back the traffic.

Implementation with Symfony

For creating a completely trustable CI/CD environment, I use PHPUnit for unit testing and Behat for functional testing. Feel free to replace them with your favorite frameworks.

For this solution I use the following tools:

  • Symfony, obviously
  • Phing, to create extendable commands with a single commit and to group the commands
  • Jenkins, as the backbone of my Continuous Delivery system
  • Linux

And for Symfony, you’ll probably need the following bundles/libraries:

  • doctrine/doctrine-migrations-bundle, for database migrations
  • lexik/maintenance-bundle, for displaying a nice looking message during the update
  • phpunit/phpunit (dev), for unit testing
  • doctrine/doctrine-fixtures-bundle (dev), for functional testing
  • behat/symfony2-extension (dev), for functional testing (framework)
  • behat/mink-extension (dev), pre-defined BDD elements for functional testing
  • behat/mink-browserkit-driver (dev), for running the tests in headless mode

In case you would like to dive deep into Continuous Delivery with Symfony, go ahead and clone a pre-prepared skeleton project. You can find additional information in the file in the repository.

No comments fo far.

Leave a Reply