This page documents the latest, unreleased version of Buildbot. For documentation for released versions, see http://docs.buildbot.net/current/.
Each Builder is equipped with a build factory, which defines the steps used to perform that particular type of build. This factory is created in the configuration file, and attached to a Builder through the factory element of its dictionary.
The steps used by these builds are defined in the next section, Build Steps.
Build factories are used with builders, and are not added directly to the buildmaster configuration dictionary.
A BuildFactory defines the steps that every build will follow. Think of it as a glorified script. For example, a build factory which consists of an SVN checkout followed by a make build would be configured as follows:
from buildbot.plugins import util, steps f = util.BuildFactory() f.addStep(steps.SVN(svnurl="http://..", mode="incremental")) f.addStep(steps.Compile(command=["make", "build"]))
This factory would then be attached to one builder (or several, if desired):
c['builders'].append( BuilderConfig(name='quick', slavenames=['bot1', 'bot2'], factory=f))
It is also possible to pass a list of steps into the BuildFactory when it is created. Using addStep is usually simpler, but there are cases where it is more convenient to create the list of steps ahead of time, perhaps using some Python tricks to generate the steps.
from buildbot.plugins import steps, util all_steps = [ steps.CVS(cvsroot=CVSROOT, cvsmodule="project", mode="update"), steps.Compile(command=["make", "build"]), ] f = util.BuildFactory(all_steps)
Finally, you can also add a sequence of steps all at once:
The following attributes can be set on a build factory after it is created, e.g.,
f = util.BuildFactory() f.useProgress = False
(defaults to 'build'): workdir given to every build step created by this factory as default. The workdir can be overridden in a build step definition.
If this attribute is set to a string, that string will be used for constructing the workdir (buildslave base + builder builddir + workdir). The attribute can also be a Python callable, for more complex cases, as described in Factory Workdir Functions.
In some cases you may not know what commands to run until after you checkout the source tree. For those cases you can dynamically add steps during a build from other steps.
The Build object provides 2 functions to do this:
Both functions only accept as an argument a list of steps to add to the build.
For example lets say you have a script checked in into your source tree called build.sh. When this script is called with the argument --list-stages it outputs a newline separated list of stage names. This can be used to generate at runtime a step for each stage in the build. Each stage is then run in this example using ./build.sh --run-stage <stage name>.
from buildbot.plugins import util, steps from buildbot.process import buildstep, logobserver from twisted.internet import defer class GenerateStagesCommand(buildstep.ShellMixin, steps.BuildStep): def __init__(self, **kwargs): kwargs = self.setupShellMixin(kwargs) steps.BuildStep.__init__(self, **kwargs) self.observer = logobserver.BufferLogObserver() self.addLogObserver('stdio', self.observer) def extract_stages(self, stdout): stages =  for line in stdout.split('\n'): stage = str(line.strip()) if stage: stages.append(stage) return stages @defer.inlineCallbacks def run(self): # run './build.sh --list-stages' to generate the list of stages cmd = yield self.makeRemoteShellCommand() yield self.runCommand(cmd) # if the command passes extract the list of stages result = cmd.results() if result == util.SUCCESS: # create a ShellCommand for each stage and add them to the build self.build.addStepsAfterCurrentStep([ steps.ShellCommand(name=stage, command=["./build.sh", "--run-stage", stage]) for stage in self.extract_stages(self.observer.getStdout()) ]) defer.returnValue(result) f = util.BuildFactory() f.addStep(steps.Git(repourl=repourl)) f.addStep(GenerateStagesCommand( name="Generate build stages", command=["./build.sh", "--list-stages"], haltOnFailure=True))
Buildbot includes a few predefined build factories that perform common build sequences. In practice, these are rarely used, as every site has slightly different requirements, but the source for these factories may provide examples for implementation of those requirements.
GNU Autoconf is a software portability tool, intended to make it possible to write programs in C (and other languages) which will run on a variety of UNIX-like systems. Most GNU software is built using autoconf. It is frequently used in combination with GNU automake. These tools both encourage a build process which usually looks like this:
% CONFIG_ENV=foo ./configure --with-flags % make all % make check # make install
(except of course the Buildbot always skips the make install part).
The Buildbot's buildbot.process.factory.GNUAutoconf factory is designed to build projects which use GNU autoconf and/or automake. The configuration environment variables, the configure flags, and command lines used for the compile and test are all configurable, in general the default values will be suitable.
f = util.GNUAutoconf(source=source.SVN(svnurl=URL, mode="copy"), flags=["--disable-nls"])
This is a subclass of GNUAutoconf which assumes the source is in CVS, and uses mode='full' and method='clobber' to always build from a clean working copy.
This class is similar to QuickBuildFactory, but uses SVN instead of CVS.
The QuickBuildFactory class is a subclass of GNUAutoconf which assumes the source is in CVS, and uses mode='incremental' to get incremental updates.
The difference between a full build and a quick build is that quick builds are generally done incrementally, starting with the tree where the previous build was performed. That simply means that the source-checkout step should be given a mode='incremental' flag, to do the source update in-place.
In addition to that, this class sets the useProgress flag to False. Incremental builds will (or at least the ought to) compile as few files as necessary, so they will take an unpredictable amount of time to run. Therefore it would be misleading to claim to predict how long the build will take.
This class is probably not of use to new projects.
Most Perl modules available from the CPAN archive use the MakeMaker module to provide configuration, build, and test services. The standard build routine for these modules looks like:
% perl Makefile.PL % make % make test # make install
(except again Buildbot skips the install step)
Buildbot provides a CPAN factory to compile and test these projects.
Most Python modules use the distutils package to provide configuration and build services. The standard build process looks like:
% python ./setup.py build % python ./setup.py install
Unfortunately, although Python provides a standard unit-test framework named unittest, to the best of my knowledge distutils does not provide a standardized target to run such unit tests. (Please let me know if I'm wrong, and I will update this factory.)
The Distutils factory provides support for running the build part of this process. It accepts the same source= parameter as the other build factories.
Twisted provides a unit test tool named trial which provides a few improvements over Python's built-in unittest module. Many python projects which use Twisted for their networking or application services also use trial for their unit tests. These modules are usually built and tested with something like the following:
% python ./setup.py build % PYTHONPATH=build/lib.linux-i686-2.3 trial -v PROJECTNAME.test % python ./setup.py install
Unfortunately, the build/lib directory into which the built/copied .py files are placed is actually architecture-dependent, and I do not yet know of a simple way to calculate its value. For many projects it is sufficient to import their libraries in place from the tree's base directory (PYTHONPATH=.).
In addition, the PROJECTNAME value where the test files are located is project-dependent: it is usually just the project's top-level library directory, as common practice suggests the unit test files are put in the test sub-module. This value cannot be guessed, the Trial class must be told where to find the test files.
The Trial class provides support for building and testing projects which use distutils and trial. If the test module name is specified, trial will be invoked. The library path used for testing can also be set.
One advantage of trial is that the Buildbot happens to know how to parse trial output, letting it identify which tests passed and which ones failed. The Buildbot can then provide fine-grained reports about how many tests have failed, when individual tests fail when they had been passing previously, etc.
Another feature of trial is that you can give it a series of source .py files, and it will search them for special test-case-name tags that indicate which test cases provide coverage for that file. Trial can then run just the appropriate tests. This is useful for quick builds, where you want to only run the test cases that cover the changed functionality.
The step can also take any of the ShellCommand arguments, e.g., haltOnFailure.
Unless one of tests or testChanges are set, the step will generate an exception.