Continuous Integration in 2009 1
A Great Idea
Continuous Integration (CI) is a really great idea.
For a guy like me it means that one week before a major product deadline I can leave early on Friday (as opposed to freaking out and working a 75 hour week.)
But, it doesn’t mean what it used to. Less that two years ago I remember talking about Continuous Integration as “Making sure someone doesn’t break the build.” Reading that statement makes me laugh now. What a ridiculously low bar.
Back then just having a server check out your code and compile it was something. Having it run unit tests the package your software for deployment was amazing.
Times have changed.
What I am now looking for in a Continuous Integration server it is completely different. I want it to grab the code and run Unit, Functional and Acceptance tests on it. Then I want a code coverage report for those tests. On top of that I want a report on standard code metrics that will tell me things like how “DRY” the code is.
To be considered exceptional all of these features need to be tightly integrated and status notifications about updates should be done over Twitter and with a Growl notifier.
Better yet the tests, coverage and metrics should be run pre-commit and anything less than 100% passing and 100% coverage should not be allowed in the repository.
Continuous Analysis & Integration
Really what we are talking about here is not Continuous Integration anymore, it is Continuous Analysis and Integration. Because it really doesn’t matter if the code integrates unless the code is also DRY and thoroughly tested.
My Wishlist
So here is my wish-list for a CI server to use on upcoming projects:
- Integration with GitHub including post commit hooks.
- The ability to run tests, coverage and metrics pre-commit via a gem (think like that Heroku magic for deploying).
- A project template that includes tabs for artifacts from test results, coverage reports and metrics
- Twitter integration.
- A growl notifier.
- Aware of Ruby/Rails for the collection of artifacts necessary for deployment.
- Integrated ability to run capistrano deployment scripts to stage a site if everything passes.
- Tasks run as worker process with customizable credentials and not as the Apache user! (I shouldn’t need to mention this one.)
- All of this out of the box without hours of configuration.
A Final Word or Two
The idea of convention over configuration is beautiful and should be applied to Continuous Integration.
A lot of systems can do anything but everything is hard. That is just dumb.
Good practices should be simple. Customization should be possible.
Post a comment if you have something that you think fits the bill. I think a lot of people would be really interested in hearing about it.
iPhone Twitter Apps demonstrate the need for automated testing practices. 1
Twitpocalypse - when the number of tweets exceeds the largest number you can store in a 32-bit signed integer. In essence twitter runs out of numbers to count peoples tweets.
The Twitpocalypse should have been a non-event. Twitter had things dealt with on their side and warned developers in advanced to update their code - May 13th in fact.
Still several apps broke, including my previous favorite - Twitterific.
Craig Hockenberry and some other iPhone developers don’t know how to test their own code. On his blog he seems to suggest that solution to the problem is that Apple needs to provide a mechanism for allowing a quick path to push a critical update through the App Store.
I am going to suggest something different entirely - it is 100% his fault for not having adequate testing practices in place.
This wasn’t a “brain-fart” or whatever term he wants to call it (and just for the record I hate that term).
This is the sort of thing you toss in your fixtures and unit tests and run every time you commit code. You mock or stub out the pieces you can’t control. Your continuous integration server should test this every time anyone commits some code.
It was a complete failure of his current testing practices.
And Apple can’t fix that with a special track to allow for quick updates.
Continuous Integration with Integrity. 2
Nick Quaranto has posted a nice article talking about their Continuous Integration setup over at Thoughtbot.
And while he did a great job of explaining what he did, the details of how exactly he did it were left as an exercise to the reader. Here are the details that you are going to need to actually get this thing running.
There are two parts to this adventure, Integrity and Metric_fu.
Integrity
First we need to get Integrity up and running. Install the following gems first:
* Rack (v 0.9.1) sudo gem install rack -v0.9.1
* Sinatra (v 0.9.1) gem install sinatra -v0.9.1
* Thin (v 1.0.0) gem install thin -v 1.0.0
If you are running on OSX then you will need to get
require 'forwardable'
into your environment.rb because it is not there. This is needed for Thin 1.0.0.
Turns out that Sinatra needs to be version 0.9.1 or the notifiers will explode.
The you can then install integrity. Got to the Integrity Website for the details on this. USE THIN. If you don’t you are going to be compiling code as www-data. Create a user account on your server that can access the console and start up thin with this account. Start and stop thin like this:
thin -C thin.yml -R config.ru start
thin -C thin.yml -R config.ru stop
You likely want to have this start with a LaunchDaemon on OSX or something else on Linux. And you likely want to toss this into your Apache config file with a little something like this
############ INTEGRITY PROXY ###########
<VirtualHost *:80>
ServerName integrity.yourserver.xxx
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Proxy balancer://mongrelcluster>
BalancerMember http://127.0.0.1:8910
BalancerMember http://127.0.0.1:8911
</Proxy>
ProxyPass / balancer://mongrelcluster/
ProxyPassReverse / balancer://mongrelcluster/
ProxyPreserveHost on
<Location />
Order allow,deny
Allow from all
</Location>
</VirtualHost>
That should get Integrity going. But, who cares unless it tells that things are breaking. Add a little Twitter notification with by adding the following to your config.ru file:
require "notifier/integrity_twitter"
Integrity::Notifier.register(Integrity::Notifier::IntegrityTwitter)
And then get an integrity-twitter notifier gem installed. I use this one:
git://github.com/hchoroomi/integrity-twitter.git
Great. Now you can get your tests running.
What I’d suggest is to manually check your stuff out and try to have it run on the server. This will help you get all the gems you need for your project installed and let you debug issues.
If things are just refusing to run, ask yourself this question “Who is thin running as and can they run on the shell?”
metric_fu
Nothing worth doing is simple.
Okay with that out of the way we need to get the gem for metric_fu installed and working. First grab qrush’s version:
git clone git://github.com/qrush/metric_fu.git
And this is where the fun starts again. Rcov have moved but no one knows yet. So grab it from here:
git clone git://github.com/relevance/rcov.git
And then install it by hand:
gem build rcov.gemspec
sudo gem install rcov-0.8.3.4.gem
Before this point you might want to delete the following lines from tasks/metric_fu.rake to stop it from opening the tests once complete:
if MetricFu.report.open_in_browser?
MetricFu.report.show_in_browser(MetricFu.output_directory)
end
Then you can install the qrush fork of metric_fu:
gem build metric_fu.gemspec
sudo gem install metric_fu-1.0.3.gem
Bringing it Together
Once this is done you can do something like:
rake test:all
rake metrics:all
And you should have some tests that run and metrics created. The question remains, how do I get this on the web?
I don’t have the answer to that yet. But I will let you know once I am operational.
Consuming SOAP Services on OSX 1
SOAP is bloated and I hate dealing with it. I still have to do it. When dealing with consuming SOAP services from OS X I like to have a couple of items in my bag of tricks to get up and running: a SOAP Client and a way to do base64 decoding. This way I am able to test the service without writing any code. Too often I beat my head against my keyboard over a piece of code only to realize the service itself is the problem.
Here is the SOAP Client that I use: SOAP Client (what an original name!). It really does the trick, though. Point it at the SOAP service WSDL and you are off to the races. It allows you to pass in arguments and call different services. It does it all and returns the XML requested.
Once you have the XML often you will then need to decode a base64 encoded string. Base64 decoding is a bit trickier. Most of the time you can use openssl to decode on a Unix based platform but for some reason it doesn't seem to work for me. I have had to resort to the following perl script:
#!/bin/sh
# decode a Base64 encoded file, as a side effect of
# openssl base64 handling (but without encryption)
/usr/bin/perl -MMIME::Base64 -e 'print decode_base64(join("", <>))' < "$1" > "$2"
The script takes two arguments: and input file and an output file. I am not a "perl" kinda guy so the script is mostly stolen and probably can be hugely improved.
If your data is a base64 encoded string of gzipped data the next step is to toss the old ".gz" extension on the file and extract the contents using the OS or using gunzip.
Basic stuff really, but it is a pain to track down so I thought I would toss it all in one place.
Agile To Do List: Prioritize Work (Get Paid)
I like getting paid.
I am not saying that I go to work for a paycheck - I love what I do - but a person has to eat and to eat they need to get paid.
For this reason I suspect you like getting paid too.
This is not a bad thing. It simply creates the reality that someone is going to have to pay for all the work that you do in a day. We call that person the customer. Whether the customer is a larger company or 100,000 teenagers they are going to have to pay for each line of code that you develop.
The truth is that this actually creates a simple answer to a complex problem. Often when developing software it is hard to know where to draw the line when it comes to features, documentation, etc. People often debate this for hours. It is actually pretty simple:
Make sure the customer is willing to pay for everything that you do.
It turns out that this actually can be broken down into two categories of user stories:
- Stories that have value so the customer is will to pay for them. (this might be that new feature you are working on.)
- Stories that have no value but are required to get paid. (this might be the documentation needed to use the new feature.)
Think of this as working and filling out a time sheet: you need to work to get paid and you need to fill out your time sheet to get paid. Valuable stories and required stories. Pretty simple.
In Scrum this simple concept forms the basis for a product backlog. The Product Owner (a representative of the customer) and the ScrumMaster make a list of stories and then assign a value to them. The team then estimates how hard a task will be to complete - lets call this the effort. Sort the list by dividing the value by the effort. Again, simple.
Priority = Value / Effort
Things only get a little tricky when we talk about required stories (the ones without value that are still needed to get paid). These should be kept up to date with the progress of the project. For example, a required manual should be updated once a feature is demo’d. This way the product can be released as needed with little notice.
As you work through the list you will eventually realize that at some point the value returned by a stories does not pay for your development costs to produce it. This is when you wrap the project up and deliver it. Again, simple.
So to recap here is the way to prioritize your work:
- Only work on stories that get you paid:
- this can mean stories with value or
- this can mean stories that have no value but are required.
- Don’t work on anything that is not required to get paid.
- Priority = Value / Effort
- Sort your list by priority.
- Even thought the priority of a required story is essentially zero, keep required stories up to date with your current progress so that you can deliver the product as requested by the customer.
- The project is done when the customer is happy with the current features or when it will cost more to develop a story than it is worth to the customer.
Follow these rules and you will get paid.
And you will be happy.
And your customer will be too.
Start small. Think BIG.
Agile To Do List: Fail (or Succeed) Quickly
I read a book by Seth Godin a while back called "The Dip." (Well, by read I mean I listened to it after buying it from Audible.) The book gets a bit repetitive but the message is relevant. It is a book about quitting as a technique for success.
I am going to repeat that for those of you skimming this post: "The Dip" is a book about quitting as a technique for success.
Initially this should seem strange. For some reason society seems to think "winners never quit." Society is wrong. Winners quit. They quit so quickly that you might not even notice they tried at all. That is the whole point.
In my post on Prioritizing Work I talk about how we need to work from a backlog that orders stories by value. Most often you will find that the high value items are usually difficult. A difficult item with low business value is something that likely will never be done - why would you waste time working on a problem that has no value. At times you will find that a projects success hinges on completing some difficult items. They may be so difficult that , for many reasons, they are impossible and the software project is doomed to fail. That is why we need to build these features first.
If a software project fails after one week, great! This is the best possible way to fail: very little time and effort invested. Chances are there is disappointment but everyone survives.
Software projects that take years to fail bring down companies. I have personally seen it happen.
The only thing better than failing quickly is succeeding quickly. What better success to start a project with: tackling the hardest problem!
In XP they would call this a spike solution. In Scrum this is the way we organize our backlog. Either way the concept is simple: don’t invest time and effort into a project that you cannot finish.
Failing early is the key to success.
I realized that this really answers a simple question and then presents a much harder one. Namely, you need to know if the problem you are working on is hard or if it is impossible.
I don’t have the answer for this one. There is no sure-fire way to measure your talent or that of your team and know if you will succeed. Analyze the problem. Be realistic about the availability of the resources need to complete it. Think about what is needed to succeed. Is success possible. Weigh the risks and rewards.
It is hard to predict success and failure. That is not what this is about. It is about honestly evaluating if success is an option and if failure is inevitable.
If you can’t succeed, fail quickly.
Start small. Think BIG.
Agile To Do List: Defining Done
Ever ask someone how they were doing and then got the reply, "Fine" - what does fine actually mean?
As far as I can tell fine used to mean a little closer to good then bad but now I am convinced that it actually the equivalent of someone saying either "You don’t really care how I am feeling and I don’t really care to tell you!" or it means "I am feeling so bad right now that if I actually tell you I am going to burst into tears and it is going to ruin your day."
I think that software teams have the same problem with the word "Done" - what does done actually mean?
Done can mean a lot of things including:
- Delivered
- Documented
- Tested on Production
- Pushed to Production
- Staged
- Tagged in the Repository
- Acceptance Tested
- Ready to Demo
- Committed to the Repository
- Unit Tested
- Peer Reviewed
- Ready to Test
- Barely Working
What does done mean for your team?
An exercise that like to do is to have everyone write down their definition of done and then read out the definitions to the team (obviously without naming who wrote the definition). Then as a group come up with a universal definition of done. Once you all agree hang it up on the wall in a nice frame. Have the creators sign it. The visibility of the definition will keep people honest.
It is important to note that the definition will need to be different for every team. You probably do not have access to the production environment. Maybe you work for a large company that has policies requiring someone else stage or acceptance test your code. Work with what is realistic.
When it comes to the definition of done the most important thing you can do is just talk about and agree upon the definition. The definition is less important.
Once things are getting done then work on expanding your definition.
When you are starting out it is sometimes a tall order to go from a concept to code that is working on production in a week. There needs to be a lot of tools in place to allow this to happen. As the team gets better include more in the definition. If you are working on a large project going from a Story to Done in a week or two might be a tall order without the right processes and the right tools.
Here are some practices and tools that will help expand your definition of done:
- Behavior Driven Development: rSpec, nBehave, NSpecify, JBehave, NSpec
- TDD and Unit Testing: xUnit (Yeah, there is a unit test framework for your platform. You need to fine it though.)
- Continuous Integration: CruiseControl, CruiseControl.NET, Cruise, TeamCity
- Virtualization: VMWare, Cirtrix Xen
- Scrum, XP: Mingle
When we started out our definition of done was demo-able. Now it means delivered.
Start small. Think BIG.
Agile To Do List
I have decided to write a series of posts that I am now going to call my Agile To Do List. If you are planning on using some form of Agile software development like Scrum these are things that you are going to need to do.
This list is not going to be in order of priority for you. You need to evaluate your own situation an determine where improvements are needed most. However, I am quite convinced that if you are able to tackle this list with your team you will succeed.
I am going to add to the list here as I write the articles so that you will be able to grab them from one central place.
Okay, without further ado here is the Agile To Do List:
- Define Done (and make sure this includes testing).
- Create a Prioritized List (Backlog) to work from.
- Ensure Quality
- Fail (or Succeed) Quickly
- Have a Scheduled Weekly Demo (that ends with a reflection).
- Have a Scheduled Weekly Reflection (that begins with a demo).
- …
Like I said, as I complete the articles I will post the links here.
So you decided to go Agile. Now what...
Agile software development makes sense. Reduce waste, improve productivity, it sounds great. Maybe you buy into Scrum, maybe Crystal Clear. There is a lot of information on the web discussing Agile project management.
The biggest challenge is not the planning, it is actually getting things done. Writing the code.
When it comes to writing code there are some practices that can help developers succeed: test driven development, continuous integration, automated testing.
We know what we need to do. We know why. But, how?
How is the real trick. How do you take a team of developers, any team of developers, and make them agile. Agile in their practices and agile in their thinking.
How is the question I intend to answer.