Hudson & Python

Today I’m going to pick some low-hanging fruits as there is a lot of documentation on this topic already. However, as there usually are a lot of gory details I’ll write on how this worked out for me.

“Hudson is a continuous integration tool” (Wikipedia). It is very useful for running Unit testing and can automatically act on new commits made to the project the Hudson server watches. You can for example set-up Hudson to notify the person having committed broken code by E-mail or even have a USB traffic light show the status of the checked source code.

Installing on Ubuntu

While one good thing about Linux distributions is that installing is merely a single command away, this is currently not given for Hudson on Ubuntu or Debian. There is currently an open ticket for packaging Hudson for Debian but so far only an unofficial package from the Hudson team itself exists.

Hudson needs Java and I could only get it to work with the official Java sources. To install Java from Sun Oracle you need to enable the “partner” repository from Ubuntu. Uncomment the following line in “/etc/apt/sources.list” (for Ubuntu 10.10):

deb http://archive.canonical.com/ubuntu maverick partner

 

And then run

$ sudo aptitude update

$ sudo aptitude install sun-java6-jre

 

Now make sure the right Java is used by running:

$ update-java-alternatives -s java-6-sun

 

Once you have Java installed you need to install the “daemon” package that Hudson needs:

$ sudo aptitude install daemon

 

Now download the Hudson “.deb” from http://hudson-ci.org/debian/ and follow the steps described there to install the package.

Hudson should now be running under http://localhost:8080/

Setting up a Python project from Git

As others have already described how to use Python with Hudson before and probably even have done it better than I could do in this place here I urge you to follow the steps described in http://www.protocolostomy.com/2010/12/02/nose-and-coverage-py-reporting-in-hu… . Make sure you have git installed and maybe other hard dependencies your project will need (e.g. python-dev when compiling packages).

There is an issue however with the first git checkout. If you haven’t used and configured Git on the system before you will probably get an error similar to the one below: “FATAL: Could not apply tag hudson-surf.virtuoso_protocol-1“. In this case you need to move to the workspace created by Hudson and do the configuration as described by <a href="http://wiki.hudson-ci.org/display/HUDSON/Git+Plugin:

http://wiki.hudson-ci.org/display/HUDSON/Git+Plugin:</p>

$ cd /var/lib/hudson/jobs/YOURPROJECT/workspace/

$ sudo git config user.name “YOUR NAME”

$ sudo git config user.email “YOUR EMAIL”

 

Managing dependencies via virtualenv

Most projects come with dependencies and while manual installation on the server will work, it is impossible to keep different conflicting versions and in general will need you to install new Python packages once dependencies change. Virtualenv which I’ve mentioned before comes in handy here.

As described in http://www.hudson-labs.org/content/python-love-story-virtualenv-and-hudson there is a quick way to introduce virtualenv into the build process.

By adding a build step “Execute shell” with the following content

if [ -d “.env” ]; then

echo “**> virtualenv exists”

else

echo “**> creating virtualenv”

virtualenv .env

fi

pip install -r requirements.txt

 

a virtual environment will be created in .env and updated on every run of the build process. All we now need is to write the file requirements.txt to include the project’s requirements. This at best is a simple file with one line per package dependency. This actually is a good use case for the method I blogged about before.

Using nose for unit testing

Nose is a very handy tool when doing unit testing. In the post about Python&Hudson mentioned above nose is already used for generating the unit test XML and code coverage results. Here’s an in my opinion nice way to use nose in any project.

Distutils has a command for running tests:

$ python setup.py test

By adding the following two lines to setup.py we can use nose for this handler:

test_suite=”nose.collector”,

setup_requires=[‘nose>=0.11’],

We can then activate xunit results and coverage by generating the file setup.cfg:

[nosetests]

with-xunit=1

with-coverage=1

cover-package=YOUR_PACKAGE

cover-html=1

To have the plug-ins activated we need to use the nose handler though (see <a href="http://somethingaboutorange.com/mrl/projects/nose/0.11.1/api/commands.html):

http://somethingaboutorange.com/mrl/projects/nose/0.11.1/api/commands.html):</p>

$ python setup.py nosetests

With this we have not only created an easy way to run the test from Hudson (using the “Execute shell” build step) but also can we now provide a dead easy way for our users to check the project’s code. I use this for example for https://github.com/nwebs/surf.virtuoso_protocol .