Multistage deployment of Symfony applications with capifony

Warning: This blog post was written a long time ago and might be no longer relevant.
Capistrano configuration

Capifony is a collection of Capistrano deployment recipes for both symfony and Symfony2 applications. Multistage is an extension for Capistrano which enables deployments to multiple servers with varying configurations or deployment procedures.

Note: If you're new to capistrano or capifony visit the project webistes to learn more about the automated deployment.

Why multistage?

Staging is a popular practice of testing software before it reaches the production environment. It's common to test a web application on a testing server before it's deployed to production. Even before code reaches the testing stage it's often tested by developers on their development machine.

Although all the environments should be similar as much as possible we often need them to vary in some aspects. Most often we want to configure the deployment procedure a little bit different on development, testing and production servers. Running Google Analytics on our test server isn't a good idea but it has to be running on production (varying configuration). Enabling development controllers might be handy on development but we definitely don't want it on production (varying procedure).

All such differences can be easily handled by Capistrano with multistage extension.

Installation

gem install capifony capistrano-ext

Capifying a project

cd /path/to/myproject
capifony .

Multistage example

To use multistage with Capistrano we need to require the extension and define our stages. We'll replace the contents of app/config/deploy.rb with the following:

set :stage_dir, 'app/config/deploy' # needed for Symfony2 only
require 'capistrano/ext/multistage'
set :stages, %w(production testing development)

set :application, "MyApp"

set :repository,  "mycompany.com:/var/repos/#{application}.git"
set :scm,         :git

set  :keep_releases,  3

Note: For symfony 1.x application we need to remove 'app/' from the path to the config files used in this article.

Production, testing and development are our deployment stages. For each stage we have to create a separate file in app/config/deploy directory. Here's an example of a production stage (app/config/deploy/production.rb):

server 'myapp.com', :app, :web, :primary => true
set :deploy_to, "/var/www/myapp.com/"

after 'deploy:finalize_update', 'symfony:project:clear_controllers'

Test server settings might be a little different (app/config/deploy/testing.rb):

server 'test.myapp.mycompany.com', :app, :web, :primary => true
set :deploy_to, "/var/www/test/myapp.mycompany.com/"
set :symfony_env_prod, "test"

While deploying our application we have to specify the target server:

cap production deploy

Of course we can do much more than just changing the configuration options. It is also possible to:

  • add hooks to alter the deployment procedure for a specific stage
  • change the behavior of existing tasks
  • extend existing namespace with new tasks
  • create a new namespace with custom tasks

In practice tasks or namespaces hardly vary between stages. In most cases we'll need to have different configuration or hooks.

Jakub Zalas

Jakub Zalas

Agile PHP Developer, addicted to BDD and Symfony