Justin and I provide operational support to the SME Toolkit project, an education portal for small to medium sized enterprises in developing countries sponsored by the IFC (which is the private sector development branch of the World Bank Group).
Recently, the source code for the Rails-based web application was migrated from Subversion to Git. This also changed how we deploy the application. Previously, we deployed a snapshot of code from a tarball placed on a bastion server. With a few changes to our Capistrano configuration, we are able to deploy directly from the source code repository.
First we switch from
set :scm, :none
set :scm, :git
set :repository, "/path/to/unzipped/snapshot"
set :repository, "git@server:project/repository.git"
Then we’ll also want to use
set :deploy_via, :remote_cache so that we’ll only need to pull down the commits since the last deploy each time rather than cloning the repository and pulling down the entire history every time.
Now we can deploy using a command like:
cap stage_name deploy -S branch=master
Deploying a Specific Tagged Version
But what if we want to deploy a specific tagged version? We should be able to use
cap stage_name deploy -S tag=3.2.1.
Unfortunately, it’s the ‘branch’ variable that’s used as a ref by Capistrano internally to resolve the revision deployed. This is not well documented, but see: lib/capistrano/recipes/deploy/scm/base.rb:77, and lib/capistrano/recipes/deploy/scm/git.rb:119, and lib/capistrano/recipes/deploy.rb:L29.
The simplest way to address this is just to
set :branch, tag in
In order to run other tasks without specifying a tag however, we should probably qualify that with a conditional:
set :branch, tag if exists?(:tag).
Updating the Version Number
There’s one last thing to be updated: the version number. Before, the developers would populate the REVISION file with a version number when creating a release tarball. Now the REVISION file is populated by Capistrano, with the SHA of the commit being deployed.
If we substitute a new file, say BUILD_VERSION for REVISION in environment.rb, then we can again control of the version number displayed in various places throughout the application. Rather than a long seemingly meaningless string of letters and numbers, we’d like to include the date the code was deployed and the semantic version number of the code.
We can do this with a small Capistrano task like:
If we put this task in the deploy namespace, we can ensure that it’s run at the end of each deployment with something like:
after "deploy:create_symlink", "deploy:build_version"
Now when we deploy, the date and the tag are prepended to the SHA for a much more meaningful build version.