Deploying CruiseControl.rb with Custom Tasks

More and more work is being done by geographically disparate teams these days, so a continuous integration tool like CruiseControl.rb is quite useful. Andre and I could have used this when we were heads down with GeoKit. But better late than never, right?

I decided I would make an attempt to deploy CruiseControl.rb to one of the hosts that I have — and do so with Capistrano. For the most part, it was pretty painless, but I did run into a gotcha or two.

First, the host I deployed to uses the Apache / Lighttpd (fastcgi) style of deployment. Unfortunately, Lighttpd just would never start up for me! After way too long, I finally figured out that I had DOS line breaks in my file that I could not see. So I zapped them with dos2unix and all was well. Unfortunately, this ate up a lot of my time as I’m not very skilled at debugging fastcgi issues.

CruiseControl.rb is a Rails app, but not your typical Rails app. It uses no Rails app, but rather stores your project information in a projects directory underneath the app root. Further, its more than just a Rails app, it utilizes additional processes as project builders.

To deploy with Capistrano, you have to preserve the projects directory so that it will persist across your releases. That’s pretty easy to do with symlinks, so that’s a piece of cake. You can use the after_update_code callback to do this.

There are two other use cases that I could see that I would need. Adding a project and starting a builder for that project. To enable those, I added Capistrano tasks for each. Both tasks rely on environment variables and both tasks could probably benefit from a bit more error-checking, but they are good enough for me.

So to start a project, I use:

NAME=GeoKit URL=svn://rubyforge.org/var/svn/geokit cap add_project

to start its builder, I use:

NAME=GeoKit cap start_builder

I added my custom tasks under config/recipes/cruisecontrol.rb and required this in deploy.rb. The custom tasks code is below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Capistrano.configuration(:must_exist).load do

  desc "Update symlink for projects directory."
  task :after_update_code do
    run <<-CMD
      rm -rf #{release_path}/projects &&
      ln -nfs #{shared_path}/projects #{release_path}/projects
    CMD
  end

  desc "Add a project to cruise control."
  task :add_project do
    unless ENV['NAME'] && ENV['URL'] 
      raise ArgumentError, "***** You must specify the NAME and URL parameters to add a project. *****" 
    end   
    run "#{current_release}/cruise add #{ENV['NAME']} --url #{ENV['URL']}"
  end
  
  desc "Start a builder for a project."
  task :start_builder do
    raise ArgumentError, "***** You must specify the NAME of the project to build. *****" unless ENV['NAME'] 
    run "#{current_release}/cruise build #{ENV['NAME']} &"   
  end
end

And with that, any of my projects can now be monitored with CruiseControl.rb.

A few caveats.

  • I had to physically edit the cruise_config.rb file (on the server) for the project to include my email address and polling interval. No big deal, its a one-time thing.
  • If your code is proprietary, you may want to protect the site with
    basic authentication to keep unwanted eyes from seeing your project assets.
  • Since your project data is on your server’s file system, you may want to consider a backup strategy if you value your build history.

Suggestions for ThoughtWorks:

  • Consider including Capistrano tasks to make it easier — mine are admittedly rough, I’m sure.
  • Consider adding some element of authorization by project. For example, I have public plugins, but I also have proprietary code that I do not wish to share. Obviously, its easy enough to deploy a second site, but that’s mildly inconvenient.

I hope this is helpful to continuous integration fans out there trying to get set up!

This entry was posted in Open Source, Ruby, Ruby on Rails. Bookmark the permalink.

4 Responses to Deploying CruiseControl.rb with Custom Tasks

  1. Pingback: CruiseControl.rb: Continuous Integration for Ruby (and Rails)

  2. Cyrille says:

    Hi Bill, thanks for this very interesting post.
    I do not understand the after_update_code. Where exactly have you installed cruise application (all the files and binaries) ?
    To my understanding there is no ./projects directory inside the release_path.

    Can you please give a little bit more details about your integration of CCrb and Capistrano?

    Thanks
    Cyrille

  3. Perhaps I glossed over it, but I created a projects directory under the shared directory since this is data that needs to survive releases.

    The presumption is that you’ve create the projects directory already. Of course, you could probably do this in an after_setup step if you wish. Or just manually do it.

    Hopefully, this clears it up.

  4. Pingback: Capistrano

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>