Next: , Up: Build Factories

4.11.1 BuildFactory

A BuildFactory defines the steps that every build will follow. Think of it as a glorified script. For example, a build which consists of a CVS checkout followed by a make build would be constructed as follows:

     from buildbot.steps import source, shell
     from buildbot.process import factory
     f = factory.BuildFactory()
     f.addStep(source.CVS(cvsroot=CVSROOT, cvsmodule="project", mode="update"))
     f.addStep(shell.Compile(command=["make", "build"]))

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 is is more convenient to create the list of steps ahead of time, perhaps using some Python tricks to generate the steps.

     from buildbot.steps import source, shell
     from buildbot.process import factory
     all_steps = [
         source.CVS(cvsroot=CVSROOT, cvsmodule="project", mode="update"),
         shell.Compile(command=["make", "build"]),
     f = factory.BuildFactory(all_steps)

Finally, you can also add a sequence of steps all at once:



(defaults to True): if True, the buildmaster keeps track of how long each step takes, so it can provide estimates of how long future builds will take. If builds are not expected to take a consistent amount of time (such as incremental builds in which a random set of files are recompiled or tested each time), this should be set to False to inhibit progress-tracking.
(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). If this attributed is set to a Python callable, that callable will be called with SourceStamp as single parameter and is supposed to return a string which will be used as above. The latter is useful in scenarios with multiple repositories submitting changes to BuildBot. In this case you likely will want to have a dedicated workdir per repository, since otherwise a sourcing step with mode = "update" will fail as a workdir with a working copy of repository A can't be "updated" for changes from a repository B. Here is an example how you can achive workdir-per-repo:
          # pre-repository working directory
          def workdir (source_stamp):
              return hashlib.md5 (source_stamp.repository).hexdigest ()[:8]
          build = factory.BuildFactory()
          build.workdir = workdir
          build.addStep (Git (mode = "update"))
          builders.append ({'name': 'mybuilder',
                            'slavename': 'myslave',
                            'builddir': 'mybuilder',
                            'factory': build})
          # You'll end up with workdirs like:
          # Repo1 => <buildslave-base>/mybuilder/a78890ba
          # Repo2	=> <buildslave-base>/mybuilder/0823ba88
          # ...

You could make the workdir() function compute other paths, based on parts of the repo URL in the sourcestamp, or lookup in a lookup table based on repo URL. As long as there is a permanent 1:1 mapping between repos and workdir this will work.

Implementation Note

The default BuildFactory, provided in the buildbot.process.factory module, contains an internal list of “BuildStep specifications”: a list of (step_class, kwargs) tuples for each. These specification tuples are constructed when the config file is read, by asking the instances passed to addStep for their subclass and arguments.

To support config files from buildbot-0.7.5 and earlier, addStep also accepts the f.addStep(shell.Compile, command=["make","build"]) form, although its use is discouraged because then the Compile step doesn't get to validate or complain about its arguments until build time. The modern pass-by-instance approach allows this validation to occur while the config file is being loaded, where the admin has a better chance of noticing problems.

When asked to create a Build, the BuildFactory puts a copy of the list of step specifications into the new Build object. When the Build is actually started, these step specifications are used to create the actual set of BuildSteps, which are then executed one at a time. This serves to give each Build an independent copy of each step.

Each step can affect the build process in the following ways:

In addition, each Step produces its own results, may create logfiles, etc. However only the flags described above have any effect on the build as a whole.

The pre-defined BuildSteps like CVS and Compile have reasonably appropriate flags set on them already. For example, without a source tree there is no point in continuing the build, so the CVS class has the haltOnFailure flag set to True. Look in buildbot/steps/*.py to see how the other Steps are marked.

Each Step is created with an additional workdir argument that indicates where its actions should take place. This is specified as a subdirectory of the slave builder's base directory, with a default value of build. This is only implemented as a step argument (as opposed to simply being a part of the base directory) because the CVS/SVN steps need to perform their checkouts from the parent directory.