CI with CruiseControlRB

I’ve written previously about Continuous Integration using cerberus. Over the last few months, we’ve moved from cerberus to cruisecontrolrb . Inside, I’ll give you some tips on how to get the most from cruise control.

While cruisecontrol and cerberus perform the same task, there are a few minor differences in how they do their job. First, cruisecontrol provides a web dashboard that includes information about the build status, as well as build logs and additional artifacts. Second, while cerberus does a fresh checkout for each test, cruisecontrol simply does an svn update. This eliminates the need for the client setup rake task I mention in my overview of cerberus. When cruisecontrol detects a change to your project, it executes rake cruise. This makes the build easy to customize.

In fact, here's our cruise rake task:

desc "Cruise Control build task"
task :cruise =>['db:migrate', :test,:spec, 'test:coverage'] do
  ENV['DEPLOY_TO']='staging'
  system("cap deploy migrate restart cleanup")
end

Taking this piece by piece, we first run db:migrate to apply any schema changes. After that is done, we run unit tests and then specs (we use both on this project). If that succeeds, we run a modified version of the test:coverage task from Mike Clark. If that goes well, we run cap deploy to push our code to our staging environment. We provide a staging environment to all clients, where they can see the code as it changes.

Since we use cruisecontrol as a client dashboard, we want to make sure that key information is included in each build. For us, this means inclusion of code coverage statistics in each release. Cruisecontrol provides an easy method for including additional information in any build. Anything written to the directory pointed to by $CC_BUILD_ARTIFACTS gets included in the build status. To get code coverage information into this directory, we use the following task:

namespace :test do
  desc 'Measures test coverage'
  task :coverage do
    rm_f "coverage"
    build_artifacts=ENV['CC_BUILD_ARTIFACTS']
    dir=(build_artifacts.nil? ? "coverage" : "#{build_artifacts}/code_coverage")
    system("mkdir -p \"#{dir}\"")
    rcov = "rcov --rails --aggregate #{dir}/coverage.data -o #{dir} -p --text-summary -Ilib"
    system("#{rcov} --no-html test/unit/*_test.rb")
    system("#{rcov} --no-html test/functional/*_test.rb")
    system("#{rcov} --no-html spec/models/*_spec.rb")
    system("#{rcov} --no-html spec/controllers/*_spec.rb")
    system("#{rcov} --no-html spec/helpers/*_spec.rb")
    system("#{rcov} --no-html spec/views/*/*_spec.rb")
    system("#{rcov} --html test/integration/*_test.rb")
  end
end

By checking for the presence of the environment variable, we let this task work both locally and on the server.

To make this into a client portal, we need to give our clients access. By default, cruisecontrol puts all of the build statuses on the main page. Because we are a small company, we don't mind our clients knowing about the existence and status of other clients. We do, however, want to restrict them from viewing the details of any project. To do this, we use apache digest authentication. For each client, we have an entry in the apache configuration that looks like:

 
  AuthType Digest
  AuthDigestProvider file
  AuthName CruiseControl
  AuthUserFile /u/apps/cruisecontrolrb/passwords
  Require user elevated client
  

We also have a global password requirement to make sure only our clients can login.

This setup is working really well for us, but there are some minor issues. First, cruisecontrol takes a lot of resources. With four or five running projects with large test suites, it is running quite a bit of the time. We did need to upgrade the hardware on our build machine. Additionally, because it uses svn update instead of a fresh checkout, it is possible for svn to get stuck. For instance, adding an ignore on a directory that was already in svn can require you to log in as the cruisecontrol user and manually clean up the build environment. Other than those minor issues, we've really enjoyed this tool.

Posted by Mike Mangino on Saturday, May 05, 2007