Suppose you park your car in a neighborhood with a lot of occurrences of vandalism and crimes. If you return two weeks later, there is a good chance that you will find the car in the same state that it were when you left it there. Now imagine if you parked the same car but with a broken window. There is a good chance that you will see an engineless car, without tires or many other parts. Of course, we did not conduct this social experiment, but we know about a theory called Broken windows theory that says if we have something intact, it has a tendency to remain intact. But if we have something broken, there is a tendency that it will be even more damaged after some time.
But how does it apply to software development? Suppose you have some developers working on a project with about a thousand tests covering all the code and all of them are passing. If a developer implements a feature and it breaks some tests, it seems reasonable that he will make an effort to make the necessary modifications so all tests pass, or maybe he’ll remove them if they don’t make sense anymore. Also, it is expected that he will write new tests to cover the new feature.
Now suppose a different scenario: the project has a thousand tests and a hundred of them are not passing. Even worse, the code coverage is about 70%. As the developer writes the new feature, there is a tendency that he may not create tests and not fix the broken tests that this implementation caused. There is an analogy with the broken windows and failing tests: if you allow a failing test to stay there, there is a good chance that your team may not work on correcting tests and the number of failing tests may increase during time, leading to a poor quality software.
OK, you have heard about the problem, but how can we solve that? A first idea is to hire a monkey that keeps an eye in the version control, and everytime there is an update there, it presses a key that runs all the tests. The monkey is actually very smart and it will scream if it sees red F’s in the screen. And every time the monkey screams, you know that somebody commited a broken test and you also know that every commit will make the monkey scream. So it’s time to fix the broken test. But you may have problems with Greenpeace doing that. So, it is a good idea to have something that does not depend on living animals. So maybe a robot? Yes, this is what we call Continuous Integration tools.
Continuous integration is what we call the process where developers integrate their codes continuously. Continuous Integration tool is an application that executes the build every time it is updated in the version control. This build can watch for compilation/interpretations errors, not passing tests, performance issues or anything you may think reasonable to watch.
There are lots of continuos integration solutions suitable for Ruby (and consequently Ruby on Rails). Some java-based (Hudson) or some in Ruby (Cruise Control rb or Signal). We tried using Signal at first, but we have some problems related to the gem environment (we could not make it change the environment to the project gemset instead of the Signal gemset environment). So we tried the minimalistic CI JOE.
CI JOE is a CI server created by the Githubber Chris Wanstrath. It is sinatra based and does not need even a database to run: all of its configurations are recorded in the .git/config file and it uses git hooks to run the desired actions. There are only two requirements: your project must use git for version control, and the build should return a zero shell status for success and anything different than zero for not successful builds. You can use it with any programming language or framework. I strongly encourage you to configure to pull the build trigger every time you do a git push (you can do that simply doing a POST to a URL).
The most awesome thing about CI JOE is that it is dead simple to configure it to do almost anything. You can configure Campfire notifications, e-mail deliveries or an alarming buzzing when it fails. The only requirement is that a shell command exists (if it requires a sequence a of shell commands, you can join them using ‘;’). A great idea is to integrate electric devices like leds, buzzers or even a semaphore.
The project comprehensive README has a lot of examples, including how to protect it with HTTP basic authentication or how to configure a queue of build requests. For our projects, we usually customize it by setting a git after-reset hook to execute “bundle install” (it always execute this git hook before the build starts) and then we modify the html template to include the project logo. Next, CI is ready to rock and roll!
And you? What do you think about CI JOE? Are you customizing it in any way? Are you using another CI solution for your Ruby on Rails projects?