I wanted to play the field of continuous integration tools a little bit more, so I finally gave Integrity a go. Its promise of being lightweight sure was tempting.

It's a small Sinatra app, and therefore should've been easy to set up using Passenger. The Integrity team recommends using nginx and Thin. Though I'm rather fond of nginx, I don't see any point using a different setup just for my CI system.

Getting it up and running is rather straight-forward. You create your local Integrity template directory using integrity install /path. For this to work with Passenger you also need a directory public in that directory, so if you create that you can just throw the usual Passenger virtual host block into your Apache configuration, the document root pointing to the freshly created public directory, and you're good to go. In the current master, there's already a fix for this issue, and running integrity install will create the public directory for you.

I have some gripes with Integrity though, one of them being that configuring notifiers for projects currently seems to be broken. It's sort of a big deal to me, because continuous integration lives from the team receiving notifications.

But otherwise, do give it a go, it's pretty slim and pretty slick too, though it doesn't yet have asynchronous building. It needs some sort a hook, e.g. a GitHub one to run automatically. There's also a demo available for your viewing pleasure.

Update: The issue with notification configuration not being saved seems to be resolved in the current master. It's not perfectly fixed, but at least now I can have Integrity notify me through Twitter. So if you need to, fetch the master, and build your own gem. Remember to rename it to 'foca-integrity' in the Rakefile's Jeweler configuration, otherwise it won't really catch on.

I've been a fan and user of continuous integration for quite a while now, yet I've been keen to pick up the book "Continuous Integration: Improving Software Quality and Reducing Risk" by Paul M. Duvall et. al. to see, if it can live up to be the first book dealing exclusively with the topic. They don't have to sell me on the idea anymore, but still, there's always something to learn.

The book is separated into two parts. The first one introduces the basic principles of continuous integration, and how it could/should work for you and your project. For me, this is the valuable part of the book. It introduces what CI can do for you, and the practices usually surrounding a project using CI are. If you didn't know that CI is more than just using CruiseControl or a similar CI server, I suggest you go out and pick up this book right away.

The second part describes five parts of a continuous integration system in detail. It deals with database integration, testing, inspection, deployment and feedback. A collection of recipes accompany each section to help you structure your project, code, configurations to make continuous integration a "non-event", as Martin Fowler put it.

Just as it should, the book emphasizes the importance of a good test suite to really find value in continuous integration. Without each other, continuous integration and testing can't unfold their full potential. The book is full of examples including configurations, code and build scripts, so you're not left standing in the rain, wondering how you can get that continuous integration magic to work for you.

Though I wouldn't say I'm the target audience for it, I still think there's a lot to learn from this book. Say, you just read Martin Fowler's original essay on the topic (which you should, anyway), and want to get more into detail, this book is for you. You'll find a good reference that'll help you introduce continuous integration into your project step by step.

The book focuses a lot on Java and its tools for examples, but you can easily apply the techniques in similar ways for, say Ruby/Rails projects or any other language. Database integration luckily is a topic you don't have to worry about that much in Rails projects.

It ends with a nice collection of tools that can be used for or with continuous integration, and an evaluation of CI servers and automated build tools.

My main gripe with this books is that when it comes to whys the book falls short from time to time. For someone who can make her own conclusions this shouldn't be a problem, but I think there would've been more in it. Two examples:

  • The book uses short dialogues to explain how a specific technique would work in a team, or how a line of reasoning could come about. In my opinion they're too short. What they want to emphasize could've just as well been written in a paragraph and would've had the same result. They're missing a bigger picture, and personally, I never had conversations like that.

  • The book states on two occasions that continuous integration should happen on the baseline of your project, and seems to imply that using it on branches is not a good idea. Why that is the case it doesn't explain. That the mainline is always the integration point of a project is pretty clear, but why that doesn't mean you can't integrate important branches remains unclear.

What struck me as odd was the constant mentioning of code inspection as part of continuous integration. I value code metrics for what they are (in fact, I used to be a big fan of them), and for what they can tell you about your code base, especially code coverage, but I have mixed feelings about including all of them in an integration build, because I have seen what time waster code metrics can be. But that might just be a matter of personal experience.

All that said, I still think this book is well worth the money, if you want to see what continuous integration can do for you and your project, and how you can apply the principles to your team. Paul M. Duvall did a great job compiling his experiences of applying and using continuous integrations, most of which I also had in one way or the other. In any way, I suggest reading Fowler's article firsthand, since it will give you a big picture about continuous integration, and then you can delve into the glory details with Duvall's book.

The book also has an accompanying website, where you can find a growing stack of videos explaining a lot of the principles of continuous integration in practice. If you're living in Germany, the book is currently on sale at Lehmanns.

Still a classic on the topic is Mike Clark's "Pragmatic Project Automation", one of the first books by the Pragmatic Programmers and, though slightly outdated, still a good reference. This book got me hooked onto the ideas of continuous integration and push-button builds in the first place.

Now here's a little gem I've been waiting for a long time, and that I just discovered today. Usually i just implemented custom scripts that would check the build status in CruiseControl and use Growl to notify me of build errors. I don't like having my email client open all the time just to see if the build failed, so this is a god-given.

CCMenu wants to remedy that, and comes along with support for all the CruiseControls out there, sitting in your menu bar, and checking your dashboards for the build status. It also signalizes, if a build is currently running.


Just as you'd expect it to, in good pragmatic automation fashion, it'll notify via Growl of the build status.

CCMenu Growl Notification

Apparently the tool has been written by ThoughtWorks people, no surprise here. Well done is all I can say. It still has some rough edges, but it's open source, so no need to complain, just more reasons to dig in.

Been using it with CruiseControl.rb all day, and it's working neatly.

When using CruiseControl.rb for continuous integration, and RSpec for testing, the defaults of CruiseControl.rb don't play that nice with RSpec. However, that can be remedied pretty simply.

By default CruiseControl.rb runs its own set of Rake task, which invoke a couple of Rails' tasks, including db:test:purge, db:migrate and test. You do want the first ones, but you'd rather have CruiseControl.rb run your specs instead of your the (most likely non-existing) Test::Unit tests.

Before running its default tasks it checks whether you have a specific task configured in your project settings, and if you have a task called cruise in your project's Rakefiles. You can use both, but I just declared a task cruise in the Rakefile, and I was good to go.

That task can to pretty much the same as the original CruiseControl.rb implementation, and even be shorter since it can be tailored for your project, but invokes spec instead of test. One caveat is to set the correct environment before running db:migrate. I split out a tiny prepare task which does just that, and can do a couple of other things, if necessary, like copying a testing version of your database.yml.

desc "Task to do some preparations for CruiseControl"
task :prepare do
  RAILS_ENV = 'test'

desc "Task for CruiseControl.rb"
task :cruise => [:prepare, "db:migrate", "spec"] do

Simple like that. The task spec will automatically invoke db:test:purge, so you don't need that.