Continuous integration/Tutorials/Test your Python

From mediawiki.org

This tutorial is aimed at getting Jenkins jobs to be triggered for your python project. We will cover steps that needs to be done in your code repository and how to have jobs added and triggered by Wikimedia continuous integration platform.

Design[edit]

The jobs are meant to be run using tox, a thin wrapper around virtualenv. As a prerequisite you will need a working setup.py to let tox install your python project in an isolated environment. Each environment defined in the tox file can then be defined as a Jenkins job. Whenever a change is proposed in Gerrit, all the defined jobs will be triggered and report back in Gerrit. The jobs are run on a CloudVPS instance under the integration project.

Prerequisites[edit]

You should have a working setup.py installed and a few tests. What is the point of writing a python module if it can not be installed and lacks even the most basic tests. One can use the python module pbr to easily bootstrap a setup.py.

Matching conventions and adding tox support[edit]

Your repository should match a bunch of conventions and support tox. Do not be afraid, that is surprisingly very easy to achieve. We will get environments to run the flake8 python linter and nose tests.

Create a configuration file setup.cfg to finely tune the behavior of the utilities:

# configuration section for nose
[nosetests]
verbosity = 1
detailed-errors = 1

# configuration for flake8
[flake8]
# W293: whitespace on blank lines is ok
ignore = W293
# Raise the default 79 limit
max-line-length = 90
# Ignore some well known paths
exclude = .venv,.tox,dist,doc,build,*.egg

List your requirements! Most probably your project will require additional modules. The convention in python world is to list the modules in two files:

requirements.txt
for modules needed to execute your software
test-requirements.txt
additional dependencies when executing tests

They will be added to tox configuration which invokes 'pip install --pre'.

Then create a tox configuration boilerplate. This is done in a file tox.ini at the root of your repository. We will define two environments: py26 and py27 for tests with python 2.6 and 2.7, then flake8 to run the linting utility. If your code is for Python 3, you could use py34 and/or py35.

# Tox configuration
[tox]
minversion = 1.6
skipsdist = True
# List the environment that will be run by default
envlist = flake8, py26, py27

[testenv]
# Default configuration. py26, py27, py34, etc. will end up using this
setenv = VIRTUAL_ENV={envdir}
# Passed to 'pip install --pre', that will install the dependencies listed in those files
deps = -r{toxinidir}/requirements.txt
       -r{toxinidir}/test-requirements.txt
commands =
     nosetests

# Settings specific to the flake8 environment
[testenv:flake8]
# The command to run:
commands = flake8
# We only need flake8 when linting, we do not care about the project dependencies
deps = flake8

[testenv:venv]
# Let you pass additional arguments when invoking tox
commands = {posargs}

Then you can install tox:

pip install tox

At first list environment triggered by default:

$ tox -l
py26
py27
flake8
$

Execute them using tox. If all went well you will seen green success.

You can execute a single environment by passing -e to tox:

$ tox -e flake8
...

Editing Zuul configuration[edit]

The configuration is held in integration/config.git repository, at zuul/layout.yaml.

Under the projects section add an entry for the Gerrit repository name (ex: team/software1). We will want to trigger on patch proposals and when someone vote +2:

  1. tox-docker

This is a special job that will run the command tox on a Debian Jessie virtual machine. You just have to create an entry for your repo and add a template:

projects:
  - name: team/software1
    template:
      - tox-docker

Or alternatively if you need Poetry in the image:

projects:
  - name: team/software1
    template:
      - tox-poetry-docker

Save, commit and propose the patch for review.

Refer to Zuul upstream documentation for configuration syntax for more details.