Monday, February 28, 2011

Continuous Integration with CIJoe

CIJoe lacks a great many things that I usually expect in a CI server.  But it is now unclear if they are really all that needed, or just added by CI marketing.  Here is now I usually get CIJoe working with the least Effort.

The abridged version:

# rvm
$ bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )
$ rvm install 1.8.7-p330
$ rvm use 1.8.7-p330@foo --create
$ gem install bundler
$ gem install cijoe
$ git clone git://github.com/XXX/foo.git
$ nohup cijoe -p 4000 foo &
$ git config --add cijoe.runner "bundle install 2>&1 && rake ci"

  1. Install RVM
Docs on installing RVM are here.  I use this to isolate my version of Ruby and Gems from other CIJoe servers that I will setup on the same machine.  This reduces the headaches later

1.1. Install Ruby
With RVM installing new versions of ruby is easy with RVM.  For example I use ruby 1.8.7-p330 on one of my projects so I run rvm install 1.8.7-p330.

1.2. Create a Gemset
For every CI Server I run I use a different gem set.  Yes it uses more disk space but it saves so many headaches if two repos need different versions of different gems it is worth it.  You can run it with the "rvm use" command.  Lets say my project is called "FOO" I would run rvm use 1.8.7-p330@foo --create to switch to ruby 1.8.7-p330 using gemset foo and create the gemset if it doesn't already exist.

1.3. Install Bundler
Bundler is a manager for RubyGems that aids in getting the correct version of the correct gems installed.  I install it so that before every make I run "bundle install" to make sure that the CI server has all the gems it needs for the test to pass.  And if it fails because of a gem problem then it means the correct gems were not noted in the GemFile and therefore it will break in production.

2. Install CIJoe
CIJoe is a gem and it should be installed in the same gemset that the repo will be run out of.  So if the code to test is Foo then run rvm use 1.8.7-p330@foo --create; gem install cijoe.

2.1. Clone your repo
git clone git://github.com/XXX/foo.git or something like that

2.2. Run CIJoe
I run it with nohup and & so it is in the background and always running.  I also give it a known port so that I blow a hole in the firewall for it (see below for why).

nohup cijoe -p 4000 foo &

3. Configure your repo
This is both a strength and weakness of CIJoe: all the configuration for what to run and how is stored in the Git repo.  The strength is that it is stored with the repo, the weakness is that .git/config and .git/hooks are not pushed to remote repos so if you need to start over you will need to recreate that config from scratch.

3.1. Add the runner command
CIJoe only allows running of a single command but it executes it in "sh" so you can use "&&" to chain them.  However, to make things easier on myself I always create a rake task called "ci" and execute that. Also, to make sure that all the gems are correctly installed I run bundler first.

Note: When chaining commands via && make sure you redirect stderr to stdout since CIJoe only reads stdout, otherwise you will get nothing in the output file.  The last command will already have stderr redirected so do not do it twice.

git config --add cijoe.runner "bundle install 2>&1 && rake ci"

3.2. Adding Notification
CIJoe just executes .git/hook/build-failed on a failure and .git/hook/build-worked on a success.  The examples show how to setup these up.

4. Auto build
Any HTTP PUSH to CIJoe will cause a build to be kicked off.  This is useful for auto-kicking a build when a new commit is pushed.

4.1. Blow a hole in the Firewall
This is so that github can get into your build server, since I assume you have your build server behind a firewall.  Your config will depend on Firewall/Router.

4.2. Configure Github
Just add a Post-Receive hook via the github admin screen.

No comments:

Post a Comment