Hello.

Over the past two weeks I've been prototyping a new tool for managing releases of Linaro validation deliverables. Some of the problems are unique (we target older releases, we are upstream) some are shared (building lots of packages together, making sure they all work, reproducing builds).

TLDR; Skip to the bottom of the message where I list the features.

I had some prior experience in this task and I wanted to see how the old solutions would map to the new environment. As we target Ubuntu Lucid aka latest LTS and most of us develop on the latest Ubuntu I wanted to ensure that all of our releases can be installed and would work correctly on Lucid. Earlier in the cycle we decided that the delivery method would be a PPA with multiple .debs, some of which may be backports required for Lucid. This is unlike using pip to pull in all the things we are interested in from various places (possibly using a requirements file).

So having those requirements my goals were to build a tool that would be useful for those two tasks:
1) Daily development helper as a sort of CI tool.
2) Monthly release helper

Both tasks have different requirements but involve similar actions. Those actions are:

*) Figuring out what packages to work on (aka project definition)
*) Getting the appropriate source/revision/tag from launchpad
*) Building a source packages for the target distribution
*) Building a binary package in pbuilder
   - this is where we also run all the unit tests that tells us if
     something is broken.

The tricky part is where we need to build test and release *multiple* source packages from *multiple* branches and target *multiple* target distributions.

For some concrete example. LAVA today is composed of the following core packages:
 - lava-server
 - lava-dashboard
 - lava-scheduler
 - lava-dispatcher
 - lava-tool
 - lava-test (-tool)
 - lava-dashboard-tool
 - lava-scheduler-tool (upcoming)

We also have a set of support libraries:
 - versiontools
 - linaro-django-xmlrpc
 - linaro-django-pagination
 - linaro-dashboard-bundle
 - django-restricted-resource
 - django-debian
 - linaro-json

We also have some libraries that are required for testing:
 - python-django-testproject
 - python-django-testscenarios
 - python-django-testinvariants (upcoming)

We also have some backports (for both production and testing):
 - python-simplejson
 - python-django 1.2 (soon 1.3)
 - python-django-south
 - python-testtools
 - python-testscenarios
 - python-fixtures

Now that's a lot of stuff to build and release manually. Granted not everything is changing but at the very least the first group (lava-*) will see a lot of activity each month.

Now the way I see it, each month, this list needs to be released. Possibly some of them will be unchanged. In that case there is no need to actually upload new packages to a PPA. Still we need to ensure that all of them build and work on all Lucid, Maverick and so on, all up to the latest version of Ubuntu.

Since we want to build Debian packages I decided to use bzr builder to create source packages from a recipe files. Recipes are a simple (2-3 lines at most) text files that say how to assemble source branches to get Debian packaging. The key feature of builder is it's ability to create derivative packages for a particular distribution. Recipe files are also used by launchpad for building source packages. In the future this tool could actually push/pull the recipes to launchpad directly.

To build binary packages I used pbuilder. The configuration is a little more complex than simple raw pbuilder or pbuilder-dist. The configuration I made turns it into a ppa-like builder that can feed from it's own packages. Each time you build a package it will land in a small apt repository and can be used to feed another build. This is a critical feature as all of our packages depend on something not available in the main archive.

The trick is to know the right sequence of builds that would satisfy build-dependencies. I did not find any existing tool to do this and after a brief discussion with doko it seems there are no such tools available. In general the problem can be simplified to a subset of real dependencies (without conflicts, virtual packages and stuff like that) and resolved automatically. I did not want implement that as our package list can be managed manually. A special sequence file contains a list of "things" to build, in order, to satisfy dependencies.

So getting everything together, lava-ci does the following:

* FEATURES *

$ ./lava-ci project help
Usage: lava-ci project [COMMAND]
Summary: Manipulate and release your project

Available commands:
 - init       - Prepare lava-ci to work with a particular project
 - help       - This message (default)


$ ./lava-ci distro help
Usage: lava-ci distro [COMMAND]
Summary: Manipulate pbuilder environments

Available commands:
 - help       - This message
 - show       - Display list of distributions and their status (default)
 - enable     - Enable one or more distributions
 - disable    - Disable one or more distributions
 - update     - Update one or more distributions

$ ./lava-ci package help
Usage: lava-ci package [COMMAND]
Summary: Manipulate source and binary packages

Available commands:
 - srcpkg     - Create a source package from a recipe
 - help       - This message
 - show       - Display list of packages and their status (default)
 - wipe       - Remove all source and binary packages
 - sequence   - Build a sequence of packages following
 - binpkg     - Create binary packages from a source package


A subset of the README file:

lava-ci - CI and release tools for the LAVA project (and others).

The purpose of this tool is to facilitate teamwork and monthly releases by
automating the act of creating and testing a release from source repositories
all the way to the binary packages for various platforms.

Workflow example:

*) Prepare recipe files (bzr help builder) for each maintained source
   package and put them in a bzr repository. Each recipe file *MUST* be
   named like the source package it builds.

*) Use `lava-ci project init lp:BRANCH-WITH-RECIPES`. This will create
   .lava-ci directory and a local checkout of you recipes in the
   current directory.

*) Use `lava-ci distro` to list the distributions you wish to target.
   For each one you are interested in do `lava-ci distro enable
   $distro`. For example to enable lucid and maverick you could use
   `lava-ci distro enable lucid maverick`.

*) Use `lava-ci package` to list available "packages" (based on
   recipes). You can add/edit more just by creating additional
   *.recipe files.

*) Use `lava-ci package src $package` to build source packages for
   the selected recipe. There will be one source package per
   distribution. You can check `lava-ci package [show]` to see what
   source packages are already available.

*) Use `lava-ci package bin $package` to build binary packages for
   the selected recipe. Again there will be multiple builds, one for
   each distribution. Each build will result with a number of
   additional debian packages being produced. You can use those
   packages as build-dependencies of other packages you maintain,
   similar to a Lauchpad PPA.

*) Write down a sequence of build operations to perform in and save it
   as `recipe/sequence`. This file should contain one word per line
   - the name of the source package to build. The order will depend on
   the build-dependencies among your packages. To test that building
   the whole sequence works do `lava-ci package wipe` followed by
   `lava-ci package sequence`. If the build succeeds you can tag your
   recipes as a working configuration and make a release.


Best regards
Zygmunt Krynicki

_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to