Continuous Integration on Multiple Ruby Versions with RVM and Hudson


NOTICE: We've run into some snags still with the hudson daemon recognizing the proper environment vars.  We are working on some solutions after speaking with Wayne Seguin, and we'll keep you updated.  So basically, the following is possibly interesting, but not yet entirely correctly implemented.

We've recently moved to Ruby 1.9.1 on a current Rails project. Since we're still working on other projects using older ruby versions, all developers are up and running on RVM. This allows us to easily switch back and forth between different versions of Ruby. There's a railscasts episode on RVM and Rails 3 if you'd like to learn up, but Rails 3 is NOT a requirement for RVM. We've seen a HUGE speed improvement running our test suite, as well as on the application itself. We've also upgraded the production environment to Ruby 1.9.1 to match. The problem we were now faced with is our continuous integration server, Hudson, is still running on ruby enterprise (1.8.6). We needed to run each project build on whichever ruby version was most appropriate.

RVM to the rescue!

So here's how we did it.  On the build server, as the user the server runs as, we installed RVM.  We also made sure to 'rvm system --default' to make sure we didn't mess with anything that was already relying on the current version. Next up was setting the environment up correctly for Hudson to recognize RVM.  We added the same line RVM prompts you to add to .bashrc and .bash_profile to our hudson startup script

if [[ -s /home/hudson/.rvm/scripts/rvm ]] ; then source /home/hudson/.rvm/scripts/rvm ; fi

The rake plugin that lets us run our tests, migrations, coverage, etc... also allows us to create and assign ruby versions for each rake task.  So in Hudson's system configuration we created entries for our rubies:

Screen shot 2010-05-04 at 7.02.45 PM

Then we can assign each rake task to the proper ruby, in this case 1.9.1.

One last snag: some things STILL appeared to be running from the default ruby, so we added two execute tasks to bookend the process.  The first 'rvm 1.9.1 --default', and the last 'rvm system --default'.  This ensures everything runs via the proper ruby version, and we reset it when we're finished.  Is this the best process for managing CI with mutiple versions of ruby? I'm not sure, but it works!