Python and Jenkins integration

Lately we started using Jenkins at work. With proper configuration for PHP it allow us to perform predefined list of tasks in response to merge requests. Tasks consist of performing tests, code coverage, PMD analyse, search for duplicate code, find CRAP code and detect massive amount of violations – from code format to function complexity. Of course nice report and charts are generated after. Its possible to browse reports, go into files and see what is wrong with them all with comments. Very, very useful. So why not use it with our Python app ? I searched The Web and found lots of information but mostly outdated. Not a nice beginning. After some research and test I managed to run nosetests with coverage report, pylint, pyflakes, SLOCCount and clonedigger. Something to start with 🙂 So lets try and create our own Jenkins Server. We will install Jenkins (on VirtualBox in my case), required plugins and additional software. Next we will create new project and link it with git repository (with Bitbucket in my case but any will do). Finally we will add all those tasks and reports.

Jenkins and plugins installation

I’m using Mint 17 installed in VirtualBox. I wont digg into how to install it. Just search the web. So lets start with Jenkins. Everything is described here: https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins+on+Ubuntu To summarize most important steps:

wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins

After those commands Jenkins was available at localhost:8080. And surprise! No login required.. that’s kinda bad. First thing to do is to add security. Don’t worry Jenkins will guide you. It also good idea to add your VM to hosts file. This will allow us to connect to vm from main computer. Now we have a bare system. Lets add some plugins. Go to manage plugins section and install:

  1. Cobertura plugin
  2. Coverage Complexity Scatter Plot PlugIn
  3. GIT plugin
  4. Violations plugin
  5. SLOCCOUNT plugin
  6. xUnit plugin
  7. Warnings plugin

Next we need to install additional libraries. But just before make sure easy_install and pip are installed.

sudo apt-get install python-setuptools
sudo apt-get install python-pip

1) Nose It will give us tests and test coverage reports

sudo easy_install nose

or

sudo pip install nose

And install coverage plugin

sudo apt-get install python-coverage

2) SLOCCount This will give us metrics about lines of codes

sudo apt-get install sloccount
sudo apt-get install cloc

3) Pyflakes It checks Python source files for errors

sudo pip install --upgrade pyflakes

4) Pylint It checks for coding standards

sudo apt-get install pylint

5) Clonedigger It checks for duplicates in code

sudo easy_install -U clonedigger

Setting git repository

I’m using bitbucket.org but it should be similar with any git. I’m gonna use a deployment key so no login/password will be required. First be sure that git is installed and configured properly

sudo apt-get install git
git config --global user.name "your name"
git config --global user.email "your_email@sample.com"

Next switch to jenkis user:

sudo su -s /bin/bash jenkins

And finally we need to generate ssh keys:

ssh-keygen -t rsa

And answer few simple question. Remember leave passphrase empty ! Now it is a good idea to run ssh and add your repository to known host:

ssh -T git@bitbucket.org

Next copy your key to clipboard – remember PUBLIC key ! This will display key in terminal:

cat .ssh/id_rsa.pub

Now open bitbucket go to your project enter settings and select deployment keys. Click add and copy this key.

Create Jenkins project

Open Jenkins server and add New Item, enter project name and select freestyle project. Now to test your connection go to Source Code Management section, select Git and enter your url (ssh one!) in form: git@bitbucket.org:xxx/yyy.git. Jenkins will test connection and if you done everything correctly no error will appear. I’m also changing Branches to build to */develop. My Master branch is for ready software. Develop is for developing current version and sometimes I’m creating branches for other tasks . What is test software without tests 🙂 lets add some jobs!

Adding tasks

Go to build section click Add build step and select execute shell. Enter command

sloccount --duplicates --wide --details . | fgrep -v .svn > sloccount.sc || :

Add another shell scripts:

find . -name 'test*.py'|xargs nosetests --with-xunit --verbose --with-coverage --all-modules --traverse-namespace --cover-inclusive
python -m coverage xml || :
find . -name '*.py'|egrep -v '^./tests/'|xargs pyflakes  > pyflakes.log || :
rm -f pylint.log
for f in `find . -name '*.py'|egrep -v '^./tests/'`; do
pylint --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" --reports=y $f >> pylint.log
done || :
clonedigger --cpd-output . || :

Click save. Now we will do manual build just to see if everything is correct. Click Build now and when the test is ongoing, click on it and open Console Output. This will show you all steps and their result. If you see something failing check if all plugins and libraries are installed correctly. Simplest way to diagnose problems is to execute scripts manually. In my case everything works ok. Time to generate all reports in more readable format.

Adding reports

Go to Post-build Actions section. Click Add post-build action and select scan for compiler warnings. Click add next to Scan workspace files and put pyflakes.log info file pattern. From parser select PyLint. Now add Publish Cobertura Coverage report and enter coverage.xml into text field. Next add Publish JUnit test result report and enter nosetests.xml. Finally add Report Violations and configure it as follows:

  • cpd – output.xml
  • pylint – pylint.log

And that’s all for now 🙂 Go back into project and run Build now after buils is ready you are able to access all kinds of reports. For me the most important is Violations. It shows how bad your code is. And currently my project is .. lets say crap 🙂 So refactoring to the rescue.

 Running Jenkins

To complete integrations is good idea to hook Jenkins and Bitbucket together. In my case its impossible – I’m behind double NAT. Bitbucket can’t connect to my virtual machine and ping it to do jobs. I have two options, run manually or set timed jobs. But I save this for later – for next part 🙂

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.