зеркало из https://github.com/mozilla/gecko-dev.git
6387 строки
252 KiB
Plaintext
6387 строки
252 KiB
Plaintext
|
\input texinfo @c -*-texinfo-*-
|
||
|
@c %**start of header
|
||
|
@setfilename buildbot.info
|
||
|
@settitle BuildBot Manual 0.7.5
|
||
|
@defcodeindex cs
|
||
|
@defcodeindex sl
|
||
|
@defcodeindex bf
|
||
|
@defcodeindex bs
|
||
|
@defcodeindex st
|
||
|
@defcodeindex bc
|
||
|
@c %**end of header
|
||
|
|
||
|
@c these indices are for classes useful in a master.cfg config file
|
||
|
@c @csindex : Change Sources
|
||
|
@c @slindex : Schedulers and Locks
|
||
|
@c @bfindex : Build Factories
|
||
|
@c @bsindex : Build Steps
|
||
|
@c @stindex : Status Targets
|
||
|
|
||
|
@c @bcindex : keys that make up BuildmasterConfig
|
||
|
|
||
|
@copying
|
||
|
This is the BuildBot manual.
|
||
|
|
||
|
Copyright (C) 2005,2006 Brian Warner
|
||
|
|
||
|
Copying and distribution of this file, with or without
|
||
|
modification, are permitted in any medium without royalty
|
||
|
provided the copyright notice and this notice are preserved.
|
||
|
|
||
|
@end copying
|
||
|
|
||
|
@titlepage
|
||
|
@title BuildBot
|
||
|
@page
|
||
|
@vskip 0pt plus 1filll
|
||
|
@insertcopying
|
||
|
@end titlepage
|
||
|
|
||
|
@c Output the table of the contents at the beginning.
|
||
|
@contents
|
||
|
|
||
|
@ifnottex
|
||
|
@node Top, Introduction, (dir), (dir)
|
||
|
@top BuildBot
|
||
|
|
||
|
@insertcopying
|
||
|
@end ifnottex
|
||
|
|
||
|
@menu
|
||
|
* Introduction:: What the BuildBot does.
|
||
|
* Installation:: Creating a buildmaster and buildslaves,
|
||
|
running them.
|
||
|
* Concepts:: What goes on in the buildbot's little mind.
|
||
|
* Configuration:: Controlling the buildbot.
|
||
|
* Getting Source Code Changes:: Discovering when to run a build.
|
||
|
* Build Process:: Controlling how each build is run.
|
||
|
* Status Delivery:: Telling the world about the build's results.
|
||
|
* Command-line tool::
|
||
|
* Resources:: Getting help.
|
||
|
* Developer's Appendix::
|
||
|
* Index of Useful Classes::
|
||
|
* Index of master.cfg keys::
|
||
|
* Index:: Complete index.
|
||
|
|
||
|
@detailmenu
|
||
|
--- The Detailed Node Listing ---
|
||
|
|
||
|
Introduction
|
||
|
|
||
|
* History and Philosophy::
|
||
|
* System Architecture::
|
||
|
* Control Flow::
|
||
|
|
||
|
System Architecture
|
||
|
|
||
|
* BuildSlave Connections::
|
||
|
* Buildmaster Architecture::
|
||
|
* Status Delivery Architecture::
|
||
|
|
||
|
Installation
|
||
|
|
||
|
* Requirements::
|
||
|
* Installing the code::
|
||
|
* Creating a buildmaster::
|
||
|
* Creating a buildslave::
|
||
|
* Launching the daemons::
|
||
|
* Logfiles::
|
||
|
* Shutdown::
|
||
|
* Maintenance::
|
||
|
* Troubleshooting::
|
||
|
|
||
|
Creating a buildslave
|
||
|
|
||
|
* Buildslave Options::
|
||
|
|
||
|
Troubleshooting
|
||
|
|
||
|
* Starting the buildslave::
|
||
|
* Connecting to the buildmaster::
|
||
|
* Forcing Builds::
|
||
|
|
||
|
Concepts
|
||
|
|
||
|
* Version Control Systems::
|
||
|
* Schedulers::
|
||
|
* BuildSet::
|
||
|
* BuildRequest::
|
||
|
* Builder::
|
||
|
* Users::
|
||
|
|
||
|
Version Control Systems
|
||
|
|
||
|
* Generalizing VC Systems::
|
||
|
* Source Tree Specifications::
|
||
|
* How Different VC Systems Specify Sources::
|
||
|
* Attributes of Changes::
|
||
|
|
||
|
Users
|
||
|
|
||
|
* Doing Things With Users::
|
||
|
* Email Addresses::
|
||
|
* IRC Nicknames::
|
||
|
* Live Status Clients::
|
||
|
|
||
|
Configuration
|
||
|
|
||
|
* Config File Format::
|
||
|
* Loading the Config File::
|
||
|
* Defining the Project::
|
||
|
* Listing Change Sources and Schedulers::
|
||
|
* Setting the slaveport::
|
||
|
* Buildslave Specifiers::
|
||
|
* Defining Builders::
|
||
|
* Defining Status Targets::
|
||
|
* Debug options::
|
||
|
|
||
|
Listing Change Sources and Schedulers
|
||
|
|
||
|
* Scheduler Types::
|
||
|
* Build Dependencies::
|
||
|
|
||
|
Getting Source Code Changes
|
||
|
|
||
|
* Change Sources::
|
||
|
|
||
|
Change Sources
|
||
|
|
||
|
* Choosing ChangeSources::
|
||
|
* CVSToys - PBService::
|
||
|
* CVSToys - mail notification::
|
||
|
* Other mail notification ChangeSources::
|
||
|
* PBChangeSource::
|
||
|
* P4Source::
|
||
|
* BonsaiPoller::
|
||
|
* SVNPoller::
|
||
|
|
||
|
Build Process
|
||
|
|
||
|
* Build Steps::
|
||
|
* Interlocks::
|
||
|
* Build Factories::
|
||
|
|
||
|
Build Steps
|
||
|
|
||
|
* Common Parameters::
|
||
|
* Source Checkout::
|
||
|
* ShellCommand::
|
||
|
* Simple ShellCommand Subclasses::
|
||
|
* Python BuildSteps::
|
||
|
* Transferring Files::
|
||
|
* Writing New BuildSteps::
|
||
|
|
||
|
Source Checkout
|
||
|
|
||
|
* CVS::
|
||
|
* SVN::
|
||
|
* Darcs::
|
||
|
* Mercurial::
|
||
|
* Arch::
|
||
|
* Bazaar::
|
||
|
* P4::
|
||
|
|
||
|
Simple ShellCommand Subclasses
|
||
|
|
||
|
* Configure::
|
||
|
* Compile::
|
||
|
* Test::
|
||
|
* Build Properties::
|
||
|
|
||
|
Python BuildSteps
|
||
|
|
||
|
* BuildEPYDoc::
|
||
|
* PyFlakes::
|
||
|
|
||
|
Writing New BuildSteps
|
||
|
|
||
|
* BuildStep LogFiles::
|
||
|
* Adding LogObservers::
|
||
|
* BuildStep URLs::
|
||
|
|
||
|
Build Factories
|
||
|
|
||
|
* BuildStep Objects::
|
||
|
* BuildFactory::
|
||
|
* Process-Specific build factories::
|
||
|
|
||
|
BuildStep Objects
|
||
|
|
||
|
* BuildFactory Attributes::
|
||
|
* Quick builds::
|
||
|
|
||
|
BuildFactory
|
||
|
|
||
|
* BuildFactory Attributes::
|
||
|
* Quick builds::
|
||
|
|
||
|
Process-Specific build factories
|
||
|
|
||
|
* GNUAutoconf::
|
||
|
* CPAN::
|
||
|
* Python distutils::
|
||
|
* Python/Twisted/trial projects::
|
||
|
|
||
|
Status Delivery
|
||
|
|
||
|
* HTML Waterfall::
|
||
|
* IRC Bot::
|
||
|
* PBListener::
|
||
|
* Writing New Status Plugins::
|
||
|
|
||
|
Command-line tool
|
||
|
|
||
|
* Administrator Tools::
|
||
|
* Developer Tools::
|
||
|
* Other Tools::
|
||
|
* .buildbot config directory::
|
||
|
|
||
|
Developer Tools
|
||
|
|
||
|
* statuslog::
|
||
|
* statusgui::
|
||
|
* try::
|
||
|
|
||
|
Other Tools
|
||
|
|
||
|
* sendchange::
|
||
|
* debugclient::
|
||
|
|
||
|
@end detailmenu
|
||
|
@end menu
|
||
|
|
||
|
@node Introduction, Installation, Top, Top
|
||
|
@chapter Introduction
|
||
|
|
||
|
@cindex introduction
|
||
|
|
||
|
The BuildBot is a system to automate the compile/test cycle required by most
|
||
|
software projects to validate code changes. By automatically rebuilding and
|
||
|
testing the tree each time something has changed, build problems are
|
||
|
pinpointed quickly, before other developers are inconvenienced by the
|
||
|
failure. The guilty developer can be identified and harassed without human
|
||
|
intervention. By running the builds on a variety of platforms, developers
|
||
|
who do not have the facilities to test their changes everywhere before
|
||
|
checkin will at least know shortly afterwards whether they have broken the
|
||
|
build or not. Warning counts, lint checks, image size, compile time, and
|
||
|
other build parameters can be tracked over time, are more visible, and
|
||
|
are therefore easier to improve.
|
||
|
|
||
|
The overall goal is to reduce tree breakage and provide a platform to
|
||
|
run tests or code-quality checks that are too annoying or pedantic for
|
||
|
any human to waste their time with. Developers get immediate (and
|
||
|
potentially public) feedback about their changes, encouraging them to
|
||
|
be more careful about testing before checkin.
|
||
|
|
||
|
Features:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
run builds on a variety of slave platforms
|
||
|
@item
|
||
|
arbitrary build process: handles projects using C, Python, whatever
|
||
|
@item
|
||
|
minimal host requirements: python and Twisted
|
||
|
@item
|
||
|
slaves can be behind a firewall if they can still do checkout
|
||
|
@item
|
||
|
status delivery through web page, email, IRC, other protocols
|
||
|
@item
|
||
|
track builds in progress, provide estimated completion time
|
||
|
@item
|
||
|
flexible configuration by subclassing generic build process classes
|
||
|
@item
|
||
|
debug tools to force a new build, submit fake Changes, query slave status
|
||
|
@item
|
||
|
released under the GPL
|
||
|
@end itemize
|
||
|
|
||
|
@menu
|
||
|
* History and Philosophy::
|
||
|
* System Architecture::
|
||
|
* Control Flow::
|
||
|
@end menu
|
||
|
|
||
|
|
||
|
@node History and Philosophy, System Architecture, Introduction, Introduction
|
||
|
@section History and Philosophy
|
||
|
|
||
|
@cindex Philosophy of operation
|
||
|
|
||
|
The Buildbot was inspired by a similar project built for a development
|
||
|
team writing a cross-platform embedded system. The various components
|
||
|
of the project were supposed to compile and run on several flavors of
|
||
|
unix (linux, solaris, BSD), but individual developers had their own
|
||
|
preferences and tended to stick to a single platform. From time to
|
||
|
time, incompatibilities would sneak in (some unix platforms want to
|
||
|
use @code{string.h}, some prefer @code{strings.h}), and then the tree
|
||
|
would compile for some developers but not others. The buildbot was
|
||
|
written to automate the human process of walking into the office,
|
||
|
updating a tree, compiling (and discovering the breakage), finding the
|
||
|
developer at fault, and complaining to them about the problem they had
|
||
|
introduced. With multiple platforms it was difficult for developers to
|
||
|
do the right thing (compile their potential change on all platforms);
|
||
|
the buildbot offered a way to help.
|
||
|
|
||
|
Another problem was when programmers would change the behavior of a
|
||
|
library without warning its users, or change internal aspects that
|
||
|
other code was (unfortunately) depending upon. Adding unit tests to
|
||
|
the codebase helps here: if an application's unit tests pass despite
|
||
|
changes in the libraries it uses, you can have more confidence that
|
||
|
the library changes haven't broken anything. Many developers
|
||
|
complained that the unit tests were inconvenient or took too long to
|
||
|
run: having the buildbot run them reduces the developer's workload to
|
||
|
a minimum.
|
||
|
|
||
|
In general, having more visibility into the project is always good,
|
||
|
and automation makes it easier for developers to do the right thing.
|
||
|
When everyone can see the status of the project, developers are
|
||
|
encouraged to keep the tree in good working order. Unit tests that
|
||
|
aren't run on a regular basis tend to suffer from bitrot just like
|
||
|
code does: exercising them on a regular basis helps to keep them
|
||
|
functioning and useful.
|
||
|
|
||
|
The current version of the Buildbot is additionally targeted at
|
||
|
distributed free-software projects, where resources and platforms are
|
||
|
only available when provided by interested volunteers. The buildslaves
|
||
|
are designed to require an absolute minimum of configuration, reducing
|
||
|
the effort a potential volunteer needs to expend to be able to
|
||
|
contribute a new test environment to the project. The goal is for
|
||
|
anyone who wishes that a given project would run on their favorite
|
||
|
platform should be able to offer that project a buildslave, running on
|
||
|
that platform, where they can verify that their portability code
|
||
|
works, and keeps working.
|
||
|
|
||
|
@node System Architecture, Control Flow, History and Philosophy, Introduction
|
||
|
@comment node-name, next, previous, up
|
||
|
@section System Architecture
|
||
|
|
||
|
The Buildbot consists of a single @code{buildmaster} and one or more
|
||
|
@code{buildslaves}, connected in a star topology. The buildmaster
|
||
|
makes all decisions about what, when, and how to build. It sends
|
||
|
commands to be run on the build slaves, which simply execute the
|
||
|
commands and return the results. (certain steps involve more local
|
||
|
decision making, where the overhead of sending a lot of commands back
|
||
|
and forth would be inappropriate, but in general the buildmaster is
|
||
|
responsible for everything).
|
||
|
|
||
|
The buildmaster is usually fed @code{Changes} by some sort of version
|
||
|
control system (@pxref{Change Sources}), which may cause builds to be
|
||
|
run. As the builds are performed, various status messages are
|
||
|
produced, which are then sent to any registered Status Targets
|
||
|
(@pxref{Status Delivery}).
|
||
|
|
||
|
@c @image{FILENAME, WIDTH, HEIGHT, ALTTEXT, EXTENSION}
|
||
|
@image{images/overview,,,Overview Diagram,}
|
||
|
|
||
|
The buildmaster is configured and maintained by the ``buildmaster
|
||
|
admin'', who is generally the project team member responsible for
|
||
|
build process issues. Each buildslave is maintained by a ``buildslave
|
||
|
admin'', who do not need to be quite as involved. Generally slaves are
|
||
|
run by anyone who has an interest in seeing the project work well on
|
||
|
their favorite platform.
|
||
|
|
||
|
@menu
|
||
|
* BuildSlave Connections::
|
||
|
* Buildmaster Architecture::
|
||
|
* Status Delivery Architecture::
|
||
|
@end menu
|
||
|
|
||
|
@node BuildSlave Connections, Buildmaster Architecture, System Architecture, System Architecture
|
||
|
@subsection BuildSlave Connections
|
||
|
|
||
|
The buildslaves are typically run on a variety of separate machines,
|
||
|
at least one per platform of interest. These machines connect to the
|
||
|
buildmaster over a TCP connection to a publically-visible port. As a
|
||
|
result, the buildslaves can live behind a NAT box or similar
|
||
|
firewalls, as long as they can get to buildmaster. The TCP connections
|
||
|
are initiated by the buildslave and accepted by the buildmaster, but
|
||
|
commands and results travel both ways within this connection. The
|
||
|
buildmaster is always in charge, so all commands travel exclusively
|
||
|
from the buildmaster to the buildslave.
|
||
|
|
||
|
To perform builds, the buildslaves must typically obtain source code
|
||
|
from a CVS/SVN/etc repository. Therefore they must also be able to
|
||
|
reach the repository. The buildmaster provides instructions for
|
||
|
performing builds, but does not provide the source code itself.
|
||
|
|
||
|
@image{images/slaves,,,BuildSlave Connections,}
|
||
|
|
||
|
@node Buildmaster Architecture, Status Delivery Architecture, BuildSlave Connections, System Architecture
|
||
|
@subsection Buildmaster Architecture
|
||
|
|
||
|
The Buildmaster consists of several pieces:
|
||
|
|
||
|
@image{images/master,,,BuildMaster Architecture,}
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
Change Sources, which create a Change object each time something is
|
||
|
modified in the VC repository. Most ChangeSources listen for messages
|
||
|
from a hook script of some sort. Some sources actively poll the
|
||
|
repository on a regular basis. All Changes are fed to the Schedulers.
|
||
|
|
||
|
@item
|
||
|
Schedulers, which decide when builds should be performed. They collect
|
||
|
Changes into BuildRequests, which are then queued for delivery to
|
||
|
Builders until a buildslave is available.
|
||
|
|
||
|
@item
|
||
|
Builders, which control exactly @emph{how} each build is performed
|
||
|
(with a series of BuildSteps, configured in a BuildFactory). Each
|
||
|
Build is run on a single buildslave.
|
||
|
|
||
|
@item
|
||
|
Status plugins, which deliver information about the build results
|
||
|
through protocols like HTTP, mail, and IRC.
|
||
|
|
||
|
@end itemize
|
||
|
|
||
|
@image{images/slavebuilder,,,SlaveBuilders,}
|
||
|
|
||
|
Each Builder is configured with a list of BuildSlaves that it will use
|
||
|
for its builds. These buildslaves are expected to behave identically:
|
||
|
the only reason to use multiple BuildSlaves for a single Builder is to
|
||
|
provide a measure of load-balancing.
|
||
|
|
||
|
Within a single BuildSlave, each Builder creates its own SlaveBuilder
|
||
|
instance. These SlaveBuilders operate independently from each other.
|
||
|
Each gets its own base directory to work in. It is quite common to
|
||
|
have many Builders sharing the same buildslave. For example, there
|
||
|
might be two buildslaves: one for i386, and a second for PowerPC.
|
||
|
There may then be a pair of Builders that do a full compile/test run,
|
||
|
one for each architecture, and a lone Builder that creates snapshot
|
||
|
source tarballs if the full builders complete successfully. The full
|
||
|
builders would each run on a single buildslave, whereas the tarball
|
||
|
creation step might run on either buildslave (since the platform
|
||
|
doesn't matter when creating source tarballs). In this case, the
|
||
|
mapping would look like:
|
||
|
|
||
|
@example
|
||
|
Builder(full-i386) -> BuildSlaves(slave-i386)
|
||
|
Builder(full-ppc) -> BuildSlaves(slave-ppc)
|
||
|
Builder(source-tarball) -> BuildSlaves(slave-i386, slave-ppc)
|
||
|
@end example
|
||
|
|
||
|
and each BuildSlave would have two SlaveBuilders inside it, one for a
|
||
|
full builder, and a second for the source-tarball builder.
|
||
|
|
||
|
Once a SlaveBuilder is available, the Builder pulls one or more
|
||
|
BuildRequests off its incoming queue. (It may pull more than one if it
|
||
|
determines that it can merge the requests together; for example, there
|
||
|
may be multiple requests to build the current HEAD revision). These
|
||
|
requests are merged into a single Build instance, which includes the
|
||
|
SourceStamp that describes what exact version of the source code
|
||
|
should be used for the build. The Build is then assigned to a
|
||
|
SlaveBuilder and the build begins.
|
||
|
|
||
|
|
||
|
@node Status Delivery Architecture, , Buildmaster Architecture, System Architecture
|
||
|
@subsection Status Delivery Architecture
|
||
|
|
||
|
The buildmaster maintains a central Status object, to which various
|
||
|
status plugins are connected. Through this Status object, a full
|
||
|
hierarchy of build status objects can be obtained.
|
||
|
|
||
|
@image{images/status,,,Status Delivery,}
|
||
|
|
||
|
The configuration file controls which status plugins are active. Each
|
||
|
status plugin gets a reference to the top-level Status object. From
|
||
|
there they can request information on each Builder, Build, Step, and
|
||
|
LogFile. This query-on-demand interface is used by the html.Waterfall
|
||
|
plugin to create the main status page each time a web browser hits the
|
||
|
main URL.
|
||
|
|
||
|
The status plugins can also subscribe to hear about new Builds as they
|
||
|
occur: this is used by the MailNotifier to create new email messages
|
||
|
for each recently-completed Build.
|
||
|
|
||
|
The Status object records the status of old builds on disk in the
|
||
|
buildmaster's base directory. This allows it to return information
|
||
|
about historical builds.
|
||
|
|
||
|
There are also status objects that correspond to Schedulers and
|
||
|
BuildSlaves. These allow status plugins to report information about
|
||
|
upcoming builds, and the online/offline status of each buildslave.
|
||
|
|
||
|
|
||
|
@node Control Flow, , System Architecture, Introduction
|
||
|
@comment node-name, next, previous, up
|
||
|
@section Control Flow
|
||
|
|
||
|
A day in the life of the buildbot:
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item
|
||
|
A developer commits some source code changes to the repository. A hook
|
||
|
script or commit trigger of some sort sends information about this
|
||
|
change to the buildmaster through one of its configured Change
|
||
|
Sources. This notification might arrive via email, or over a network
|
||
|
connection (either initiated by the buildmaster as it ``subscribes''
|
||
|
to changes, or by the commit trigger as it pushes Changes towards the
|
||
|
buildmaster). The Change contains information about who made the
|
||
|
change, what files were modified, which revision contains the change,
|
||
|
and any checkin comments.
|
||
|
|
||
|
@item
|
||
|
The buildmaster distributes this change to all of its configured
|
||
|
Schedulers. Any ``important'' changes cause the ``tree-stable-timer''
|
||
|
to be started, and the Change is added to a list of those that will go
|
||
|
into a new Build. When the timer expires, a Build is started on each
|
||
|
of a set of configured Builders, all compiling/testing the same source
|
||
|
code. Unless configured otherwise, all Builds run in parallel on the
|
||
|
various buildslaves.
|
||
|
|
||
|
@item
|
||
|
The Build consists of a series of Steps. Each Step causes some number
|
||
|
of commands to be invoked on the remote buildslave associated with
|
||
|
that Builder. The first step is almost always to perform a checkout of
|
||
|
the appropriate revision from the same VC system that produced the
|
||
|
Change. The rest generally perform a compile and run unit tests. As
|
||
|
each Step runs, the buildslave reports back command output and return
|
||
|
status to the buildmaster.
|
||
|
|
||
|
@item
|
||
|
As the Build runs, status messages like ``Build Started'', ``Step
|
||
|
Started'', ``Build Finished'', etc, are published to a collection of
|
||
|
Status Targets. One of these targets is usually the HTML ``Waterfall''
|
||
|
display, which shows a chronological list of events, and summarizes
|
||
|
the results of the most recent build at the top of each column.
|
||
|
Developers can periodically check this page to see how their changes
|
||
|
have fared. If they see red, they know that they've made a mistake and
|
||
|
need to fix it. If they see green, they know that they've done their
|
||
|
duty and don't need to worry about their change breaking anything.
|
||
|
|
||
|
@item
|
||
|
If a MailNotifier status target is active, the completion of a build
|
||
|
will cause email to be sent to any developers whose Changes were
|
||
|
incorporated into this Build. The MailNotifier can be configured to
|
||
|
only send mail upon failing builds, or for builds which have just
|
||
|
transitioned from passing to failing. Other status targets can provide
|
||
|
similar real-time notification via different communication channels,
|
||
|
like IRC.
|
||
|
|
||
|
@end itemize
|
||
|
|
||
|
|
||
|
@node Installation, Concepts, Introduction, Top
|
||
|
@chapter Installation
|
||
|
|
||
|
@menu
|
||
|
* Requirements::
|
||
|
* Installing the code::
|
||
|
* Creating a buildmaster::
|
||
|
* Creating a buildslave::
|
||
|
* Launching the daemons::
|
||
|
* Logfiles::
|
||
|
* Shutdown::
|
||
|
* Maintenance::
|
||
|
* Troubleshooting::
|
||
|
@end menu
|
||
|
|
||
|
@node Requirements, Installing the code, Installation, Installation
|
||
|
@section Requirements
|
||
|
|
||
|
At a bare minimum, you'll need the following (for both the buildmaster
|
||
|
and a buildslave):
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
Python: http://www.python.org
|
||
|
|
||
|
Buildbot requires python-2.2 or later, and is primarily developed
|
||
|
against python-2.3. The buildmaster uses generators, a feature which
|
||
|
is not available in python-2.1, and both master and slave require a
|
||
|
version of Twisted which only works with python-2.2 or later. Certain
|
||
|
features (like the inclusion of build logs in status emails) require
|
||
|
python-2.2.2 or later. The IRC ``force build'' command requires
|
||
|
python-2.3 (for the shlex.split function).
|
||
|
|
||
|
@item
|
||
|
Twisted: http://twistedmatrix.com
|
||
|
|
||
|
Both the buildmaster and the buildslaves require Twisted-1.3.0 or
|
||
|
later. It has been mainly developed against Twisted-2.0.1, but has
|
||
|
been tested against Twisted-2.1.0 (the most recent as of this
|
||
|
writing), and might even work on versions as old as Twisted-1.1.0, but
|
||
|
as always the most recent version is recommended.
|
||
|
|
||
|
Twisted-1.3.0 and earlier were released as a single monolithic
|
||
|
package. When you run Buildbot against Twisted-2.0.0 or later (which
|
||
|
are split into a number of smaller subpackages), you'll need at least
|
||
|
"Twisted" (the core package), and you'll also want TwistedMail,
|
||
|
TwistedWeb, and TwistedWords (for sending email, serving a web status
|
||
|
page, and delivering build status via IRC, respectively).
|
||
|
@end itemize
|
||
|
|
||
|
Certain other packages may be useful on the system running the
|
||
|
buildmaster:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
CVSToys: http://purl.net/net/CVSToys
|
||
|
|
||
|
If your buildmaster uses FreshCVSSource to receive change notification
|
||
|
from a cvstoys daemon, it will require CVSToys be installed (tested
|
||
|
with CVSToys-1.0.10). If the it doesn't use that source (i.e. if you
|
||
|
only use a mail-parsing change source, or the SVN notification
|
||
|
script), you will not need CVSToys.
|
||
|
|
||
|
@end itemize
|
||
|
|
||
|
And of course, your project's build process will impose additional
|
||
|
requirements on the buildslaves. These hosts must have all the tools
|
||
|
necessary to compile and test your project's source code.
|
||
|
|
||
|
|
||
|
@node Installing the code, Creating a buildmaster, Requirements, Installation
|
||
|
@section Installing the code
|
||
|
|
||
|
@cindex installation
|
||
|
|
||
|
The Buildbot is installed using the standard python @code{distutils}
|
||
|
module. After unpacking the tarball, the process is:
|
||
|
|
||
|
@example
|
||
|
python setup.py build
|
||
|
python setup.py install
|
||
|
@end example
|
||
|
|
||
|
where the install step may need to be done as root. This will put the
|
||
|
bulk of the code in somewhere like
|
||
|
/usr/lib/python2.3/site-packages/buildbot . It will also install the
|
||
|
@code{buildbot} command-line tool in /usr/bin/buildbot.
|
||
|
|
||
|
To test this, shift to a different directory (like /tmp), and run:
|
||
|
|
||
|
@example
|
||
|
buildbot --version
|
||
|
@end example
|
||
|
|
||
|
If it shows you the versions of Buildbot and Twisted, the install went
|
||
|
ok. If it says @code{no such command} or it gets an @code{ImportError}
|
||
|
when it tries to load the libaries, then something went wrong.
|
||
|
@code{pydoc buildbot} is another useful diagnostic tool.
|
||
|
|
||
|
Windows users will find these files in other places. You will need to
|
||
|
make sure that python can find the libraries, and will probably find
|
||
|
it convenient to have @code{buildbot} on your PATH.
|
||
|
|
||
|
If you wish, you can run the buildbot unit test suite like this:
|
||
|
|
||
|
@example
|
||
|
PYTHONPATH=. trial buildbot.test
|
||
|
@end example
|
||
|
|
||
|
This should run up to 192 tests, depending upon what VC tools you have
|
||
|
installed. On my desktop machine it takes about five minutes to
|
||
|
complete. Nothing should fail, a few might be skipped. If any of the
|
||
|
tests fail, you should stop and investigate the cause before
|
||
|
continuing the installation process, as it will probably be easier to
|
||
|
track down the bug early.
|
||
|
|
||
|
If you cannot or do not wish to install the buildbot into a site-wide
|
||
|
location like @file{/usr} or @file{/usr/local}, you can also install
|
||
|
it into the account's home directory. Do the install command like
|
||
|
this:
|
||
|
|
||
|
@example
|
||
|
python setup.py install --home=~
|
||
|
@end example
|
||
|
|
||
|
That will populate @file{~/lib/python} and create
|
||
|
@file{~/bin/buildbot}. Make sure this lib directory is on your
|
||
|
@code{PYTHONPATH}.
|
||
|
|
||
|
|
||
|
@node Creating a buildmaster, Creating a buildslave, Installing the code, Installation
|
||
|
@section Creating a buildmaster
|
||
|
|
||
|
As you learned earlier (@pxref{System Architecture}), the buildmaster
|
||
|
runs on a central host (usually one that is publically visible, so
|
||
|
everybody can check on the status of the project), and controls all
|
||
|
aspects of the buildbot system. Let us call this host
|
||
|
@code{buildbot.example.org}.
|
||
|
|
||
|
You may wish to create a separate user account for the buildmaster,
|
||
|
perhaps named @code{buildmaster}. This can help keep your personal
|
||
|
configuration distinct from that of the buildmaster and is useful if
|
||
|
you have to use a mail-based notification system (@pxref{Change
|
||
|
Sources}). However, the Buildbot will work just fine with your regular
|
||
|
user account.
|
||
|
|
||
|
You need to choose a directory for the buildmaster, called the
|
||
|
@code{basedir}. This directory will be owned by the buildmaster, which
|
||
|
will use configuration files therein, and create status files as it
|
||
|
runs. @file{~/Buildbot} is a likely value. If you run multiple
|
||
|
buildmasters in the same account, or if you run both masters and
|
||
|
slaves, you may want a more distinctive name like
|
||
|
@file{~/Buildbot/master/gnomovision} or
|
||
|
@file{~/Buildmasters/fooproject}. If you are using a separate user
|
||
|
account, this might just be @file{~buildmaster/masters/fooproject}.
|
||
|
|
||
|
Once you've picked a directory, use the @command{buildbot
|
||
|
create-master} command to create the directory and populate it with
|
||
|
startup files:
|
||
|
|
||
|
@example
|
||
|
buildbot create-master @var{basedir}
|
||
|
@end example
|
||
|
|
||
|
You will need to create a configuration file (@pxref{Configuration})
|
||
|
before starting the buildmaster. Most of the rest of this manual is
|
||
|
dedicated to explaining how to do this. A sample configuration file is
|
||
|
placed in the working directory, named @file{master.cfg.sample}, which
|
||
|
can be copied to @file{master.cfg} and edited to suit your purposes.
|
||
|
|
||
|
(Internal details: This command creates a file named
|
||
|
@file{buildbot.tac} that contains all the state necessary to create
|
||
|
the buildmaster. Twisted has a tool called @code{twistd} which can use
|
||
|
this .tac file to create and launch a buildmaster instance. twistd
|
||
|
takes care of logging and daemonization (running the program in the
|
||
|
background). @file{/usr/bin/buildbot} is a front end which runs twistd
|
||
|
for you.)
|
||
|
|
||
|
In addition to @file{buildbot.tac}, a small @file{Makefile.sample} is
|
||
|
installed. This can be used as the basis for customized daemon startup,
|
||
|
@xref{Launching the daemons}.
|
||
|
|
||
|
|
||
|
@node Creating a buildslave, Launching the daemons, Creating a buildmaster, Installation
|
||
|
@section Creating a buildslave
|
||
|
|
||
|
Typically, you will be adding a buildslave to an existing buildmaster,
|
||
|
to provide additional architecture coverage. The buildbot
|
||
|
administrator will give you several pieces of information necessary to
|
||
|
connect to the buildmaster. You should also be somewhat familiar with
|
||
|
the project being tested, so you can troubleshoot build problems
|
||
|
locally.
|
||
|
|
||
|
The buildbot exists to make sure that the project's stated ``how to
|
||
|
build it'' process actually works. To this end, the buildslave should
|
||
|
run in an environment just like that of your regular developers.
|
||
|
Typically the project build process is documented somewhere
|
||
|
(@file{README}, @file{INSTALL}, etc), in a document that should
|
||
|
mention all library dependencies and contain a basic set of build
|
||
|
instructions. This document will be useful as you configure the host
|
||
|
and account in which the buildslave runs.
|
||
|
|
||
|
Here's a good checklist for setting up a buildslave:
|
||
|
|
||
|
@enumerate
|
||
|
@item
|
||
|
Set up the account
|
||
|
|
||
|
It is recommended (although not mandatory) to set up a separate user
|
||
|
account for the buildslave. This account is frequently named
|
||
|
@code{buildbot} or @code{buildslave}. This serves to isolate your
|
||
|
personal working environment from that of the slave's, and helps to
|
||
|
minimize the security threat posed by letting possibly-unknown
|
||
|
contributors run arbitrary code on your system. The account should
|
||
|
have a minimum of fancy init scripts.
|
||
|
|
||
|
@item
|
||
|
Install the buildbot code
|
||
|
|
||
|
Follow the instructions given earlier (@pxref{Installing the code}).
|
||
|
If you use a separate buildslave account, and you didn't install the
|
||
|
buildbot code to a shared location, then you will need to install it
|
||
|
with @code{--home=~} for each account that needs it.
|
||
|
|
||
|
@item
|
||
|
Set up the host
|
||
|
|
||
|
Make sure the host can actually reach the buildmaster. Usually the
|
||
|
buildmaster is running a status webserver on the same machine, so
|
||
|
simply point your web browser at it and see if you can get there.
|
||
|
Install whatever additional packages or libraries the project's
|
||
|
INSTALL document advises. (or not: if your buildslave is supposed to
|
||
|
make sure that building without optional libraries still works, then
|
||
|
don't install those libraries).
|
||
|
|
||
|
Again, these libraries don't necessarily have to be installed to a
|
||
|
site-wide shared location, but they must be available to your build
|
||
|
process. Accomplishing this is usually very specific to the build
|
||
|
process, so installing them to @file{/usr} or @file{/usr/local} is
|
||
|
usually the best approach.
|
||
|
|
||
|
@item
|
||
|
Test the build process
|
||
|
|
||
|
Follow the instructions in the INSTALL document, in the buildslave's
|
||
|
account. Perform a full CVS (or whatever) checkout, configure, make,
|
||
|
run tests, etc. Confirm that the build works without manual fussing.
|
||
|
If it doesn't work when you do it by hand, it will be unlikely to work
|
||
|
when the buildbot attempts to do it in an automated fashion.
|
||
|
|
||
|
@item
|
||
|
Choose a base directory
|
||
|
|
||
|
This should be somewhere in the buildslave's account, typically named
|
||
|
after the project which is being tested. The buildslave will not touch
|
||
|
any file outside of this directory. Something like @file{~/Buildbot}
|
||
|
or @file{~/Buildslaves/fooproject} is appropriate.
|
||
|
|
||
|
@item
|
||
|
Get the buildmaster host/port, botname, and password
|
||
|
|
||
|
When the buildbot admin configures the buildmaster to accept and use
|
||
|
your buildslave, they will provide you with the following pieces of
|
||
|
information:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
your buildslave's name
|
||
|
@item
|
||
|
the password assigned to your buildslave
|
||
|
@item
|
||
|
the hostname and port number of the buildmaster, i.e. buildbot.example.org:8007
|
||
|
@end itemize
|
||
|
|
||
|
@item
|
||
|
Create the buildslave
|
||
|
|
||
|
Now run the 'buildbot' command as follows:
|
||
|
|
||
|
@example
|
||
|
buildbot create-slave @var{BASEDIR} @var{MASTERHOST}:@var{PORT} @var{SLAVENAME} @var{PASSWORD}
|
||
|
@end example
|
||
|
|
||
|
This will create the base directory and a collection of files inside,
|
||
|
including the @file{buildbot.tac} file that contains all the
|
||
|
information you passed to the @code{buildbot} command.
|
||
|
|
||
|
@item
|
||
|
Fill in the hostinfo files
|
||
|
|
||
|
When it first connects, the buildslave will send a few files up to the
|
||
|
buildmaster which describe the host that it is running on. These files
|
||
|
are presented on the web status display so that developers have more
|
||
|
information to reproduce any test failures that are witnessed by the
|
||
|
buildbot. There are sample files in the @file{info} subdirectory of
|
||
|
the buildbot's base directory. You should edit these to correctly
|
||
|
describe you and your host.
|
||
|
|
||
|
@file{BASEDIR/info/admin} should contain your name and email address.
|
||
|
This is the ``buildslave admin address'', and will be visible from the
|
||
|
build status page (so you may wish to munge it a bit if
|
||
|
address-harvesting spambots are a concern).
|
||
|
|
||
|
@file{BASEDIR/info/host} should be filled with a brief description of
|
||
|
the host: OS, version, memory size, CPU speed, versions of relevant
|
||
|
libraries installed, and finally the version of the buildbot code
|
||
|
which is running the buildslave.
|
||
|
|
||
|
If you run many buildslaves, you may want to create a single
|
||
|
@file{~buildslave/info} file and share it among all the buildslaves
|
||
|
with symlinks.
|
||
|
|
||
|
@end enumerate
|
||
|
|
||
|
@menu
|
||
|
* Buildslave Options::
|
||
|
@end menu
|
||
|
|
||
|
@node Buildslave Options, , Creating a buildslave, Creating a buildslave
|
||
|
@subsection Buildslave Options
|
||
|
|
||
|
There are a handful of options you might want to use when creating the
|
||
|
buildslave with the @command{buildbot create-slave <options> DIR <params>}
|
||
|
command. You can type @command{buildbot create-slave --help} for a summary.
|
||
|
To use these, just include them on the @command{buildbot create-slave}
|
||
|
command line, like this:
|
||
|
|
||
|
@example
|
||
|
buildbot create-slave --umask=022 ~/buildslave buildmaster.example.org:42012 myslavename mypasswd
|
||
|
@end example
|
||
|
|
||
|
@table @code
|
||
|
@item --usepty
|
||
|
This is a boolean flag that tells the buildslave whether to launch
|
||
|
child processes in a PTY (the default) or with regular pipes. The
|
||
|
advantage of using a PTY is that ``grandchild'' processes are more
|
||
|
likely to be cleaned up if the build is interrupted or times out
|
||
|
(since it enables the use of a ``process group'' in which all child
|
||
|
processes will be placed). The disadvantages: some forms of Unix have
|
||
|
problems with PTYs, some of your unit tests may behave differently
|
||
|
when run under a PTY (generally those which check to see if they are
|
||
|
being run interactively), and PTYs will merge the stdout and stderr
|
||
|
streams into a single output stream (which means the red-vs-black
|
||
|
coloring in the logfiles will be lost). If you encounter problems, you
|
||
|
can add @code{--usepty=0} to disable the use of PTYs. Note that
|
||
|
windows buildslaves never use PTYs.
|
||
|
|
||
|
@item --umask
|
||
|
This is a string (generally an octal representation of an integer)
|
||
|
which will cause the buildslave process' ``umask'' value to be set
|
||
|
shortly after initialization. The ``twistd'' daemonization utility
|
||
|
forces the umask to 077 at startup (which means that all files created
|
||
|
by the buildslave or its child processes will be unreadable by any
|
||
|
user other than the buildslave account). If you want build products to
|
||
|
be readable by other accounts, you can add @code{--umask=022} to tell
|
||
|
the buildslave to fix the umask after twistd clobbers it. If you want
|
||
|
build products to be @emph{writable} by other accounts too, use
|
||
|
@code{--umask=000}, but this is likely to be a security problem.
|
||
|
|
||
|
@item --keepalive
|
||
|
This is a number that indicates how frequently ``keepalive'' messages
|
||
|
should be sent from the buildslave to the buildmaster, expressed in
|
||
|
seconds. The default (600) causes a message to be sent to the
|
||
|
buildmaster at least once every 10 minutes. To set this to a lower
|
||
|
value, use e.g. @code{--keepalive=120}.
|
||
|
|
||
|
If the buildslave is behind a NAT box or stateful firewall, these
|
||
|
messages may help to keep the connection alive: some NAT boxes tend to
|
||
|
forget about a connection if it has not been used in a while. When
|
||
|
this happens, the buildmaster will think that the buildslave has
|
||
|
disappeared, and builds will time out. Meanwhile the buildslave will
|
||
|
not realize than anything is wrong.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node Launching the daemons, Logfiles, Creating a buildslave, Installation
|
||
|
@section Launching the daemons
|
||
|
|
||
|
Both the buildmaster and the buildslave run as daemon programs. To
|
||
|
launch them, pass the working directory to the @code{buildbot}
|
||
|
command:
|
||
|
|
||
|
@example
|
||
|
buildbot start @var{BASEDIR}
|
||
|
@end example
|
||
|
|
||
|
This command will start the daemon and then return, so normally it
|
||
|
will not produce any output. To verify that the programs are indeed
|
||
|
running, look for a pair of files named @file{twistd.log} and
|
||
|
@file{twistd.pid} that should be created in the working directory.
|
||
|
@file{twistd.pid} contains the process ID of the newly-spawned daemon.
|
||
|
|
||
|
When the buildslave connects to the buildmaster, new directories will
|
||
|
start appearing in its base directory. The buildmaster tells the slave
|
||
|
to create a directory for each Builder which will be using that slave.
|
||
|
All build operations are performed within these directories: CVS
|
||
|
checkouts, compiles, and tests.
|
||
|
|
||
|
Once you get everything running, you will want to arrange for the
|
||
|
buildbot daemons to be started at boot time. One way is to use
|
||
|
@code{cron}, by putting them in a @@reboot crontab entry@footnote{this
|
||
|
@@reboot syntax is understood by Vixie cron, which is the flavor
|
||
|
usually provided with linux systems. Other unices may have a cron that
|
||
|
doesn't understand @@reboot}:
|
||
|
|
||
|
@example
|
||
|
@@reboot buildbot start @var{BASEDIR}
|
||
|
@end example
|
||
|
|
||
|
When you run @command{crontab} to set this up, remember to do it as
|
||
|
the buildmaster or buildslave account! If you add this to your crontab
|
||
|
when running as your regular account (or worse yet, root), then the
|
||
|
daemon will run as the wrong user, quite possibly as one with more
|
||
|
authority than you intended to provide.
|
||
|
|
||
|
It is important to remember that the environment provided to cron jobs
|
||
|
and init scripts can be quite different that your normal runtime.
|
||
|
There may be fewer environment variables specified, and the PATH may
|
||
|
be shorter than usual. It is a good idea to test out this method of
|
||
|
launching the buildslave by using a cron job with a time in the near
|
||
|
future, with the same command, and then check @file{twistd.log} to
|
||
|
make sure the slave actually started correctly. Common problems here
|
||
|
are for @file{/usr/local} or @file{~/bin} to not be on your
|
||
|
@code{PATH}, or for @code{PYTHONPATH} to not be set correctly.
|
||
|
Sometimes @code{HOME} is messed up too.
|
||
|
|
||
|
To modify the way the daemons are started (perhaps you want to set
|
||
|
some environment variables first, or perform some cleanup each time),
|
||
|
you can create a file named @file{Makefile.buildbot} in the base
|
||
|
directory. When the @file{buildbot} front-end tool is told to
|
||
|
@command{start} the daemon, and it sees this file (and
|
||
|
@file{/usr/bin/make} exists), it will do @command{make -f
|
||
|
Makefile.buildbot start} instead of its usual action (which involves
|
||
|
running @command{twistd}). When the buildmaster or buildslave is
|
||
|
installed, a @file{Makefile.sample} is created which implements the
|
||
|
same behavior as the the @file{buildbot} tool uses, so if you want to
|
||
|
customize the process, just copy @file{Makefile.sample} to
|
||
|
@file{Makefile.buildbot} and edit it as necessary.
|
||
|
|
||
|
@node Logfiles, Shutdown, Launching the daemons, Installation
|
||
|
@section Logfiles
|
||
|
|
||
|
@cindex logfiles
|
||
|
|
||
|
While a buildbot daemon runs, it emits text to a logfile, named
|
||
|
@file{twistd.log}. A command like @code{tail -f twistd.log} is useful
|
||
|
to watch the command output as it runs.
|
||
|
|
||
|
The buildmaster will announce any errors with its configuration file
|
||
|
in the logfile, so it is a good idea to look at the log at startup
|
||
|
time to check for any problems. Most buildmaster activities will cause
|
||
|
lines to be added to the log.
|
||
|
|
||
|
@node Shutdown, Maintenance, Logfiles, Installation
|
||
|
@section Shutdown
|
||
|
|
||
|
To stop a buildmaster or buildslave manually, use:
|
||
|
|
||
|
@example
|
||
|
buildbot stop @var{BASEDIR}
|
||
|
@end example
|
||
|
|
||
|
This simply looks for the @file{twistd.pid} file and kills whatever
|
||
|
process is identified within.
|
||
|
|
||
|
At system shutdown, all processes are sent a @code{SIGKILL}. The
|
||
|
buildmaster and buildslave will respond to this by shutting down
|
||
|
normally.
|
||
|
|
||
|
The buildmaster will respond to a @code{SIGHUP} by re-reading its
|
||
|
config file. The following shortcut is available:
|
||
|
|
||
|
@example
|
||
|
buildbot reconfig @var{BASEDIR}
|
||
|
@end example
|
||
|
|
||
|
When you update the Buildbot code to a new release, you will need to
|
||
|
restart the buildmaster and/or buildslave before it can take advantage
|
||
|
of the new code. You can do a @code{buildbot stop @var{BASEDIR}} and
|
||
|
@code{buildbot start @var{BASEDIR}} in quick succession, or you can
|
||
|
use the @code{restart} shortcut, which does both steps for you:
|
||
|
|
||
|
@example
|
||
|
buildbot restart @var{BASEDIR}
|
||
|
@end example
|
||
|
|
||
|
|
||
|
@node Maintenance, Troubleshooting, Shutdown, Installation
|
||
|
@section Maintenance
|
||
|
|
||
|
It is a good idea to check the buildmaster's status page every once in
|
||
|
a while, to see if your buildslave is still online. Eventually the
|
||
|
buildbot will probably be enhanced to send you email (via the
|
||
|
@file{info/admin} email address) when the slave has been offline for
|
||
|
more than a few hours.
|
||
|
|
||
|
If you find you can no longer provide a buildslave to the project, please
|
||
|
let the project admins know, so they can put out a call for a
|
||
|
replacement.
|
||
|
|
||
|
The Buildbot records status and logs output continually, each time a
|
||
|
build is performed. The status tends to be small, but the build logs
|
||
|
can become quite large. Each build and log are recorded in a separate
|
||
|
file, arranged hierarchically under the buildmaster's base directory.
|
||
|
To prevent these files from growing without bound, you should
|
||
|
periodically delete old build logs. A simple cron job to delete
|
||
|
anything older than, say, two weeks should do the job. The only trick
|
||
|
is to leave the @file{buildbot.tac} and other support files alone, for
|
||
|
which find's @code{-mindepth} argument helps skip everything in the
|
||
|
top directory. You can use something like the following:
|
||
|
|
||
|
@example
|
||
|
@@weekly cd BASEDIR && find . -mindepth 2 -type f -mtime +14 -exec rm @{@} \;
|
||
|
@@weekly cd BASEDIR && find twistd.log* -mtime +14 -exec rm @{@} \;
|
||
|
@end example
|
||
|
|
||
|
@node Troubleshooting, , Maintenance, Installation
|
||
|
@section Troubleshooting
|
||
|
|
||
|
Here are a few hints on diagnosing common problems.
|
||
|
|
||
|
@menu
|
||
|
* Starting the buildslave::
|
||
|
* Connecting to the buildmaster::
|
||
|
* Forcing Builds::
|
||
|
@end menu
|
||
|
|
||
|
@node Starting the buildslave, Connecting to the buildmaster, Troubleshooting, Troubleshooting
|
||
|
@subsection Starting the buildslave
|
||
|
|
||
|
Cron jobs are typically run with a minimal shell (@file{/bin/sh}, not
|
||
|
@file{/bin/bash}), and tilde expansion is not always performed in such
|
||
|
commands. You may want to use explicit paths, because the @code{PATH}
|
||
|
is usually quite short and doesn't include anything set by your
|
||
|
shell's startup scripts (@file{.profile}, @file{.bashrc}, etc). If
|
||
|
you've installed buildbot (or other python libraries) to an unusual
|
||
|
location, you may need to add a @code{PYTHONPATH} specification (note
|
||
|
that python will do tilde-expansion on @code{PYTHONPATH} elements by
|
||
|
itself). Sometimes it is safer to fully-specify everything:
|
||
|
|
||
|
@example
|
||
|
@@reboot PYTHONPATH=~/lib/python /usr/local/bin/buildbot start /usr/home/buildbot/basedir
|
||
|
@end example
|
||
|
|
||
|
Take the time to get the @@reboot job set up. Otherwise, things will work
|
||
|
fine for a while, but the first power outage or system reboot you have will
|
||
|
stop the buildslave with nothing but the cries of sorrowful developers to
|
||
|
remind you that it has gone away.
|
||
|
|
||
|
@node Connecting to the buildmaster, Forcing Builds, Starting the buildslave, Troubleshooting
|
||
|
@subsection Connecting to the buildmaster
|
||
|
|
||
|
If the buildslave cannot connect to the buildmaster, the reason should
|
||
|
be described in the @file{twistd.log} logfile. Some common problems
|
||
|
are an incorrect master hostname or port number, or a mistyped bot
|
||
|
name or password. If the buildslave loses the connection to the
|
||
|
master, it is supposed to attempt to reconnect with an
|
||
|
exponentially-increasing backoff. Each attempt (and the time of the
|
||
|
next attempt) will be logged. If you get impatient, just manually stop
|
||
|
and re-start the buildslave.
|
||
|
|
||
|
When the buildmaster is restarted, all slaves will be disconnected,
|
||
|
and will attempt to reconnect as usual. The reconnect time will depend
|
||
|
upon how long the buildmaster is offline (i.e. how far up the
|
||
|
exponential backoff curve the slaves have travelled). Again,
|
||
|
@code{buildbot stop @var{BASEDIR}; buildbot start @var{BASEDIR}} will
|
||
|
speed up the process.
|
||
|
|
||
|
@node Forcing Builds, , Connecting to the buildmaster, Troubleshooting
|
||
|
@subsection Forcing Builds
|
||
|
|
||
|
From the buildmaster's main status web page, you can force a build to
|
||
|
be run on your build slave. Figure out which column is for a builder
|
||
|
that runs on your slave, click on that builder's name, and the page
|
||
|
that comes up will have a ``Force Build'' button. Fill in the form,
|
||
|
hit the button, and a moment later you should see your slave's
|
||
|
@file{twistd.log} filling with commands being run. Using @code{pstree}
|
||
|
or @code{top} should also reveal the cvs/make/gcc/etc processes being
|
||
|
run by the buildslave. Note that the same web page should also show
|
||
|
the @file{admin} and @file{host} information files that you configured
|
||
|
earlier.
|
||
|
|
||
|
@node Concepts, Configuration, Installation, Top
|
||
|
@chapter Concepts
|
||
|
|
||
|
This chapter defines some of the basic concepts that the Buildbot
|
||
|
uses. You'll need to understand how the Buildbot sees the world to
|
||
|
configure it properly.
|
||
|
|
||
|
@menu
|
||
|
* Version Control Systems::
|
||
|
* Schedulers::
|
||
|
* BuildSet::
|
||
|
* BuildRequest::
|
||
|
* Builder::
|
||
|
* Users::
|
||
|
@end menu
|
||
|
|
||
|
@node Version Control Systems, Schedulers, Concepts, Concepts
|
||
|
@section Version Control Systems
|
||
|
|
||
|
@cindex Version Control
|
||
|
|
||
|
These source trees come from a Version Control System of some kind.
|
||
|
CVS and Subversion are two popular ones, but the Buildbot supports
|
||
|
others. All VC systems have some notion of an upstream
|
||
|
@code{repository} which acts as a server@footnote{except Darcs, but
|
||
|
since the Buildbot never modifies its local source tree we can ignore
|
||
|
the fact that Darcs uses a less centralized model}, from which clients
|
||
|
can obtain source trees according to various parameters. The VC
|
||
|
repository provides source trees of various projects, for different
|
||
|
branches, and from various points in time. The first thing we have to
|
||
|
do is to specify which source tree we want to get.
|
||
|
|
||
|
@menu
|
||
|
* Generalizing VC Systems::
|
||
|
* Source Tree Specifications::
|
||
|
* How Different VC Systems Specify Sources::
|
||
|
* Attributes of Changes::
|
||
|
@end menu
|
||
|
|
||
|
@node Generalizing VC Systems, Source Tree Specifications, Version Control Systems, Version Control Systems
|
||
|
@subsection Generalizing VC Systems
|
||
|
|
||
|
For the purposes of the Buildbot, we will try to generalize all VC
|
||
|
systems as having repositories that each provide sources for a variety
|
||
|
of projects. Each project is defined as a directory tree with source
|
||
|
files. The individual files may each have revisions, but we ignore
|
||
|
that and treat the project as a whole as having a set of revisions.
|
||
|
Each time someone commits a change to the project, a new revision
|
||
|
becomes available. These revisions can be described by a tuple with
|
||
|
two items: the first is a branch tag, and the second is some kind of
|
||
|
timestamp or revision stamp. Complex projects may have multiple branch
|
||
|
tags, but there is always a default branch. The timestamp may be an
|
||
|
actual timestamp (such as the -D option to CVS), or it may be a
|
||
|
monotonically-increasing transaction number (such as the change number
|
||
|
used by SVN and P4, or the revision number used by Arch, or a labeled
|
||
|
tag used in CVS)@footnote{many VC systems provide more complexity than
|
||
|
this: in particular the local views that P4 and ClearCase can assemble
|
||
|
out of various source directories are more complex than we're prepared
|
||
|
to take advantage of here}. The SHA1 revision ID used by Monotone and
|
||
|
Mercurial is also a kind of revision stamp, in that it specifies a
|
||
|
unique copy of the source tree, as does a Darcs ``context'' file.
|
||
|
|
||
|
When we aren't intending to make any changes to the sources we check out
|
||
|
(at least not any that need to be committed back upstream), there are two
|
||
|
basic ways to use a VC system:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
Retrieve a specific set of source revisions: some tag or key is used
|
||
|
to index this set, which is fixed and cannot be changed by subsequent
|
||
|
developers committing new changes to the tree. Releases are built from
|
||
|
tagged revisions like this, so that they can be rebuilt again later
|
||
|
(probably with controlled modifications).
|
||
|
@item
|
||
|
Retrieve the latest sources along a specific branch: some tag is used
|
||
|
to indicate which branch is to be used, but within that constraint we want
|
||
|
to get the latest revisions.
|
||
|
@end itemize
|
||
|
|
||
|
Build personnel or CM staff typically use the first approach: the
|
||
|
build that results is (ideally) completely specified by the two
|
||
|
parameters given to the VC system: repository and revision tag. This
|
||
|
gives QA and end-users something concrete to point at when reporting
|
||
|
bugs. Release engineers are also reportedly fond of shipping code that
|
||
|
can be traced back to a concise revision tag of some sort.
|
||
|
|
||
|
Developers are more likely to use the second approach: each morning
|
||
|
the developer does an update to pull in the changes committed by the
|
||
|
team over the last day. These builds are not easy to fully specify: it
|
||
|
depends upon exactly when you did a checkout, and upon what local
|
||
|
changes the developer has in their tree. Developers do not normally
|
||
|
tag each build they produce, because there is usually significant
|
||
|
overhead involved in creating these tags. Recreating the trees used by
|
||
|
one of these builds can be a challenge. Some VC systems may provide
|
||
|
implicit tags (like a revision number), while others may allow the use
|
||
|
of timestamps to mean ``the state of the tree at time X'' as opposed
|
||
|
to a tree-state that has been explicitly marked.
|
||
|
|
||
|
The Buildbot is designed to help developers, so it usually works in
|
||
|
terms of @emph{the latest} sources as opposed to specific tagged
|
||
|
revisions. However, it would really prefer to build from reproducible
|
||
|
source trees, so implicit revisions are used whenever possible.
|
||
|
|
||
|
@node Source Tree Specifications, How Different VC Systems Specify Sources, Generalizing VC Systems, Version Control Systems
|
||
|
@subsection Source Tree Specifications
|
||
|
|
||
|
So for the Buildbot's purposes we treat each VC system as a server
|
||
|
which can take a list of specifications as input and produce a source
|
||
|
tree as output. Some of these specifications are static: they are
|
||
|
attributes of the builder and do not change over time. Others are more
|
||
|
variable: each build will have a different value. The repository is
|
||
|
changed over time by a sequence of Changes, each of which represents a
|
||
|
single developer making changes to some set of files. These Changes
|
||
|
are cumulative@footnote{Monotone's @emph{multiple heads} feature
|
||
|
violates this assumption of cumulative Changes, but in most situations
|
||
|
the changes don't occur frequently enough for this to be a significant
|
||
|
problem}.
|
||
|
|
||
|
For normal builds, the Buildbot wants to get well-defined source trees
|
||
|
that contain specific Changes, and exclude other Changes that may have
|
||
|
occurred after the desired ones. We assume that the Changes arrive at
|
||
|
the buildbot (through one of the mechanisms described in @pxref{Change
|
||
|
Sources}) in the same order in which they are committed to the
|
||
|
repository. The Buildbot waits for the tree to become ``stable''
|
||
|
before initiating a build, for two reasons. The first is that
|
||
|
developers frequently make multiple related commits in quick
|
||
|
succession, even when the VC system provides ways to make atomic
|
||
|
transactions involving multiple files at the same time. Running a
|
||
|
build in the middle of these sets of changes would use an inconsistent
|
||
|
set of source files, and is likely to fail (and is certain to be less
|
||
|
useful than a build which uses the full set of changes). The
|
||
|
tree-stable-timer is intended to avoid these useless builds that
|
||
|
include some of the developer's changes but not all. The second reason
|
||
|
is that some VC systems (i.e. CVS) do not provide repository-wide
|
||
|
transaction numbers, so that timestamps are the only way to refer to
|
||
|
a specific repository state. These timestamps may be somewhat
|
||
|
ambiguous, due to processing and notification delays. By waiting until
|
||
|
the tree has been stable for, say, 10 minutes, we can choose a
|
||
|
timestamp from the middle of that period to use for our source
|
||
|
checkout, and then be reasonably sure that any clock-skew errors will
|
||
|
not cause the build to be performed on an inconsistent set of source
|
||
|
files.
|
||
|
|
||
|
The Schedulers always use the tree-stable-timer, with a timeout that
|
||
|
is configured to reflect a reasonable tradeoff between build latency
|
||
|
and change frequency. When the VC system provides coherent
|
||
|
repository-wide revision markers (such as Subversion's revision
|
||
|
numbers, or in fact anything other than CVS's timestamps), the
|
||
|
resulting Build is simply performed against a source tree defined by
|
||
|
that revision marker. When the VC system does not provide this, a
|
||
|
timestamp from the middle of the tree-stable period is used to
|
||
|
generate the source tree@footnote{this @code{checkoutDelay} defaults
|
||
|
to half the tree-stable timer, but it can be overridden with an
|
||
|
argument to the Source Step}.
|
||
|
|
||
|
@node How Different VC Systems Specify Sources, Attributes of Changes, Source Tree Specifications, Version Control Systems
|
||
|
@subsection How Different VC Systems Specify Sources
|
||
|
|
||
|
For CVS, the static specifications are @code{repository} and
|
||
|
@code{module}. In addition to those, each build uses a timestamp (or
|
||
|
omits the timestamp to mean @code{the latest}) and @code{branch tag}
|
||
|
(which defaults to HEAD). These parameters collectively specify a set
|
||
|
of sources from which a build may be performed.
|
||
|
|
||
|
@uref{http://subversion.tigris.org, Subversion} combines the
|
||
|
repository, module, and branch into a single @code{Subversion URL}
|
||
|
parameter. Within that scope, source checkouts can be specified by a
|
||
|
numeric @code{revision number} (a repository-wide
|
||
|
monotonically-increasing marker, such that each transaction that
|
||
|
changes the repository is indexed by a different revision number), or
|
||
|
a revision timestamp. When branches are used, the repository and
|
||
|
module form a static @code{baseURL}, while each build has a
|
||
|
@code{revision number} and a @code{branch} (which defaults to a
|
||
|
statically-specified @code{defaultBranch}). The @code{baseURL} and
|
||
|
@code{branch} are simply concatenated together to derive the
|
||
|
@code{svnurl} to use for the checkout.
|
||
|
|
||
|
@uref{http://www.perforce.com/, Perforce} is similar. The server
|
||
|
is specified through a @code{P4PORT} parameter. Module and branch
|
||
|
are specified in a single depot path, and revisions are
|
||
|
depot-wide. When branches are used, the @code{p4base} and
|
||
|
@code{defaultBranch} are concatenated together to produce the depot
|
||
|
path.
|
||
|
|
||
|
@uref{http://wiki.gnuarch.org/, Arch} and
|
||
|
@uref{http://bazaar.canonical.com/, Bazaar} specify a repository by
|
||
|
URL, as well as a @code{version} which is kind of like a branch name.
|
||
|
Arch uses the word @code{archive} to represent the repository. Arch
|
||
|
lets you push changes from one archive to another, removing the strict
|
||
|
centralization required by CVS and SVN. It retains the distinction
|
||
|
between repository and working directory that most other VC systems
|
||
|
use. For complex multi-module directory structures, Arch has a
|
||
|
built-in @code{build config} layer with which the checkout process has
|
||
|
two steps. First, an initial bootstrap checkout is performed to
|
||
|
retrieve a set of build-config files. Second, one of these files is
|
||
|
used to figure out which archives/modules should be used to populate
|
||
|
subdirectories of the initial checkout.
|
||
|
|
||
|
Builders which use Arch and Bazaar therefore have a static archive
|
||
|
@code{url}, and a default ``branch'' (which is a string that specifies
|
||
|
a complete category--branch--version triple). Each build can have its
|
||
|
own branch (the category--branch--version string) to override the
|
||
|
default, as well as a revision number (which is turned into a
|
||
|
--patch-NN suffix when performing the checkout).
|
||
|
|
||
|
@uref{http://abridgegame.org/darcs/, Darcs} doesn't really have the
|
||
|
notion of a single master repository. Nor does it really have
|
||
|
branches. In Darcs, each working directory is also a repository, and
|
||
|
there are operations to push and pull patches from one of these
|
||
|
@code{repositories} to another. For the Buildbot's purposes, all you
|
||
|
need to do is specify the URL of a repository that you want to build
|
||
|
from. The build slave will then pull the latest patches from that
|
||
|
repository and build them. Multiple branches are implemented by using
|
||
|
multiple repositories (possibly living on the same server).
|
||
|
|
||
|
Builders which use Darcs therefore have a static @code{repourl} which
|
||
|
specifies the location of the repository. If branches are being used,
|
||
|
the source Step is instead configured with a @code{baseURL} and a
|
||
|
@code{defaultBranch}, and the two strings are simply concatenated
|
||
|
together to obtain the repository's URL. Each build then has a
|
||
|
specific branch which replaces @code{defaultBranch}, or just uses the
|
||
|
default one. Instead of a revision number, each build can have a
|
||
|
``context'', which is a string that records all the patches that are
|
||
|
present in a given tree (this is the output of @command{darcs changes
|
||
|
--context}, and is considerably less concise than, e.g. Subversion's
|
||
|
revision number, but the patch-reordering flexibility of Darcs makes
|
||
|
it impossible to provide a shorter useful specification).
|
||
|
|
||
|
@uref{http://selenic.com/mercurial, Mercurial} is like Darcs, in that
|
||
|
each branch is stored in a separate repository. The @code{repourl},
|
||
|
@code{baseURL}, and @code{defaultBranch} arguments are all handled the
|
||
|
same way as with Darcs. The ``revision'', however, is the hash
|
||
|
identifier returned by @command{hg identify}.
|
||
|
|
||
|
|
||
|
@node Attributes of Changes, , How Different VC Systems Specify Sources, Version Control Systems
|
||
|
@subsection Attributes of Changes
|
||
|
|
||
|
@heading Who
|
||
|
|
||
|
Each Change has a @code{who} attribute, which specifies which
|
||
|
developer is responsible for the change. This is a string which comes
|
||
|
from a namespace controlled by the VC repository. Frequently this
|
||
|
means it is a username on the host which runs the repository, but not
|
||
|
all VC systems require this (Arch, for example, uses a fully-qualified
|
||
|
@code{Arch ID}, which looks like an email address, as does Darcs).
|
||
|
Each StatusNotifier will map the @code{who} attribute into something
|
||
|
appropriate for their particular means of communication: an email
|
||
|
address, an IRC handle, etc.
|
||
|
|
||
|
@heading Files
|
||
|
|
||
|
It also has a list of @code{files}, which are just the tree-relative
|
||
|
filenames of any files that were added, deleted, or modified for this
|
||
|
Change. These filenames are used by the @code{isFileImportant}
|
||
|
function (in the Scheduler) to decide whether it is worth triggering a
|
||
|
new build or not, e.g. the function could use
|
||
|
@code{filename.endswith(".c")} to only run a build if a C file were
|
||
|
checked in. Certain BuildSteps can also use the list of changed files
|
||
|
to run a more targeted series of tests, e.g. the
|
||
|
@code{python_twisted.Trial} step can run just the unit tests that
|
||
|
provide coverage for the modified .py files instead of running the
|
||
|
full test suite.
|
||
|
|
||
|
@heading Comments
|
||
|
|
||
|
The Change also has a @code{comments} attribute, which is a string
|
||
|
containing any checkin comments.
|
||
|
|
||
|
@heading Revision
|
||
|
|
||
|
Each Change can have a @code{revision} attribute, which describes how
|
||
|
to get a tree with a specific state: a tree which includes this Change
|
||
|
(and all that came before it) but none that come after it. If this
|
||
|
information is unavailable, the @code{.revision} attribute will be
|
||
|
@code{None}. These revisions are provided by the ChangeSource, and
|
||
|
consumed by the @code{computeSourceRevision} method in the appropriate
|
||
|
@code{step.Source} class.
|
||
|
|
||
|
@table @samp
|
||
|
@item CVS
|
||
|
@code{revision} is an int, seconds since the epoch
|
||
|
@item SVN
|
||
|
@code{revision} is an int, a transation number (r%d)
|
||
|
@item Darcs
|
||
|
@code{revision} is a large string, the output of @code{darcs changes --context}
|
||
|
@item Mercurial
|
||
|
@code{revision} is a short string (a hash ID), the output of @code{hg identify}
|
||
|
@item Arch/Bazaar
|
||
|
@code{revision} is the full revision ID (ending in --patch-%d)
|
||
|
@item P4
|
||
|
@code{revision} is an int, the transaction number
|
||
|
@end table
|
||
|
|
||
|
@heading Branches
|
||
|
|
||
|
The Change might also have a @code{branch} attribute. This indicates
|
||
|
that all of the Change's files are in the same named branch. The
|
||
|
Schedulers get to decide whether the branch should be built or not.
|
||
|
|
||
|
For VC systems like CVS, Arch, and Monotone, the @code{branch} name is
|
||
|
unrelated to the filename. (that is, the branch name and the filename
|
||
|
inhabit unrelated namespaces). For SVN, branches are expressed as
|
||
|
subdirectories of the repository, so the file's ``svnurl'' is a
|
||
|
combination of some base URL, the branch name, and the filename within
|
||
|
the branch. (In a sense, the branch name and the filename inhabit the
|
||
|
same namespace). Darcs branches are subdirectories of a base URL just
|
||
|
like SVN. Mercurial branches are the same as Darcs.
|
||
|
|
||
|
@table @samp
|
||
|
@item CVS
|
||
|
branch='warner-newfeature', files=['src/foo.c']
|
||
|
@item SVN
|
||
|
branch='branches/warner-newfeature', files=['src/foo.c']
|
||
|
@item Darcs
|
||
|
branch='warner-newfeature', files=['src/foo.c']
|
||
|
@item Mercurial
|
||
|
branch='warner-newfeature', files=['src/foo.c']
|
||
|
@item Arch/Bazaar
|
||
|
branch='buildbot--usebranches--0', files=['buildbot/master.py']
|
||
|
@end table
|
||
|
|
||
|
@heading Links
|
||
|
|
||
|
@c TODO: who is using 'links'? how is it being used?
|
||
|
|
||
|
Finally, the Change might have a @code{links} list, which is intended
|
||
|
to provide a list of URLs to a @emph{viewcvs}-style web page that
|
||
|
provides more detail for this Change, perhaps including the full file
|
||
|
diffs.
|
||
|
|
||
|
|
||
|
@node Schedulers, BuildSet, Version Control Systems, Concepts
|
||
|
@section Schedulers
|
||
|
|
||
|
@cindex Scheduler
|
||
|
|
||
|
Each Buildmaster has a set of @code{Scheduler} objects, each of which
|
||
|
gets a copy of every incoming Change. The Schedulers are responsible
|
||
|
for deciding when Builds should be run. Some Buildbot installations
|
||
|
might have a single Scheduler, while others may have several, each for
|
||
|
a different purpose.
|
||
|
|
||
|
For example, a ``quick'' scheduler might exist to give immediate
|
||
|
feedback to developers, hoping to catch obvious problems in the code
|
||
|
that can be detected quickly. These typically do not run the full test
|
||
|
suite, nor do they run on a wide variety of platforms. They also
|
||
|
usually do a VC update rather than performing a brand-new checkout
|
||
|
each time. You could have a ``quick'' scheduler which used a 30 second
|
||
|
timeout, and feeds a single ``quick'' Builder that uses a VC
|
||
|
@code{mode='update'} setting.
|
||
|
|
||
|
A separate ``full'' scheduler would run more comprehensive tests a
|
||
|
little while later, to catch more subtle problems. This scheduler
|
||
|
would have a longer tree-stable-timer, maybe 30 minutes, and would
|
||
|
feed multiple Builders (with a @code{mode=} of @code{'copy'},
|
||
|
@code{'clobber'}, or @code{'export'}).
|
||
|
|
||
|
The @code{tree-stable-timer} and @code{isFileImportant} decisions are
|
||
|
made by the Scheduler. Dependencies are also implemented here.
|
||
|
Periodic builds (those which are run every N seconds rather than after
|
||
|
new Changes arrive) are triggered by a special @code{Periodic}
|
||
|
Scheduler subclass. The default Scheduler class can also be told to
|
||
|
watch for specific branches, ignoring Changes on other branches. This
|
||
|
may be useful if you have a trunk and a few release branches which
|
||
|
should be tracked, but when you don't want to have the Buildbot pay
|
||
|
attention to several dozen private user branches.
|
||
|
|
||
|
Some Schedulers may trigger builds for other reasons, other than
|
||
|
recent Changes. For example, a Scheduler subclass could connect to a
|
||
|
remote buildmaster and watch for builds of a library to succeed before
|
||
|
triggering a local build that uses that library.
|
||
|
|
||
|
Each Scheduler creates and submits @code{BuildSet} objects to the
|
||
|
@code{BuildMaster}, which is then responsible for making sure the
|
||
|
individual @code{BuildRequests} are delivered to the target
|
||
|
@code{Builders}.
|
||
|
|
||
|
@code{Scheduler} instances are activated by placing them in the
|
||
|
@code{c['schedulers']} list in the buildmaster config file. Each
|
||
|
Scheduler has a unique name.
|
||
|
|
||
|
|
||
|
@node BuildSet, BuildRequest, Schedulers, Concepts
|
||
|
@section BuildSet
|
||
|
|
||
|
@cindex BuildSet
|
||
|
|
||
|
A @code{BuildSet} is the name given to a set of Builds that all
|
||
|
compile/test the same version of the tree on multiple Builders. In
|
||
|
general, all these component Builds will perform the same sequence of
|
||
|
Steps, using the same source code, but on different platforms or
|
||
|
against a different set of libraries.
|
||
|
|
||
|
The @code{BuildSet} is tracked as a single unit, which fails if any of
|
||
|
the component Builds have failed, and therefore can succeed only if
|
||
|
@emph{all} of the component Builds have succeeded. There are two kinds
|
||
|
of status notification messages that can be emitted for a BuildSet:
|
||
|
the @code{firstFailure} type (which fires as soon as we know the
|
||
|
BuildSet will fail), and the @code{Finished} type (which fires once
|
||
|
the BuildSet has completely finished, regardless of whether the
|
||
|
overall set passed or failed).
|
||
|
|
||
|
A @code{BuildSet} is created with a @emph{source stamp} tuple of
|
||
|
(branch, revision, changes, patch), some of which may be None, and a
|
||
|
list of Builders on which it is to be run. They are then given to the
|
||
|
BuildMaster, which is responsible for creating a separate
|
||
|
@code{BuildRequest} for each Builder.
|
||
|
|
||
|
There are a couple of different likely values for the
|
||
|
@code{SourceStamp}:
|
||
|
|
||
|
@table @code
|
||
|
@item (revision=None, changes=[CHANGES], patch=None)
|
||
|
This is a @code{SourceStamp} used when a series of Changes have
|
||
|
triggered a build. The VC step will attempt to check out a tree that
|
||
|
contains CHANGES (and any changes that occurred before CHANGES, but
|
||
|
not any that occurred after them).
|
||
|
|
||
|
@item (revision=None, changes=None, patch=None)
|
||
|
This builds the most recent code on the default branch. This is the
|
||
|
sort of @code{SourceStamp} that would be used on a Build that was
|
||
|
triggered by a user request, or a Periodic scheduler. It is also
|
||
|
possible to configure the VC Source Step to always check out the
|
||
|
latest sources rather than paying attention to the Changes in the
|
||
|
SourceStamp, which will result in same behavior as this.
|
||
|
|
||
|
@item (branch=BRANCH, revision=None, changes=None, patch=None)
|
||
|
This builds the most recent code on the given BRANCH. Again, this is
|
||
|
generally triggered by a user request or Periodic build.
|
||
|
|
||
|
@item (revision=REV, changes=None, patch=(LEVEL, DIFF))
|
||
|
This checks out the tree at the given revision REV, then applies a
|
||
|
patch (using @code{diff -pLEVEL <DIFF}). The @ref{try} feature uses
|
||
|
this kind of @code{SourceStamp}. If @code{patch} is None, the patching
|
||
|
step is bypassed.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
The buildmaster is responsible for turning the @code{BuildSet} into a
|
||
|
set of @code{BuildRequest} objects and queueing them on the
|
||
|
appropriate Builders.
|
||
|
|
||
|
|
||
|
@node BuildRequest, Builder, BuildSet, Concepts
|
||
|
@section BuildRequest
|
||
|
|
||
|
@cindex BuildRequest
|
||
|
|
||
|
A @code{BuildRequest} is a request to build a specific set of sources
|
||
|
on a single specific Builder. Each Builder runs the
|
||
|
@code{BuildRequest} as soon as it can (i.e. when an associated
|
||
|
buildslave becomes free).
|
||
|
|
||
|
The @code{BuildRequest} contains the @code{SourceStamp} specification.
|
||
|
The actual process of running the build (the series of Steps that will
|
||
|
be executed) is implemented by the @code{Build} object. In this future
|
||
|
this might be changed, to have the @code{Build} define @emph{what}
|
||
|
gets built, and a separate @code{BuildProcess} (provided by the
|
||
|
Builder) to define @emph{how} it gets built.
|
||
|
|
||
|
The @code{BuildRequest} may be mergeable with other compatible
|
||
|
@code{BuildRequest}s. Builds that are triggered by incoming Changes
|
||
|
will generally be mergeable. Builds that are triggered by user
|
||
|
requests are generally not, unless they are multiple requests to build
|
||
|
the @emph{latest sources} of the same branch.
|
||
|
|
||
|
@node Builder, Users, BuildRequest, Concepts
|
||
|
@section Builder
|
||
|
|
||
|
@cindex Builder
|
||
|
|
||
|
The @code{Builder} is a long-lived object which controls all Builds of
|
||
|
a given type. Each one is created when the config file is first
|
||
|
parsed, and lives forever (or rather until it is removed from the
|
||
|
config file). It mediates the connections to the buildslaves that do
|
||
|
all the work, and is responsible for creating the @code{Build} objects
|
||
|
that decide @emph{how} a build is performed (i.e., which steps are
|
||
|
executed in what order).
|
||
|
|
||
|
Each @code{Builder} gets a unique name, and the path name of a
|
||
|
directory where it gets to do all its work (there is a
|
||
|
buildmaster-side directory for keeping status information, as well as
|
||
|
a buildslave-side directory where the actual checkout/compile/test
|
||
|
commands are executed). It also gets a @code{BuildFactory}, which is
|
||
|
responsible for creating new @code{Build} instances: because the
|
||
|
@code{Build} instance is what actually performs each build, choosing
|
||
|
the @code{BuildFactory} is the way to specify what happens each time a
|
||
|
build is done.
|
||
|
|
||
|
Each @code{Builder} is associated with one of more @code{BuildSlaves}.
|
||
|
A @code{Builder} which is used to perform OS-X builds (as opposed to
|
||
|
Linux or Solaris builds) should naturally be associated with an
|
||
|
OS-X-based buildslave.
|
||
|
|
||
|
|
||
|
@node Users, , Builder, Concepts
|
||
|
@section Users
|
||
|
|
||
|
@cindex Users
|
||
|
|
||
|
Buildbot has a somewhat limited awareness of @emph{users}. It assumes
|
||
|
the world consists of a set of developers, each of whom can be
|
||
|
described by a couple of simple attributes. These developers make
|
||
|
changes to the source code, causing builds which may succeed or fail.
|
||
|
|
||
|
Each developer is primarily known through the source control system. Each
|
||
|
Change object that arrives is tagged with a @code{who} field that
|
||
|
typically gives the account name (on the repository machine) of the user
|
||
|
responsible for that change. This string is the primary key by which the
|
||
|
User is known, and is displayed on the HTML status pages and in each Build's
|
||
|
``blamelist''.
|
||
|
|
||
|
To do more with the User than just refer to them, this username needs to
|
||
|
be mapped into an address of some sort. The responsibility for this mapping
|
||
|
is left up to the status module which needs the address. The core code knows
|
||
|
nothing about email addresses or IRC nicknames, just user names.
|
||
|
|
||
|
@menu
|
||
|
* Doing Things With Users::
|
||
|
* Email Addresses::
|
||
|
* IRC Nicknames::
|
||
|
* Live Status Clients::
|
||
|
@end menu
|
||
|
|
||
|
@node Doing Things With Users, Email Addresses, Users, Users
|
||
|
@subsection Doing Things With Users
|
||
|
|
||
|
Each Change has a single User who is responsible for that Change. Most
|
||
|
Builds have a set of Changes: the Build represents the first time these
|
||
|
Changes have been built and tested by the Buildbot. The build has a
|
||
|
``blamelist'' that consists of a simple union of the Users responsible
|
||
|
for all the Build's Changes.
|
||
|
|
||
|
The Build provides (through the IBuildStatus interface) a list of Users
|
||
|
who are ``involved'' in the build. For now this is equal to the
|
||
|
blamelist, but in the future it will be expanded to include a ``build
|
||
|
sheriff'' (a person who is ``on duty'' at that time and responsible for
|
||
|
watching over all builds that occur during their shift), as well as
|
||
|
per-module owners who simply want to keep watch over their domain (chosen by
|
||
|
subdirectory or a regexp matched against the filenames pulled out of the
|
||
|
Changes). The Involved Users are those who probably have an interest in the
|
||
|
results of any given build.
|
||
|
|
||
|
In the future, Buildbot will acquire the concept of ``Problems'',
|
||
|
which last longer than builds and have beginnings and ends. For example, a
|
||
|
test case which passed in one build and then failed in the next is a
|
||
|
Problem. The Problem lasts until the test case starts passing again, at
|
||
|
which point the Problem is said to be ``resolved''.
|
||
|
|
||
|
If there appears to be a code change that went into the tree at the
|
||
|
same time as the test started failing, that Change is marked as being
|
||
|
resposible for the Problem, and the user who made the change is added
|
||
|
to the Problem's ``Guilty'' list. In addition to this user, there may
|
||
|
be others who share responsibility for the Problem (module owners,
|
||
|
sponsoring developers). In addition to the Responsible Users, there
|
||
|
may be a set of Interested Users, who take an interest in the fate of
|
||
|
the Problem.
|
||
|
|
||
|
Problems therefore have sets of Users who may want to be kept aware of
|
||
|
the condition of the problem as it changes over time. If configured, the
|
||
|
Buildbot can pester everyone on the Responsible list with increasing
|
||
|
harshness until the problem is resolved, with the most harshness reserved
|
||
|
for the Guilty parties themselves. The Interested Users may merely be told
|
||
|
when the problem starts and stops, as they are not actually responsible for
|
||
|
fixing anything.
|
||
|
|
||
|
@node Email Addresses, IRC Nicknames, Doing Things With Users, Users
|
||
|
@subsection Email Addresses
|
||
|
|
||
|
The @code{buildbot.status.mail.MailNotifier} class provides a
|
||
|
status target which can send email about the results of each build. It
|
||
|
accepts a static list of email addresses to which each message should be
|
||
|
delivered, but it can also be configured to send mail to the Build's
|
||
|
Interested Users. To do this, it needs a way to convert User names into
|
||
|
email addresses.
|
||
|
|
||
|
For many VC systems, the User Name is actually an account name on the
|
||
|
system which hosts the repository. As such, turning the name into an
|
||
|
email address is a simple matter of appending
|
||
|
``@@repositoryhost.com''. Some projects use other kinds of mappings
|
||
|
(for example the preferred email address may be at ``project.org''
|
||
|
despite the repository host being named ``cvs.project.org''), and some
|
||
|
VC systems have full separation between the concept of a user and that
|
||
|
of an account on the repository host (like Perforce). Some systems
|
||
|
(like Arch) put a full contact email address in every change.
|
||
|
|
||
|
To convert these names to addresses, the MailNotifier uses an EmailLookup
|
||
|
object. This provides a .getAddress method which accepts a name and
|
||
|
(eventually) returns an address. The default @code{MailNotifier}
|
||
|
module provides an EmailLookup which simply appends a static string,
|
||
|
configurable when the notifier is created. To create more complex behaviors
|
||
|
(perhaps using an LDAP lookup, or using ``finger'' on a central host to
|
||
|
determine a preferred address for the developer), provide a different object
|
||
|
as the @code{lookup} argument.
|
||
|
|
||
|
In the future, when the Problem mechanism has been set up, the Buildbot
|
||
|
will need to send mail to arbitrary Users. It will do this by locating a
|
||
|
MailNotifier-like object among all the buildmaster's status targets, and
|
||
|
asking it to send messages to various Users. This means the User-to-address
|
||
|
mapping only has to be set up once, in your MailNotifier, and every email
|
||
|
message the buildbot emits will take advantage of it.
|
||
|
|
||
|
@node IRC Nicknames, Live Status Clients, Email Addresses, Users
|
||
|
@subsection IRC Nicknames
|
||
|
|
||
|
Like MailNotifier, the @code{buildbot.status.words.IRC} class
|
||
|
provides a status target which can announce the results of each build. It
|
||
|
also provides an interactive interface by responding to online queries
|
||
|
posted in the channel or sent as private messages.
|
||
|
|
||
|
In the future, the buildbot can be configured map User names to IRC
|
||
|
nicknames, to watch for the recent presence of these nicknames, and to
|
||
|
deliver build status messages to the interested parties. Like
|
||
|
@code{MailNotifier} does for email addresses, the @code{IRC} object
|
||
|
will have an @code{IRCLookup} which is responsible for nicknames. The
|
||
|
mapping can be set up statically, or it can be updated by online users
|
||
|
themselves (by claiming a username with some kind of ``buildbot: i am
|
||
|
user warner'' commands).
|
||
|
|
||
|
Once the mapping is established, the rest of the buildbot can ask the
|
||
|
@code{IRC} object to send messages to various users. It can report on
|
||
|
the likelihood that the user saw the given message (based upon how long the
|
||
|
user has been inactive on the channel), which might prompt the Problem
|
||
|
Hassler logic to send them an email message instead.
|
||
|
|
||
|
@node Live Status Clients, , IRC Nicknames, Users
|
||
|
@subsection Live Status Clients
|
||
|
|
||
|
The Buildbot also offers a PB-based status client interface which can
|
||
|
display real-time build status in a GUI panel on the developer's desktop.
|
||
|
This interface is normally anonymous, but it could be configured to let the
|
||
|
buildmaster know @emph{which} developer is using the status client. The
|
||
|
status client could then be used as a message-delivery service, providing an
|
||
|
alternative way to deliver low-latency high-interruption messages to the
|
||
|
developer (like ``hey, you broke the build'').
|
||
|
|
||
|
|
||
|
@node Configuration, Getting Source Code Changes, Concepts, Top
|
||
|
@chapter Configuration
|
||
|
|
||
|
@cindex Configuration
|
||
|
|
||
|
The buildbot's behavior is defined by the ``config file'', which
|
||
|
normally lives in the @file{master.cfg} file in the buildmaster's base
|
||
|
directory (but this can be changed with an option to the
|
||
|
@code{buildbot create-master} command). This file completely specifies
|
||
|
which Builders are to be run, which slaves they should use, how
|
||
|
Changes should be tracked, and where the status information is to be
|
||
|
sent. The buildmaster's @file{buildbot.tac} file names the base
|
||
|
directory; everything else comes from the config file.
|
||
|
|
||
|
A sample config file was installed for you when you created the
|
||
|
buildmaster, but you will need to edit it before your buildbot will do
|
||
|
anything useful.
|
||
|
|
||
|
This chapter gives an overview of the format of this file and the
|
||
|
various sections in it. You will need to read the later chapters to
|
||
|
understand how to fill in each section properly.
|
||
|
|
||
|
@menu
|
||
|
* Config File Format::
|
||
|
* Loading the Config File::
|
||
|
* Defining the Project::
|
||
|
* Listing Change Sources and Schedulers::
|
||
|
* Setting the slaveport::
|
||
|
* Buildslave Specifiers::
|
||
|
* Defining Builders::
|
||
|
* Defining Status Targets::
|
||
|
* Debug options::
|
||
|
@end menu
|
||
|
|
||
|
@node Config File Format, Loading the Config File, Configuration, Configuration
|
||
|
@section Config File Format
|
||
|
|
||
|
The config file is, fundamentally, just a piece of Python code which
|
||
|
defines a dictionary named @code{BuildmasterConfig}, with a number of
|
||
|
keys that are treated specially. You don't need to know Python to do
|
||
|
basic configuration, though, you can just copy the syntax of the
|
||
|
sample file. If you @emph{are} comfortable writing Python code,
|
||
|
however, you can use all the power of a full programming language to
|
||
|
achieve more complicated configurations.
|
||
|
|
||
|
The @code{BuildmasterConfig} name is the only one which matters: all
|
||
|
other names defined during the execution of the file are discarded.
|
||
|
When parsing the config file, the Buildmaster generally compares the
|
||
|
old configuration with the new one and performs the minimum set of
|
||
|
actions necessary to bring the buildbot up to date: Builders which are
|
||
|
not changed are left untouched, and Builders which are modified get to
|
||
|
keep their old event history.
|
||
|
|
||
|
Basic Python syntax: comments start with a hash character (``#''),
|
||
|
tuples are defined with @code{(parenthesis, pairs)}, arrays are
|
||
|
defined with @code{[square, brackets]}, tuples and arrays are mostly
|
||
|
interchangeable. Dictionaries (data structures which map ``keys'' to
|
||
|
``values'') are defined with curly braces: @code{@{'key1': 'value1',
|
||
|
'key2': 'value2'@} }. Function calls (and object instantiation) can use
|
||
|
named parameters, like @code{w = html.Waterfall(http_port=8010)}.
|
||
|
|
||
|
The config file starts with a series of @code{import} statements,
|
||
|
which make various kinds of Steps and Status targets available for
|
||
|
later use. The main @code{BuildmasterConfig} dictionary is created,
|
||
|
then it is populated with a variety of keys. These keys are broken
|
||
|
roughly into the following sections, each of which is documented in
|
||
|
the rest of this chapter:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
Project Definitions
|
||
|
@item
|
||
|
Change Sources / Schedulers
|
||
|
@item
|
||
|
Slaveport
|
||
|
@item
|
||
|
Buildslave Configuration
|
||
|
@item
|
||
|
Builders / Interlocks
|
||
|
@item
|
||
|
Status Targets
|
||
|
@item
|
||
|
Debug options
|
||
|
@end itemize
|
||
|
|
||
|
The config file can use a few names which are placed into its namespace:
|
||
|
|
||
|
@table @code
|
||
|
@item basedir
|
||
|
the base directory for the buildmaster. This string has not been
|
||
|
expanded, so it may start with a tilde. It needs to be expanded before
|
||
|
use. The config file is located in
|
||
|
@code{os.path.expanduser(os.path.join(basedir, 'master.cfg'))}
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node Loading the Config File, Defining the Project, Config File Format, Configuration
|
||
|
@section Loading the Config File
|
||
|
|
||
|
The config file is only read at specific points in time. It is first
|
||
|
read when the buildmaster is launched. Once it is running, there are
|
||
|
various ways to ask it to reload the config file. If you are on the
|
||
|
system hosting the buildmaster, you can send a @code{SIGHUP} signal to
|
||
|
it: the @command{buildbot} tool has a shortcut for this:
|
||
|
|
||
|
@example
|
||
|
buildbot reconfig @var{BASEDIR}
|
||
|
@end example
|
||
|
|
||
|
This command will show you all of the lines from @file{twistd.log}
|
||
|
that relate to the reconfiguration. If there are any problems during
|
||
|
the config-file reload, they will be displayed in these lines.
|
||
|
|
||
|
The debug tool (@code{buildbot debugclient --master HOST:PORT}) has a
|
||
|
``Reload .cfg'' button which will also trigger a reload. In the
|
||
|
future, there will be other ways to accomplish this step (probably a
|
||
|
password-protected button on the web page, as well as a privileged IRC
|
||
|
command).
|
||
|
|
||
|
When reloading the config file, the buildmaster will endeavor to
|
||
|
change as little as possible about the running system. For example,
|
||
|
although old status targets may be shut down and new ones started up,
|
||
|
any status targets that were not changed since the last time the
|
||
|
config file was read will be left running and untouched. Likewise any
|
||
|
Builders which have not been changed will be left running. If a
|
||
|
Builder is modified (say, the build process is changed) while a Build
|
||
|
is currently running, that Build will keep running with the old
|
||
|
process until it completes. Any previously queued Builds (or Builds
|
||
|
which get queued after the reconfig) will use the new process.
|
||
|
|
||
|
@node Defining the Project, Listing Change Sources and Schedulers, Loading the Config File, Configuration
|
||
|
@section Defining the Project
|
||
|
|
||
|
There are a couple of basic settings that you use to tell the buildbot
|
||
|
what project it is working on. This information is used by status
|
||
|
reporters to let users find out more about the codebase being
|
||
|
exercised by this particular Buildbot installation.
|
||
|
|
||
|
@example
|
||
|
c['projectName'] = "Buildbot"
|
||
|
c['projectURL'] = "http://buildbot.sourceforge.net/"
|
||
|
c['buildbotURL'] = "http://localhost:8010/"
|
||
|
@end example
|
||
|
|
||
|
@bcindex c['projectName']
|
||
|
@code{projectName} is a short string will be used to describe the
|
||
|
project that this buildbot is working on. For example, it is used as
|
||
|
the title of the waterfall HTML page.
|
||
|
|
||
|
@bcindex c['projectURL']
|
||
|
@code{projectURL} is a string that gives a URL for the project as a
|
||
|
whole. HTML status displays will show @code{projectName} as a link to
|
||
|
@code{projectURL}, to provide a link from buildbot HTML pages to your
|
||
|
project's home page.
|
||
|
|
||
|
@bcindex c['buildbotURL']
|
||
|
The @code{buildbotURL} string should point to the location where the
|
||
|
buildbot's internal web server (usually the @code{html.Waterfall}
|
||
|
page) is visible. This typically uses the port number set when you
|
||
|
create the @code{Waterfall} object: the buildbot needs your help to
|
||
|
figure out a suitable externally-visible host name.
|
||
|
|
||
|
When status notices are sent to users (either by email or over IRC),
|
||
|
@code{buildbotURL} will be used to create a URL to the specific build
|
||
|
or problem that they are being notified about. It will also be made
|
||
|
available to queriers (over IRC) who want to find out where to get
|
||
|
more information about this buildbot.
|
||
|
|
||
|
|
||
|
@node Listing Change Sources and Schedulers, Setting the slaveport, Defining the Project, Configuration
|
||
|
@section Listing Change Sources and Schedulers
|
||
|
|
||
|
@bcindex c['sources']
|
||
|
The @code{c['sources']} key is a list of ChangeSource
|
||
|
instances@footnote{To be precise, it is a list of objects which all
|
||
|
implement the @code{buildbot.interfaces.IChangeSource} Interface}.
|
||
|
This defines how the buildmaster learns about source code changes.
|
||
|
More information about what goes here is available in @xref{Getting
|
||
|
Source Code Changes}.
|
||
|
|
||
|
@example
|
||
|
import buildbot.changes.pb
|
||
|
c['sources'] = [buildbot.changes.pb.PBChangeSource()]
|
||
|
@end example
|
||
|
|
||
|
@bcindex c['schedulers']
|
||
|
@code{c['schedulers']} is a list of Scheduler instances, each of which
|
||
|
causes builds to be started on a particular set of Builders. The two
|
||
|
basic Scheduler classes you are likely to start with are
|
||
|
@code{Scheduler} and @code{Periodic}, but you can write a customized
|
||
|
subclass to implement more complicated build scheduling.
|
||
|
|
||
|
The docstring for @code{buildbot.scheduler.Scheduler} is the best
|
||
|
place to see all the options that can be used. Type @code{pydoc
|
||
|
buildbot.scheduler.Scheduler} to see it, or look in
|
||
|
@file{buildbot/scheduler.py} directly.
|
||
|
|
||
|
The basic Scheduler takes four arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item name
|
||
|
Each Scheduler must have a unique name. This is only used in status
|
||
|
displays.
|
||
|
|
||
|
@item branch
|
||
|
This Scheduler will pay attention to a single branch, ignoring Changes
|
||
|
that occur on other branches. Setting @code{branch} equal to the
|
||
|
special value of @code{None} means it should only pay attention to the
|
||
|
default branch. Note that @code{None} is a keyword, not a string, so
|
||
|
you want to use @code{None} and not @code{"None"}.
|
||
|
|
||
|
@item treeStableTimer
|
||
|
The Scheduler will wait for this many seconds before starting the
|
||
|
build. If new changes are made during this interval, the timer will be
|
||
|
restarted, so really the build will be started after a change and then
|
||
|
after this many seconds of inactivity.
|
||
|
|
||
|
@item builderNames
|
||
|
When the tree-stable-timer finally expires, builds will be started on
|
||
|
these Builders. Each Builder gets a unique name: these strings must
|
||
|
match.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@example
|
||
|
from buildbot import scheduler
|
||
|
quick = scheduler.Scheduler("quick", None, 60,
|
||
|
["quick-linux", "quick-netbsd"])
|
||
|
full = scheduler.Scheduler("full", None, 5*60,
|
||
|
["full-linux", "full-netbsd", "full-OSX"])
|
||
|
nightly = scheduler.Periodic("nightly", ["full-solaris"], 24*60*60)
|
||
|
c['schedulers'] = [quick, full, nightly]
|
||
|
@end example
|
||
|
|
||
|
In this example, the two ``quick'' builds are triggered 60 seconds
|
||
|
after the tree has been changed. The ``full'' builds do not run quite
|
||
|
so quickly (they wait 5 minutes), so hopefully if the quick builds
|
||
|
fail due to a missing file or really simple typo, the developer can
|
||
|
discover and fix the problem before the full builds are started. Both
|
||
|
Schedulers only pay attention to the default branch: any changes on
|
||
|
other branches are ignored by these Schedulers. Each Scheduler
|
||
|
triggers a different set of Builders, referenced by name.
|
||
|
|
||
|
The third Scheduler in this example just runs the full solaris build
|
||
|
once per day. (note that this Scheduler only lets you control the time
|
||
|
between builds, not the absolute time-of-day of each Build, so this
|
||
|
could easily wind up a ``daily'' or ``every afternoon'' scheduler
|
||
|
depending upon when it was first activated).
|
||
|
|
||
|
@menu
|
||
|
* Scheduler Types::
|
||
|
* Build Dependencies::
|
||
|
@end menu
|
||
|
|
||
|
@node Scheduler Types, Build Dependencies, Listing Change Sources and Schedulers, Listing Change Sources and Schedulers
|
||
|
@subsection Scheduler Types
|
||
|
|
||
|
@slindex buildbot.scheduler.Scheduler
|
||
|
@slindex buildbot.scheduler.AnyBranchScheduler
|
||
|
@slindex buildbot.scheduler.Periodic
|
||
|
@slindex buildbot.scheduler.Nightly
|
||
|
|
||
|
Here is a brief catalog of the available Scheduler types. All these
|
||
|
Schedulers are classes in @code{buildbot.scheduler}, and the
|
||
|
docstrings there are the best source of documentation on the arguments
|
||
|
taken by each one.
|
||
|
|
||
|
@table @code
|
||
|
@item Scheduler
|
||
|
This is the default Scheduler class. It follows exactly one branch,
|
||
|
and starts a configurable tree-stable-timer after each change on that
|
||
|
branch. When the timer expires, it starts a build on some set of
|
||
|
Builders. The Scheduler accepts a @code{fileIsImportant} function
|
||
|
which can be used to ignore some Changes if they do not affect any
|
||
|
``important'' files.
|
||
|
|
||
|
@item AnyBranchScheduler
|
||
|
This scheduler uses a tree-stable-timer like the default one, but
|
||
|
follows multiple branches at once. Each branch gets a separate timer.
|
||
|
|
||
|
@item Dependent
|
||
|
This scheduler watches an ``upstream'' Builder. When that Builder
|
||
|
successfully builds a particular set of Changes, it triggers builds of
|
||
|
the same code on a configured set of ``downstream'' builders. The next
|
||
|
section (@pxref{Build Dependencies}) describes this scheduler in more
|
||
|
detail.
|
||
|
|
||
|
@item Periodic
|
||
|
This simple scheduler just triggers a build every N seconds.
|
||
|
|
||
|
@item Nightly
|
||
|
This is highly configurable periodic build scheduler, which triggers a
|
||
|
build at particular times of day, week, month, or year. The
|
||
|
configuration syntax is very similar to the well-known @code{crontab}
|
||
|
format, in which you provide values for minute, hour, day, and month
|
||
|
(some of which can be wildcards), and a build is triggered whenever
|
||
|
the current time matches the given constraints. This can run a build
|
||
|
every night, every morning, every weekend, alternate Thursdays, on
|
||
|
your boss's birthday, etc.
|
||
|
|
||
|
@item Try_Jobdir / Try_Userpass
|
||
|
This scheduler allows developers to use the @code{buildbot try}
|
||
|
command to trigger builds of code they have not yet committed. See
|
||
|
@ref{try} for complete details.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@node Build Dependencies, , Scheduler Types, Listing Change Sources and Schedulers
|
||
|
@subsection Build Dependencies
|
||
|
|
||
|
@cindex Dependent
|
||
|
@cindex Dependencies
|
||
|
@slindex buildbot.scheduler.Dependent
|
||
|
|
||
|
It is common to wind up with one kind of build which should only be
|
||
|
performed if the same source code was successfully handled by some
|
||
|
other kind of build first. An example might be a packaging step: you
|
||
|
might only want to produce .deb or RPM packages from a tree that was
|
||
|
known to compile successfully and pass all unit tests. You could put
|
||
|
the packaging step in the same Build as the compile and testing steps,
|
||
|
but there might be other reasons to not do this (in particular you
|
||
|
might have several Builders worth of compiles/tests, but only wish to
|
||
|
do the packaging once). Another example is if you want to skip the
|
||
|
``full'' builds after a failing ``quick'' build of the same source
|
||
|
code. Or, if one Build creates a product (like a compiled library)
|
||
|
that is used by some other Builder, you'd want to make sure the
|
||
|
consuming Build is run @emph{after} the producing one.
|
||
|
|
||
|
You can use @code{Dependencies} to express this relationship to the
|
||
|
Buildbot. There is a special kind of Scheduler named
|
||
|
@code{scheduler.Dependent} that will watch an ``upstream'' Scheduler
|
||
|
for builds to complete successfully (on all of its Builders). Each
|
||
|
time that happens, the same source code (i.e. the same
|
||
|
@code{SourceStamp}) will be used to start a new set of builds, on a
|
||
|
different set of Builders. This ``downstream'' scheduler doesn't pay
|
||
|
attention to Changes at all, it only pays attention to the upstream
|
||
|
scheduler.
|
||
|
|
||
|
If the SourceStamp fails on any of the Builders in the upstream set,
|
||
|
the downstream builds will not fire.
|
||
|
|
||
|
@example
|
||
|
from buildbot import scheduler
|
||
|
tests = scheduler.Scheduler("tests", None, 5*60,
|
||
|
["full-linux", "full-netbsd", "full-OSX"])
|
||
|
package = scheduler.Dependent("package",
|
||
|
tests, # upstream scheduler
|
||
|
["make-tarball", "make-deb", "make-rpm"])
|
||
|
c['schedulers'] = [tests, package]
|
||
|
@end example
|
||
|
|
||
|
Note that @code{Dependent}'s upstream scheduler argument is given as a
|
||
|
@code{Scheduler} @emph{instance}, not a name. This makes it impossible
|
||
|
to create circular dependencies in the config file.
|
||
|
|
||
|
|
||
|
@node Setting the slaveport, Buildslave Specifiers, Listing Change Sources and Schedulers, Configuration
|
||
|
@section Setting the slaveport
|
||
|
|
||
|
@bcindex c['slavePortnum']
|
||
|
|
||
|
The buildmaster will listen on a TCP port of your choosing for
|
||
|
connections from buildslaves. It can also use this port for
|
||
|
connections from remote Change Sources, status clients, and debug
|
||
|
tools. This port should be visible to the outside world, and you'll
|
||
|
need to tell your buildslave admins about your choice.
|
||
|
|
||
|
It does not matter which port you pick, as long it is externally
|
||
|
visible, however you should probably use something larger than 1024,
|
||
|
since most operating systems don't allow non-root processes to bind to
|
||
|
low-numbered ports. If your buildmaster is behind a firewall or a NAT
|
||
|
box of some sort, you may have to configure your firewall to permit
|
||
|
inbound connections to this port.
|
||
|
|
||
|
@example
|
||
|
c['slavePortnum'] = 10000
|
||
|
@end example
|
||
|
|
||
|
@code{c['slavePortnum']} is a @emph{strports} specification string,
|
||
|
defined in the @code{twisted.application.strports} module (try
|
||
|
@command{pydoc twisted.application.strports} to get documentation on
|
||
|
the format). This means that you can have the buildmaster listen on a
|
||
|
localhost-only port by doing:
|
||
|
|
||
|
@example
|
||
|
c['slavePortnum'] = "tcp:10000:interface=127.0.0.1"
|
||
|
@end example
|
||
|
|
||
|
This might be useful if you only run buildslaves on the same machine,
|
||
|
and they are all configured to contact the buildmaster at
|
||
|
@code{localhost:10000}.
|
||
|
|
||
|
|
||
|
@node Buildslave Specifiers, Defining Builders, Setting the slaveport, Configuration
|
||
|
@section Buildslave Specifiers
|
||
|
|
||
|
@bcindex c['bots']
|
||
|
|
||
|
The @code{c['bots']} key is a list of known buildslaves. Each
|
||
|
buildslave is defined by a tuple of (slavename, slavepassword). These
|
||
|
are the same two values that need to be provided to the buildslave
|
||
|
administrator when they create the buildslave.
|
||
|
|
||
|
@example
|
||
|
c['bots'] = [('bot-solaris', 'solarispasswd'),
|
||
|
('bot-bsd', 'bsdpasswd'),
|
||
|
]
|
||
|
@end example
|
||
|
|
||
|
The slavenames must be unique, of course. The password exists to
|
||
|
prevent evildoers from interfering with the buildbot by inserting
|
||
|
their own (broken) buildslaves into the system and thus displacing the
|
||
|
real ones.
|
||
|
|
||
|
Buildslaves with an unrecognized slavename or a non-matching password
|
||
|
will be rejected when they attempt to connect, and a message
|
||
|
describing the problem will be put in the log file (see @ref{Logfiles}).
|
||
|
|
||
|
|
||
|
@node Defining Builders, Defining Status Targets, Buildslave Specifiers, Configuration
|
||
|
@section Defining Builders
|
||
|
|
||
|
@bcindex c['builders']
|
||
|
|
||
|
The @code{c['builders']} key is a list of dictionaries which specify
|
||
|
the Builders. The Buildmaster runs a collection of Builders, each of
|
||
|
which handles a single type of build (e.g. full versus quick), on a
|
||
|
single build slave. A Buildbot which makes sure that the latest code
|
||
|
(``HEAD'') compiles correctly across four separate architecture will
|
||
|
have four Builders, each performing the same build but on different
|
||
|
slaves (one per platform).
|
||
|
|
||
|
Each Builder gets a separate column in the waterfall display. In
|
||
|
general, each Builder runs independently (although various kinds of
|
||
|
interlocks can cause one Builder to have an effect on another).
|
||
|
|
||
|
Each Builder specification dictionary has several required keys:
|
||
|
|
||
|
@table @code
|
||
|
@item name
|
||
|
This specifies the Builder's name, which is used in status
|
||
|
reports.
|
||
|
|
||
|
@item slavename
|
||
|
This specifies which buildslave will be used by this Builder.
|
||
|
@code{slavename} must appear in the @code{c['bots']} list. Each
|
||
|
buildslave can accomodate multiple Builders.
|
||
|
|
||
|
@item slavenames
|
||
|
If you provide @code{slavenames} instead of @code{slavename}, you can
|
||
|
give a list of buildslaves which are capable of running this Builder.
|
||
|
If multiple buildslaves are available for any given Builder, you will
|
||
|
have some measure of redundancy: in case one slave goes offline, the
|
||
|
others can still keep the Builder working. In addition, multiple
|
||
|
buildslaves will allow multiple simultaneous builds for the same
|
||
|
Builder, which might be useful if you have a lot of forced or ``try''
|
||
|
builds taking place.
|
||
|
|
||
|
If you use this feature, it is important to make sure that the
|
||
|
buildslaves are all, in fact, capable of running the given build. The
|
||
|
slave hosts should be configured similarly, otherwise you will spend a
|
||
|
lot of time trying (unsuccessfully) to reproduce a failure that only
|
||
|
occurs on some of the buildslaves and not the others. Different
|
||
|
platforms, operating systems, versions of major programs or libraries,
|
||
|
all these things mean you should use separate Builders.
|
||
|
|
||
|
@item builddir
|
||
|
This specifies the name of a subdirectory (under the base directory)
|
||
|
in which everything related to this builder will be placed. On the
|
||
|
buildmaster, this holds build status information. On the buildslave,
|
||
|
this is where checkouts, compiles, and tests are run.
|
||
|
|
||
|
@item factory
|
||
|
This is a @code{buildbot.process.factory.BuildFactory} instance which
|
||
|
controls how the build is performed. Full details appear in their own
|
||
|
chapter, @xref{Build Process}. Parameters like the location of the CVS
|
||
|
repository and the compile-time options used for the build are
|
||
|
generally provided as arguments to the factory's constructor.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
Other optional keys may be set on each Builder:
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item category
|
||
|
If provided, this is a string that identifies a category for the
|
||
|
builder to be a part of. Status clients can limit themselves to a
|
||
|
subset of the available categories. A common use for this is to add
|
||
|
new builders to your setup (for a new module, or for a new buildslave)
|
||
|
that do not work correctly yet and allow you to integrate them with
|
||
|
the active builders. You can put these new builders in a test
|
||
|
category, make your main status clients ignore them, and have only
|
||
|
private status clients pick them up. As soon as they work, you can
|
||
|
move them over to the active category.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node Defining Status Targets, Debug options, Defining Builders, Configuration
|
||
|
@section Defining Status Targets
|
||
|
|
||
|
The Buildmaster has a variety of ways to present build status to
|
||
|
various users. Each such delivery method is a ``Status Target'' object
|
||
|
in the configuration's @code{status} list. To add status targets, you
|
||
|
just append more objects to this list:
|
||
|
|
||
|
@bcindex c['status']
|
||
|
|
||
|
@example
|
||
|
c['status'] = []
|
||
|
|
||
|
from buildbot.status import html
|
||
|
c['status'].append(html.Waterfall(http_port=8010))
|
||
|
|
||
|
from buildbot.status import mail
|
||
|
m = mail.MailNotifier(fromaddr="buildbot@@localhost",
|
||
|
extraRecipients=["builds@@lists.example.com"],
|
||
|
sendToInterestedUsers=False)
|
||
|
c['status'].append(m)
|
||
|
|
||
|
from buildbot.status import words
|
||
|
c['status'].append(words.IRC(host="irc.example.com", nick="bb",
|
||
|
channels=["#example"]))
|
||
|
@end example
|
||
|
|
||
|
Status delivery has its own chapter, @xref{Status Delivery}, in which
|
||
|
all the built-in status targets are documented.
|
||
|
|
||
|
|
||
|
@node Debug options, , Defining Status Targets, Configuration
|
||
|
@section Debug options
|
||
|
|
||
|
|
||
|
@bcindex c['debugPassword']
|
||
|
If you set @code{c['debugPassword']}, then you can connect to the
|
||
|
buildmaster with the diagnostic tool launched by @code{buildbot
|
||
|
debugclient MASTER:PORT}. From this tool, you can reload the config
|
||
|
file, manually force builds, and inject changes, which may be useful
|
||
|
for testing your buildmaster without actually commiting changes to
|
||
|
your repository (or before you have the Change Sources set up). The
|
||
|
debug tool uses the same port number as the slaves do:
|
||
|
@code{c['slavePortnum']}, and is authenticated with this password.
|
||
|
|
||
|
@example
|
||
|
c['debugPassword'] = "debugpassword"
|
||
|
@end example
|
||
|
|
||
|
@bcindex c['manhole']
|
||
|
If you set @code{c['manhole']} to an instance of one of the classes in
|
||
|
@code{buildbot.manhole}, you can telnet or ssh into the buildmaster
|
||
|
and get an interactive Python shell, which may be useful for debugging
|
||
|
buildbot internals. It is probably only useful for buildbot
|
||
|
developers. It exposes full access to the buildmaster's account
|
||
|
(including the ability to modify and delete files), so it should not
|
||
|
be enabled with a weak or easily guessable password.
|
||
|
|
||
|
There are three separate @code{Manhole} classes. Two of them use SSH,
|
||
|
one uses unencrypted telnet. Two of them use a username+password
|
||
|
combination to grant access, one of them uses an SSH-style
|
||
|
@file{authorized_keys} file which contains a list of ssh public keys.
|
||
|
|
||
|
@table @code
|
||
|
@item manhole.AuthorizedKeysManhole
|
||
|
You construct this with the name of a file that contains one SSH
|
||
|
public key per line, just like @file{~/.ssh/authorized_keys}. If you
|
||
|
provide a non-absolute filename, it will be interpreted relative to
|
||
|
the buildmaster's base directory.
|
||
|
|
||
|
@item manhole.PasswordManhole
|
||
|
This one accepts SSH connections but asks for a username and password
|
||
|
when authenticating. It accepts only one such pair.
|
||
|
|
||
|
|
||
|
@item manhole.TelnetManhole
|
||
|
This accepts regular unencrypted telnet connections, and asks for a
|
||
|
username/password pair before providing access. Because this
|
||
|
username/password is transmitted in the clear, and because Manhole
|
||
|
access to the buildmaster is equivalent to granting full shell
|
||
|
privileges to both the buildmaster and all the buildslaves (and to all
|
||
|
accounts which then run code produced by the buildslaves), it is
|
||
|
highly recommended that you use one of the SSH manholes instead.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@example
|
||
|
# some examples:
|
||
|
from buildbot import manhole
|
||
|
c['manhole'] = manhole.AuthorizedKeysManhole(1234, "authorized_keys")
|
||
|
c['manhole'] = manhole.PasswordManhole(1234, "alice", "mysecretpassword")
|
||
|
c['manhole'] = manhole.TelnetManhole(1234, "bob", "snoop_my_password_please")
|
||
|
@end example
|
||
|
|
||
|
The @code{Manhole} instance can be configured to listen on a specific
|
||
|
port. You may wish to have this listening port bind to the loopback
|
||
|
interface (sometimes known as ``lo0'', ``localhost'', or 127.0.0.1) to
|
||
|
restrict access to clients which are running on the same host.
|
||
|
|
||
|
@example
|
||
|
from buildbot.manhole import PasswordManhole
|
||
|
c['manhole'] = PasswordManhole("tcp:9999:interface=127.0.0.1","admin","passwd")
|
||
|
@end example
|
||
|
|
||
|
To have the @code{Manhole} listen on all interfaces, use
|
||
|
@code{"tcp:9999"} or simply 9999. This port specification uses
|
||
|
@code{twisted.application.strports}, so you can make it listen on SSL
|
||
|
or even UNIX-domain sockets if you want.
|
||
|
|
||
|
Note that using any Manhole requires that the TwistedConch package be
|
||
|
installed, and that you be using Twisted version 2.0 or later.
|
||
|
|
||
|
The buildmaster's SSH server will use a different host key than the
|
||
|
normal sshd running on a typical unix host. This will cause the ssh
|
||
|
client to complain about a ``host key mismatch'', because it does not
|
||
|
realize there are two separate servers running on the same host. To
|
||
|
avoid this, use a clause like the following in your @file{.ssh/config}
|
||
|
file:
|
||
|
|
||
|
@example
|
||
|
Host remotehost-buildbot
|
||
|
HostName remotehost
|
||
|
HostKeyAlias remotehost-buildbot
|
||
|
Port 9999
|
||
|
# use 'user' if you use PasswordManhole and your name is not 'admin'.
|
||
|
# if you use AuthorizedKeysManhole, this probably doesn't matter.
|
||
|
User admin
|
||
|
@end example
|
||
|
|
||
|
|
||
|
@node Getting Source Code Changes, Build Process, Configuration, Top
|
||
|
@chapter Getting Source Code Changes
|
||
|
|
||
|
The most common way to use the Buildbot is centered around the idea of
|
||
|
@code{Source Trees}: a directory tree filled with source code of some form
|
||
|
which can be compiled and/or tested. Some projects use languages that don't
|
||
|
involve any compilation step: nevertheless there may be a @code{build} phase
|
||
|
where files are copied or rearranged into a form that is suitable for
|
||
|
installation. Some projects do not have unit tests, and the Buildbot is
|
||
|
merely helping to make sure that the sources can compile correctly. But in
|
||
|
all of these cases, the thing-being-tested is a single source tree.
|
||
|
|
||
|
A Version Control System mantains a source tree, and tells the
|
||
|
buildmaster when it changes. The first step of each Build is typically
|
||
|
to acquire a copy of some version of this tree.
|
||
|
|
||
|
This chapter describes how the Buildbot learns about what Changes have
|
||
|
occurred. For more information on VC systems and Changes, see
|
||
|
@ref{Version Control Systems}.
|
||
|
|
||
|
|
||
|
@menu
|
||
|
* Change Sources::
|
||
|
@end menu
|
||
|
|
||
|
|
||
|
|
||
|
@node Change Sources, , Getting Source Code Changes, Getting Source Code Changes
|
||
|
@section Change Sources
|
||
|
|
||
|
@c TODO: rework this, the one-buildmaster-one-tree thing isn't quite
|
||
|
@c so narrow-minded anymore
|
||
|
|
||
|
Each Buildmaster watches a single source tree. Changes can be provided
|
||
|
by a variety of ChangeSource types, however any given project will
|
||
|
typically have only a single ChangeSource active. This section
|
||
|
provides a description of all available ChangeSource types and
|
||
|
explains how to set up each of them.
|
||
|
|
||
|
There are a variety of ChangeSources available, some of which are
|
||
|
meant to be used in conjunction with other tools to deliver Change
|
||
|
events from the VC repository to the buildmaster.
|
||
|
|
||
|
@itemize @bullet
|
||
|
|
||
|
@item CVSToys
|
||
|
This ChangeSource opens a TCP connection from the buildmaster to a
|
||
|
waiting FreshCVS daemon that lives on the repository machine, and
|
||
|
subscribes to hear about Changes.
|
||
|
|
||
|
@item MaildirSource
|
||
|
This one watches a local maildir-format inbox for email sent out by
|
||
|
the repository when a change is made. When a message arrives, it is
|
||
|
parsed to create the Change object. A variety of parsing functions are
|
||
|
available to accomodate different email-sending tools.
|
||
|
|
||
|
@item PBChangeSource
|
||
|
This ChangeSource listens on a local TCP socket for inbound
|
||
|
connections from a separate tool. Usually, this tool would be run on
|
||
|
the VC repository machine in a commit hook. It is expected to connect
|
||
|
to the TCP socket and send a Change message over the network
|
||
|
connection. The @command{buildbot sendchange} command is one example
|
||
|
of a tool that knows how to send these messages, so you can write a
|
||
|
commit script for your VC system that calls it to deliver the Change.
|
||
|
There are other tools in the contrib/ directory that use the same
|
||
|
protocol.
|
||
|
|
||
|
@end itemize
|
||
|
|
||
|
As a quick guide, here is a list of VC systems and the ChangeSources
|
||
|
that might be useful with them. All of these ChangeSources are in the
|
||
|
@code{buildbot.changes} module.
|
||
|
|
||
|
@table @code
|
||
|
@item CVS
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item freshcvs.FreshCVSSource (connected via TCP to the freshcvs daemon)
|
||
|
@item mail.FCMaildirSource (watching for email sent by a freshcvs daemon)
|
||
|
@item mail.BonsaiMaildirSource (watching for email sent by Bonsai)
|
||
|
@item mail.SyncmailMaildirSource (watching for email sent by syncmail)
|
||
|
@item pb.PBChangeSource (listening for connections from @code{buildbot
|
||
|
sendchange} run in a loginfo script)
|
||
|
@item pb.PBChangeSource (listening for connections from a long-running
|
||
|
@code{contrib/viewcvspoll.py} polling process which examines the ViewCVS
|
||
|
database directly
|
||
|
@end itemize
|
||
|
|
||
|
@item SVN
|
||
|
@itemize @bullet
|
||
|
@item pb.PBChangeSource (listening for connections from
|
||
|
@code{contrib/svn_buildbot.py} run in a postcommit script)
|
||
|
@item pb.PBChangeSource (listening for connections from a long-running
|
||
|
@code{contrib/svn_watcher.py} or @code{contrib/svnpoller.py} polling
|
||
|
process
|
||
|
@item svnpoller.SVNPoller (polling the SVN repository)
|
||
|
@end itemize
|
||
|
|
||
|
@item Darcs
|
||
|
@itemize @bullet
|
||
|
@item pb.PBChangeSource (listening for connections from
|
||
|
@code{contrib/darcs_buildbot.py} in a commit script
|
||
|
@end itemize
|
||
|
|
||
|
@item Mercurial
|
||
|
@itemize @bullet
|
||
|
@item pb.PBChangeSource (listening for connections from
|
||
|
@code{contrib/hg_buildbot.py} run in an 'incoming' hook)
|
||
|
@end itemize
|
||
|
|
||
|
@item Arch/Bazaar
|
||
|
@itemize @bullet
|
||
|
@item pb.PBChangeSource (listening for connections from
|
||
|
@code{contrib/arch_buildbot.py} run in a commit hook)
|
||
|
@end itemize
|
||
|
|
||
|
@end table
|
||
|
|
||
|
All VC systems can be driven by a PBChangeSource and the
|
||
|
@code{buildbot sendchange} tool run from some form of commit script.
|
||
|
If you write an email parsing function, they can also all be driven by
|
||
|
a suitable @code{MaildirSource}.
|
||
|
|
||
|
|
||
|
@menu
|
||
|
* Choosing ChangeSources::
|
||
|
* CVSToys - PBService::
|
||
|
* CVSToys - mail notification::
|
||
|
* Other mail notification ChangeSources::
|
||
|
* PBChangeSource::
|
||
|
* P4Source::
|
||
|
* BonsaiPoller::
|
||
|
* SVNPoller::
|
||
|
@end menu
|
||
|
|
||
|
@node Choosing ChangeSources, CVSToys - PBService, Change Sources, Change Sources
|
||
|
@subsection Choosing ChangeSources
|
||
|
|
||
|
The @code{master.cfg} configuration file has a dictionary key named
|
||
|
@code{BuildmasterConfig['sources']}, which holds a list of
|
||
|
@code{IChangeSource} objects. The config file will typically create an
|
||
|
object from one of the classes described below and stuff it into the
|
||
|
list.
|
||
|
|
||
|
@example
|
||
|
s = FreshCVSSourceNewcred(host="host", port=4519,
|
||
|
user="alice", passwd="secret",
|
||
|
prefix="Twisted")
|
||
|
BuildmasterConfig['sources'] = [s]
|
||
|
@end example
|
||
|
|
||
|
Each source tree has a nominal @code{top}. Each Change has a list of
|
||
|
filenames, which are all relative to this top location. The
|
||
|
ChangeSource is responsible for doing whatever is necessary to
|
||
|
accomplish this. Most sources have a @code{prefix} argument: a partial
|
||
|
pathname which is stripped from the front of all filenames provided to
|
||
|
that @code{ChangeSource}. Files which are outside this sub-tree are
|
||
|
ignored by the changesource: it does not generate Changes for those
|
||
|
files.
|
||
|
|
||
|
|
||
|
@node CVSToys - PBService, CVSToys - mail notification, Choosing ChangeSources, Change Sources
|
||
|
@subsection CVSToys - PBService
|
||
|
|
||
|
@csindex buildbot.changes.freshcvs.FreshCVSSource
|
||
|
|
||
|
The @uref{http://purl.net/net/CVSToys, CVSToys} package provides a
|
||
|
server which runs on the machine that hosts the CVS repository it
|
||
|
watches. It has a variety of ways to distribute commit notifications,
|
||
|
and offers a flexible regexp-based way to filter out uninteresting
|
||
|
changes. One of the notification options is named @code{PBService} and
|
||
|
works by listening on a TCP port for clients. These clients subscribe
|
||
|
to hear about commit notifications.
|
||
|
|
||
|
The buildmaster has a CVSToys-compatible @code{PBService} client built
|
||
|
in. There are two versions of it, one for old versions of CVSToys
|
||
|
(1.0.9 and earlier) which used the @code{oldcred} authentication
|
||
|
framework, and one for newer versions (1.0.10 and later) which use
|
||
|
@code{newcred}. Both are classes in the
|
||
|
@code{buildbot.changes.freshcvs} package.
|
||
|
|
||
|
@code{FreshCVSSourceNewcred} objects are created with the following
|
||
|
parameters:
|
||
|
|
||
|
@table @samp
|
||
|
|
||
|
@item @code{host} and @code{port}
|
||
|
these specify where the CVSToys server can be reached
|
||
|
|
||
|
@item @code{user} and @code{passwd}
|
||
|
these specify the login information for the CVSToys server
|
||
|
(@code{freshcvs}). These must match the server's values, which are
|
||
|
defined in the @code{freshCfg} configuration file (which lives in the
|
||
|
CVSROOT directory of the repository).
|
||
|
|
||
|
@item @code{prefix}
|
||
|
this is the prefix to be found and stripped from filenames delivered
|
||
|
by the CVSToys server. Most projects live in sub-directories of the
|
||
|
main repository, as siblings of the CVSROOT sub-directory, so
|
||
|
typically this prefix is set to that top sub-directory name.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@heading Example
|
||
|
|
||
|
To set up the freshCVS server, add a statement like the following to
|
||
|
your @file{freshCfg} file:
|
||
|
|
||
|
@example
|
||
|
pb = ConfigurationSet([
|
||
|
(None, None, None, PBService(userpass=('foo', 'bar'), port=4519)),
|
||
|
])
|
||
|
@end example
|
||
|
|
||
|
This will announce all changes to a client which connects to port 4519
|
||
|
using a username of 'foo' and a password of 'bar'.
|
||
|
|
||
|
Then add a clause like this to your buildmaster's @file{master.cfg}:
|
||
|
|
||
|
@example
|
||
|
BuildmasterConfig['sources'] = [FreshCVSSource("cvs.example.com", 4519,
|
||
|
"foo", "bar",
|
||
|
prefix="glib/")]
|
||
|
@end example
|
||
|
|
||
|
where "cvs.example.com" is the host that is running the FreshCVS daemon, and
|
||
|
"glib" is the top-level directory (relative to the repository's root) where
|
||
|
all your source code lives. Most projects keep one or more projects in the
|
||
|
same repository (along with CVSROOT/ to hold admin files like loginfo and
|
||
|
freshCfg); the prefix= argument tells the buildmaster to ignore everything
|
||
|
outside that directory, and to strip that common prefix from all pathnames
|
||
|
it handles.
|
||
|
|
||
|
|
||
|
|
||
|
@node CVSToys - mail notification, Other mail notification ChangeSources, CVSToys - PBService, Change Sources
|
||
|
@subsection CVSToys - mail notification
|
||
|
|
||
|
@csindex buildbot.changes.mail.FCMaildirSource
|
||
|
|
||
|
CVSToys also provides a @code{MailNotification} action which will send
|
||
|
email to a list of recipients for each commit. This tends to work
|
||
|
better than using @code{/bin/mail} from within the CVSROOT/loginfo
|
||
|
file directly, as CVSToys will batch together all files changed during
|
||
|
the same CVS invocation, and can provide more information (like
|
||
|
creating a ViewCVS URL for each file changed).
|
||
|
|
||
|
The Buildbot's @code{FCMaildirSource} is a ChangeSource which knows
|
||
|
how to parse these CVSToys messages and turn them into Change objects.
|
||
|
It watches a Maildir for new messages. The usually installation
|
||
|
process looks like:
|
||
|
|
||
|
@enumerate
|
||
|
@item
|
||
|
Create a mailing list, @code{projectname-commits}.
|
||
|
@item
|
||
|
In CVSToys' freshCfg file, use a @code{MailNotification} action to
|
||
|
send commit mail to this mailing list.
|
||
|
@item
|
||
|
Subscribe the buildbot user to the mailing list.
|
||
|
@item
|
||
|
Configure your .qmail or .forward file to deliver these messages into
|
||
|
a maildir.
|
||
|
@item
|
||
|
In the Buildbot's master.cfg file, use a @code{FCMaildirSource} to
|
||
|
watch the maildir for commit messages.
|
||
|
@end enumerate
|
||
|
|
||
|
The @code{FCMaildirSource} is created with two parameters: the
|
||
|
directory name of the maildir root, and the prefix to strip.
|
||
|
|
||
|
@node Other mail notification ChangeSources, PBChangeSource, CVSToys - mail notification, Change Sources
|
||
|
@subsection Other mail notification ChangeSources
|
||
|
|
||
|
@csindex buildbot.changes.mail.SyncmailMaildirSource
|
||
|
@csindex buildbot.changes.mail.BonsaiMaildirSource
|
||
|
|
||
|
There are other types of maildir-watching ChangeSources, which only
|
||
|
differ in the function used to parse the message body.
|
||
|
|
||
|
@code{SyncmailMaildirSource} knows how to parse the message format
|
||
|
used in mail sent by Syncmail.
|
||
|
|
||
|
@code{BonsaiMaildirSource} parses messages sent out by Bonsai.
|
||
|
|
||
|
@node PBChangeSource, P4Source, Other mail notification ChangeSources, Change Sources
|
||
|
@subsection PBChangeSource
|
||
|
|
||
|
@csindex buildbot.changes.pb.PBChangeSource
|
||
|
|
||
|
The last kind of ChangeSource actually listens on a TCP port for
|
||
|
clients to connect and push change notices @emph{into} the
|
||
|
Buildmaster. This is used by the built-in @code{buildbot sendchange}
|
||
|
notification tool, as well as the VC-specific
|
||
|
@file{contrib/svn_buildbot.py} and @file{contrib/arch_buildbot.py}
|
||
|
tools. These tools are run by the repository (in a commit hook
|
||
|
script), and connect to the buildmaster directly each time a file is
|
||
|
comitted. This is also useful for creating new kinds of change sources
|
||
|
that work on a @code{push} model instead of some kind of subscription
|
||
|
scheme, for example a script which is run out of an email .forward
|
||
|
file.
|
||
|
|
||
|
This ChangeSource can be configured to listen on its own TCP port, or
|
||
|
it can share the port that the buildmaster is already using for the
|
||
|
buildslaves to connect. (This is possible because the
|
||
|
@code{PBChangeSource} uses the same protocol as the buildslaves, and
|
||
|
they can be distinguished by the @code{username} attribute used when
|
||
|
the initial connection is established). It might be useful to have it
|
||
|
listen on a different port if, for example, you wanted to establish
|
||
|
different firewall rules for that port. You could allow only the SVN
|
||
|
repository machine access to the @code{PBChangeSource} port, while
|
||
|
allowing only the buildslave machines access to the slave port. Or you
|
||
|
could just expose one port and run everything over it. @emph{Note:
|
||
|
this feature is not yet implemented, the PBChangeSource will always
|
||
|
share the slave port and will always have a @code{user} name of
|
||
|
@code{change}, and a passwd of @code{changepw}. These limitations will
|
||
|
be removed in the future.}.
|
||
|
|
||
|
|
||
|
The @code{PBChangeSource} is created with the following arguments. All
|
||
|
are optional.
|
||
|
|
||
|
@table @samp
|
||
|
@item @code{port}
|
||
|
which port to listen on. If @code{None} (which is the default), it
|
||
|
shares the port used for buildslave connections. @emph{Not
|
||
|
Implemented, always set to @code{None}}.
|
||
|
|
||
|
@item @code{user} and @code{passwd}
|
||
|
The user/passwd account information that the client program must use
|
||
|
to connect. Defaults to @code{change} and @code{changepw}. @emph{Not
|
||
|
Implemented, @code{user} is currently always set to @code{change},
|
||
|
@code{passwd} is always set to @code{changepw}}.
|
||
|
|
||
|
@item @code{prefix}
|
||
|
The prefix to be found and stripped from filenames delivered over the
|
||
|
connection. Any filenames which do not start with this prefix will be
|
||
|
removed. If all the filenames in a given Change are removed, the that
|
||
|
whole Change will be dropped. This string should probably end with a
|
||
|
directory separator.
|
||
|
|
||
|
This is useful for changes coming from version control systems that
|
||
|
represent branches as parent directories within the repository (like
|
||
|
SVN and Perforce). Use a prefix of 'trunk/' or
|
||
|
'project/branches/foobranch/' to only follow one branch and to get
|
||
|
correct tree-relative filenames. Without a prefix, the PBChangeSource
|
||
|
will probably deliver Changes with filenames like @file{trunk/foo.c}
|
||
|
instead of just @file{foo.c}. Of course this also depends upon the
|
||
|
tool sending the Changes in (like @command{buildbot sendchange}) and
|
||
|
what filenames it is delivering: that tool may be filtering and
|
||
|
stripping prefixes at the sending end.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@node P4Source, BonsaiPoller, PBChangeSource, Change Sources
|
||
|
@subsection P4Source
|
||
|
|
||
|
@csindex buildbot.changes.p4poller.P4Source
|
||
|
|
||
|
The @code{P4Source} periodically polls a @uref{http://www.perforce.com/,
|
||
|
Perforce} depot for changes. It accepts the following arguments:
|
||
|
|
||
|
@table @samp
|
||
|
@item @code{p4base}
|
||
|
The base depot path to watch, without the trailing '/...'.
|
||
|
|
||
|
@item @code{p4port}
|
||
|
The Perforce server to connect to (as host:port).
|
||
|
|
||
|
@item @code{p4user}
|
||
|
The Perforce user.
|
||
|
|
||
|
@item @code{p4passwd}
|
||
|
The Perforce password.
|
||
|
|
||
|
@item @code{split_file}
|
||
|
A function that maps a pathname, without the leading @code{p4base}, to a
|
||
|
(branch, filename) tuple. The default just returns (None, branchfile),
|
||
|
which effectively disables branch support. You should supply a function
|
||
|
which understands your repository structure.
|
||
|
|
||
|
@item @code{pollinterval}
|
||
|
How often to poll, in seconds. Defaults to 600 (10 minutes).
|
||
|
|
||
|
@item @code{histmax}
|
||
|
The maximum number of changes to inspect at a time. If more than this
|
||
|
number occur since the last poll, older changes will be silently
|
||
|
ignored.
|
||
|
@end table
|
||
|
|
||
|
@heading Example
|
||
|
|
||
|
This configuration uses the @code{P4PORT}, @code{P4USER}, and @code{P4PASSWD}
|
||
|
specified in the buildmaster's environment. It watches a project in which the
|
||
|
branch name is simply the next path component, and the file is all path
|
||
|
components after.
|
||
|
|
||
|
@example
|
||
|
import buildbot.changes.p4poller
|
||
|
c['sources'].append(p4poller.P4Source(
|
||
|
p4base='//depot/project/',
|
||
|
split_file=lambda branchfile: branchfile.split('/',1)
|
||
|
))
|
||
|
@end example
|
||
|
|
||
|
@node BonsaiPoller, SVNPoller, P4Source, Change Sources
|
||
|
@subsection BonsaiPoller
|
||
|
|
||
|
@csindex buildbot.changes.bonsaipoller.BonsaiPoller
|
||
|
|
||
|
The @code{BonsaiPoller} periodically polls a Bonsai server. This is a
|
||
|
CGI script accessed through a web server that provides information
|
||
|
about a CVS tree, for example the Mozilla bonsai server at
|
||
|
@uref{http://bonsai.mozilla.org}. Bonsai servers are usable by both
|
||
|
humans and machines. In this case, the buildbot's change source forms
|
||
|
a query which asks about any files in the specified branch which have
|
||
|
changed since the last query.
|
||
|
|
||
|
Please take a look at the BonsaiPoller docstring for details about the
|
||
|
arguments it accepts.
|
||
|
|
||
|
|
||
|
@node SVNPoller, , BonsaiPoller, Change Sources
|
||
|
@subsection SVNPoller
|
||
|
|
||
|
@csindex buildbot.changes.svnpoller.SVNPoller
|
||
|
|
||
|
The @code{buildbot.changes.svnpoller.SVNPoller} is a ChangeSource
|
||
|
which periodically polls a @uref{http://subversion.tigris.org/,
|
||
|
Subversion} repository for new revisions, by running the @code{svn
|
||
|
log} command in a subshell. It can watch a single branch or multiple
|
||
|
branches.
|
||
|
|
||
|
@code{SVNPoller} accepts the following arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item svnurl
|
||
|
The base URL path to watch, like
|
||
|
@code{svn://svn.twistedmatrix.com/svn/Twisted/trunk}, or
|
||
|
@code{http://divmod.org/svn/Divmod/}, or even
|
||
|
@code{file:///home/svn/Repository/ProjectA/branches/1.5/}. This must
|
||
|
include the access scheme, the location of the repository (both the
|
||
|
hostname for remote ones, and any additional directory names necessary
|
||
|
to get to the repository), and the sub-path within the repository's
|
||
|
virtual filesystem for the project and branch of interest.
|
||
|
|
||
|
The @code{SVNPoller} will only pay attention to files inside the
|
||
|
subdirectory specified by the complete svnurl.
|
||
|
|
||
|
@item split_file
|
||
|
A function to convert pathnames into (branch, relative_pathname)
|
||
|
tuples. Use this to explain your repository's branch-naming policy to
|
||
|
@code{SVNPoller}. This function must accept a single string and return
|
||
|
a two-entry tuple. There are a few utility functions in
|
||
|
@code{buildbot.changes.svnpoller} that can be used as a
|
||
|
@code{split_file} function, see below for details.
|
||
|
|
||
|
The default value always returns (None, path), which indicates that
|
||
|
all files are on the trunk.
|
||
|
|
||
|
Subclasses of @code{SVNPoller} can override the @code{split_file}
|
||
|
method instead of using the @code{split_file=} argument.
|
||
|
|
||
|
@item svnuser
|
||
|
An optional string parameter. If set, the @code{--user} argument will
|
||
|
be added to all @code{svn} commands. Use this if you have to
|
||
|
authenticate to the svn server before you can do @code{svn info} or
|
||
|
@code{svn log} commands.
|
||
|
|
||
|
@item svnpasswd
|
||
|
Like @code{svnuser}, this will cause a @code{--password} argument to
|
||
|
be passed to all svn commands.
|
||
|
|
||
|
@item pollinterval
|
||
|
How often to poll, in seconds. Defaults to 600 (checking once every 10
|
||
|
minutes). Lower this if you want the buildbot to notice changes
|
||
|
faster, raise it if you want to reduce the network and CPU load on
|
||
|
your svn server. Please be considerate of public SVN repositories by
|
||
|
using a large interval when polling them.
|
||
|
|
||
|
@item histmax
|
||
|
The maximum number of changes to inspect at a time. Every POLLINTERVAL
|
||
|
seconds, the @code{SVNPoller} asks for the last HISTMAX changes and
|
||
|
looks through them for any ones it does not already know about. If
|
||
|
more than HISTMAX revisions have been committed since the last poll,
|
||
|
older changes will be silently ignored. Larger values of histmax will
|
||
|
cause more time and memory to be consumed on each poll attempt.
|
||
|
@code{histmax} defaults to 100.
|
||
|
|
||
|
@item svnbin
|
||
|
This controls the @code{svn} executable to use. If subversion is
|
||
|
installed in a weird place on your system (outside of the
|
||
|
buildmaster's @code{$PATH}), use this to tell @code{SVNPoller} where
|
||
|
to find it. The default value of ``svn'' will almost always be
|
||
|
sufficient.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@heading Branches
|
||
|
|
||
|
Each source file that is tracked by a Subversion repository has a
|
||
|
fully-qualified SVN URL in the following form:
|
||
|
(REPOURL)(PROJECT-plus-BRANCH)(FILEPATH). When you create the
|
||
|
@code{SVNPoller}, you give it a @code{svnurl} value that includes all
|
||
|
of the REPOURL and possibly some portion of the PROJECT-plus-BRANCH
|
||
|
string. The @code{SVNPoller} is responsible for producing Changes that
|
||
|
contain a branch name and a FILEPATH (which is relative to the top of
|
||
|
a checked-out tree). The details of how these strings are split up
|
||
|
depend upon how your repository names its branches.
|
||
|
|
||
|
@subheading PROJECT/BRANCHNAME/FILEPATH repositories
|
||
|
|
||
|
One common layout is to have all the various projects that share a
|
||
|
repository get a single top-level directory each. Then under a given
|
||
|
project's directory, you get two subdirectories, one named ``trunk''
|
||
|
and another named ``branches''. Under ``branches'' you have a bunch of
|
||
|
other directories, one per branch, with names like ``1.5.x'' and
|
||
|
``testing''. It is also common to see directories like ``tags'' and
|
||
|
``releases'' next to ``branches'' and ``trunk''.
|
||
|
|
||
|
For example, the Twisted project has a subversion server on
|
||
|
``svn.twistedmatrix.com'' that hosts several sub-projects. The
|
||
|
repository is available through a SCHEME of ``svn:''. The primary
|
||
|
sub-project is Twisted, of course, with a repository root of
|
||
|
``svn://svn.twistedmatrix.com/svn/Twisted''. Another sub-project is
|
||
|
Informant, with a root of
|
||
|
``svn://svn.twistedmatrix.com/svn/Informant'', etc. Inside any
|
||
|
checked-out Twisted tree, there is a file named bin/trial (which is
|
||
|
used to run unit test suites).
|
||
|
|
||
|
The trunk for Twisted is in
|
||
|
``svn://svn.twistedmatrix.com/svn/Twisted/trunk'', and the
|
||
|
fully-qualified SVN URL for the trunk version of @code{trial} would be
|
||
|
``svn://svn.twistedmatrix.com/svn/Twisted/trunk/bin/trial''. The same
|
||
|
SVNURL for that file on a branch named ``1.5.x'' would be
|
||
|
``svn://svn.twistedmatrix.com/svn/Twisted/branches/1.5.x/bin/trial''.
|
||
|
|
||
|
To set up a @code{SVNPoller} that watches the Twisted trunk (and
|
||
|
nothing else), we would use the following:
|
||
|
|
||
|
@example
|
||
|
from buildbot.changes.svnpoller import SVNPoller
|
||
|
s = SVNPoller("svn://svn.twistedmatrix.com/svn/Twisted/trunk")
|
||
|
c['sources'].append(ss)
|
||
|
@end example
|
||
|
|
||
|
In this case, every Change that our @code{SVNPoller} produces will
|
||
|
have @code{.branch=None}, to indicate that the Change is on the trunk.
|
||
|
No other sub-projects or branches will be tracked.
|
||
|
|
||
|
If we want our ChangeSource to follow multiple branches, we have to do
|
||
|
two things. First we have to change our @code{svnurl=} argument to
|
||
|
watch more than just ``.../Twisted/trunk''. We will set it to
|
||
|
``.../Twisted'' so that we'll see both the trunk and all the branches.
|
||
|
Second, we have to tell @code{SVNPoller} how to split the
|
||
|
(PROJECT-plus-BRANCH)(FILEPATH) strings it gets from the repository
|
||
|
out into (BRANCH) and (FILEPATH) pairs.
|
||
|
|
||
|
We do the latter by providing a ``split_file'' function. This function
|
||
|
is responsible for splitting something like
|
||
|
``branches/1.5.x/bin/trial'' into @code{branch}=''branches/1.5.x'' and
|
||
|
@code{filepath}=''bin/trial''. This function is always given a string
|
||
|
that names a file relative to the subdirectory pointed to by the
|
||
|
@code{SVNPoller}'s @code{svnurl=} argument. It is expected to return a
|
||
|
(BRANCHNAME, FILEPATH) tuple (in which FILEPATH is relative to the
|
||
|
branch indicated), or None to indicate that the file is outside any
|
||
|
project of interest.
|
||
|
|
||
|
(note that we want to see ``branches/1.5.x'' rather than just
|
||
|
``1.5.x'' because when we perform the SVN checkout, we will probably
|
||
|
append the branch name to the baseURL, which requires that we keep the
|
||
|
``branches'' component in there. Other VC schemes use a different
|
||
|
approach towards branches and may not require this artifact.)
|
||
|
|
||
|
If your repository uses this same PROJECT/BRANCH/FILEPATH naming
|
||
|
scheme, the following function will work:
|
||
|
|
||
|
@example
|
||
|
def split_file_branches(path):
|
||
|
pieces = path.split('/')
|
||
|
if pieces[0] == 'trunk':
|
||
|
return (None, '/'.join(pieces[1:]))
|
||
|
elif pieces[0] == 'branches':
|
||
|
return ('/'.join(pieces[0:2]),
|
||
|
'/'.join(pieces[2:]))
|
||
|
else:
|
||
|
return None
|
||
|
@end example
|
||
|
|
||
|
This function is provided as
|
||
|
@code{buildbot.changes.svnpoller.split_file_branches} for your
|
||
|
convenience. So to have our Twisted-watching @code{SVNPoller} follow
|
||
|
multiple branches, we would use this:
|
||
|
|
||
|
@example
|
||
|
from buildbot.changes.svnpoller import SVNPoller, split_file_branches
|
||
|
s = SVNPoller("svn://svn.twistedmatrix.com/svn/Twisted",
|
||
|
split_file=split_file_branches)
|
||
|
c['sources'].append(ss)
|
||
|
@end example
|
||
|
|
||
|
Changes for all sorts of branches (with names like ``branches/1.5.x'',
|
||
|
and None to indicate the trunk) will be delivered to the Schedulers.
|
||
|
Each Scheduler is then free to use or ignore each branch as it sees
|
||
|
fit.
|
||
|
|
||
|
@subheading BRANCHNAME/PROJECT/FILEPATH repositories
|
||
|
|
||
|
Another common way to organize a Subversion repository is to put the
|
||
|
branch name at the top, and the projects underneath. This is
|
||
|
especially frequent when there are a number of related sub-projects
|
||
|
that all get released in a group.
|
||
|
|
||
|
For example, Divmod.org hosts a project named ``Nevow'' as well as one
|
||
|
named ``Quotient''. In a checked-out Nevow tree there is a directory
|
||
|
named ``formless'' that contains a python source file named
|
||
|
``webform.py''. This repository is accessible via webdav (and thus
|
||
|
uses an ``http:'' scheme) through the divmod.org hostname. There are
|
||
|
many branches in this repository, and they use a
|
||
|
(BRANCHNAME)/(PROJECT) naming policy.
|
||
|
|
||
|
The fully-qualified SVN URL for the trunk version of webform.py is
|
||
|
@code{http://divmod.org/svn/Divmod/trunk/Nevow/formless/webform.py}.
|
||
|
You can do an @code{svn co} with that URL and get a copy of the latest
|
||
|
version. The 1.5.x branch version of this file would have a URL of
|
||
|
@code{http://divmod.org/svn/Divmod/branches/1.5.x/Nevow/formless/webform.py}.
|
||
|
The whole Nevow trunk would be checked out with
|
||
|
@code{http://divmod.org/svn/Divmod/trunk/Nevow}, while the Quotient
|
||
|
trunk would be checked out using
|
||
|
@code{http://divmod.org/svn/Divmod/trunk/Quotient}.
|
||
|
|
||
|
Now suppose we want to have an @code{SVNPoller} that only cares about
|
||
|
the Nevow trunk. This case looks just like the PROJECT/BRANCH layout
|
||
|
described earlier:
|
||
|
|
||
|
@example
|
||
|
from buildbot.changes.svnpoller import SVNPoller
|
||
|
s = SVNPoller("http://divmod.org/svn/Divmod/trunk/Nevow")
|
||
|
c['sources'].append(ss)
|
||
|
@end example
|
||
|
|
||
|
But what happens when we want to track multiple Nevow branches? We
|
||
|
have to point our @code{svnurl=} high enough to see all those
|
||
|
branches, but we also don't want to include Quotient changes (since
|
||
|
we're only building Nevow). To accomplish this, we must rely upon the
|
||
|
@code{split_file} function to help us tell the difference between
|
||
|
files that belong to Nevow and those that belong to Quotient, as well
|
||
|
as figuring out which branch each one is on.
|
||
|
|
||
|
@example
|
||
|
from buildbot.changes.svnpoller import SVNPoller
|
||
|
s = SVNPoller("http://divmod.org/svn/Divmod",
|
||
|
split_file=my_file_splitter)
|
||
|
c['sources'].append(ss)
|
||
|
@end example
|
||
|
|
||
|
The @code{my_file_splitter} function will be called with
|
||
|
repository-relative pathnames like:
|
||
|
|
||
|
@table @code
|
||
|
@item trunk/Nevow/formless/webform.py
|
||
|
This is a Nevow file, on the trunk. We want the Change that includes this
|
||
|
to see a filename of @code{formless/webform.py"}, and a branch of None
|
||
|
|
||
|
@item branches/1.5.x/Nevow/formless/webform.py
|
||
|
This is a Nevow file, on a branch. We want to get
|
||
|
branch=''branches/1.5.x'' and filename=''formless/webform.py''.
|
||
|
|
||
|
@item trunk/Quotient/setup.py
|
||
|
This is a Quotient file, so we want to ignore it by having
|
||
|
@code{my_file_splitter} return None.
|
||
|
|
||
|
@item branches/1.5.x/Quotient/setup.py
|
||
|
This is also a Quotient file, which should be ignored.
|
||
|
@end table
|
||
|
|
||
|
The following definition for @code{my_file_splitter} will do the job:
|
||
|
|
||
|
@example
|
||
|
def my_file_splitter(path):
|
||
|
pieces = path.split('/')
|
||
|
if pieces[0] == 'trunk':
|
||
|
branch = None
|
||
|
pieces.pop(0) # remove 'trunk'
|
||
|
elif pieces[0] == 'branches':
|
||
|
pieces.pop(0) # remove 'branches'
|
||
|
# grab branch name
|
||
|
branch = 'branches/' + pieces.pop(0)
|
||
|
else:
|
||
|
return None # something weird
|
||
|
projectname = pieces.pop(0)
|
||
|
if projectname != 'Nevow':
|
||
|
return None # wrong project
|
||
|
return (branch, '/'.join(pieces))
|
||
|
@end example
|
||
|
|
||
|
|
||
|
@node Build Process, Status Delivery, Getting Source Code Changes, Top
|
||
|
@chapter Build Process
|
||
|
|
||
|
A @code{Build} object is responsible for actually performing a build.
|
||
|
It gets access to a remote @code{SlaveBuilder} where it may run
|
||
|
commands, and a @code{BuildStatus} object where it must emit status
|
||
|
events. The @code{Build} is created by the Builder's
|
||
|
@code{BuildFactory}.
|
||
|
|
||
|
The default @code{Build} class is made up of a fixed sequence of
|
||
|
@code{BuildSteps}, executed one after another until all are complete
|
||
|
(or one of them indicates that the build should be halted early). The
|
||
|
default @code{BuildFactory} creates instances of this @code{Build}
|
||
|
class with a list of @code{BuildSteps}, so the basic way to configure
|
||
|
the build is to provide a list of @code{BuildSteps} to your
|
||
|
@code{BuildFactory}.
|
||
|
|
||
|
More complicated @code{Build} subclasses can make other decisions:
|
||
|
execute some steps only if certain files were changed, or if certain
|
||
|
previous steps passed or failed. The base class has been written to
|
||
|
allow users to express basic control flow without writing code, but
|
||
|
you can always subclass and customize to achieve more specialized
|
||
|
behavior.
|
||
|
|
||
|
@menu
|
||
|
* Build Steps::
|
||
|
* Interlocks::
|
||
|
* Build Factories::
|
||
|
@end menu
|
||
|
|
||
|
@node Build Steps, Interlocks, Build Process, Build Process
|
||
|
@section Build Steps
|
||
|
|
||
|
@code{BuildStep}s are usually specified in the buildmaster's
|
||
|
configuration file, in a list of ``step specifications'' that is used
|
||
|
to create the @code{BuildFactory}. These ``step specifications'' are
|
||
|
not actual steps, but rather a tuple of the @code{BuildStep} subclass
|
||
|
to be created and a dictionary of arguments. (the actual
|
||
|
@code{BuildStep} instances are not created until the Build is started,
|
||
|
so that each Build gets an independent copy of each BuildStep). The
|
||
|
preferred way to create these step specifications is with the
|
||
|
@code{BuildFactory}'s @code{addStep} method:
|
||
|
|
||
|
@example
|
||
|
from buildbot.steps import source, shell
|
||
|
from buildbot.process import factory
|
||
|
|
||
|
f = factory.BuildFactory()
|
||
|
f.addStep(source.SVN, svnurl="http://svn.example.org/Trunk/")
|
||
|
f.addStep(shell.ShellCommand, command=["make", "all"])
|
||
|
f.addStep(shell.ShellCommand, command=["make", "test"])
|
||
|
@end example
|
||
|
|
||
|
The rest of this section lists all the standard BuildStep objects
|
||
|
available for use in a Build, and the parameters which can be used to
|
||
|
control each.
|
||
|
|
||
|
@menu
|
||
|
* Common Parameters::
|
||
|
* Source Checkout::
|
||
|
* ShellCommand::
|
||
|
* Simple ShellCommand Subclasses::
|
||
|
* Python BuildSteps::
|
||
|
* Transferring Files::
|
||
|
* Writing New BuildSteps::
|
||
|
@end menu
|
||
|
|
||
|
@node Common Parameters, Source Checkout, Build Steps, Build Steps
|
||
|
@subsection Common Parameters
|
||
|
|
||
|
The standard @code{Build} runs a series of @code{BuildStep}s in order,
|
||
|
only stopping when it runs out of steps or if one of them requests
|
||
|
that the build be halted. It collects status information from each one
|
||
|
to create an overall build status (of SUCCESS, WARNINGS, or FAILURE).
|
||
|
|
||
|
All BuildSteps accept some common parameters. Some of these control
|
||
|
how their individual status affects the overall build. Others are used
|
||
|
to specify which @code{Locks} (see @pxref{Interlocks}) should be
|
||
|
acquired before allowing the step to run.
|
||
|
|
||
|
Arguments common to all @code{BuildStep} subclasses:
|
||
|
|
||
|
|
||
|
@table @code
|
||
|
@item name
|
||
|
the name used to describe the step on the status display. It is also
|
||
|
used to give a name to any LogFiles created by this step.
|
||
|
|
||
|
@item haltOnFailure
|
||
|
if True, a FAILURE of this build step will cause the build to halt
|
||
|
immediately with an overall result of FAILURE.
|
||
|
|
||
|
@item flunkOnWarnings
|
||
|
when True, a WARNINGS or FAILURE of this build step will mark the
|
||
|
overall build as FAILURE. The remaining steps will still be executed.
|
||
|
|
||
|
@item flunkOnFailure
|
||
|
when True, a FAILURE of this build step will mark the overall build as
|
||
|
a FAILURE. The remaining steps will still be executed.
|
||
|
|
||
|
@item warnOnWarnings
|
||
|
when True, a WARNINGS or FAILURE of this build step will mark the
|
||
|
overall build as having WARNINGS. The remaining steps will still be
|
||
|
executed.
|
||
|
|
||
|
@item warnOnFailure
|
||
|
when True, a FAILURE of this build step will mark the overall build as
|
||
|
having WARNINGS. The remaining steps will still be executed.
|
||
|
|
||
|
@item locks
|
||
|
a list of Locks (instances of @code{buildbot.locks.SlaveLock} or
|
||
|
@code{buildbot.locks.MasterLock}) that should be acquired before
|
||
|
starting this Step. The Locks will be released when the step is
|
||
|
complete. Note that this is a list of actual Lock instances, not
|
||
|
names. Also note that all Locks must have unique names.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node Source Checkout, ShellCommand, Common Parameters, Build Steps
|
||
|
@subsection Source Checkout
|
||
|
|
||
|
The first step of any build is typically to acquire the source code
|
||
|
from which the build will be performed. There are several classes to
|
||
|
handle this, one for each of the different source control system that
|
||
|
Buildbot knows about. For a description of how Buildbot treats source
|
||
|
control in general, see @ref{Version Control Systems}.
|
||
|
|
||
|
All source checkout steps accept some common parameters to control how
|
||
|
they get the sources and where they should be placed. The remaining
|
||
|
per-VC-system parameters are mostly to specify where exactly the
|
||
|
sources are coming from.
|
||
|
|
||
|
@table @code
|
||
|
@item mode
|
||
|
|
||
|
a string describing the kind of VC operation that is desired. Defaults
|
||
|
to @code{update}.
|
||
|
|
||
|
@table @code
|
||
|
@item update
|
||
|
specifies that the CVS checkout/update should be performed directly
|
||
|
into the workdir. Each build is performed in the same directory,
|
||
|
allowing for incremental builds. This minimizes disk space, bandwidth,
|
||
|
and CPU time. However, it may encounter problems if the build process
|
||
|
does not handle dependencies properly (sometimes you must do a ``clean
|
||
|
build'' to make sure everything gets compiled), or if source files are
|
||
|
deleted but generated files can influence test behavior (e.g. python's
|
||
|
.pyc files), or when source directories are deleted but generated
|
||
|
files prevent CVS from removing them. Builds ought to be correct
|
||
|
regardless of whether they are done ``from scratch'' or incrementally,
|
||
|
but it is useful to test both kinds: this mode exercises the
|
||
|
incremental-build style.
|
||
|
|
||
|
@item copy
|
||
|
specifies that the CVS workspace should be maintained in a separate
|
||
|
directory (called the 'copydir'), using checkout or update as
|
||
|
necessary. For each build, a new workdir is created with a copy of the
|
||
|
source tree (rm -rf workdir; cp -r copydir workdir). This doubles the
|
||
|
disk space required, but keeps the bandwidth low (update instead of a
|
||
|
full checkout). A full 'clean' build is performed each time. This
|
||
|
avoids any generated-file build problems, but is still occasionally
|
||
|
vulnerable to CVS problems such as a repository being manually
|
||
|
rearranged, causing CVS errors on update which are not an issue with a
|
||
|
full checkout.
|
||
|
|
||
|
@c TODO: something is screwy about this, revisit. Is it the source
|
||
|
@c directory or the working directory that is deleted each time?
|
||
|
|
||
|
@item clobber
|
||
|
specifes that the working directory should be deleted each time,
|
||
|
necessitating a full checkout for each build. This insures a clean
|
||
|
build off a complete checkout, avoiding any of the problems described
|
||
|
above. This mode exercises the ``from-scratch'' build style.
|
||
|
|
||
|
@item export
|
||
|
this is like @code{clobber}, except that the 'cvs export' command is
|
||
|
used to create the working directory. This command removes all CVS
|
||
|
metadata files (the CVS/ directories) from the tree, which is
|
||
|
sometimes useful for creating source tarballs (to avoid including the
|
||
|
metadata in the tar file).
|
||
|
@end table
|
||
|
|
||
|
@item workdir
|
||
|
like all Steps, this indicates the directory where the build will take
|
||
|
place. Source Steps are special in that they perform some operations
|
||
|
outside of the workdir (like creating the workdir itself).
|
||
|
|
||
|
@item alwaysUseLatest
|
||
|
if True, bypass the usual ``update to the last Change'' behavior, and
|
||
|
always update to the latest changes instead.
|
||
|
|
||
|
@item retry
|
||
|
If set, this specifies a tuple of @code{(delay, repeats)} which means
|
||
|
that when a full VC checkout fails, it should be retried up to
|
||
|
@var{repeats} times, waiting @var{delay} seconds between attempts. If
|
||
|
you don't provide this, it defaults to @code{None}, which means VC
|
||
|
operations should not be retried. This is provided to make life easier
|
||
|
for buildslaves which are stuck behind poor network connections.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
My habit as a developer is to do a @code{cvs update} and @code{make} each
|
||
|
morning. Problems can occur, either because of bad code being checked in, or
|
||
|
by incomplete dependencies causing a partial rebuild to fail where a
|
||
|
complete from-scratch build might succeed. A quick Builder which emulates
|
||
|
this incremental-build behavior would use the @code{mode='update'}
|
||
|
setting.
|
||
|
|
||
|
On the other hand, other kinds of dependency problems can cause a clean
|
||
|
build to fail where a partial build might succeed. This frequently results
|
||
|
from a link step that depends upon an object file that was removed from a
|
||
|
later version of the tree: in the partial tree, the object file is still
|
||
|
around (even though the Makefiles no longer know how to create it).
|
||
|
|
||
|
``official'' builds (traceable builds performed from a known set of
|
||
|
source revisions) are always done as clean builds, to make sure it is
|
||
|
not influenced by any uncontrolled factors (like leftover files from a
|
||
|
previous build). A ``full'' Builder which behaves this way would want
|
||
|
to use the @code{mode='clobber'} setting.
|
||
|
|
||
|
Each VC system has a corresponding source checkout class: their
|
||
|
arguments are described on the following pages.
|
||
|
|
||
|
|
||
|
@menu
|
||
|
* CVS::
|
||
|
* SVN::
|
||
|
* Darcs::
|
||
|
* Mercurial::
|
||
|
* Arch::
|
||
|
* Bazaar::
|
||
|
* P4::
|
||
|
@end menu
|
||
|
|
||
|
@node CVS, SVN, Source Checkout, Source Checkout
|
||
|
@subsubsection CVS
|
||
|
|
||
|
@cindex CVS Checkout
|
||
|
@bsindex buildbot.steps.source.CVS
|
||
|
|
||
|
|
||
|
The @code{CVS} build step performs a @uref{http://www.nongnu.org/cvs/,
|
||
|
CVS} checkout or update. It takes the following arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item cvsroot
|
||
|
(required): specify the CVSROOT value, which points to a CVS
|
||
|
repository, probably on a remote machine. For example, the cvsroot
|
||
|
value you would use to get a copy of the Buildbot source code is
|
||
|
@code{:pserver:anonymous@@cvs.sourceforge.net:/cvsroot/buildbot}
|
||
|
|
||
|
@item cvsmodule
|
||
|
(required): specify the cvs @code{module}, which is generally a
|
||
|
subdirectory of the CVSROOT. The cvsmodule for the Buildbot source
|
||
|
code is @code{buildbot}.
|
||
|
|
||
|
@item branch
|
||
|
a string which will be used in a @code{-r} argument. This is most
|
||
|
useful for specifying a branch to work on. Defaults to @code{HEAD}.
|
||
|
|
||
|
@item global_options
|
||
|
a list of flags to be put before the verb in the CVS command.
|
||
|
|
||
|
@item checkoutDelay
|
||
|
if set, the number of seconds to put between the timestamp of the last
|
||
|
known Change and the value used for the @code{-D} option. Defaults to
|
||
|
half of the parent Build's treeStableTimer.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node SVN, Darcs, CVS, Source Checkout
|
||
|
@subsubsection SVN
|
||
|
|
||
|
@cindex SVN Checkout
|
||
|
@bsindex buildbot.steps.source.SVN
|
||
|
|
||
|
|
||
|
The @code{SVN} build step performs a
|
||
|
@uref{http://subversion.tigris.org, Subversion} checkout or update.
|
||
|
There are two basic ways of setting up the checkout step, depending
|
||
|
upon whether you are using multiple branches or not.
|
||
|
|
||
|
If all of your builds use the same branch, then you should create the
|
||
|
@code{SVN} step with the @code{svnurl} argument:
|
||
|
|
||
|
@table @code
|
||
|
@item svnurl
|
||
|
(required): this specifies the @code{URL} argument that will be given
|
||
|
to the @code{svn checkout} command. It dictates both where the
|
||
|
repository is located and which sub-tree should be extracted. In this
|
||
|
respect, it is like a combination of the CVS @code{cvsroot} and
|
||
|
@code{cvsmodule} arguments. For example, if you are using a remote
|
||
|
Subversion repository which is accessible through HTTP at a URL of
|
||
|
@code{http://svn.example.com/repos}, and you wanted to check out the
|
||
|
@code{trunk/calc} sub-tree, you would use
|
||
|
@code{svnurl="http://svn.example.com/repos/trunk/calc"} as an argument
|
||
|
to your @code{SVN} step.
|
||
|
@end table
|
||
|
|
||
|
If, on the other hand, you are building from multiple branches, then
|
||
|
you should create the @code{SVN} step with the @code{baseURL} and
|
||
|
@code{defaultBranch} arguments instead:
|
||
|
|
||
|
@table @code
|
||
|
@item baseURL
|
||
|
(required): this specifies the base repository URL, to which a branch
|
||
|
name will be appended. It should probably end in a slash.
|
||
|
|
||
|
@item defaultBranch
|
||
|
this specifies the name of the branch to use when a Build does not
|
||
|
provide one of its own. This will be appended to @code{baseURL} to
|
||
|
create the string that will be passed to the @code{svn checkout}
|
||
|
command.
|
||
|
@end table
|
||
|
|
||
|
If you are using branches, you must also make sure your
|
||
|
@code{ChangeSource} will report the correct branch names.
|
||
|
|
||
|
@heading branch example
|
||
|
|
||
|
Let's suppose that the ``MyProject'' repository uses branches for the
|
||
|
trunk, for various users' individual development efforts, and for
|
||
|
several new features that will require some amount of work (involving
|
||
|
multiple developers) before they are ready to merge onto the trunk.
|
||
|
Such a repository might be organized as follows:
|
||
|
|
||
|
@example
|
||
|
svn://svn.example.org/MyProject/trunk
|
||
|
svn://svn.example.org/MyProject/branches/User1/foo
|
||
|
svn://svn.example.org/MyProject/branches/User1/bar
|
||
|
svn://svn.example.org/MyProject/branches/User2/baz
|
||
|
svn://svn.example.org/MyProject/features/newthing
|
||
|
svn://svn.example.org/MyProject/features/otherthing
|
||
|
@end example
|
||
|
|
||
|
Further assume that we want the Buildbot to run tests against the
|
||
|
trunk and against all the feature branches (i.e., do a
|
||
|
checkout/compile/build of branch X when a file has been changed on
|
||
|
branch X, when X is in the set [trunk, features/newthing,
|
||
|
features/otherthing]). We do not want the Buildbot to automatically
|
||
|
build any of the user branches, but it should be willing to build a
|
||
|
user branch when explicitly requested (most likely by the user who
|
||
|
owns that branch).
|
||
|
|
||
|
There are three things that need to be set up to accomodate this
|
||
|
system. The first is a ChangeSource that is capable of identifying the
|
||
|
branch which owns any given file. This depends upon a user-supplied
|
||
|
function, in an external program that runs in the SVN commit hook and
|
||
|
connects to the buildmaster's @code{PBChangeSource} over a TCP
|
||
|
connection. (you can use the ``@code{buildbot sendchange}'' utility
|
||
|
for this purpose, but you will still need an external program to
|
||
|
decide what value should be passed to the @code{--branch=} argument).
|
||
|
For example, a change to a file with the SVN url of
|
||
|
``svn://svn.example.org/MyProject/features/newthing/src/foo.c'' should
|
||
|
be broken down into a Change instance with
|
||
|
@code{branch='features/newthing'} and @code{file='src/foo.c'}.
|
||
|
|
||
|
The second piece is an @code{AnyBranchScheduler} which will pay
|
||
|
attention to the desired branches. It will not pay attention to the
|
||
|
user branches, so it will not automatically start builds in response
|
||
|
to changes there. The AnyBranchScheduler class requires you to
|
||
|
explicitly list all the branches you want it to use, but it would not
|
||
|
be difficult to write a subclass which used
|
||
|
@code{branch.startswith('features/'} to remove the need for this
|
||
|
explicit list. Or, if you want to build user branches too, you can use
|
||
|
AnyBranchScheduler with @code{branches=None} to indicate that you want
|
||
|
it to pay attention to all branches.
|
||
|
|
||
|
The third piece is an @code{SVN} checkout step that is configured to
|
||
|
handle the branches correctly, with a @code{baseURL} value that
|
||
|
matches the way the ChangeSource splits each file's URL into base,
|
||
|
branch, and file.
|
||
|
|
||
|
@example
|
||
|
from buildbot.changes.pb import PBChangeSource
|
||
|
from buildbot.scheduler import AnyBranchScheduler
|
||
|
from buildbot.process import source, factory
|
||
|
from buildbot.steps import source, shell
|
||
|
|
||
|
c['sources'] = [PBChangeSource()]
|
||
|
s1 = AnyBranchScheduler('main',
|
||
|
['trunk', 'features/newthing', 'features/otherthing'],
|
||
|
10*60, ['test-i386', 'test-ppc'])
|
||
|
c['schedulers'] = [s1]
|
||
|
|
||
|
f = factory.BuildFactory()
|
||
|
f.addStep(source.SVN, mode='update',
|
||
|
baseURL='svn://svn.example.org/MyProject/',
|
||
|
defaultBranch='trunk')
|
||
|
f.addStep(shell.Compile, command="make all")
|
||
|
f.addStep(shell.Test, command="make test")
|
||
|
|
||
|
c['builders'] = [
|
||
|
@{'name':'test-i386', 'slavename':'bot-i386', 'builddir':'test-i386',
|
||
|
'factory':f @},
|
||
|
@{'name':'test-ppc', 'slavename':'bot-ppc', 'builddir':'test-ppc',
|
||
|
'factory':f @},
|
||
|
]
|
||
|
@end example
|
||
|
|
||
|
In this example, when a change arrives with a @code{branch} attribute
|
||
|
of ``trunk'', the resulting build will have an SVN step that
|
||
|
concatenates ``svn://svn.example.org/MyProject/'' (the baseURL) with
|
||
|
``trunk'' (the branch name) to get the correct svn command. If the
|
||
|
``newthing'' branch has a change to ``src/foo.c'', then the SVN step
|
||
|
will concatenate ``svn://svn.example.org/MyProject/'' with
|
||
|
``features/newthing'' to get the svnurl for checkout.
|
||
|
|
||
|
@node Darcs, Mercurial, SVN, Source Checkout
|
||
|
@subsubsection Darcs
|
||
|
|
||
|
@cindex Darcs Checkout
|
||
|
@bsindex buildbot.steps.source.Darcs
|
||
|
|
||
|
|
||
|
The @code{Darcs} build step performs a
|
||
|
@uref{http://abridgegame.org/darcs/, Darcs} checkout or update.
|
||
|
|
||
|
Like @xref{SVN}, this step can either be configured to always check
|
||
|
out a specific tree, or set up to pull from a particular branch that
|
||
|
gets specified separately for each build. Also like SVN, the
|
||
|
repository URL given to Darcs is created by concatenating a
|
||
|
@code{baseURL} with the branch name, and if no particular branch is
|
||
|
requested, it uses a @code{defaultBranch}. The only difference in
|
||
|
usage is that each potential Darcs repository URL must point to a
|
||
|
fully-fledged repository, whereas SVN URLs usually point to sub-trees
|
||
|
of the main Subversion repository. In other words, doing an SVN
|
||
|
checkout of @code{baseURL} is legal, but silly, since you'd probably
|
||
|
wind up with a copy of every single branch in the whole repository.
|
||
|
Doing a Darcs checkout of @code{baseURL} is just plain wrong, since
|
||
|
the parent directory of a collection of Darcs repositories is not
|
||
|
itself a valid repository.
|
||
|
|
||
|
The Darcs step takes the following arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item repourl
|
||
|
(required unless @code{baseURL} is provided): the URL at which the
|
||
|
Darcs source repository is available.
|
||
|
|
||
|
@item baseURL
|
||
|
(required unless @code{repourl} is provided): the base repository URL,
|
||
|
to which a branch name will be appended. It should probably end in a
|
||
|
slash.
|
||
|
|
||
|
@item defaultBranch
|
||
|
(allowed if and only if @code{baseURL} is provided): this specifies
|
||
|
the name of the branch to use when a Build does not provide one of its
|
||
|
own. This will be appended to @code{baseURL} to create the string that
|
||
|
will be passed to the @code{darcs get} command.
|
||
|
@end table
|
||
|
|
||
|
@node Mercurial, Arch, Darcs, Source Checkout
|
||
|
@subsubsection Mercurial
|
||
|
|
||
|
@cindex Mercurial Checkout
|
||
|
@bsindex buildbot.steps.source.Mercurial
|
||
|
|
||
|
|
||
|
The @code{Mercurial} build step performs a
|
||
|
@uref{http://selenic.com/mercurial, Mercurial} (aka ``hg'') checkout
|
||
|
or update.
|
||
|
|
||
|
Branches are handled just like @xref{Darcs}.
|
||
|
|
||
|
The Mercurial step takes the following arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item repourl
|
||
|
(required unless @code{baseURL} is provided): the URL at which the
|
||
|
Mercurial source repository is available.
|
||
|
|
||
|
@item baseURL
|
||
|
(required unless @code{repourl} is provided): the base repository URL,
|
||
|
to which a branch name will be appended. It should probably end in a
|
||
|
slash.
|
||
|
|
||
|
@item defaultBranch
|
||
|
(allowed if and only if @code{baseURL} is provided): this specifies
|
||
|
the name of the branch to use when a Build does not provide one of its
|
||
|
own. This will be appended to @code{baseURL} to create the string that
|
||
|
will be passed to the @code{hg clone} command.
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node Arch, Bazaar, Mercurial, Source Checkout
|
||
|
@subsubsection Arch
|
||
|
|
||
|
@cindex Arch Checkout
|
||
|
@bsindex buildbot.steps.source.Arch
|
||
|
|
||
|
|
||
|
The @code{Arch} build step performs an @uref{http://gnuarch.org/,
|
||
|
Arch} checkout or update using the @code{tla} client. It takes the
|
||
|
following arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item url
|
||
|
(required): this specifies the URL at which the Arch source archive is
|
||
|
available.
|
||
|
|
||
|
@item version
|
||
|
(required): this specifies which ``development line'' (like a branch)
|
||
|
should be used. This provides the default branch name, but individual
|
||
|
builds may specify a different one.
|
||
|
|
||
|
@item archive
|
||
|
(optional): Each repository knows its own archive name. If this
|
||
|
parameter is provided, it must match the repository's archive name.
|
||
|
The parameter is accepted for compatibility with the @code{Bazaar}
|
||
|
step, below.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@node Bazaar, P4, Arch, Source Checkout
|
||
|
@subsubsection Bazaar
|
||
|
|
||
|
@cindex Bazaar Checkout
|
||
|
@bsindex buildbot.steps.source.Bazaar
|
||
|
|
||
|
|
||
|
@code{Bazaar} is an alternate implementation of the Arch VC system,
|
||
|
which uses a client named @code{baz}. The checkout semantics are just
|
||
|
different enough from @code{tla} that there is a separate BuildStep for
|
||
|
it.
|
||
|
|
||
|
It takes exactly the same arguments as @code{Arch}, except that the
|
||
|
@code{archive=} parameter is required. (baz does not emit the archive
|
||
|
name when you do @code{baz register-archive}, so we must provide it
|
||
|
ourselves).
|
||
|
|
||
|
|
||
|
@node P4, , Bazaar, Source Checkout
|
||
|
@subsubsection P4
|
||
|
|
||
|
@cindex Perforce Update
|
||
|
@bsindex buildbot.steps.source.P4
|
||
|
@c TODO @bsindex buildbot.steps.source.P4Sync
|
||
|
|
||
|
|
||
|
The @code{P4} build step creates a @uref{http://www.perforce.com/,
|
||
|
Perforce} client specification and performs an update.
|
||
|
|
||
|
@table @code
|
||
|
@item p4base
|
||
|
A view into the Perforce depot without branch name or trailing "...".
|
||
|
Typically "//depot/proj/".
|
||
|
@item defaultBranch
|
||
|
A branch name to append on build requests if none is specified.
|
||
|
Typically "trunk".
|
||
|
@item p4port
|
||
|
(optional): the host:port string describing how to get to the P4 Depot
|
||
|
(repository), used as the -p argument for all p4 commands.
|
||
|
@item p4user
|
||
|
(optional): the Perforce user, used as the -u argument to all p4
|
||
|
commands.
|
||
|
@item p4passwd
|
||
|
(optional): the Perforce password, used as the -p argument to all p4
|
||
|
commands.
|
||
|
@item p4extra_views
|
||
|
(optional): a list of (depotpath, clientpath) tuples containing extra
|
||
|
views to be mapped into the client specification. Both will have
|
||
|
"/..." appended automatically. The client name and source directory
|
||
|
will be prepended to the client path.
|
||
|
@item p4client
|
||
|
(optional): The name of the client to use. In mode='copy' and
|
||
|
mode='update', it's particularly important that a unique name is used
|
||
|
for each checkout directory to avoid incorrect synchronization. For
|
||
|
this reason, Python percent substitution will be performed on this value
|
||
|
to replace %(slave)s with the slave name and %(builder)s with the
|
||
|
builder name. The default is "buildbot_%(slave)s_%(build)s".
|
||
|
@end table
|
||
|
|
||
|
@node ShellCommand, Simple ShellCommand Subclasses, Source Checkout, Build Steps
|
||
|
@subsection ShellCommand
|
||
|
|
||
|
@bsindex buildbot.steps.shell.ShellCommand
|
||
|
@c TODO @bsindex buildbot.steps.shell.TreeSize
|
||
|
|
||
|
This is a useful base class for just about everything you might want
|
||
|
to do during a build (except for the initial source checkout). It runs
|
||
|
a single command in a child shell on the buildslave. All stdout/stderr
|
||
|
is recorded into a LogFile. The step finishes with a status of FAILURE
|
||
|
if the command's exit code is non-zero, otherwise it has a status of
|
||
|
SUCCESS.
|
||
|
|
||
|
The preferred way to specify the command is with a list of argv strings,
|
||
|
since this allows for spaces in filenames and avoids doing any fragile
|
||
|
shell-escaping. You can also specify the command with a single string, in
|
||
|
which case the string is given to '/bin/sh -c COMMAND' for parsing.
|
||
|
|
||
|
All ShellCommands are run by default in the ``workdir'', which
|
||
|
defaults to the ``@file{build}'' subdirectory of the slave builder's
|
||
|
base directory. The absolute path of the workdir will thus be the
|
||
|
slave's basedir (set as an option to @code{buildbot create-slave},
|
||
|
@pxref{Creating a buildslave}) plus the builder's basedir (set in the
|
||
|
builder's @code{c['builddir']} key in master.cfg) plus the workdir
|
||
|
itself (a class-level attribute of the BuildFactory, defaults to
|
||
|
``@file{build}'').
|
||
|
|
||
|
@code{ShellCommand} arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item command
|
||
|
a list of strings (preferred) or single string (discouraged) which
|
||
|
specifies the command to be run. A list of strings is preferred
|
||
|
because it can be used directly as an argv array. Using a single
|
||
|
string (with embedded spaces) requires the buildslave to pass the
|
||
|
string to /bin/sh for interpretation, which raises all sorts of
|
||
|
difficult questions about how to escape or interpret shell
|
||
|
metacharacters.
|
||
|
|
||
|
@item env
|
||
|
a dictionary of environment strings which will be added to the child
|
||
|
command's environment. For example, to run tests with a different i18n
|
||
|
language setting, you might use
|
||
|
|
||
|
@example
|
||
|
f.addStep(ShellCommand, command=["make", "test"],
|
||
|
env=@{'LANG': 'fr_FR'@})
|
||
|
@end example
|
||
|
|
||
|
These variable settings will override any existing ones in the
|
||
|
buildslave's environment. The exception is PYTHONPATH, which is merged
|
||
|
with (actually prepended to) any existing $PYTHONPATH setting. The
|
||
|
value is treated as a list of directories to prepend, and a single
|
||
|
string is treated like a one-item list. For example, to prepend both
|
||
|
@file{/usr/local/lib/python2.3} and @file{/home/buildbot/lib/python}
|
||
|
to any existing $PYTHONPATH setting, you would do something like the
|
||
|
following:
|
||
|
|
||
|
@example
|
||
|
f.addStep(ShellCommand, command=["make", "test"],
|
||
|
env=@{'PYTHONPATH': ["/usr/local/lib/python2.3",
|
||
|
"/home/buildbot/lib/python"] @})
|
||
|
@end example
|
||
|
|
||
|
@item want_stdout
|
||
|
if False, stdout from the child process is discarded rather than being
|
||
|
sent to the buildmaster for inclusion in the step's LogFile.
|
||
|
|
||
|
@item want_stderr
|
||
|
like @code{want_stdout} but for stderr. Note that commands run through
|
||
|
a PTY do not have separate stdout/stderr streams: both are merged into
|
||
|
stdout.
|
||
|
|
||
|
@item logfiles
|
||
|
Sometimes commands will log interesting data to a local file, rather
|
||
|
than emitting everything to stdout or stderr. For example, Twisted's
|
||
|
``trial'' command (which runs unit tests) only presents summary
|
||
|
information to stdout, and puts the rest into a file named
|
||
|
@file{_trial_temp/test.log}. It is often useful to watch these files
|
||
|
as the command runs, rather than using @command{/bin/cat} to dump
|
||
|
their contents afterwards.
|
||
|
|
||
|
The @code{logfiles=} argument allows you to collect data from these
|
||
|
secondary logfiles in near-real-time, as the step is running. It
|
||
|
accepts a dictionary which maps from a local Log name (which is how
|
||
|
the log data is presented in the build results) to a remote filename
|
||
|
(interpreted relative to the build's working directory). Each named
|
||
|
file will be polled on a regular basis (every couple of seconds) as
|
||
|
the build runs, and any new text will be sent over to the buildmaster.
|
||
|
|
||
|
@example
|
||
|
f.addStep(ShellCommand, command=["make", "test"],
|
||
|
logfiles=@{"triallog": "_trial_temp/test.log"@})
|
||
|
@end example
|
||
|
|
||
|
|
||
|
@item timeout
|
||
|
if the command fails to produce any output for this many seconds, it
|
||
|
is assumed to be locked up and will be killed.
|
||
|
|
||
|
@item description
|
||
|
This will be used to describe the command (on the Waterfall display)
|
||
|
while the command is still running. It should be a single
|
||
|
imperfect-tense verb, like ``compiling'' or ``testing''. The preferred
|
||
|
form is a list of short strings, which allows the HTML Waterfall
|
||
|
display to create narrower columns by emitting a <br> tag between each
|
||
|
word. You may also provide a single string.
|
||
|
|
||
|
@item descriptionDone
|
||
|
This will be used to describe the command once it has finished. A
|
||
|
simple noun like ``compile'' or ``tests'' should be used. Like
|
||
|
@code{description}, this may either be a list of short strings or a
|
||
|
single string.
|
||
|
|
||
|
If neither @code{description} nor @code{descriptionDone} are set, the
|
||
|
actual command arguments will be used to construct the description.
|
||
|
This may be a bit too wide to fit comfortably on the Waterfall
|
||
|
display.
|
||
|
|
||
|
@example
|
||
|
f.addStep(ShellCommand, command=["make", "test"],
|
||
|
description=["testing"],
|
||
|
descriptionDone=["tests"])
|
||
|
@end example
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@node Simple ShellCommand Subclasses, Python BuildSteps, ShellCommand, Build Steps
|
||
|
@subsection Simple ShellCommand Subclasses
|
||
|
|
||
|
Several subclasses of ShellCommand are provided as starting points for
|
||
|
common build steps. These are all very simple: they just override a few
|
||
|
parameters so you don't have to specify them yourself, making the master.cfg
|
||
|
file less verbose.
|
||
|
|
||
|
@menu
|
||
|
* Configure::
|
||
|
* Compile::
|
||
|
* Test::
|
||
|
* Build Properties::
|
||
|
@end menu
|
||
|
|
||
|
@node Configure, Compile, Simple ShellCommand Subclasses, Simple ShellCommand Subclasses
|
||
|
@subsubsection Configure
|
||
|
|
||
|
@bsindex buildbot.steps.shell.Configure
|
||
|
|
||
|
This is intended to handle the @code{./configure} step from
|
||
|
autoconf-style projects, or the @code{perl Makefile.PL} step from perl
|
||
|
MakeMaker.pm-style modules. The default command is @code{./configure}
|
||
|
but you can change this by providing a @code{command=} parameter.
|
||
|
|
||
|
@node Compile, Test, Configure, Simple ShellCommand Subclasses
|
||
|
@subsubsection Compile
|
||
|
|
||
|
@bsindex buildbot.steps.shell.Compile
|
||
|
|
||
|
This is meant to handle compiling or building a project written in C. The
|
||
|
default command is @code{make all}. When the compile is finished, the
|
||
|
log file is scanned for GCC error/warning messages and a summary log is
|
||
|
created with any problems that were seen (TODO: the summary is not yet
|
||
|
created).
|
||
|
|
||
|
@node Test, Build Properties, Compile, Simple ShellCommand Subclasses
|
||
|
@subsubsection Test
|
||
|
|
||
|
@bsindex buildbot.steps.shell.Test
|
||
|
|
||
|
This is meant to handle unit tests. The default command is @code{make
|
||
|
test}, and the @code{warnOnFailure} flag is set.
|
||
|
|
||
|
|
||
|
|
||
|
@node Build Properties, , Test, Simple ShellCommand Subclasses
|
||
|
@subsubsection Build Properties
|
||
|
|
||
|
@cindex build properties
|
||
|
|
||
|
Each build has a set of ``Build Properties'', which can be used by its
|
||
|
BuildStep to modify their actions. For example, the SVN revision
|
||
|
number of the source code being built is available as a build
|
||
|
property, and a ShellCommand step could incorporate this number into a
|
||
|
command which create a numbered release tarball.
|
||
|
|
||
|
Some build properties are set when the build starts, such as the
|
||
|
SourceStamp information. Other properties can be set by BuildSteps as
|
||
|
they run, for example the various Source steps will set the
|
||
|
@code{got_revision} property to the source revision that was actually
|
||
|
checked out (which can be useful when the SourceStamp in use merely
|
||
|
requested the ``latest revision'': @code{got_revision} will tell you
|
||
|
what was actually built).
|
||
|
|
||
|
In custom BuildSteps, you can get and set the build properties with
|
||
|
the @code{getProperty}/@code{setProperty} methods. Each takes a string
|
||
|
for the name of the property, and returns or accepts an
|
||
|
arbitrary@footnote{Build properties are serialized along with the
|
||
|
build results, so they must be serializable. For this reason, the
|
||
|
value of any build property should be simple inert data: strings,
|
||
|
numbers, lists, tuples, and dictionaries. They should not contain
|
||
|
class instances.} object. For example:
|
||
|
|
||
|
@example
|
||
|
class MakeTarball(ShellCommand):
|
||
|
def start(self):
|
||
|
self.setCommand(["tar", "czf",
|
||
|
"build-%s.tar.gz" % self.getProperty("revision"),
|
||
|
"source"])
|
||
|
ShellCommand.start(self)
|
||
|
@end example
|
||
|
|
||
|
@cindex WithProperties
|
||
|
|
||
|
You can use build properties in ShellCommands by using the
|
||
|
@code{WithProperties} wrapper when setting the arguments of the
|
||
|
ShellCommand. This interpolates the named build properties into the
|
||
|
generated shell command.
|
||
|
|
||
|
@example
|
||
|
from buildbot.steps.shell import ShellCommand, WithProperties
|
||
|
|
||
|
f.addStep(ShellCommand,
|
||
|
command=["tar", "czf",
|
||
|
WithProperties("build-%s.tar.gz", "revision"),
|
||
|
"source"])
|
||
|
@end example
|
||
|
|
||
|
If this BuildStep were used in a tree obtained from Subversion, it
|
||
|
would create a tarball with a name like @file{build-1234.tar.gz}.
|
||
|
|
||
|
The @code{WithProperties} function does @code{printf}-style string
|
||
|
interpolation, using strings obtained by calling
|
||
|
@code{build.getProperty(propname)}. Note that for every @code{%s} (or
|
||
|
@code{%d}, etc), you must have exactly one additional argument to
|
||
|
indicate which build property you want to insert.
|
||
|
|
||
|
|
||
|
You can also use python dictionary-style string interpolation by using
|
||
|
the @code{%(propname)s} syntax. In this form, the property name goes
|
||
|
in the parentheses, and WithProperties takes @emph{no} additional
|
||
|
arguments:
|
||
|
|
||
|
@example
|
||
|
f.addStep(ShellCommand,
|
||
|
command=["tar", "czf",
|
||
|
WithProperties("build-%(revision)s.tar.gz"),
|
||
|
"source"])
|
||
|
@end example
|
||
|
|
||
|
Don't forget the extra ``s'' after the closing parenthesis! This is
|
||
|
the cause of many confusing errors. Also note that you can only use
|
||
|
WithProperties in the list form of the command= definition. You cannot
|
||
|
currently use it in the (discouraged) @code{command="stuff"}
|
||
|
single-string form. However, you can use something like
|
||
|
@code{command=["/bin/sh", "-c", "stuff", WithProperties(stuff)]} to
|
||
|
use both shell expansion and WithProperties interpolation.
|
||
|
|
||
|
Note that, like python, you can either do positional-argument
|
||
|
interpolation @emph{or} keyword-argument interpolation, not both. Thus
|
||
|
you cannot use a string like
|
||
|
@code{WithProperties("foo-%(revision)s-%s", "branch")}.
|
||
|
|
||
|
At the moment, the only way to set build properties is by writing a
|
||
|
custom BuildStep.
|
||
|
|
||
|
@heading Common Build Properties
|
||
|
|
||
|
The following build properties are set when the build is started, and
|
||
|
are available to all steps.
|
||
|
|
||
|
@table @code
|
||
|
@item branch
|
||
|
|
||
|
This comes from the build's SourceStamp, and describes which branch is
|
||
|
being checked out. This will be @code{None} (which interpolates into
|
||
|
@code{WithProperties} as an empty string) if the build is on the
|
||
|
default branch, which is generally the trunk. Otherwise it will be a
|
||
|
string like ``branches/beta1.4''. The exact syntax depends upon the VC
|
||
|
system being used.
|
||
|
|
||
|
@item revision
|
||
|
|
||
|
This also comes from the SourceStamp, and is the revision of the
|
||
|
source code tree that was requested from the VC system. When a build
|
||
|
is requested of a specific revision (as is generally the case when the
|
||
|
build is triggered by Changes), this will contain the revision
|
||
|
specification. The syntax depends upon the VC system in use: for SVN
|
||
|
it is an integer, for Mercurial it is a short string, for Darcs it is
|
||
|
a rather large string, etc.
|
||
|
|
||
|
If the ``force build'' button was pressed, the revision will be
|
||
|
@code{None}, which means to use the most recent revision available.
|
||
|
This is a ``trunk build''. This will be interpolated as an empty
|
||
|
string.
|
||
|
|
||
|
@item got_revision
|
||
|
|
||
|
This is set when a Source step checks out the source tree, and
|
||
|
provides the revision that was actually obtained from the VC system.
|
||
|
In general this should be the same as @code{revision}, except for
|
||
|
trunk builds, where @code{got_revision} indicates what revision was
|
||
|
current when the checkout was performed. This can be used to rebuild
|
||
|
the same source code later.
|
||
|
|
||
|
Note that for some VC systems (Darcs in particular), the revision is a
|
||
|
large string containing newlines, and is not suitable for
|
||
|
interpolation into a filename.
|
||
|
|
||
|
@item buildername
|
||
|
|
||
|
This is a string that indicates which Builder the build was a part of.
|
||
|
The combination of buildername and buildnumber uniquely identify a
|
||
|
build.
|
||
|
|
||
|
@item buildnumber
|
||
|
|
||
|
Each build gets a number, scoped to the Builder (so the first build
|
||
|
performed on any given Builder will have a build number of 0). This
|
||
|
integer property contains the build's number.
|
||
|
|
||
|
@item slavename
|
||
|
|
||
|
This is a string which identifies which buildslave the build is
|
||
|
running on.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
@node Python BuildSteps, Transferring Files, Simple ShellCommand Subclasses, Build Steps
|
||
|
@subsection Python BuildSteps
|
||
|
|
||
|
Here are some BuildSteps that are specifcally useful for projects
|
||
|
implemented in Python.
|
||
|
|
||
|
@menu
|
||
|
* BuildEPYDoc::
|
||
|
* PyFlakes::
|
||
|
@end menu
|
||
|
|
||
|
@node BuildEPYDoc, PyFlakes, Python BuildSteps, Python BuildSteps
|
||
|
@subsubsection BuildEPYDoc
|
||
|
|
||
|
@bsindex buildbot.steps.python.BuildEPYDoc
|
||
|
|
||
|
@url{http://epydoc.sourceforge.net/, epydoc} is a tool for generating
|
||
|
API documentation for Python modules from their docstrings. It reads
|
||
|
all the .py files from your source tree, processes the docstrings
|
||
|
therein, and creates a large tree of .html files (or a single .pdf
|
||
|
file).
|
||
|
|
||
|
The @code{buildbot.steps.python.BuildEPYDoc} step will run
|
||
|
@command{epydoc} to produce this API documentation, and will count the
|
||
|
errors and warnings from its output.
|
||
|
|
||
|
You must supply the command line to be used. The default is
|
||
|
@command{make epydocs}, which assumes that your project has a Makefile
|
||
|
with an ``epydocs'' target. You might wish to use something like
|
||
|
@command{epydoc -o apiref source/PKGNAME} instead. You might also want
|
||
|
to add @command{--pdf} to generate a PDF file instead of a large tree
|
||
|
of HTML files.
|
||
|
|
||
|
The API docs are generated in-place in the build tree (under the
|
||
|
workdir, in the subdirectory controlled by the ``-o'' argument). To
|
||
|
make them useful, you will probably have to copy them to somewhere
|
||
|
they can be read. A command like @command{rsync -ad apiref/
|
||
|
dev.example.com:~public_html/current-apiref/} might be useful. You
|
||
|
might instead want to bundle them into a tarball and publish it in the
|
||
|
same place where the generated install tarball is placed.
|
||
|
|
||
|
@example
|
||
|
from buildbot.steps.python import BuildEPYDoc
|
||
|
|
||
|
...
|
||
|
f.addStep(BuildEPYDoc, command=["epydoc", "-o", "apiref", "source/mypkg"])
|
||
|
@end example
|
||
|
|
||
|
|
||
|
@node PyFlakes, , BuildEPYDoc, Python BuildSteps
|
||
|
@subsubsection PyFlakes
|
||
|
|
||
|
@bsindex buildbot.steps.python.PyFlakes
|
||
|
|
||
|
@url{http://divmod.org/trac/wiki/DivmodPyflakes, PyFlakes} is a tool
|
||
|
to perform basic static analysis of Python code to look for simple
|
||
|
errors, like missing imports and references of undefined names. It is
|
||
|
like a fast and simple form of the C ``lint'' program. Other tools
|
||
|
(like pychecker) provide more detailed results but take longer to run.
|
||
|
|
||
|
The @code{buildbot.steps.python.PyFlakes} step will run pyflakes and
|
||
|
count the various kinds of errors and warnings it detects.
|
||
|
|
||
|
You must supply the command line to be used. The default is
|
||
|
@command{make pyflakes}, which assumes you have a top-level Makefile
|
||
|
with a ``pyflakes'' target. You might want to use something like
|
||
|
@command{pyflakes .} or @command{pyflakes src}.
|
||
|
|
||
|
@example
|
||
|
from buildbot.steps.python import PyFlakes
|
||
|
|
||
|
...
|
||
|
f.addStep(PyFlakes, command=["pyflakes", "src"])
|
||
|
@end example
|
||
|
|
||
|
|
||
|
@node Transferring Files, Writing New BuildSteps, Python BuildSteps, Build Steps
|
||
|
@subsection Transferring Files
|
||
|
|
||
|
@cindex File Transfer
|
||
|
@bsindex buildbot.steps.transfer.FileUpload
|
||
|
@bsindex buildbot.steps.transfer.FileDownload
|
||
|
|
||
|
Most of the work involved in a build will take place on the
|
||
|
buildslave. But occasionally it is useful to do some work on the
|
||
|
buildmaster side. The most basic way to involve the buildmaster is
|
||
|
simply to move a file from the slave to the master, or vice versa.
|
||
|
There are a pair of BuildSteps named @code{FileUpload} and
|
||
|
@code{FileDownload} to provide this functionality. @code{FileUpload}
|
||
|
moves a file @emph{up to} the master, while @code{FileDownload} moves
|
||
|
a file @emph{down from} the master.
|
||
|
|
||
|
As an example, let's assume that there is a step which produces an
|
||
|
HTML file within the source tree that contains some sort of generated
|
||
|
project documentation. We want to move this file to the buildmaster,
|
||
|
into a @file{~/public_html} directory, so it can be visible to
|
||
|
developers. This file will wind up in the slave-side working directory
|
||
|
under the name @file{docs/reference.html}. We want to put it into the
|
||
|
master-side @file{~/public_html/ref.html}.
|
||
|
|
||
|
@example
|
||
|
from buildbot.steps.shell import ShellCommand
|
||
|
from buildbot.steps.transfer import FileUpload
|
||
|
|
||
|
f.addStep(ShellCommand, command=["make", "docs"])
|
||
|
f.addStep(FileUpload,
|
||
|
slavesrc="docs/reference.html",
|
||
|
masterdest="~/public_html/ref.html")
|
||
|
@end example
|
||
|
|
||
|
The @code{masterdest=} argument will be passed to os.path.expanduser,
|
||
|
so things like ``~'' will be expanded properly. Non-absolute paths
|
||
|
will be interpreted relative to the buildmaster's base directory.
|
||
|
Likewise, the @code{slavesrc=} argument will be expanded and
|
||
|
interpreted relative to the builder's working directory.
|
||
|
|
||
|
|
||
|
To move a file from the master to the slave, use the
|
||
|
@code{FileDownload} command. For example, let's assume that some step
|
||
|
requires a configuration file that, for whatever reason, could not be
|
||
|
recorded in the source code repository or generated on the buildslave
|
||
|
side:
|
||
|
|
||
|
@example
|
||
|
from buildbot.steps.shell import ShellCommand
|
||
|
from buildbot.steps.transfer import FileUpload
|
||
|
|
||
|
f.addStep(FileDownload
|
||
|
mastersrc="~/todays_build_config.txt",
|
||
|
slavedest="build_config.txt")
|
||
|
f.addStep(ShellCommand, command=["make", "config"])
|
||
|
@end example
|
||
|
|
||
|
Like @code{FileUpload}, the @code{mastersrc=} argument is interpreted
|
||
|
relative to the buildmaster's base directory, and the
|
||
|
@code{slavedest=} argument is relative to the builder's working
|
||
|
directory. If the buildslave is running in @file{~buildslave}, and the
|
||
|
builder's ``builddir'' is something like @file{tests-i386}, then the
|
||
|
workdir is going to be @file{~buildslave/tests-i386/build}, and a
|
||
|
@code{slavedest=} of @file{foo/bar.html} will get put in
|
||
|
@file{~buildslave/tests-i386/build/foo/bar.html}. Remember that
|
||
|
neither of these commands will create missing directories for you.
|
||
|
|
||
|
|
||
|
@subheading Other Parameters
|
||
|
|
||
|
The @code{maxsize=} argument lets you set a maximum size for the file
|
||
|
to be transferred. This may help to avoid surprises: transferring a
|
||
|
100MB coredump when you were expecting to move a 10kB status file
|
||
|
might take an awfully long time. The @code{blocksize=} argument
|
||
|
controls how the file is sent over the network: larger blocksizes are
|
||
|
slightly more efficient but also consume more memory on each end, and
|
||
|
there is a hard-coded limit of about 640kB.
|
||
|
|
||
|
The @code{mode=} argument allows you to control the access permissions
|
||
|
of the target file, traditionally expressed as an octal integer. The
|
||
|
most common value is probably 0755, which sets the ``x'' executable
|
||
|
bit on the file (useful for shell scripts and the like). The default
|
||
|
value for @code{mode=} is None, which means the permission bits will
|
||
|
default to whatever the umask of the writing process is. The default
|
||
|
umask tends to be fairly restrictive, but at least on the buildslave
|
||
|
you can make it less restrictive with a --umask command-line option at
|
||
|
creation time (@pxref{Buildslave Options}).
|
||
|
|
||
|
|
||
|
@node Writing New BuildSteps, , Transferring Files, Build Steps
|
||
|
@subsection Writing New BuildSteps
|
||
|
|
||
|
While it is a good idea to keep your build process self-contained in
|
||
|
the source code tree, sometimes it is convenient to put more
|
||
|
intelligence into your Buildbot configuration. One was to do this is
|
||
|
to write a custom BuildStep. Once written, this Step can be used in
|
||
|
the @file{master.cfg} file.
|
||
|
|
||
|
The best reason for writing a custom BuildStep is to better parse the
|
||
|
results of the command being run. For example, a BuildStep that knows
|
||
|
about JUnit could look at the logfiles to determine which tests had
|
||
|
been run, how many passed and how many failed, and then report more
|
||
|
detailed information than a simple @code{rc==0} -based ``good/bad''
|
||
|
decision.
|
||
|
|
||
|
TODO: add more description of BuildSteps.
|
||
|
|
||
|
@menu
|
||
|
* BuildStep LogFiles::
|
||
|
* Adding LogObservers::
|
||
|
* BuildStep URLs::
|
||
|
@end menu
|
||
|
|
||
|
@node BuildStep LogFiles, Adding LogObservers, Writing New BuildSteps, Writing New BuildSteps
|
||
|
@subsubsection BuildStep LogFiles
|
||
|
|
||
|
Each BuildStep has a collection of ``logfiles''. Each one has a short
|
||
|
name, like ``stdio'' or ``warnings''. Each LogFile contains an
|
||
|
arbitrary amount of text, usually the contents of some output file
|
||
|
generated during a build or test step, or a record of everything that
|
||
|
was printed to stdout/stderr during the execution of some command.
|
||
|
|
||
|
These LogFiles are stored to disk, so they can be retrieved later.
|
||
|
|
||
|
Each can contain multiple ``channels'', generally limited to three
|
||
|
basic ones: stdout, stderr, and ``headers''. For example, when a
|
||
|
ShellCommand runs, it writes a few lines to the ``headers'' channel to
|
||
|
indicate the exact argv strings being run, which directory the command
|
||
|
is being executed in, and the contents of the current environment
|
||
|
variables. Then, as the command runs, it adds a lot of ``stdout'' and
|
||
|
``stderr'' messages. When the command finishes, a final ``header''
|
||
|
line is added with the exit code of the process.
|
||
|
|
||
|
Status display plugins can format these different channels in
|
||
|
different ways. For example, the web page shows LogFiles as text/html,
|
||
|
with header lines in blue text, stdout in black, and stderr in red. A
|
||
|
different URL is available which provides a text/plain format, in
|
||
|
which stdout and stderr are collapsed together, and header lines are
|
||
|
stripped completely. This latter option makes it easy to save the
|
||
|
results to a file and run @command{grep} or whatever against the
|
||
|
output.
|
||
|
|
||
|
Each BuildStep contains a mapping (implemented in a python dictionary)
|
||
|
from LogFile name to the actual LogFile objects. Status plugins can
|
||
|
get a list of LogFiles to display, for example, a list of HREF links
|
||
|
that, when clicked, provide the full contents of the LogFile.
|
||
|
|
||
|
@heading Using LogFiles in custom BuildSteps
|
||
|
|
||
|
The most common way for a custom BuildStep to use a LogFile is to
|
||
|
summarize the results of a ShellCommand (after the command has
|
||
|
finished running). For example, a compile step with thousands of lines
|
||
|
of output might want to create a summary of just the warning messages.
|
||
|
If you were doing this from a shell, you would use something like:
|
||
|
|
||
|
@example
|
||
|
grep "warning:" output.log >warnings.log
|
||
|
@end example
|
||
|
|
||
|
In a custom BuildStep, you could instead create a ``warnings'' LogFile
|
||
|
that contained the same text. To do this, you would add code to your
|
||
|
@code{createSummary} method that pulls lines from the main output log
|
||
|
and creates a new LogFile with the results:
|
||
|
|
||
|
@example
|
||
|
def createSummary(self, log):
|
||
|
warnings = []
|
||
|
for line in log.readlines():
|
||
|
if "warning:" in line:
|
||
|
warnings.append()
|
||
|
self.addCompleteLog('warnings', "".join(warnings))
|
||
|
@end example
|
||
|
|
||
|
This example uses the @code{addCompleteLog} method, which creates a
|
||
|
new LogFile, puts some text in it, and then ``closes'' it, meaning
|
||
|
that no further contents will be added. This LogFile will appear in
|
||
|
the HTML display under an HREF with the name ``warnings'', since that
|
||
|
is the name of the LogFile.
|
||
|
|
||
|
You can also use @code{addHTMLLog} to create a complete (closed)
|
||
|
LogFile that contains HTML instead of plain text. The normal LogFile
|
||
|
will be HTML-escaped if presented through a web page, but the HTML
|
||
|
LogFile will not. At the moment this is only used to present a pretty
|
||
|
HTML representation of an otherwise ugly exception traceback when
|
||
|
something goes badly wrong during the BuildStep.
|
||
|
|
||
|
In contrast, you might want to create a new LogFile at the beginning
|
||
|
of the step, and add text to it as the command runs. You can create
|
||
|
the LogFile and attach it to the build by calling @code{addLog}, which
|
||
|
returns the LogFile object. You then add text to this LogFile by
|
||
|
calling methods like @code{addStdout} and @code{addHeader}. When you
|
||
|
are done, you must call the @code{finish} method so the LogFile can be
|
||
|
closed. It may be useful to create and populate a LogFile like this
|
||
|
from a LogObserver method @xref{Adding LogObservers}.
|
||
|
|
||
|
The @code{logfiles=} argument to @code{ShellCommand} (see
|
||
|
@pxref{ShellCommand}) creates new LogFiles and fills them in realtime
|
||
|
by asking the buildslave to watch a actual file on disk. The
|
||
|
buildslave will look for additions in the target file and report them
|
||
|
back to the BuildStep. These additions will be added to the LogFile by
|
||
|
calling @code{addStdout}. These secondary LogFiles can be used as the
|
||
|
source of a LogObserver just like the normal ``stdio'' LogFile.
|
||
|
|
||
|
|
||
|
@node Adding LogObservers, BuildStep URLs, BuildStep LogFiles, Writing New BuildSteps
|
||
|
@subsubsection Adding LogObservers
|
||
|
|
||
|
@cindex LogObserver
|
||
|
@cindex LogLineObserver
|
||
|
|
||
|
Most shell commands emit messages to stdout or stderr as they operate,
|
||
|
especially if you ask them nicely with a @code{--verbose} flag of some
|
||
|
sort. They may also write text to a log file while they run. Your
|
||
|
BuildStep can watch this output as it arrives, to keep track of how
|
||
|
much progress the command has made. You can get a better measure of
|
||
|
progress by counting the number of source files compiled or test cases
|
||
|
run than by merely tracking the number of bytes that have been written
|
||
|
to stdout. This improves the accuracy and the smoothness of the ETA
|
||
|
display.
|
||
|
|
||
|
To accomplish this, you will need to attach a @code{LogObserver} to
|
||
|
one of the log channels, most commonly to the ``stdio'' channel but
|
||
|
perhaps to another one which tracks a log file. This observer is given
|
||
|
all text as it is emitted from the command, and has the opportunity to
|
||
|
parse that output incrementally. Once the observer has decided that
|
||
|
some event has occurred (like a source file being compiled), it can
|
||
|
use the @code{setProgress} method to tell the BuildStep about the
|
||
|
progress that this event represents.
|
||
|
|
||
|
There are a number of pre-built @code{LogObserver} classes that you
|
||
|
can choose from (defined in @code{buildbot.process.buildstep}, and of
|
||
|
course you can subclass them to add further customization. The
|
||
|
@code{LogLineObserver} class handles the grunt work of buffering and
|
||
|
scanning for end-of-line delimiters, allowing your parser to operate
|
||
|
on complete stdout/stderr lines.
|
||
|
|
||
|
For example, let's take a look at the @code{TrialTestCaseCounter},
|
||
|
which is used by the Trial step to count test cases as they are run.
|
||
|
As Trial executes, it emits lines like the following:
|
||
|
|
||
|
@example
|
||
|
buildbot.test.test_config.ConfigTest.testDebugPassword ... [OK]
|
||
|
buildbot.test.test_config.ConfigTest.testEmpty ... [OK]
|
||
|
buildbot.test.test_config.ConfigTest.testIRC ... [FAIL]
|
||
|
buildbot.test.test_config.ConfigTest.testLocks ... [OK]
|
||
|
@end example
|
||
|
|
||
|
When the tests are finished, trial emits a long line of ``======'' and
|
||
|
then some lines which summarize the tests that failed. We want to
|
||
|
avoid parsing these trailing lines, because their format is less
|
||
|
well-defined than the ``[OK]'' lines.
|
||
|
|
||
|
The parser class looks like this:
|
||
|
|
||
|
@example
|
||
|
from buildbot.process.buildstep import LogLineObserver
|
||
|
|
||
|
class TrialTestCaseCounter(LogLineObserver):
|
||
|
_line_re = re.compile(r'^([\w\.]+) \.\.\. \[([^\]]+)\]$')
|
||
|
numTests = 0
|
||
|
finished = False
|
||
|
|
||
|
def outLineReceived(self, line):
|
||
|
if self.finished:
|
||
|
return
|
||
|
if line.startswith("=" * 40):
|
||
|
self.finished = True
|
||
|
return
|
||
|
|
||
|
m = self._line_re.search(line.strip())
|
||
|
if m:
|
||
|
testname, result = m.groups()
|
||
|
self.numTests += 1
|
||
|
self.step.setProgress('tests', self.numTests)
|
||
|
@end example
|
||
|
|
||
|
This parser only pays attention to stdout, since that's where trial
|
||
|
writes the progress lines. It has a mode flag named @code{finished} to
|
||
|
ignore everything after the ``===='' marker, and a scary-looking
|
||
|
regular expression to match each line while hopefully ignoring other
|
||
|
messages that might get displayed as the test runs.
|
||
|
|
||
|
Each time it identifies a test has been completed, it increments its
|
||
|
counter and delivers the new progress value to the step with
|
||
|
@code{self.step.setProgress}. This class is specifically measuring
|
||
|
progress along the ``tests'' metric, in units of test cases (as
|
||
|
opposed to other kinds of progress like the ``output'' metric, which
|
||
|
measures in units of bytes). The Progress-tracking code uses each
|
||
|
progress metric separately to come up with an overall completion
|
||
|
percentage and an ETA value.
|
||
|
|
||
|
To connect this parser into the @code{Trial} BuildStep,
|
||
|
@code{Trial.__init__} ends with the following clause:
|
||
|
|
||
|
@example
|
||
|
# this counter will feed Progress along the 'test cases' metric
|
||
|
counter = TrialTestCaseCounter()
|
||
|
self.addLogObserver('stdio', counter)
|
||
|
@end example
|
||
|
|
||
|
This creates a TrialTestCaseCounter and tells the step that the
|
||
|
counter wants to watch the ``stdio'' log. The observer is
|
||
|
automatically given a reference to the step in its @code{.step}
|
||
|
attribute.
|
||
|
|
||
|
@subheading A Somewhat Whimsical Example
|
||
|
|
||
|
Let's say that we've got some snazzy new unit-test framework called
|
||
|
Framboozle. It's the hottest thing since sliced bread. It slices, it
|
||
|
dices, it runs unit tests like there's no tomorrow. Plus if your unit
|
||
|
tests fail, you can use its name for a Web 2.1 startup company, make
|
||
|
millions of dollars, and hire engineers to fix the bugs for you, while
|
||
|
you spend your afternoons lazily hang-gliding along a scenic pacific
|
||
|
beach, blissfully unconcerned about the state of your
|
||
|
tests.@footnote{framboozle.com is still available. Remember, I get 10%
|
||
|
:).}
|
||
|
|
||
|
To run a Framboozle-enabled test suite, you just run the 'framboozler'
|
||
|
command from the top of your source code tree. The 'framboozler'
|
||
|
command emits a bunch of stuff to stdout, but the most interesting bit
|
||
|
is that it emits the line "FNURRRGH!" every time it finishes running a
|
||
|
test case@footnote{Framboozle gets very excited about running unit
|
||
|
tests.}. You'd like to have a test-case counting LogObserver that
|
||
|
watches for these lines and counts them, because counting them will
|
||
|
help the buildbot more accurately calculate how long the build will
|
||
|
take, and this will let you know exactly how long you can sneak out of
|
||
|
the office for your hang-gliding lessons without anyone noticing that
|
||
|
you're gone.
|
||
|
|
||
|
This will involve writing a new BuildStep (probably named
|
||
|
"Framboozle") which inherits from ShellCommand. The BuildStep class
|
||
|
definition itself will look something like this:
|
||
|
|
||
|
@example
|
||
|
# START
|
||
|
from buildbot.steps.shell import ShellCommand
|
||
|
from buildbot.process.buildstep import LogLineObserver
|
||
|
|
||
|
class FNURRRGHCounter(LogLineObserver):
|
||
|
numTests = 0
|
||
|
def outLineReceived(self, line):
|
||
|
if "FNURRRGH!" in line:
|
||
|
self.numTests += 1
|
||
|
self.step.setProgress('tests', self.numTests)
|
||
|
|
||
|
class Framboozle(ShellCommand):
|
||
|
command = ["framboozler"]
|
||
|
|
||
|
def __init__(self, **kwargs):
|
||
|
ShellCommand.__init__(self, **kwargs) # always upcall!
|
||
|
counter = FNURRRGHCounter())
|
||
|
self.addLogObserver(counter)
|
||
|
# FINISH
|
||
|
@end example
|
||
|
|
||
|
So that's the code that we want to wind up using. How do we actually
|
||
|
deploy it?
|
||
|
|
||
|
You have a couple of different options.
|
||
|
|
||
|
Option 1: The simplest technique is to simply put this text
|
||
|
(everything from START to FINISH) in your master.cfg file, somewhere
|
||
|
before the BuildFactory definition where you actually use it in a
|
||
|
clause like:
|
||
|
|
||
|
@example
|
||
|
f = BuildFactory()
|
||
|
f.addStep(SVN, svnurl="stuff")
|
||
|
f.addStep(Framboozle)
|
||
|
@end example
|
||
|
|
||
|
Remember that master.cfg is secretly just a python program with one
|
||
|
job: populating the BuildmasterConfig dictionary. And python programs
|
||
|
are allowed to define as many classes as they like. So you can define
|
||
|
classes and use them in the same file, just as long as the class is
|
||
|
defined before some other code tries to use it.
|
||
|
|
||
|
This is easy, and it keeps the point of definition very close to the
|
||
|
point of use, and whoever replaces you after that unfortunate
|
||
|
hang-gliding accident will appreciate being able to easily figure out
|
||
|
what the heck this stupid "Framboozle" step is doing anyways. The
|
||
|
downside is that every time you reload the config file, the Framboozle
|
||
|
class will get redefined, which means that the buildmaster will think
|
||
|
that you've reconfigured all the Builders that use it, even though
|
||
|
nothing changed. Bleh.
|
||
|
|
||
|
Option 2: Instead, we can put this code in a separate file, and import
|
||
|
it into the master.cfg file just like we would the normal buildsteps
|
||
|
like ShellCommand and SVN.
|
||
|
|
||
|
Create a directory named ~/lib/python, put everything from START to
|
||
|
FINISH in ~/lib/python/framboozle.py, and run your buildmaster using:
|
||
|
|
||
|
@example
|
||
|
PYTHONPATH=~/lib/python buildbot start MASTERDIR
|
||
|
@end example
|
||
|
|
||
|
or use the @file{Makefile.buildbot} to control the way
|
||
|
@command{buildbot start} works. Or add something like this to
|
||
|
something like your ~/.bashrc or ~/.bash_profile or ~/.cshrc:
|
||
|
|
||
|
@example
|
||
|
export PYTHONPATH=~/lib/python
|
||
|
@end example
|
||
|
|
||
|
Once we've done this, our master.cfg can look like:
|
||
|
|
||
|
@example
|
||
|
from framboozle import Framboozle
|
||
|
f = BuildFactory()
|
||
|
f.addStep(SVN, svnurl="stuff")
|
||
|
f.addStep(Framboozle)
|
||
|
@end example
|
||
|
|
||
|
or:
|
||
|
|
||
|
@example
|
||
|
import framboozle
|
||
|
f = BuildFactory()
|
||
|
f.addStep(SVN, svnurl="stuff")
|
||
|
f.addStep(framboozle.Framboozle)
|
||
|
@end example
|
||
|
|
||
|
(check out the python docs for details about how "import" and "from A
|
||
|
import B" work).
|
||
|
|
||
|
What we've done here is to tell python that every time it handles an
|
||
|
"import" statement for some named module, it should look in our
|
||
|
~/lib/python/ for that module before it looks anywhere else. After our
|
||
|
directories, it will try in a bunch of standard directories too
|
||
|
(including the one where buildbot is installed). By setting the
|
||
|
PYTHONPATH environment variable, you can add directories to the front
|
||
|
of this search list.
|
||
|
|
||
|
Python knows that once it "import"s a file, it doesn't need to
|
||
|
re-import it again. This means that reconfiguring the buildmaster
|
||
|
(with "buildbot reconfig", for example) won't make it think the
|
||
|
Framboozle class has changed every time, so the Builders that use it
|
||
|
will not be spuriously restarted. On the other hand, you either have
|
||
|
to start your buildmaster in a slightly weird way, or you have to
|
||
|
modify your environment to set the PYTHONPATH variable.
|
||
|
|
||
|
|
||
|
Option 3: Install this code into a standard python library directory
|
||
|
|
||
|
Find out what your python's standard include path is by asking it:
|
||
|
|
||
|
@example
|
||
|
80:warner@@luther% python
|
||
|
Python 2.4.4c0 (#2, Oct 2 2006, 00:57:46)
|
||
|
[GCC 4.1.2 20060928 (prerelease) (Debian 4.1.1-15)] on linux2
|
||
|
Type "help", "copyright", "credits" or "license" for more information.
|
||
|
>>> import sys
|
||
|
>>> print sys.path
|
||
|
['', '/usr/lib/python24.zip', '/usr/lib/python2.4', '/usr/lib/python2.4/plat-linux2', '/usr/lib/python2.4/lib-tk', '/usr/lib/python2.4/lib-dynload', '/usr/local/lib/python2.4/site-packages', '/usr/lib/python2.4/site-packages', '/usr/lib/python2.4/site-packages/Numeric', '/var/lib/python-support/python2.4', '/usr/lib/site-python']
|
||
|
>>>
|
||
|
@end example
|
||
|
|
||
|
In this case, putting the code into
|
||
|
/usr/local/lib/python2.4/site-packages/framboozle.py would work just
|
||
|
fine. We can use the same master.cfg "import framboozle" statement as
|
||
|
in Option 2. By putting it in a standard include directory (instead of
|
||
|
the decidedly non-standard ~/lib/python), we don't even have to set
|
||
|
PYTHONPATH to anything special. The downside is that you probably have
|
||
|
to be root to write to one of those standard include directories.
|
||
|
|
||
|
|
||
|
Option 4: Submit the code for inclusion in the Buildbot distribution
|
||
|
|
||
|
Contribute the code in an Enhancement Request on SourceForge, via
|
||
|
http://buildbot.sf.net . Lobby, convince, coerce, bribe, badger,
|
||
|
harass, threaten, or otherwise encourage the author to accept the
|
||
|
patch. This lets you do something like:
|
||
|
|
||
|
@example
|
||
|
from buildbot.steps import framboozle
|
||
|
f = BuildFactory()
|
||
|
f.addStep(SVN, svnurl="stuff")
|
||
|
f.addStep(framboozle.Framboozle)
|
||
|
@end example
|
||
|
|
||
|
And then you don't even have to install framboozle.py anywhere on your
|
||
|
system, since it will ship with Buildbot. You don't have to be root,
|
||
|
you don't have to set PYTHONPATH. But you do have to make a good case
|
||
|
for Framboozle being worth going into the main distribution, you'll
|
||
|
probably have to provide docs and some unit test cases, you'll need to
|
||
|
figure out what kind of beer the author likes, and then you'll have to
|
||
|
wait until the next release. But in some environments, all this is
|
||
|
easier than getting root on your buildmaster box, so the tradeoffs may
|
||
|
actually be worth it.
|
||
|
|
||
|
|
||
|
|
||
|
Putting the code in master.cfg (1) makes it available to that
|
||
|
buildmaster instance. Putting it in a file in a personal library
|
||
|
directory (2) makes it available for any buildmasters you might be
|
||
|
running. Putting it in a file in a system-wide shared library
|
||
|
directory (3) makes it available for any buildmasters that anyone on
|
||
|
that system might be running. Getting it into the buildbot's upstream
|
||
|
repository (4) makes it available for any buildmasters that anyone in
|
||
|
the world might be running. It's all a matter of how widely you want
|
||
|
to deploy that new class.
|
||
|
|
||
|
|
||
|
|
||
|
@node BuildStep URLs, , Adding LogObservers, Writing New BuildSteps
|
||
|
@subsubsection BuildStep URLs
|
||
|
|
||
|
@cindex links
|
||
|
@cindex BuildStep URLs
|
||
|
@cindex addURL
|
||
|
|
||
|
Each BuildStep has a collection of ``links''. Like its collection of
|
||
|
LogFiles, each link has a name and a target URL. The web status page
|
||
|
creates HREFs for each link in the same box as it does for LogFiles,
|
||
|
except that the target of the link is the external URL instead of an
|
||
|
internal link to a page that shows the contents of the LogFile.
|
||
|
|
||
|
These external links can be used to point at build information hosted
|
||
|
on other servers. For example, the test process might produce an
|
||
|
intricate description of which tests passed and failed, or some sort
|
||
|
of code coverage data in HTML form, or a PNG or GIF image with a graph
|
||
|
of memory usage over time. The external link can provide an easy way
|
||
|
for users to navigate from the buildbot's status page to these
|
||
|
external web sites or file servers. Note that the step itself is
|
||
|
responsible for insuring that there will be a document available at
|
||
|
the given URL (perhaps by using @command{scp} to copy the HTML output
|
||
|
to a @file{~/public_html/} directory on a remote web server). Calling
|
||
|
@code{addURL} does not magically populate a web server.
|
||
|
|
||
|
To set one of these links, the BuildStep should call the @code{addURL}
|
||
|
method with the name of the link and the target URL. Multiple URLs can
|
||
|
be set.
|
||
|
|
||
|
In this example, we assume that the @command{make test} command causes
|
||
|
a collection of HTML files to be created and put somewhere on the
|
||
|
coverage.example.org web server, in a filename that incorporates the
|
||
|
build number.
|
||
|
|
||
|
@example
|
||
|
class TestWithCodeCoverage(BuildStep):
|
||
|
command = ["make", "test",
|
||
|
WithProperties("buildnum=%s" % "buildnumber")]
|
||
|
|
||
|
def createSummary(self, log):
|
||
|
buildnumber = self.getProperty("buildnumber")
|
||
|
url = "http://coverage.example.org/builds/%s.html" % buildnumber
|
||
|
self.addURL("coverage", url)
|
||
|
@end example
|
||
|
|
||
|
You might also want to extract the URL from some special message
|
||
|
output by the build process itself:
|
||
|
|
||
|
@example
|
||
|
class TestWithCodeCoverage(BuildStep):
|
||
|
command = ["make", "test",
|
||
|
WithProperties("buildnum=%s" % "buildnumber")]
|
||
|
|
||
|
def createSummary(self, log):
|
||
|
output = StringIO(log.getText())
|
||
|
for line in output.readlines():
|
||
|
if line.startswith("coverage-url:"):
|
||
|
url = line[len("coverage-url:"):].strip()
|
||
|
self.addURL("coverage", url)
|
||
|
return
|
||
|
@end example
|
||
|
|
||
|
Note that a build process which emits both stdout and stderr might
|
||
|
cause this line to be split or interleaved between other lines. It
|
||
|
might be necessary to restrict the getText() call to only stdout with
|
||
|
something like this:
|
||
|
|
||
|
@example
|
||
|
output = StringIO("".join([c[1]
|
||
|
for c in log.getChunks()
|
||
|
if c[0] == LOG_CHANNEL_STDOUT]))
|
||
|
@end example
|
||
|
|
||
|
Of course if the build is run under a PTY, then stdout and stderr will
|
||
|
be merged before the buildbot ever sees them, so such interleaving
|
||
|
will be unavoidable.
|
||
|
|
||
|
|
||
|
@node Interlocks, Build Factories, Build Steps, Build Process
|
||
|
@section Interlocks
|
||
|
|
||
|
@cindex locks
|
||
|
@slindex buildbot.locks.MasterLock
|
||
|
@slindex buildbot.locks.SlaveLock
|
||
|
|
||
|
For various reasons, you may want to prevent certain Steps (or perhaps
|
||
|
entire Builds) from running simultaneously. Limited CPU speed or
|
||
|
network bandwidth to the VC server, problems with simultaneous access
|
||
|
to a database server used by unit tests, or multiple Builds which
|
||
|
access shared state may all require some kind of interlock to prevent
|
||
|
corruption, confusion, or resource overload. These resources might
|
||
|
require completely exclusive access, or it might be sufficient to
|
||
|
establish a limit of two or three simultaneous builds.
|
||
|
|
||
|
@code{Locks} are the mechanism used to express these kinds of
|
||
|
constraints on when Builds or Steps can be run. There are two kinds of
|
||
|
@code{Locks}, each with their own scope: @code{MasterLock} instances
|
||
|
are scoped to the buildbot as a whole, while @code{SlaveLock}s are
|
||
|
scoped to a single buildslave. This means that each buildslave has a
|
||
|
separate copy of each @code{SlaveLock}, which could enforce a
|
||
|
one-Build-at-a-time limit for each machine, but still allow as many
|
||
|
simultaneous builds as there are machines.
|
||
|
|
||
|
Each @code{Lock} is created with a unique name. Each lock gets a count
|
||
|
of how many owners it may have: how many processes can claim it at ths
|
||
|
same time. This limit defaults to one, and is controllable through the
|
||
|
@code{maxCount} argument. On @code{SlaveLock}s you can set the owner
|
||
|
count on a per-slave basis by providing a dictionary (that maps from
|
||
|
slavename to maximum owner count) to its @code{maxCountForSlave}
|
||
|
argument. Any buildslaves that aren't mentioned in
|
||
|
@code{maxCountForSlave} get their owner count from @code{maxCount}.
|
||
|
|
||
|
To use a lock, simply include it in the @code{locks=} argument of the
|
||
|
@code{BuildStep} object that should obtain the lock before it runs.
|
||
|
This argument accepts a list of @code{Lock} objects: the Step will
|
||
|
acquire all of them before it runs.
|
||
|
|
||
|
To claim a lock for the whole Build, add a @code{'locks'} key to the
|
||
|
builder specification dictionary with the same list of @code{Lock}
|
||
|
objects. (This is the dictionary that has the @code{'name'},
|
||
|
@code{'slavename'}, @code{'builddir'}, and @code{'factory'} keys). The
|
||
|
@code{Build} object also accepts a @code{locks=} argument, but unless
|
||
|
you are writing your own @code{BuildFactory} subclass then it will be
|
||
|
easier to set the locks in the builder dictionary.
|
||
|
|
||
|
Note that there are no partial-acquire or partial-release semantics:
|
||
|
this prevents deadlocks caused by two Steps each waiting for a lock
|
||
|
held by the other@footnote{Also note that a clever buildmaster admin
|
||
|
could still create the opportunity for deadlock: Build A obtains Lock
|
||
|
1, inside which Step A.two tries to acquire Lock 2 at the Step level.
|
||
|
Meanwhile Build B obtains Lock 2, and has a Step B.two which wants to
|
||
|
acquire Lock 1 at the Step level. Don't Do That.}. This also means
|
||
|
that waiting to acquire a @code{Lock} can take an arbitrarily long
|
||
|
time: if the buildmaster is very busy, a Step or Build which requires
|
||
|
only one @code{Lock} may starve another that is waiting for that
|
||
|
@code{Lock} plus some others.
|
||
|
|
||
|
|
||
|
In the following example, we run the same build on three different
|
||
|
platforms. The unit-test steps of these builds all use a common
|
||
|
database server, and would interfere with each other if allowed to run
|
||
|
simultaneously. The @code{Lock} prevents more than one of these builds
|
||
|
from happening at the same time.
|
||
|
|
||
|
@example
|
||
|
from buildbot import locks
|
||
|
from buildbot.steps import source, shell
|
||
|
from buildbot.process import factory
|
||
|
|
||
|
db_lock = locks.MasterLock("database")
|
||
|
f = factory.BuildFactory()
|
||
|
f.addStep(source.SVN, svnurl="http://example.org/svn/Trunk")
|
||
|
f.addStep(shell.ShellCommand, command="make all")
|
||
|
f.addStep(shell.ShellCommand, command="make test", locks=[db_lock])
|
||
|
b1 = @{'name': 'full1', 'slavename': 'bot-1', builddir='f1', 'factory': f@}
|
||
|
b2 = @{'name': 'full2', 'slavename': 'bot-2', builddir='f2', 'factory': f@}
|
||
|
b3 = @{'name': 'full3', 'slavename': 'bot-3', builddir='f3', 'factory': f@}
|
||
|
c['builders'] = [b1, b2, b3]
|
||
|
@end example
|
||
|
|
||
|
In the next example, we have one buildslave hosting three separate
|
||
|
Builders (each running tests against a different version of Python).
|
||
|
The machine which hosts this buildslave is not particularly fast, so
|
||
|
we want to prevent all three builds from all happening at the same
|
||
|
time. (Assume we've experimentally determined that one build leaves
|
||
|
unused CPU capacity, three builds causes a lot of disk thrashing, but
|
||
|
two builds at a time is Just Right). We use a @code{SlaveLock} because
|
||
|
the builds happening on this one slow slave should not affect builds
|
||
|
running on other slaves, and we use the lock on the build as a whole
|
||
|
because the slave is so slow that even multiple simultaneous SVN
|
||
|
checkouts would be too taxing. We set @code{maxCount=2} to achieve our
|
||
|
goal of two simultaneous builds per slave.
|
||
|
|
||
|
@example
|
||
|
from buildbot import locks
|
||
|
from buildbot.steps import source
|
||
|
from buildbot.process import s, factory
|
||
|
|
||
|
slow_lock = locks.SlaveLock("cpu", maxCount=2)
|
||
|
source = s(source.SVN, svnurl="http://example.org/svn/Trunk")
|
||
|
f22 = factory.Trial(source, trialpython=["python2.2"])
|
||
|
f23 = factory.Trial(source, trialpython=["python2.3"])
|
||
|
f24 = factory.Trial(source, trialpython=["python2.4"])
|
||
|
b1 = @{'name': 'p22', 'slavename': 'bot-1', builddir='p22', 'factory': f22,
|
||
|
'locks': [slow_lock] @}
|
||
|
b2 = @{'name': 'p23', 'slavename': 'bot-1', builddir='p23', 'factory': f23,
|
||
|
'locks': [slow_lock] @}
|
||
|
b3 = @{'name': 'p24', 'slavename': 'bot-1', builddir='p24', 'factory': f24,
|
||
|
'locks': [slow_lock] @}
|
||
|
c['builders'] = [b1, b2, b3]
|
||
|
@end example
|
||
|
|
||
|
In the last example, we use two Locks at the same time. In this case,
|
||
|
we're concerned about both of the previous constraints, but we'll say
|
||
|
that only the tests are computationally intensive, and that they have
|
||
|
been split into those which use the database and those which do not.
|
||
|
In addition, two of the Builds run on a fast machine which does not
|
||
|
need to worry about the cpu lock, but which still must be prevented
|
||
|
from simultaneous database access. We use @code{maxCountForSlave} to
|
||
|
limit the slow machine to one simultanous build, but allow practically
|
||
|
unlimited concurrent builds on the fast machine.
|
||
|
|
||
|
@example
|
||
|
from buildbot import locks
|
||
|
from buildbot.steps import source, shell
|
||
|
from buildbot.process import factory
|
||
|
|
||
|
db_lock = locks.MasterLock("database")
|
||
|
slavecounts = @{"bot-slow": 1, "bot-fast": 100@}
|
||
|
cpu_lock = locks.SlaveLock("cpu", maxCountForSlave=slavecounts)
|
||
|
f = factory.BuildFactory()
|
||
|
f.addStep(source.SVN, svnurl="http://example.org/svn/Trunk")
|
||
|
f.addStep(shell.ShellCommand, command="make all", locks=[cpu_lock])
|
||
|
f.addStep(shell.ShellCommand, command="make test", locks=[cpu_lock])
|
||
|
f.addStep(shell.ShellCommand, command="make db-test",
|
||
|
locks=[db_lock, cpu_lock])
|
||
|
|
||
|
b1 = @{'name': 'full1', 'slavename': 'bot-slow', builddir='full1',
|
||
|
'factory': f@}
|
||
|
b2 = @{'name': 'full2', 'slavename': 'bot-slow', builddir='full2',
|
||
|
'factory': f@}
|
||
|
b3 = @{'name': 'full3', 'slavename': 'bot-fast', builddir='full3',
|
||
|
'factory': f@}
|
||
|
b4 = @{'name': 'full4', 'slavename': 'bot-fast', builddir='full4',
|
||
|
'factory': f@}
|
||
|
c['builders'] = [b1, b2, b3, b4]
|
||
|
@end example
|
||
|
|
||
|
As a final note, remember that a unit test system which breaks when
|
||
|
multiple people run it at the same time is fragile and should be
|
||
|
fixed. Asking your human developers to serialize themselves when
|
||
|
running unit tests will just discourage them from running the unit
|
||
|
tests at all. Find a way to fix this: change the database tests to
|
||
|
create a new (uniquely-named) user or table for each test run, don't
|
||
|
use fixed listening TCP ports for network tests (instead listen on
|
||
|
port 0 to let the kernel choose a port for you and then query the
|
||
|
socket to find out what port was allocated). @code{MasterLock}s can be
|
||
|
used to accomodate broken test systems like this, but are really
|
||
|
intended for other purposes: build processes that store or retrieve
|
||
|
products in shared directories, or which do things that human
|
||
|
developers would not (or which might slow down or break in ways that
|
||
|
require human attention to deal with).
|
||
|
|
||
|
@code{SlaveLocks}s can be used to keep automated performance tests
|
||
|
from interfering with each other, when there are multiple Builders all
|
||
|
using the same buildslave. But they can't prevent other users from
|
||
|
running CPU-intensive jobs on that host while the tests are running.
|
||
|
|
||
|
@node Build Factories, , Interlocks, Build Process
|
||
|
@section Build Factories
|
||
|
|
||
|
|
||
|
Each Builder is equipped with a ``build factory'', which is
|
||
|
responsible for producing the actual @code{Build} objects that perform
|
||
|
each build. This factory is created in the configuration file, and
|
||
|
attached to a Builder through the @code{factory} element of its
|
||
|
dictionary.
|
||
|
|
||
|
The standard @code{BuildFactory} object creates @code{Build} objects
|
||
|
by default. These Builds will each execute a collection of BuildSteps
|
||
|
in a fixed sequence. Each step can affect the results of the build,
|
||
|
but in general there is little intelligence to tie the different steps
|
||
|
together. You can create subclasses of @code{Build} to implement more
|
||
|
sophisticated build processes, and then use a subclass of
|
||
|
@code{BuildFactory} (or simply set the @code{buildClass} attribute) to
|
||
|
create instances of your new Build subclass.
|
||
|
|
||
|
|
||
|
@menu
|
||
|
* BuildStep Objects::
|
||
|
* BuildFactory::
|
||
|
* Process-Specific build factories::
|
||
|
@end menu
|
||
|
|
||
|
@node BuildStep Objects, BuildFactory, Build Factories, Build Factories
|
||
|
@subsection BuildStep Objects
|
||
|
|
||
|
The steps used by these builds are all subclasses of @code{BuildStep}.
|
||
|
The standard ones provided with Buildbot are documented later,
|
||
|
@xref{Build Steps}. You can also write your own subclasses to use in
|
||
|
builds.
|
||
|
|
||
|
The basic behavior for a @code{BuildStep} is to:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
run for a while, then stop
|
||
|
@item
|
||
|
possibly invoke some RemoteCommands on the attached build slave
|
||
|
@item
|
||
|
possibly produce a set of log files
|
||
|
@item
|
||
|
finish with a status described by one of four values defined in
|
||
|
buildbot.status.builder: SUCCESS, WARNINGS, FAILURE, SKIPPED
|
||
|
@item
|
||
|
provide a list of short strings to describe the step
|
||
|
@item
|
||
|
define a color (generally green, orange, or red) with which the
|
||
|
step should be displayed
|
||
|
@end itemize
|
||
|
|
||
|
|
||
|
More sophisticated steps may produce additional information and
|
||
|
provide it to later build steps, or store it in the factory to provide
|
||
|
to later builds.
|
||
|
|
||
|
|
||
|
@menu
|
||
|
* BuildFactory Attributes::
|
||
|
* Quick builds::
|
||
|
@end menu
|
||
|
|
||
|
@node BuildFactory, Process-Specific build factories, BuildStep Objects, Build Factories
|
||
|
@subsection BuildFactory
|
||
|
|
||
|
@bfindex buildbot.process.factory.BuildFactory
|
||
|
@bfindex buildbot.process.factory.BasicBuildFactory
|
||
|
@c TODO: what is BasicSVN anyway?
|
||
|
@bfindex buildbot.process.factory.BasicSVN
|
||
|
|
||
|
The default @code{BuildFactory}, provided in the
|
||
|
@code{buildbot.process.factory} module, contains a list of ``BuildStep
|
||
|
specifications'': a list of @code{(step_class, kwargs)} tuples for
|
||
|
each. When asked to create a Build, it loads the list of steps 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. For example, a build which consists
|
||
|
of a CVS checkout followed by a @code{make build} would be constructed
|
||
|
as follows:
|
||
|
|
||
|
@example
|
||
|
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"])
|
||
|
@end example
|
||
|
|
||
|
It is also possible to pass a list of step specifications into the
|
||
|
@code{BuildFactory} when it is created. Using @code{addStep} is
|
||
|
usually simpler, but there are cases where is is more convenient to
|
||
|
create the list of steps ahead of time. To make this approach easier,
|
||
|
a convenience function named @code{s} is available:
|
||
|
|
||
|
@example
|
||
|
from buildbot.steps import source, shell
|
||
|
from buildbot.process import factory
|
||
|
from buildbot.factory import s
|
||
|
# s is a convenience function, defined with:
|
||
|
# def s(steptype, **kwargs): return (steptype, kwargs)
|
||
|
|
||
|
all_steps = [s(source.CVS, cvsroot=CVSROOT, cvsmodule="project",
|
||
|
mode="update"),
|
||
|
s(shell.Compile, command=["make", "build"]),
|
||
|
]
|
||
|
f = factory.BuildFactory(all_steps)
|
||
|
@end example
|
||
|
|
||
|
|
||
|
Each step can affect the build process in the following ways:
|
||
|
|
||
|
@itemize @bullet
|
||
|
@item
|
||
|
If the step's @code{haltOnFailure} attribute is True, then a failure
|
||
|
in the step (i.e. if it completes with a result of FAILURE) will cause
|
||
|
the whole build to be terminated immediately: no further steps will be
|
||
|
executed. This is useful for setup steps upon which the rest of the
|
||
|
build depends: if the CVS checkout or @code{./configure} process
|
||
|
fails, there is no point in trying to compile or test the resulting
|
||
|
tree.
|
||
|
|
||
|
@item
|
||
|
If the @code{flunkOnFailure} or @code{flunkOnWarnings} flag is set,
|
||
|
then a result of FAILURE or WARNINGS will mark the build as a whole as
|
||
|
FAILED. However, the remaining steps will still be executed. This is
|
||
|
appropriate for things like multiple testing steps: a failure in any
|
||
|
one of them will indicate that the build has failed, however it is
|
||
|
still useful to run them all to completion.
|
||
|
|
||
|
@item
|
||
|
Similarly, if the @code{warnOnFailure} or @code{warnOnWarnings} flag
|
||
|
is set, then a result of FAILURE or WARNINGS will mark the build as
|
||
|
having WARNINGS, and the remaining steps will still be executed. This
|
||
|
may be appropriate for certain kinds of optional build or test steps.
|
||
|
For example, a failure experienced while building documentation files
|
||
|
should be made visible with a WARNINGS result but not be serious
|
||
|
enough to warrant marking the whole build with a FAILURE.
|
||
|
|
||
|
@end itemize
|
||
|
|
||
|
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 @code{CVS} and @code{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
|
||
|
@code{CVS} class has the @code{haltOnFailure} flag set to True. Look
|
||
|
in @file{buildbot/process/step.py} to see how the other Steps are
|
||
|
marked.
|
||
|
|
||
|
Each Step is created with an additional @code{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 @code{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.
|
||
|
|
||
|
@menu
|
||
|
* BuildFactory Attributes::
|
||
|
* Quick builds::
|
||
|
@end menu
|
||
|
|
||
|
@node BuildFactory Attributes, Quick builds, BuildFactory, BuildFactory
|
||
|
@subsubsection BuildFactory Attributes
|
||
|
|
||
|
Some attributes from the BuildFactory are copied into each Build.
|
||
|
|
||
|
@cindex treeStableTimer
|
||
|
|
||
|
@table @code
|
||
|
@item useProgress
|
||
|
(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.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node Quick builds, , BuildFactory Attributes, BuildFactory
|
||
|
@subsubsection Quick builds
|
||
|
|
||
|
@bfindex buildbot.process.factory.QuickBuildFactory
|
||
|
|
||
|
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 @code{mode='update'} flag, to
|
||
|
do the source update in-place.
|
||
|
|
||
|
In addition to that, the @code{useProgress} flag should be set 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.
|
||
|
|
||
|
|
||
|
@node Process-Specific build factories, , BuildFactory, Build Factories
|
||
|
@subsection Process-Specific build factories
|
||
|
|
||
|
Many projects use one of a few popular build frameworks to simplify
|
||
|
the creation and maintenance of Makefiles or other compilation
|
||
|
structures. Buildbot provides several pre-configured BuildFactory
|
||
|
subclasses which let you build these projects with a minimum of fuss.
|
||
|
|
||
|
@menu
|
||
|
* GNUAutoconf::
|
||
|
* CPAN::
|
||
|
* Python distutils::
|
||
|
* Python/Twisted/trial projects::
|
||
|
@end menu
|
||
|
|
||
|
@node GNUAutoconf, CPAN, Process-Specific build factories, Process-Specific build factories
|
||
|
@subsubsection GNUAutoconf
|
||
|
|
||
|
@bfindex buildbot.process.factory.GNUAutoconf
|
||
|
|
||
|
@uref{http://www.gnu.org/software/autoconf/, 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:
|
||
|
|
||
|
@example
|
||
|
% CONFIG_ENV=foo ./configure --with-flags
|
||
|
% make all
|
||
|
% make check
|
||
|
# make install
|
||
|
@end example
|
||
|
|
||
|
(except of course the Buildbot always skips the @code{make install}
|
||
|
part).
|
||
|
|
||
|
The Buildbot's @code{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.
|
||
|
|
||
|
Example:
|
||
|
|
||
|
@example
|
||
|
# use the s() convenience function defined earlier
|
||
|
f = factory.GNUAutoconf(source=s(step.SVN, svnurl=URL, mode="copy"),
|
||
|
flags=["--disable-nls"])
|
||
|
@end example
|
||
|
|
||
|
Required Arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item source
|
||
|
This argument must be a step specification tuple that provides a
|
||
|
BuildStep to generate the source tree.
|
||
|
@end table
|
||
|
|
||
|
Optional Arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item configure
|
||
|
The command used to configure the tree. Defaults to
|
||
|
@code{./configure}. Accepts either a string or a list of shell argv
|
||
|
elements.
|
||
|
|
||
|
@item configureEnv
|
||
|
The environment used for the initial configuration step. This accepts
|
||
|
a dictionary which will be merged into the buildslave's normal
|
||
|
environment. This is commonly used to provide things like
|
||
|
@code{CFLAGS="-O2 -g"} (to turn off debug symbols during the compile).
|
||
|
Defaults to an empty dictionary.
|
||
|
|
||
|
@item configureFlags
|
||
|
A list of flags to be appended to the argument list of the configure
|
||
|
command. This is commonly used to enable or disable specific features
|
||
|
of the autoconf-controlled package, like @code{["--without-x"]} to
|
||
|
disable windowing support. Defaults to an empty list.
|
||
|
|
||
|
@item compile
|
||
|
this is a shell command or list of argv values which is used to
|
||
|
actually compile the tree. It defaults to @code{make all}. If set to
|
||
|
None, the compile step is skipped.
|
||
|
|
||
|
@item test
|
||
|
this is a shell command or list of argv values which is used to run
|
||
|
the tree's self-tests. It defaults to @code{make check}. If set to
|
||
|
None, the test step is skipped.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node CPAN, Python distutils, GNUAutoconf, Process-Specific build factories
|
||
|
@subsubsection CPAN
|
||
|
|
||
|
@bfindex buildbot.process.factory.CPAN
|
||
|
|
||
|
Most Perl modules available from the @uref{http://www.cpan.org/, CPAN}
|
||
|
archive use the @code{MakeMaker} module to provide configuration,
|
||
|
build, and test services. The standard build routine for these modules
|
||
|
looks like:
|
||
|
|
||
|
@example
|
||
|
% perl Makefile.PL
|
||
|
% make
|
||
|
% make test
|
||
|
# make install
|
||
|
@end example
|
||
|
|
||
|
(except again Buildbot skips the install step)
|
||
|
|
||
|
Buildbot provides a @code{CPAN} factory to compile and test these
|
||
|
projects.
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
@table @code
|
||
|
@item source
|
||
|
(required): A step specification tuple, that that used by GNUAutoconf.
|
||
|
|
||
|
@item perl
|
||
|
A string which specifies the @code{perl} executable to use. Defaults
|
||
|
to just @code{perl}.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node Python distutils, Python/Twisted/trial projects, CPAN, Process-Specific build factories
|
||
|
@subsubsection Python distutils
|
||
|
|
||
|
@bfindex buildbot.process.factory.Distutils
|
||
|
|
||
|
Most Python modules use the @code{distutils} package to provide
|
||
|
configuration and build services. The standard build process looks
|
||
|
like:
|
||
|
|
||
|
@example
|
||
|
% python ./setup.py build
|
||
|
% python ./setup.py install
|
||
|
@end example
|
||
|
|
||
|
Unfortunately, although Python provides a standard unit-test framework
|
||
|
named @code{unittest}, to the best of my knowledge @code{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 @code{Distutils} factory provides support for running the build
|
||
|
part of this process. It accepts the same @code{source=} parameter as
|
||
|
the other build factories.
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
@table @code
|
||
|
@item source
|
||
|
(required): A step specification tuple, that that used by GNUAutoconf.
|
||
|
|
||
|
@item python
|
||
|
A string which specifies the @code{python} executable to use. Defaults
|
||
|
to just @code{python}.
|
||
|
|
||
|
@item test
|
||
|
Provides a shell command which runs unit tests. This accepts either a
|
||
|
string or a list. The default value is None, which disables the test
|
||
|
step (since there is no common default command to run unit tests in
|
||
|
distutils modules).
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node Python/Twisted/trial projects, , Python distutils, Process-Specific build factories
|
||
|
@subsubsection Python/Twisted/trial projects
|
||
|
|
||
|
@bfindex buildbot.process.factory.Trial
|
||
|
@c TODO: document these steps better
|
||
|
@bsindex buildbot.steps.python_twisted.HLint
|
||
|
@bsindex buildbot.steps.python_twisted.Trial
|
||
|
@bsindex buildbot.steps.python_twisted.ProcessDocs
|
||
|
@bsindex buildbot.steps.python_twisted.BuildDebs
|
||
|
@bsindex buildbot.steps.python_twisted.RemovePYCs
|
||
|
|
||
|
Twisted provides a unit test tool named @code{trial} which provides a
|
||
|
few improvements over Python's built-in @code{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:
|
||
|
|
||
|
@example
|
||
|
% python ./setup.py build
|
||
|
% PYTHONPATH=build/lib.linux-i686-2.3 trial -v PROJECTNAME.test
|
||
|
% python ./setup.py install
|
||
|
@end example
|
||
|
|
||
|
Unfortunately, the @file{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 (@code{PYTHONPATH=.}).
|
||
|
|
||
|
In addition, the @var{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 @code{test} sub-module. This value cannot be
|
||
|
guessed, the @code{Trial} class must be told where to find the test
|
||
|
files.
|
||
|
|
||
|
The @code{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 @code{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.
|
||
|
|
||
|
Arguments:
|
||
|
@table @code
|
||
|
@item source
|
||
|
(required): A step specification tuple, like that used by GNUAutoconf.
|
||
|
|
||
|
@item buildpython
|
||
|
A list (argv array) of strings which specifies the @code{python}
|
||
|
executable to use when building the package. Defaults to just
|
||
|
@code{['python']}. It may be useful to add flags here, to supress
|
||
|
warnings during compilation of extension modules. This list is
|
||
|
extended with @code{['./setup.py', 'build']} and then executed in a
|
||
|
ShellCommand.
|
||
|
|
||
|
@item testpath
|
||
|
Provides a directory to add to @code{PYTHONPATH} when running the unit
|
||
|
tests, if tests are being run. Defaults to @code{.} to include the
|
||
|
project files in-place. The generated build library is frequently
|
||
|
architecture-dependent, but may simply be @file{build/lib} for
|
||
|
pure-python modules.
|
||
|
|
||
|
@item trialpython
|
||
|
Another list of strings used to build the command that actually runs
|
||
|
trial. This is prepended to the contents of the @code{trial} argument
|
||
|
below. It may be useful to add @code{-W} flags here to supress
|
||
|
warnings that occur while tests are being run. Defaults to an empty
|
||
|
list, meaning @code{trial} will be run without an explicit
|
||
|
interpreter, which is generally what you want if you're using
|
||
|
@file{/usr/bin/trial} instead of, say, the @file{./bin/trial} that
|
||
|
lives in the Twisted source tree.
|
||
|
|
||
|
@item trial
|
||
|
provides the name of the @code{trial} command. It is occasionally
|
||
|
useful to use an alternate executable, such as @code{trial2.2} which
|
||
|
might run the tests under an older version of Python. Defaults to
|
||
|
@code{trial}.
|
||
|
|
||
|
@item tests
|
||
|
Provides a module name or names which contain the unit tests for this
|
||
|
project. Accepts a string, typically @code{PROJECTNAME.test}, or a
|
||
|
list of strings. Defaults to None, indicating that no tests should be
|
||
|
run. You must either set this or @code{useTestCaseNames} to do anyting
|
||
|
useful with the Trial factory.
|
||
|
|
||
|
@item useTestCaseNames
|
||
|
Tells the Step to provide the names of all changed .py files to trial,
|
||
|
so it can look for test-case-name tags and run just the matching test
|
||
|
cases. Suitable for use in quick builds. Defaults to False.
|
||
|
|
||
|
@item randomly
|
||
|
If @code{True}, tells Trial (with the @code{--random=0} argument) to
|
||
|
run the test cases in random order, which sometimes catches subtle
|
||
|
inter-test dependency bugs. Defaults to @code{False}.
|
||
|
|
||
|
@item recurse
|
||
|
If @code{True}, tells Trial (with the @code{--recurse} argument) to
|
||
|
look in all subdirectories for additional test cases. It isn't clear
|
||
|
to me how this works, but it may be useful to deal with the
|
||
|
unknown-PROJECTNAME problem described above, and is currently used in
|
||
|
the Twisted buildbot to accomodate the fact that test cases are now
|
||
|
distributed through multiple twisted.SUBPROJECT.test directories.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
Unless one of @code{trialModule} or @code{useTestCaseNames}
|
||
|
are set, no tests will be run.
|
||
|
|
||
|
Some quick examples follow. Most of these examples assume that the
|
||
|
target python code (the ``code under test'') can be reached directly
|
||
|
from the root of the target tree, rather than being in a @file{lib/}
|
||
|
subdirectory.
|
||
|
|
||
|
@example
|
||
|
# Trial(source, tests="toplevel.test") does:
|
||
|
# python ./setup.py build
|
||
|
# PYTHONPATH=. trial -to toplevel.test
|
||
|
|
||
|
# Trial(source, tests=["toplevel.test", "other.test"]) does:
|
||
|
# python ./setup.py build
|
||
|
# PYTHONPATH=. trial -to toplevel.test other.test
|
||
|
|
||
|
# Trial(source, useTestCaseNames=True) does:
|
||
|
# python ./setup.py build
|
||
|
# PYTHONPATH=. trial -to --testmodule=foo/bar.py.. (from Changes)
|
||
|
|
||
|
# Trial(source, buildpython=["python2.3", "-Wall"], tests="foo.tests"):
|
||
|
# python2.3 -Wall ./setup.py build
|
||
|
# PYTHONPATH=. trial -to foo.tests
|
||
|
|
||
|
# Trial(source, trialpython="python2.3", trial="/usr/bin/trial",
|
||
|
# tests="foo.tests") does:
|
||
|
# python2.3 -Wall ./setup.py build
|
||
|
# PYTHONPATH=. python2.3 /usr/bin/trial -to foo.tests
|
||
|
|
||
|
# For running trial out of the tree being tested (only useful when the
|
||
|
# tree being built is Twisted itself):
|
||
|
# Trial(source, trialpython=["python2.3", "-Wall"], trial="./bin/trial",
|
||
|
# tests="foo.tests") does:
|
||
|
# python2.3 -Wall ./setup.py build
|
||
|
# PYTHONPATH=. python2.3 -Wall ./bin/trial -to foo.tests
|
||
|
@end example
|
||
|
|
||
|
If the output directory of @code{./setup.py build} is known, you can
|
||
|
pull the python code from the built location instead of the source
|
||
|
directories. This should be able to handle variations in where the
|
||
|
source comes from, as well as accomodating binary extension modules:
|
||
|
|
||
|
@example
|
||
|
# Trial(source,tests="toplevel.test",testpath='build/lib.linux-i686-2.3')
|
||
|
# does:
|
||
|
# python ./setup.py build
|
||
|
# PYTHONPATH=build/lib.linux-i686-2.3 trial -to toplevel.test
|
||
|
@end example
|
||
|
|
||
|
|
||
|
@node Status Delivery, Command-line tool, Build Process, Top
|
||
|
@chapter Status Delivery
|
||
|
|
||
|
More details are available in the docstrings for each class, use
|
||
|
@code{pydoc buildbot.status.html.Waterfall} to see them. Most status
|
||
|
delivery objects take a @code{categories=} argument, which can contain
|
||
|
a list of ``category'' names: in this case, it will only show status
|
||
|
for Builders that are in one of the named categories.
|
||
|
|
||
|
(implementor's note: each of these objects should be a
|
||
|
service.MultiService which will be attached to the BuildMaster object
|
||
|
when the configuration is processed. They should use
|
||
|
@code{self.parent.getStatus()} to get access to the top-level IStatus
|
||
|
object, either inside @code{startService} or later. They may call
|
||
|
@code{status.subscribe()} in @code{startService} to receive
|
||
|
notifications of builder events, in which case they must define
|
||
|
@code{builderAdded} and related methods. See the docstrings in
|
||
|
@file{buildbot/interfaces.py} for full details.)
|
||
|
|
||
|
@menu
|
||
|
* HTML Waterfall::
|
||
|
* IRC Bot::
|
||
|
* PBListener::
|
||
|
* Writing New Status Plugins::
|
||
|
@end menu
|
||
|
|
||
|
@c @node Email Delivery, , Status Delivery, Status Delivery
|
||
|
@c @subsection Email Delivery
|
||
|
|
||
|
@c DOCUMENT THIS
|
||
|
|
||
|
@node HTML Waterfall, IRC Bot, Status Delivery, Status Delivery
|
||
|
@section HTML Waterfall
|
||
|
|
||
|
@cindex Waterfall
|
||
|
@stindex buildbot.status.html.Waterfall
|
||
|
|
||
|
|
||
|
@example
|
||
|
from buildbot.status import html
|
||
|
w = html.Waterfall(http_port=8080)
|
||
|
c['status'].append(w)
|
||
|
@end example
|
||
|
|
||
|
The @code{buildbot.status.html.Waterfall} status target creates an
|
||
|
HTML ``waterfall display'', which shows a time-based chart of events.
|
||
|
This display provides detailed information about all steps of all
|
||
|
recent builds, and provides hyperlinks to look at individual build
|
||
|
logs and source changes. If the @code{http_port} argument is provided,
|
||
|
it provides a strports specification for the port that the web server
|
||
|
should listen on. This can be a simple port number, or a string like
|
||
|
@code{tcp:8080:interface=127.0.0.1} (to limit connections to the
|
||
|
loopback interface, and therefore to clients running on the same
|
||
|
host)@footnote{It may even be possible to provide SSL access by using
|
||
|
a specification like
|
||
|
@code{"ssl:12345:privateKey=mykey.pen:certKey=cert.pem"}, but this is
|
||
|
completely untested}.
|
||
|
|
||
|
If instead (or in addition) you provide the @code{distrib_port}
|
||
|
argument, a twisted.web distributed server will be started either on a
|
||
|
TCP port (if @code{distrib_port} is like @code{"tcp:12345"}) or more
|
||
|
likely on a UNIX socket (if @code{distrib_port} is like
|
||
|
@code{"unix:/path/to/socket"}).
|
||
|
|
||
|
The @code{distrib_port} option means that, on a host with a
|
||
|
suitably-configured twisted-web server, you do not need to consume a
|
||
|
separate TCP port for the buildmaster's status web page. When the web
|
||
|
server is constructed with @code{mktap web --user}, URLs that point to
|
||
|
@code{http://host/~username/} are dispatched to a sub-server that is
|
||
|
listening on a UNIX socket at @code{~username/.twisted-web-pb}. On
|
||
|
such a system, it is convenient to create a dedicated @code{buildbot}
|
||
|
user, then set @code{distrib_port} to
|
||
|
@code{"unix:"+os.path.expanduser("~/.twistd-web-pb")}. This
|
||
|
configuration will make the HTML status page available at
|
||
|
@code{http://host/~buildbot/} . Suitable URL remapping can make it
|
||
|
appear at @code{http://host/buildbot/}, and the right virtual host
|
||
|
setup can even place it at @code{http://buildbot.host/} .
|
||
|
|
||
|
Other arguments:
|
||
|
|
||
|
@table @code
|
||
|
@item allowForce
|
||
|
If set to True (the default), then the web page will provide a ``Force
|
||
|
Build'' button that allows visitors to manually trigger builds. This
|
||
|
is useful for developers to re-run builds that have failed because of
|
||
|
intermittent problems in the test suite, or because of libraries that
|
||
|
were not installed at the time of the previous build. You may not wish
|
||
|
to allow strangers to cause a build to run: in that case, set this to
|
||
|
False to remove these buttons.
|
||
|
|
||
|
@item favicon
|
||
|
If set to a string, this will be interpreted as a filename containing
|
||
|
a ``favicon'': a small image that contains an icon for the web site.
|
||
|
This is returned to browsers that request the @code{favicon.ico} file,
|
||
|
and should point to a .png or .ico image file. The default value uses
|
||
|
the buildbot/buildbot.png image (a small hex nut) contained in the
|
||
|
buildbot distribution. You can set this to None to avoid using a
|
||
|
favicon at all.
|
||
|
|
||
|
@item robots_txt
|
||
|
If set to a string, this will be interpreted as a filename containing
|
||
|
the contents of ``robots.txt''. Many search engine spiders request
|
||
|
this file before indexing the site. Setting it to a file which
|
||
|
contains:
|
||
|
@example
|
||
|
User-agent: *
|
||
|
Disallow: /
|
||
|
@end example
|
||
|
will prevent most search engines from trawling the (voluminous)
|
||
|
generated status pages.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node IRC Bot, PBListener, HTML Waterfall, Status Delivery
|
||
|
@section IRC Bot
|
||
|
|
||
|
@cindex IRC
|
||
|
@stindex buildbot.status.words.IRC
|
||
|
|
||
|
|
||
|
The @code{buildbot.status.words.IRC} status target creates an IRC bot
|
||
|
which will attach to certain channels and be available for status
|
||
|
queries. It can also be asked to announce builds as they occur, or be
|
||
|
told to shut up.
|
||
|
|
||
|
@example
|
||
|
from twisted.status import words
|
||
|
irc = words.IRC("irc.example.org", "botnickname",
|
||
|
channels=["channel1", "channel2"],
|
||
|
password="mysecretpassword")
|
||
|
c['status'].append(irc)
|
||
|
@end example
|
||
|
|
||
|
Take a look at the docstring for @code{words.IRC} for more details on
|
||
|
configuring this service. The @code{password} argument, if provided,
|
||
|
will be sent to Nickserv to claim the nickname: some IRC servers will
|
||
|
not allow clients to send private messages until they have logged in
|
||
|
with a password.
|
||
|
|
||
|
To use the service, you address messages at the buildbot, either
|
||
|
normally (@code{botnickname: status}) or with private messages
|
||
|
(@code{/msg botnickname status}). The buildbot will respond in kind.
|
||
|
|
||
|
Some of the commands currently available:
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item list builders
|
||
|
Emit a list of all configured builders
|
||
|
@item status BUILDER
|
||
|
Announce the status of a specific Builder: what it is doing right now.
|
||
|
@item status all
|
||
|
Announce the status of all Builders
|
||
|
@item watch BUILDER
|
||
|
If the given Builder is currently running, wait until the Build is
|
||
|
finished and then announce the results.
|
||
|
@item last BUILDER
|
||
|
Return the results of the last build to run on the given Builder.
|
||
|
|
||
|
@item help COMMAND
|
||
|
Describe a command. Use @code{help commands} to get a list of known
|
||
|
commands.
|
||
|
@item source
|
||
|
Announce the URL of the Buildbot's home page.
|
||
|
@item version
|
||
|
Announce the version of this Buildbot.
|
||
|
@end table
|
||
|
|
||
|
If the @code{allowForce=True} option was used, some addtional commands
|
||
|
will be available:
|
||
|
|
||
|
@table @code
|
||
|
@item force build BUILDER REASON
|
||
|
Tell the given Builder to start a build of the latest code. The user
|
||
|
requesting the build and REASON are recorded in the Build status. The
|
||
|
buildbot will announce the build's status when it finishes.
|
||
|
|
||
|
@item stop build BUILDER REASON
|
||
|
Terminate any running build in the given Builder. REASON will be added
|
||
|
to the build status to explain why it was stopped. You might use this
|
||
|
if you committed a bug, corrected it right away, and don't want to
|
||
|
wait for the first build (which is destined to fail) to complete
|
||
|
before starting the second (hopefully fixed) build.
|
||
|
@end table
|
||
|
|
||
|
@node PBListener, Writing New Status Plugins, IRC Bot, Status Delivery
|
||
|
@section PBListener
|
||
|
|
||
|
@cindex PBListener
|
||
|
@stindex buildbot.status.client.PBListener
|
||
|
|
||
|
|
||
|
@example
|
||
|
import buildbot.status.client
|
||
|
pbl = buildbot.status.client.PBListener(port=int, user=str,
|
||
|
passwd=str)
|
||
|
c['status'].append(pbl)
|
||
|
@end example
|
||
|
|
||
|
This sets up a PB listener on the given TCP port, to which a PB-based
|
||
|
status client can connect and retrieve status information.
|
||
|
@code{buildbot statusgui} (@pxref{statusgui}) is an example of such a
|
||
|
status client. The @code{port} argument can also be a strports
|
||
|
specification string.
|
||
|
|
||
|
@node Writing New Status Plugins, , PBListener, Status Delivery
|
||
|
@section Writing New Status Plugins
|
||
|
|
||
|
TODO: this needs a lot more examples
|
||
|
|
||
|
Each status plugin is an object which provides the
|
||
|
@code{twisted.application.service.IService} interface, which creates a
|
||
|
tree of Services with the buildmaster at the top [not strictly true].
|
||
|
The status plugins are all children of an object which implements
|
||
|
@code{buildbot.interfaces.IStatus}, the main status object. From this
|
||
|
object, the plugin can retrieve anything it wants about current and
|
||
|
past builds. It can also subscribe to hear about new and upcoming
|
||
|
builds.
|
||
|
|
||
|
Status plugins which only react to human queries (like the Waterfall
|
||
|
display) never need to subscribe to anything: they are idle until
|
||
|
someone asks a question, then wake up and extract the information they
|
||
|
need to answer it, then they go back to sleep. Plugins which need to
|
||
|
act spontaneously when builds complete (like the Mail plugin) need to
|
||
|
subscribe to hear about new builds.
|
||
|
|
||
|
If the status plugin needs to run network services (like the HTTP
|
||
|
server used by the Waterfall plugin), they can be attached as Service
|
||
|
children of the plugin itself, using the @code{IServiceCollection}
|
||
|
interface.
|
||
|
|
||
|
|
||
|
|
||
|
@node Command-line tool, Resources, Status Delivery, Top
|
||
|
@chapter Command-line tool
|
||
|
|
||
|
The @command{buildbot} command-line tool can be used to start or stop a
|
||
|
buildmaster or buildbot, and to interact with a running buildmaster.
|
||
|
Some of its subcommands are intended for buildmaster admins, while
|
||
|
some are for developers who are editing the code that the buildbot is
|
||
|
monitoring.
|
||
|
|
||
|
@menu
|
||
|
* Administrator Tools::
|
||
|
* Developer Tools::
|
||
|
* Other Tools::
|
||
|
* .buildbot config directory::
|
||
|
@end menu
|
||
|
|
||
|
@node Administrator Tools, Developer Tools, Command-line tool, Command-line tool
|
||
|
@section Administrator Tools
|
||
|
|
||
|
The following @command{buildbot} sub-commands are intended for
|
||
|
buildmaster administrators:
|
||
|
|
||
|
@heading create-master
|
||
|
|
||
|
This creates a new directory and populates it with files that allow it
|
||
|
to be used as a buildmaster's base directory.
|
||
|
|
||
|
@example
|
||
|
buildbot create-master BASEDIR
|
||
|
@end example
|
||
|
|
||
|
@heading create-slave
|
||
|
|
||
|
This creates a new directory and populates it with files that let it
|
||
|
be used as a buildslave's base directory. You must provide several
|
||
|
arguments, which are used to create the initial @file{buildbot.tac}
|
||
|
file.
|
||
|
|
||
|
@example
|
||
|
buildbot create-slave @var{BASEDIR} @var{MASTERHOST}:@var{PORT} @var{SLAVENAME} @var{PASSWORD}
|
||
|
@end example
|
||
|
|
||
|
@heading start
|
||
|
|
||
|
This starts a buildmaster or buildslave which was already created in
|
||
|
the given base directory. The daemon is launched in the background,
|
||
|
with events logged to a file named @file{twistd.log}.
|
||
|
|
||
|
@example
|
||
|
buildbot start BASEDIR
|
||
|
@end example
|
||
|
|
||
|
@heading stop
|
||
|
|
||
|
This terminates the daemon (either buildmaster or buildslave) running
|
||
|
in the given directory.
|
||
|
|
||
|
@example
|
||
|
buildbot stop BASEDIR
|
||
|
@end example
|
||
|
|
||
|
@heading sighup
|
||
|
|
||
|
This sends a SIGHUP to the buildmaster running in the given directory,
|
||
|
which causes it to re-read its @file{master.cfg} file.
|
||
|
|
||
|
@example
|
||
|
buildbot sighup BASEDIR
|
||
|
@end example
|
||
|
|
||
|
@node Developer Tools, Other Tools, Administrator Tools, Command-line tool
|
||
|
@section Developer Tools
|
||
|
|
||
|
These tools are provided for use by the developers who are working on
|
||
|
the code that the buildbot is monitoring.
|
||
|
|
||
|
@menu
|
||
|
* statuslog::
|
||
|
* statusgui::
|
||
|
* try::
|
||
|
@end menu
|
||
|
|
||
|
@node statuslog, statusgui, Developer Tools, Developer Tools
|
||
|
@subsection statuslog
|
||
|
|
||
|
@example
|
||
|
buildbot statuslog --master @var{MASTERHOST}:@var{PORT}
|
||
|
@end example
|
||
|
|
||
|
This command starts a simple text-based status client, one which just
|
||
|
prints out a new line each time an event occurs on the buildmaster.
|
||
|
|
||
|
The @option{--master} option provides the location of the
|
||
|
@code{buildbot.status.client.PBListener} status port, used to deliver
|
||
|
build information to realtime status clients. The option is always in
|
||
|
the form of a string, with hostname and port number separated by a
|
||
|
colon (@code{HOSTNAME:PORTNUM}). Note that this port is @emph{not} the
|
||
|
same as the slaveport (although a future version may allow the same
|
||
|
port number to be used for both purposes). If you get an error message
|
||
|
to the effect of ``Failure: twisted.cred.error.UnauthorizedLogin:'',
|
||
|
this may indicate that you are connecting to the slaveport rather than
|
||
|
a @code{PBListener} port.
|
||
|
|
||
|
The @option{--master} option can also be provided by the
|
||
|
@code{masterstatus} name in @file{.buildbot/options} (@pxref{.buildbot
|
||
|
config directory}).
|
||
|
|
||
|
@node statusgui, try, statuslog, Developer Tools
|
||
|
@subsection statusgui
|
||
|
|
||
|
@cindex statusgui
|
||
|
|
||
|
If you have set up a PBListener (@pxref{PBListener}), you will be able
|
||
|
to monitor your Buildbot using a simple Gtk+ application invoked with
|
||
|
the @code{buildbot statusgui} command:
|
||
|
|
||
|
@example
|
||
|
buildbot statusgui --master @var{MASTERHOST}:@var{PORT}
|
||
|
@end example
|
||
|
|
||
|
This command starts a simple Gtk+-based status client, which contains
|
||
|
a few boxes for each Builder that change color as events occur. It
|
||
|
uses the same @option{--master} argument as the @command{buildbot
|
||
|
statuslog} command (@pxref{statuslog}).
|
||
|
|
||
|
@node try, , statusgui, Developer Tools
|
||
|
@subsection try
|
||
|
|
||
|
This lets a developer to ask the question ``What would happen if I
|
||
|
committed this patch right now?''. It runs the unit test suite (across
|
||
|
multiple build platforms) on the developer's current code, allowing
|
||
|
them to make sure they will not break the tree when they finally
|
||
|
commit their changes.
|
||
|
|
||
|
The @command{buildbot try} command is meant to be run from within a
|
||
|
developer's local tree, and starts by figuring out the base revision
|
||
|
of that tree (what revision was current the last time the tree was
|
||
|
updated), and a patch that can be applied to that revision of the tree
|
||
|
to make it match the developer's copy. This (revision, patch) pair is
|
||
|
then sent to the buildmaster, which runs a build with that
|
||
|
SourceStamp. If you want, the tool will emit status messages as the
|
||
|
builds run, and will not terminate until the first failure has been
|
||
|
detected (or the last success).
|
||
|
|
||
|
For this command to work, several pieces must be in place:
|
||
|
|
||
|
|
||
|
@heading TryScheduler
|
||
|
|
||
|
@slindex buildbot.scheduler.Try_Jobdir
|
||
|
@slindex buildbot.scheduler.Try_Userpass
|
||
|
|
||
|
The buildmaster must have a @code{scheduler.Try} instance in
|
||
|
the config file's @code{c['schedulers']} list. This lets the
|
||
|
administrator control who may initiate these ``trial'' builds, which
|
||
|
branches are eligible for trial builds, and which Builders should be
|
||
|
used for them.
|
||
|
|
||
|
The @code{TryScheduler} has various means to accept build requests:
|
||
|
all of them enforce more security than the usual buildmaster ports do.
|
||
|
Any source code being built can be used to compromise the buildslave
|
||
|
accounts, but in general that code must be checked out from the VC
|
||
|
repository first, so only people with commit privileges can get
|
||
|
control of the buildslaves. The usual force-build control channels can
|
||
|
waste buildslave time but do not allow arbitrary commands to be
|
||
|
executed by people who don't have those commit privileges. However,
|
||
|
the source code patch that is provided with the trial build does not
|
||
|
have to go through the VC system first, so it is important to make
|
||
|
sure these builds cannot be abused by a non-committer to acquire as
|
||
|
much control over the buildslaves as a committer has. Ideally, only
|
||
|
developers who have commit access to the VC repository would be able
|
||
|
to start trial builds, but unfortunately the buildmaster does not, in
|
||
|
general, have access to VC system's user list.
|
||
|
|
||
|
As a result, the @code{TryScheduler} requires a bit more
|
||
|
configuration. There are currently two ways to set this up:
|
||
|
|
||
|
@table @strong
|
||
|
@item jobdir (ssh)
|
||
|
|
||
|
This approach creates a command queue directory, called the
|
||
|
``jobdir'', in the buildmaster's working directory. The buildmaster
|
||
|
admin sets the ownership and permissions of this directory to only
|
||
|
grant write access to the desired set of developers, all of whom must
|
||
|
have accounts on the machine. The @code{buildbot try} command creates
|
||
|
a special file containing the source stamp information and drops it in
|
||
|
the jobdir, just like a standard maildir. When the buildmaster notices
|
||
|
the new file, it unpacks the information inside and starts the builds.
|
||
|
|
||
|
The config file entries used by 'buildbot try' either specify a local
|
||
|
queuedir (for which write and mv are used) or a remote one (using scp
|
||
|
and ssh).
|
||
|
|
||
|
The advantage of this scheme is that it is quite secure, the
|
||
|
disadvantage is that it requires fiddling outside the buildmaster
|
||
|
config (to set the permissions on the jobdir correctly). If the
|
||
|
buildmaster machine happens to also house the VC repository, then it
|
||
|
can be fairly easy to keep the VC userlist in sync with the
|
||
|
trial-build userlist. If they are on different machines, this will be
|
||
|
much more of a hassle. It may also involve granting developer accounts
|
||
|
on a machine that would not otherwise require them.
|
||
|
|
||
|
To implement this, the buildslave invokes 'ssh -l username host
|
||
|
buildbot tryserver ARGS', passing the patch contents over stdin. The
|
||
|
arguments must include the inlet directory and the revision
|
||
|
information.
|
||
|
|
||
|
@item user+password (PB)
|
||
|
|
||
|
In this approach, each developer gets a username/password pair, which
|
||
|
are all listed in the buildmaster's configuration file. When the
|
||
|
developer runs @code{buildbot try}, their machine connects to the
|
||
|
buildmaster via PB and authenticates themselves using that username
|
||
|
and password, then sends a PB command to start the trial build.
|
||
|
|
||
|
The advantage of this scheme is that the entire configuration is
|
||
|
performed inside the buildmaster's config file. The disadvantages are
|
||
|
that it is less secure (while the ``cred'' authentication system does
|
||
|
not expose the password in plaintext over the wire, it does not offer
|
||
|
most of the other security properties that SSH does). In addition, the
|
||
|
buildmaster admin is responsible for maintaining the username/password
|
||
|
list, adding and deleting entries as developers come and go.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
For example, to set up the ``jobdir'' style of trial build, using a
|
||
|
command queue directory of @file{MASTERDIR/jobdir} (and assuming that
|
||
|
all your project developers were members of the @code{developers} unix
|
||
|
group), you would first create that directory (with @command{mkdir
|
||
|
MASTERDIR/jobdir MASTERDIR/jobdir/new MASTERDIR/jobdir/cur
|
||
|
MASTERDIR/jobdir/tmp; chgrp developers MASTERDIR/jobdir
|
||
|
MASTERDIR/jobdir/*; chmod g+rwx,o-rwx MASTERDIR/jobdir
|
||
|
MASTERDIR/jobdir/*}), and then use the following scheduler in the
|
||
|
buildmaster's config file:
|
||
|
|
||
|
@example
|
||
|
from buildbot.scheduler import Try_Jobdir
|
||
|
s = Try_Jobdir("try1", ["full-linux", "full-netbsd", "full-OSX"],
|
||
|
jobdir="jobdir")
|
||
|
c['schedulers'] = [s]
|
||
|
@end example
|
||
|
|
||
|
Note that you must create the jobdir before telling the buildmaster to
|
||
|
use this configuration, otherwise you will get an error. Also remember
|
||
|
that the buildmaster must be able to read and write to the jobdir as
|
||
|
well. Be sure to watch the @file{twistd.log} file (@pxref{Logfiles})
|
||
|
as you start using the jobdir, to make sure the buildmaster is happy
|
||
|
with it.
|
||
|
|
||
|
To use the username/password form of authentication, create a
|
||
|
@code{Try_Userpass} instance instead. It takes the same
|
||
|
@code{builderNames} argument as the @code{Try_Jobdir} form, but
|
||
|
accepts an addtional @code{port} argument (to specify the TCP port to
|
||
|
listen on) and a @code{userpass} list of username/password pairs to
|
||
|
accept. Remember to use good passwords for this: the security of the
|
||
|
buildslave accounts depends upon it:
|
||
|
|
||
|
@example
|
||
|
from buildbot.scheduler import Try_Userpass
|
||
|
s = Try_Userpass("try2", ["full-linux", "full-netbsd", "full-OSX"],
|
||
|
port=8031, userpass=[("alice","pw1"), ("bob", "pw2")] )
|
||
|
c['schedulers'] = [s]
|
||
|
@end example
|
||
|
|
||
|
Like most places in the buildbot, the @code{port} argument takes a
|
||
|
strports specification. See @code{twisted.application.strports} for
|
||
|
details.
|
||
|
|
||
|
|
||
|
@heading locating the master
|
||
|
|
||
|
The @command{try} command needs to be told how to connect to the
|
||
|
@code{TryScheduler}, and must know which of the authentication
|
||
|
approaches described above is in use by the buildmaster. You specify
|
||
|
the approach by using @option{--connect=ssh} or @option{--connect=pb}
|
||
|
(or @code{try_connect = 'ssh'} or @code{try_connect = 'pb'} in
|
||
|
@file{.buildbot/options}).
|
||
|
|
||
|
For the PB approach, the command must be given a @option{--master}
|
||
|
argument (in the form HOST:PORT) that points to TCP port that you
|
||
|
picked in the @code{Try_Userpass} scheduler. It also takes a
|
||
|
@option{--username} and @option{--passwd} pair of arguments that match
|
||
|
one of the entries in the buildmaster's @code{userpass} list. These
|
||
|
arguments can also be provided as @code{try_master},
|
||
|
@code{try_username}, and @code{try_password} entries in the
|
||
|
@file{.buildbot/options} file.
|
||
|
|
||
|
For the SSH approach, the command must be given @option{--tryhost},
|
||
|
@option{--username}, and optionally @option{--password} (TODO:
|
||
|
really?) to get to the buildmaster host. It must also be given
|
||
|
@option{--trydir}, which points to the inlet directory configured
|
||
|
above. The trydir can be relative to the user's home directory, but
|
||
|
most of the time you will use an explicit path like
|
||
|
@file{~buildbot/project/trydir}. These arguments can be provided in
|
||
|
@file{.buildbot/options} as @code{try_host}, @code{try_username},
|
||
|
@code{try_password}, and @code{try_dir}.
|
||
|
|
||
|
In addition, the SSH approach needs to connect to a PBListener status
|
||
|
port, so it can retrieve and report the results of the build (the PB
|
||
|
approach uses the existing connection to retrieve status information,
|
||
|
so this step is not necessary). This requires a @option{--master}
|
||
|
argument, or a @code{masterstatus} entry in @file{.buildbot/options},
|
||
|
in the form of a HOSTNAME:PORT string.
|
||
|
|
||
|
|
||
|
@heading choosing the Builders
|
||
|
|
||
|
A trial build is performed on multiple Builders at the same time, and
|
||
|
the developer gets to choose which Builders are used (limited to a set
|
||
|
selected by the buildmaster admin with the TryScheduler's
|
||
|
@code{builderNames=} argument). The set you choose will depend upon
|
||
|
what your goals are: if you are concerned about cross-platform
|
||
|
compatibility, you should use multiple Builders, one from each
|
||
|
platform of interest. You might use just one builder if that platform
|
||
|
has libraries or other facilities that allow better test coverage than
|
||
|
what you can accomplish on your own machine, or faster test runs.
|
||
|
|
||
|
The set of Builders to use can be specified with multiple
|
||
|
@option{--builder} arguments on the command line. It can also be
|
||
|
specified with a single @code{try_builders} option in
|
||
|
@file{.buildbot/options} that uses a list of strings to specify all
|
||
|
the Builder names:
|
||
|
|
||
|
@example
|
||
|
try_builders = ["full-OSX", "full-win32", "full-linux"]
|
||
|
@end example
|
||
|
|
||
|
@heading specifying the VC system
|
||
|
|
||
|
The @command{try} command also needs to know how to take the
|
||
|
developer's current tree and extract the (revision, patch)
|
||
|
source-stamp pair. Each VC system uses a different process, so you
|
||
|
start by telling the @command{try} command which VC system you are
|
||
|
using, with an argument like @option{--vc=cvs} or @option{--vc=tla}.
|
||
|
This can also be provided as @code{try_vc} in
|
||
|
@file{.buildbot/options}.
|
||
|
|
||
|
The following names are recognized: @code{cvs} @code{svn} @code{baz}
|
||
|
@code{tla} @code{hg} @code{darcs}
|
||
|
|
||
|
|
||
|
@heading finding the top of the tree
|
||
|
|
||
|
Some VC systems (notably CVS and SVN) track each directory
|
||
|
more-or-less independently, which means the @command{try} command
|
||
|
needs to move up to the top of the project tree before it will be able
|
||
|
to construct a proper full-tree patch. To accomplish this, the
|
||
|
@command{try} command will crawl up through the parent directories
|
||
|
until it finds a marker file. The default name for this marker file is
|
||
|
@file{.buildbot-top}, so when you are using CVS or SVN you should
|
||
|
@code{touch .buildbot-top} from the top of your tree before running
|
||
|
@command{buildbot try}. Alternatively, you can use a filename like
|
||
|
@file{ChangeLog} or @file{README}, since many projects put one of
|
||
|
these files in their top-most directory (and nowhere else). To set
|
||
|
this filename, use @option{--try-topfile=ChangeLog}, or set it in the
|
||
|
options file with @code{try_topfile = 'ChangeLog'}.
|
||
|
|
||
|
You can also manually set the top of the tree with
|
||
|
@option{--try-topdir=~/trees/mytree}, or @code{try_topdir =
|
||
|
'~/trees/mytree'}. If you use @code{try_topdir}, in a
|
||
|
@file{.buildbot/options} file, you will need a separate options file
|
||
|
for each tree you use, so it may be more convenient to use the
|
||
|
@code{try_topfile} approach instead.
|
||
|
|
||
|
Other VC systems which work on full projects instead of individual
|
||
|
directories (tla, baz, darcs, monotone, mercurial) do not require
|
||
|
@command{try} to know the top directory, so the @option{--try-topfile}
|
||
|
and @option{--try-topdir} arguments will be ignored.
|
||
|
@c is this true? I think I currently require topdirs all the time.
|
||
|
|
||
|
If the @command{try} command cannot find the top directory, it will
|
||
|
abort with an error message.
|
||
|
|
||
|
@heading determining the branch name
|
||
|
|
||
|
Some VC systems record the branch information in a way that ``try''
|
||
|
can locate it, in particular Arch (both @command{tla} and
|
||
|
@command{baz}). For the others, if you are using something other than
|
||
|
the default branch, you will have to tell the buildbot which branch
|
||
|
your tree is using. You can do this with either the @option{--branch}
|
||
|
argument, or a @option{try_branch} entry in the
|
||
|
@file{.buildbot/options} file.
|
||
|
|
||
|
@heading determining the revision and patch
|
||
|
|
||
|
Each VC system has a separate approach for determining the tree's base
|
||
|
revision and computing a patch.
|
||
|
|
||
|
@table @code
|
||
|
|
||
|
@item CVS
|
||
|
|
||
|
@command{try} pretends that the tree is up to date. It converts the
|
||
|
current time into a @code{-D} time specification, uses it as the base
|
||
|
revision, and computes the diff between the upstream tree as of that
|
||
|
point in time versus the current contents. This works, more or less,
|
||
|
but requires that the local clock be in reasonably good sync with the
|
||
|
repository.
|
||
|
|
||
|
@item SVN
|
||
|
@command{try} does a @code{svn status -u} to find the latest
|
||
|
repository revision number (emitted on the last line in the ``Status
|
||
|
against revision: NN'' message). It then performs an @code{svn diff
|
||
|
-rNN} to find out how your tree differs from the repository version,
|
||
|
and sends the resulting patch to the buildmaster. If your tree is not
|
||
|
up to date, this will result in the ``try'' tree being created with
|
||
|
the latest revision, then @emph{backwards} patches applied to bring it
|
||
|
``back'' to the version you actually checked out (plus your actual
|
||
|
code changes), but this will still result in the correct tree being
|
||
|
used for the build.
|
||
|
|
||
|
@item baz
|
||
|
@command{try} does a @code{baz tree-id} to determine the
|
||
|
fully-qualified version and patch identifier for the tree
|
||
|
(ARCHIVE/VERSION--patch-NN), and uses the VERSION--patch-NN component
|
||
|
as the base revision. It then does a @code{baz diff} to obtain the
|
||
|
patch.
|
||
|
|
||
|
@item tla
|
||
|
@command{try} does a @code{tla tree-version} to get the
|
||
|
fully-qualified version identifier (ARCHIVE/VERSION), then takes the
|
||
|
first line of @code{tla logs --reverse} to figure out the base
|
||
|
revision. Then it does @code{tla changes --diffs} to obtain the patch.
|
||
|
|
||
|
@item Darcs
|
||
|
@code{darcs changes --context} emits a text file that contains a list
|
||
|
of all patches back to and including the last tag was made. This text
|
||
|
file (plus the location of a repository that contains all these
|
||
|
patches) is sufficient to re-create the tree. Therefore the contents
|
||
|
of this ``context'' file @emph{are} the revision stamp for a
|
||
|
Darcs-controlled source tree.
|
||
|
|
||
|
So @command{try} does a @code{darcs changes --context} to determine
|
||
|
what your tree's base revision is, and then does a @code{darcs diff
|
||
|
-u} to compute the patch relative to that revision.
|
||
|
|
||
|
@item Mercurial
|
||
|
@code{hg identify} emits a short revision ID (basically a truncated
|
||
|
SHA1 hash of the current revision's contents), which is used as the
|
||
|
base revision. @code{hg diff} then provides the patch relative to that
|
||
|
revision. For @command{try} to work, your working directory must only
|
||
|
have patches that are available from the same remotely-available
|
||
|
repository that the build process' @code{step.Mercurial} will use.
|
||
|
|
||
|
@c TODO: monotone, git
|
||
|
@end table
|
||
|
|
||
|
@heading waiting for results
|
||
|
|
||
|
If you provide the @option{--wait} option (or @code{try_wait = True}
|
||
|
in @file{.buildbot/options}), the @command{buildbot try} command will
|
||
|
wait until your changes have either been proven good or bad before
|
||
|
exiting. Unless you use the @option{--quiet} option (or
|
||
|
@code{try_quiet=True}), it will emit a progress message every 60
|
||
|
seconds until the builds have completed.
|
||
|
|
||
|
|
||
|
@node Other Tools, .buildbot config directory, Developer Tools, Command-line tool
|
||
|
@section Other Tools
|
||
|
|
||
|
These tools are generally used by buildmaster administrators.
|
||
|
|
||
|
@menu
|
||
|
* sendchange::
|
||
|
* debugclient::
|
||
|
@end menu
|
||
|
|
||
|
@node sendchange, debugclient, Other Tools, Other Tools
|
||
|
@subsection sendchange
|
||
|
|
||
|
This command is used to tell the buildmaster about source changes. It
|
||
|
is intended to be used from within a commit script, installed on the
|
||
|
VC server. It requires that you have a PBChangeSource
|
||
|
(@pxref{PBChangeSource}) running in the buildmaster (by being included
|
||
|
in the @code{c['sources']} list).
|
||
|
|
||
|
|
||
|
@example
|
||
|
buildbot sendchange --master @var{MASTERHOST}:@var{PORT} --username @var{USER} @var{FILENAMES..}
|
||
|
@end example
|
||
|
|
||
|
There are other (optional) arguments which can influence the
|
||
|
@code{Change} that gets submitted:
|
||
|
|
||
|
@table @code
|
||
|
@item --branch
|
||
|
This provides the (string) branch specifier. If omitted, it defaults
|
||
|
to None, indicating the ``default branch''. All files included in this
|
||
|
Change must be on the same branch.
|
||
|
|
||
|
@item --revision_number
|
||
|
This provides a (numeric) revision number for the change, used for VC systems
|
||
|
that use numeric transaction numbers (like Subversion).
|
||
|
|
||
|
@item --revision
|
||
|
This provides a (string) revision specifier, for VC systems that use
|
||
|
strings (Arch would use something like patch-42 etc).
|
||
|
|
||
|
@item --revision_file
|
||
|
This provides a filename which will be opened and the contents used as
|
||
|
the revision specifier. This is specifically for Darcs, which uses the
|
||
|
output of @command{darcs changes --context} as a revision specifier.
|
||
|
This context file can be a couple of kilobytes long, spanning a couple
|
||
|
lines per patch, and would be a hassle to pass as a command-line
|
||
|
argument.
|
||
|
|
||
|
@item --comments
|
||
|
This provides the change comments as a single argument. You may want
|
||
|
to use @option{--logfile} instead.
|
||
|
|
||
|
@item --logfile
|
||
|
This instructs the tool to read the change comments from the given
|
||
|
file. If you use @code{-} as the filename, the tool will read the
|
||
|
change comments from stdin.
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node debugclient, , sendchange, Other Tools
|
||
|
@subsection debugclient
|
||
|
|
||
|
@example
|
||
|
buildbot debugclient --master @var{MASTERHOST}:@var{PORT} --passwd @var{DEBUGPW}
|
||
|
@end example
|
||
|
|
||
|
This launches a small Gtk+/Glade-based debug tool, connecting to the
|
||
|
buildmaster's ``debug port''. This debug port shares the same port
|
||
|
number as the slaveport (@pxref{Setting the slaveport}), but the
|
||
|
@code{debugPort} is only enabled if you set a debug password in the
|
||
|
buildmaster's config file (@pxref{Debug options}). The
|
||
|
@option{--passwd} option must match the @code{c['debugPassword']}
|
||
|
value.
|
||
|
|
||
|
@option{--master} can also be provided in @file{.debug/options} by the
|
||
|
@code{master} key. @option{--passwd} can be provided by the
|
||
|
@code{debugPassword} key.
|
||
|
|
||
|
The @code{Connect} button must be pressed before any of the other
|
||
|
buttons will be active. This establishes the connection to the
|
||
|
buildmaster. The other sections of the tool are as follows:
|
||
|
|
||
|
@table @code
|
||
|
@item Reload .cfg
|
||
|
Forces the buildmaster to reload its @file{master.cfg} file. This is
|
||
|
equivalent to sending a SIGHUP to the buildmaster, but can be done
|
||
|
remotely through the debug port. Note that it is a good idea to be
|
||
|
watching the buildmaster's @file{twistd.log} as you reload the config
|
||
|
file, as any errors which are detected in the config file will be
|
||
|
announced there.
|
||
|
|
||
|
@item Rebuild .py
|
||
|
(not yet implemented). The idea here is to use Twisted's ``rebuild''
|
||
|
facilities to replace the buildmaster's running code with a new
|
||
|
version. Even if this worked, it would only be used by buildbot
|
||
|
developers.
|
||
|
|
||
|
@item poke IRC
|
||
|
This locates a @code{words.IRC} status target and causes it to emit a
|
||
|
message on all the channels to which it is currently connected. This
|
||
|
was used to debug a problem in which the buildmaster lost the
|
||
|
connection to the IRC server and did not attempt to reconnect.
|
||
|
|
||
|
@item Commit
|
||
|
This allows you to inject a Change, just as if a real one had been
|
||
|
delivered by whatever VC hook you are using. You can set the name of
|
||
|
the committed file and the name of the user who is doing the commit.
|
||
|
Optionally, you can also set a revision for the change. If the
|
||
|
revision you provide looks like a number, it will be sent as an
|
||
|
integer, otherwise it will be sent as a string.
|
||
|
|
||
|
@item Force Build
|
||
|
This lets you force a Builder (selected by name) to start a build of
|
||
|
the current source tree.
|
||
|
|
||
|
@item Currently
|
||
|
(obsolete). This was used to manually set the status of the given
|
||
|
Builder, but the status-assignment code was changed in an incompatible
|
||
|
way and these buttons are no longer meaningful.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
@node .buildbot config directory, , Other Tools, Command-line tool
|
||
|
@section .buildbot config directory
|
||
|
|
||
|
Many of the @command{buildbot} tools must be told how to contact the
|
||
|
buildmaster that they interact with. This specification can be
|
||
|
provided as a command-line argument, but most of the time it will be
|
||
|
easier to set them in an ``options'' file. The @command{buildbot}
|
||
|
command will look for a special directory named @file{.buildbot},
|
||
|
starting from the current directory (where the command was run) and
|
||
|
crawling upwards, eventually looking in the user's home directory. It
|
||
|
will look for a file named @file{options} in this directory, and will
|
||
|
evaluate it as a python script, looking for certain names to be set.
|
||
|
You can just put simple @code{name = 'value'} pairs in this file to
|
||
|
set the options.
|
||
|
|
||
|
For a description of the names used in this file, please see the
|
||
|
documentation for the individual @command{buildbot} sub-commands. The
|
||
|
following is a brief sample of what this file's contents could be.
|
||
|
|
||
|
@example
|
||
|
# for status-reading tools
|
||
|
masterstatus = 'buildbot.example.org:12345'
|
||
|
# for 'sendchange' or the debug port
|
||
|
master = 'buildbot.example.org:18990'
|
||
|
debugPassword = 'eiv7Po'
|
||
|
@end example
|
||
|
|
||
|
@table @code
|
||
|
@item masterstatus
|
||
|
Location of the @code{client.PBListener} status port, used by
|
||
|
@command{statuslog} and @command{statusgui}.
|
||
|
|
||
|
@item master
|
||
|
Location of the @code{debugPort} (for @command{debugclient}). Also the
|
||
|
location of the @code{pb.PBChangeSource} (for @command{sendchange}).
|
||
|
Usually shares the slaveport, but a future version may make it
|
||
|
possible to have these listen on a separate port number.
|
||
|
|
||
|
@item debugPassword
|
||
|
Must match the value of @code{c['debugPassword']}, used to protect the
|
||
|
debug port, for the @command{debugclient} command.
|
||
|
|
||
|
@item username
|
||
|
Provides a default username for the @command{sendchange} command.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
The following options are used by the @code{buildbot try} command
|
||
|
(@pxref{try}):
|
||
|
|
||
|
@table @code
|
||
|
@item try_connect
|
||
|
This specifies how the ``try'' command should deliver its request to
|
||
|
the buildmaster. The currently accepted values are ``ssh'' and ``pb''.
|
||
|
@item try_builders
|
||
|
Which builders should be used for the ``try'' build.
|
||
|
@item try_vc
|
||
|
This specifies the version control system being used.
|
||
|
@item try_branch
|
||
|
This indicates that the current tree is on a non-trunk branch.
|
||
|
@item try_topdir
|
||
|
@item try_topfile
|
||
|
Use @code{try_topdir} to explicitly indicate the top of your working
|
||
|
tree, or @code{try_topfile} to name a file that will only be found in
|
||
|
that top-most directory.
|
||
|
|
||
|
@item try_host
|
||
|
@item try_username
|
||
|
@item try_dir
|
||
|
When try_connect is ``ssh'', the command will pay attention to
|
||
|
@code{try_host}, @code{try_username}, and @code{try_dir}.
|
||
|
|
||
|
@item try_username
|
||
|
@item try_password
|
||
|
@item try_master
|
||
|
Instead, when @code{try_connect} is ``pb'', the command will pay
|
||
|
attention to @code{try_username}, @code{try_password}, and
|
||
|
@code{try_master}.
|
||
|
|
||
|
@item try_wait
|
||
|
@item masterstatus
|
||
|
@code{try_wait} and @code{masterstatus} are used to ask the ``try''
|
||
|
command to wait for the requested build to complete.
|
||
|
|
||
|
@end table
|
||
|
|
||
|
|
||
|
|
||
|
@node Resources, Developer's Appendix, Command-line tool, Top
|
||
|
@chapter Resources
|
||
|
|
||
|
The Buildbot's home page is at @uref{http://buildbot.sourceforge.net/}
|
||
|
|
||
|
For configuration questions and general discussion, please use the
|
||
|
@code{buildbot-devel} mailing list. The subscription instructions and
|
||
|
archives are available at
|
||
|
@uref{http://lists.sourceforge.net/lists/listinfo/buildbot-devel}
|
||
|
|
||
|
@node Developer's Appendix, Index of Useful Classes, Resources, Top
|
||
|
@unnumbered Developer's Appendix
|
||
|
|
||
|
This appendix contains random notes about the implementation of the
|
||
|
Buildbot, and is likely to only be of use to people intending to
|
||
|
extend the Buildbot's internals.
|
||
|
|
||
|
The buildmaster consists of a tree of Service objects, which is shaped
|
||
|
as follows:
|
||
|
|
||
|
@example
|
||
|
BuildMaster
|
||
|
ChangeMaster (in .change_svc)
|
||
|
[IChangeSource instances]
|
||
|
[IScheduler instances] (in .schedulers)
|
||
|
BotMaster (in .botmaster)
|
||
|
[IStatusTarget instances] (in .statusTargets)
|
||
|
@end example
|
||
|
|
||
|
The BotMaster has a collection of Builder objects as values of its
|
||
|
@code{.builders} dictionary.
|
||
|
|
||
|
|
||
|
@node Index of Useful Classes, Index of master.cfg keys, Developer's Appendix, Top
|
||
|
@unnumbered Index of Useful Classes
|
||
|
|
||
|
This is a list of all user-visible classes. There are the ones that
|
||
|
are useful in @file{master.cfg}, the buildmaster's configuration file.
|
||
|
Classes that are not listed here are generally internal things that
|
||
|
admins are unlikely to have much use for.
|
||
|
|
||
|
|
||
|
@heading Change Sources
|
||
|
@printindex cs
|
||
|
|
||
|
@heading Schedulers and Locks
|
||
|
@printindex sl
|
||
|
|
||
|
@heading Build Factories
|
||
|
@printindex bf
|
||
|
|
||
|
@heading Build Steps
|
||
|
@printindex bs
|
||
|
|
||
|
@c undocumented steps
|
||
|
@bsindex buildbot.steps.source.Git
|
||
|
@bsindex buildbot.steps.maxq.MaxQ
|
||
|
|
||
|
|
||
|
@heading Status Targets
|
||
|
@printindex st
|
||
|
|
||
|
@c TODO: undocumented targets
|
||
|
@stindex buildbot.status.mail.MailNotifier
|
||
|
|
||
|
@node Index of master.cfg keys, Index, Index of Useful Classes, Top
|
||
|
@unnumbered Index of master.cfg keys
|
||
|
|
||
|
This is a list of all of the significant keys in master.cfg . Recall
|
||
|
that master.cfg is effectively a small python program one
|
||
|
responsibility: create a dictionary named @code{BuildmasterConfig}.
|
||
|
The keys of this dictionary are listed here. The beginning of the
|
||
|
master.cfg file typically starts with something like:
|
||
|
|
||
|
@example
|
||
|
BuildmasterConfig = c = @{@}
|
||
|
@end example
|
||
|
|
||
|
Therefore a config key of @code{sources} will usually appear in
|
||
|
master.cfg as @code{c['sources']}.
|
||
|
|
||
|
@printindex bc
|
||
|
|
||
|
|
||
|
@node Index, , Index of master.cfg keys, Top
|
||
|
@unnumbered Index
|
||
|
|
||
|
@printindex cp
|
||
|
|
||
|
|
||
|
@bye
|
||
|
|