diff options
Diffstat (limited to 'buildbot/docs/buildbot.texinfo')
-rw-r--r-- | buildbot/docs/buildbot.texinfo | 8807 |
1 files changed, 0 insertions, 8807 deletions
diff --git a/buildbot/docs/buildbot.texinfo b/buildbot/docs/buildbot.texinfo deleted file mode 100644 index 639103b..0000000 --- a/buildbot/docs/buildbot.texinfo +++ /dev/null @@ -1,8807 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@c %**start of header -@setfilename buildbot.info -@settitle BuildBot Manual 0.7.10 -@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:: -* Upgrading an Existing 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:: -* Build Properties:: - -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:: -* Testing the Config File:: -* Defining the Project:: -* Change Sources and Schedulers:: -* Setting the slaveport:: -* Buildslave Specifiers:: -* On-Demand ("Latent") Buildslaves:: -* Defining Global Properties:: -* Defining Builders:: -* Defining Status Targets:: -* Debug options:: - -Change Sources and Schedulers - -* Scheduler Scheduler:: -* AnyBranchScheduler:: -* Dependent Scheduler:: -* Periodic Scheduler:: -* Nightly Scheduler:: -* Try Schedulers:: -* Triggerable Scheduler:: - -Buildslave Specifiers -* When Buildslaves Go Missing:: - -On-Demand ("Latent") Buildslaves -* Amazon Web Services Elastic Compute Cloud ("AWS EC2"):: -* Dangers with Latent Buildslaves:: -* Writing New Latent Buildslaves:: - -Getting Source Code Changes - -* Change Sources:: -* Choosing ChangeSources:: -* CVSToys - PBService:: -* Mail-parsing ChangeSources:: -* PBChangeSource:: -* P4Source:: -* BonsaiPoller:: -* SVNPoller:: -* MercurialHook:: -* Bzr Hook:: -* Bzr Poller:: - -Mail-parsing ChangeSources - -* Subscribing the Buildmaster:: -* Using Maildirs:: -* Parsing Email Change Messages:: - -Parsing Email Change Messages - -* FCMaildirSource:: -* SyncmailMaildirSource:: -* BonsaiMaildirSource:: -* SVNCommitEmailMaildirSource:: - -Build Process - -* Build Steps:: -* Interlocks:: -* Build Factories:: - -Build Steps - -* Common Parameters:: -* Using Build Properties:: -* Source Checkout:: -* ShellCommand:: -* Simple ShellCommand Subclasses:: -* Python BuildSteps:: -* Transferring Files:: -* Steps That Run on the Master:: -* Triggering Schedulers:: -* Writing New BuildSteps:: - -Source Checkout - -* CVS:: -* SVN:: -* Darcs:: -* Mercurial:: -* Arch:: -* Bazaar:: -* Bzr:: -* P4:: -* Git:: - -Simple ShellCommand Subclasses - -* Configure:: -* Compile:: -* Test:: -* TreeSize:: -* PerlModuleTest:: -* SetProperty:: - -Python BuildSteps - -* BuildEPYDoc:: -* PyFlakes:: -* PyLint:: - -Writing New BuildSteps - -* BuildStep LogFiles:: -* Reading 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 - -* WebStatus:: -* MailNotifier:: -* IRC Bot:: -* PBListener:: -* Writing New Status Plugins:: - -WebStatus - -* WebStatus Configuration Parameters:: -* Buildbot Web Resources:: -* XMLRPC server:: -* HTML Waterfall:: - -Command-line tool - -* Administrator Tools:: -* Developer Tools:: -* Other Tools:: -* .buildbot config directory:: - -Developer Tools - -* statuslog:: -* statusgui:: -* try:: - -waiting for results - -* try --diff:: - -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 randomly assigned to a -free SlaveBuilder and the build begins. - -The behaviour when BuildRequests are merged can be customized, @pxref{Merging -BuildRequests}. - -@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:: -* Upgrading an Existing 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.3 or later, and is primarily developed -against python-2.4. It is also tested against python-2.5 . - -@item -Twisted: http://twistedmatrix.com - -Both the buildmaster and the buildslaves require Twisted-2.0.x or -later. It has been tested against all releases of Twisted up to -Twisted-2.5.0 (the most recent as of this writing). As always, the -most recent version is recommended. - -Twisted is delivered as a collection of 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). You might -also want TwistedConch (for the encrypted Manhole debug port). Note -that Twisted requires ZopeInterface to be installed as well. - -@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, Upgrading an Existing Buildmaster, 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 Upgrading an Existing Buildmaster, Creating a buildslave, Creating a buildmaster, Installation -@section Upgrading an Existing Buildmaster - -If you have just installed a new version of the Buildbot code, and you -have buildmasters that were created using an older version, you'll -need to upgrade these buildmasters before you can use them. The -upgrade process adds and modifies files in the buildmaster's base -directory to make it compatible with the new code. - -@example -buildbot upgrade-master @var{basedir} -@end example - -This command will also scan your @file{master.cfg} file for -incompatbilities (by loading it and printing any errors or deprecation -warnings that occur). Each buildbot release tries to be compatible -with configurations that worked cleanly (i.e. without deprecation -warnings) on the previous release: any functions or classes that are -to be removed will first be deprecated in a release, to give users a -chance to start using their replacement. - -The 0.7.6 release introduced the @file{public_html/} directory, which -contains @file{index.html} and other files served by the -@code{WebStatus} and @code{Waterfall} status displays. The -@code{upgrade-master} command will create these files if they do not -already exist. It will not modify existing copies, but it will write a -new copy in e.g. @file{index.html.new} if the new version differs from -the version that already exists. - -The @code{upgrade-master} command is idempotent. It is safe to run it -multiple times. After each upgrade of the buildbot code, you should -use @code{upgrade-master} on all your buildmasters. - - -@node Creating a buildslave, Launching the daemons, Upgrading an Existing 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 or with regular pipes (the default) when the master does not -specify. This option is deprecated, as this particular parameter is better -specified on the master. - -@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. - -@item --maxdelay -This is a number that indicates the maximum amount of time the -buildslave will wait between connection attempts, expressed in -seconds. The default (300) causes the buildslave to wait at most 5 -minutes before trying to connect to the buildmaster again. - -@item --log-size -This is the size in bytes when to rotate the Twisted log files. - -@item --log-count -This is the number of log rotations to keep around. You can either -specify a number or @code{None} (the default) to keep all -@file{twistd.log} files around. - -@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. - -Some distributions may include conveniences to make starting buildbot -at boot time easy. For instance, with the default buildbot package in -Debian-based distributions, you may only need to modify -@code{/etc/default/buildbot} (see also @code{/etc/init.d/buildbot}, which -reads the configuration in @code{/etc/default/buildbot}). - -@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. Of course, this only works on unix-like systems with -signal support, and won't work on Windows. 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 - -There are certain configuration changes that are not handled cleanly -by @code{buildbot reconfig}. If this occurs, @code{buildbot restart} -is a more robust tool to fully switch over to the new configuration. - -@code{buildbot restart} may also be used to start a stopped Buildbot -instance. This behaviour is useful when writing scripts that stop, start -and restart Buildbot. - -A buildslave may also be gracefully shutdown from the -@pxref{WebStatus} status plugin. This is useful to shutdown a -buildslave without interrupting any current builds. The buildmaster -will wait until the buildslave is finished all its current builds, and -will then tell the buildslave to shutdown. - -@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 i-path './public_html/*' -prune -o -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:: -* Build Properties:: -@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 -(CVS is really the only VC system still in widespread use that has -per-file revisions.. everything modern has moved to atomic tree-wide -changesets). 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 revision stamp or timestamp. 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/Baz/Bazaar, 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, Mercurial, and Git 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://bazaar-vcs.org, Bzr} (which is a descendant of -Arch/Bazaar, and is frequently referred to as ``Bazaar'') has the same -sort of repository-vs-workspace model as Arch, but the repository data -can either be stored inside the working directory or kept elsewhere -(either on the same machine or on an entirely different machine). For -the purposes of Buildbot (which never commits changes), the repository -is specified with a URL and a revision number. - -The most common way to obtain read-only access to a bzr tree is via -HTTP, simply by making the repository visible through a web server -like Apache. Bzr can also use FTP and SFTP servers, if the buildslave -process has sufficient privileges to access them. Higher performance -can be obtained by running a special Bazaar-specific server. None of -these matter to the buildbot: the repository URL just has to match the -kind of server being used. The @code{repoURL} argument provides the -location of the repository. - -Branches are expressed as subdirectories of the main central -repository, which means that if branches are being used, the BZR step -is given a @code{baseURL} and @code{defaultBranch} instead of getting -the @code{repoURL} argument. - - -@uref{http://darcs.net/, 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}. - -@uref{http://git.or.cz/, Git} also follows a decentralized model, and -each repository can have several branches and tags. The source Step is -configured with a static @code{repourl} which specifies the location -of the repository. In addition, an optional @code{branch} parameter -can be specified to check out code from a specific branch instead of -the default ``master'' branch. The ``revision'' is specified as a SHA1 -hash as returned by e.g. @command{git rev-parse}. No attempt is made -to ensure that the specified revision is actually a subset of the -specified branch. - - -@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{fileIsImportant} -function (in the Scheduler) to decide whether it is worth triggering a -new build or not, e.g. the function could use the following function -to only run a build if a C file were checked in: - -@example -def has_C_files(change): - for name in change.files: - if name.endswith(".c"): - return True - return False -@end example - -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, the changeset 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 -@item Git -@code{revision} is a short string (a SHA1 hash), the output of e.g. -@code{git rev-parse} -@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, Monotone, and Git, 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'] -@item Git -branch='warner-newfeature', files=['src/foo.c'] -@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{fileIsImportant} 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. - -When the setup has multiple sources of Changes the @code{category} -can be used for @code{Scheduler} objects to filter out a subset -of the Changes. Note that not all change sources can attach a category. - -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{patch -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 @code{Builder}. Each @code{Builder} runs the -@code{BuildRequest} as soon as it can (i.e. when an associated -buildslave becomes free). @code{BuildRequest}s are prioritized from -oldest to newest, so when a buildslave becomes free, the -@code{Builder} with the oldest @code{BuildRequest} is run. - -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. - -@code{BuildRequest} is created with optional @code{Properties}. One -of these, @code{owner}, is collected by the resultant @code{Build} and -added to the set of @emph{interested users} to which status -notifications will be sent, depending on the configuration for each -status object. - -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. - -A @code{Builder} may be given a set of environment variables to be used -in its @pxref{ShellCommand}s. These variables will override anything in the -buildslave's environment. Variables passed directly to a ShellCommand will -override variables of the same name passed to the Builder. - -For example, if you a pool of identical slaves it is often easier to manage -variables like PATH from Buildbot rather than manually editing it inside of -the slaves' environment. - -@example -f = factory.BuildFactory -f.addStep(ShellCommand( - command=['bash', './configure'])) -f.addStep(Compile()) - -c['builders'] = [ - @{'name': 'test', 'slavenames': ['slave1', 'slave2', 'slave3', 'slave4', - 'slave5', 'slave6'], - 'builddir': 'test', 'factory': f', - 'env': @{'PATH': '/opt/local/bin:/opt/app/bin:/usr/local/bin:/usr/bin'@}@} - -@end example - -@node Users, Build Properties, 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 -(@pxref{MailNotifier}) 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 Build Properties, , Users, Concepts -@section Build Properties -@cindex Properties - -Each build has a set of ``Build Properties'', which can be used by its -BuildStep to modify their actions. These properties, in the form of -key-value pairs, provide a general framework for dynamically altering -the behavior of a build based on its circumstances. - -Properties come from a number of places: -@itemize -@item global configuration -- -These properties apply to all builds. -@item schedulers -- -A scheduler can specify properties available to all the builds it -starts. -@item buildslaves -- -A buildslave can pass properties on to the builds it performs. -@item builds -- -A build automatically sets a number of properties on itself. -@item steps -- -Steps of a build can set properties that are available to subsequent -steps. In particular, source steps set a number of properties. -@end itemize - -Properties are very flexible, and can be used to implement all manner -of functionality. Here are some examples: - -Most Source steps record the revision that they checked out in -the @code{got_revision} property. A later step could use this -property to specify the name of a fully-built tarball, dropped in an -easily-acessible directory for later testing. - -Some projects want to perform nightly builds as well as in response -to committed changes. Such a project would run two schedulers, -both pointing to the same set of builders, but could provide an -@code{is_nightly} property so that steps can distinguish the nightly -builds, perhaps to run more resource-intensive tests. - -Some projects have different build processes on different systems. -Rather than create a build factory for each slave, the steps can use -buildslave properties to identify the unique aspects of each slave -and adapt the build process dynamically. - -@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:: -* Testing the Config File:: -* Defining the Project:: -* Change Sources and Schedulers:: -* Merging BuildRequests:: -* Setting the slaveport:: -* Buildslave Specifiers:: -* On-Demand ("Latent") Buildslaves:: -* Defining Global Properties:: -* 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, Testing the Config File, 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 Testing the Config File, Defining the Project, Loading the Config File, Configuration -@section Testing the Config File - -To verify that the config file is well-formed and contains no -deprecated or invalid elements, use the ``checkconfig'' command: - -@example -% buildbot checkconfig master.cfg -Config file is good! -@end example - -If the config file has deprecated features (perhaps because you've -upgraded the buildmaster and need to update the config file to match), -they will be announced by checkconfig. In this case, the config file -will work, but you should really remove the deprecated items and use -the recommended replacements instead: - -@example -% buildbot checkconfig master.cfg -/usr/lib/python2.4/site-packages/buildbot/master.py:559: DeprecationWarning: c['sources'] is -deprecated as of 0.7.6 and will be removed by 0.8.0 . Please use c['change_source'] instead. - warnings.warn(m, DeprecationWarning) -Config file is good! -@end example - -If the config file is simply broken, that will be caught too: - -@example -% buildbot checkconfig master.cfg -Traceback (most recent call last): - File "/usr/lib/python2.4/site-packages/buildbot/scripts/runner.py", line 834, in doCheckConfig - ConfigLoader(configFile) - File "/usr/lib/python2.4/site-packages/buildbot/scripts/checkconfig.py", line 31, in __init__ - self.loadConfig(configFile) - File "/usr/lib/python2.4/site-packages/buildbot/master.py", line 480, in loadConfig - exec f in localDict - File "/home/warner/BuildBot/master/foolscap/master.cfg", line 90, in ? - c[bogus] = "stuff" -NameError: name 'bogus' is not defined -@end example - - -@node Defining the Project, Change Sources and Schedulers, Testing 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. - -@bcindex c['logCompressionLimit'] -The @code{logCompressionLimit} enables bz2-compression of build logs on -disk for logs that are bigger than the given size, or disables that -completely if given @code{False}. The default value is 4k, which should -be a reasonable default on most file systems. This setting has no impact -on status plugins, and merely affects the required disk space on the -master for build logs. - - -@node Change Sources and Schedulers, Merging BuildRequests, Defining the Project, Configuration -@section Change Sources and Schedulers - -@bcindex c['sources'] -@bcindex c['change_source'] - -The @code{c['change_source']} key is the ChangeSource -instance@footnote{To be precise, it is an object or a list of objects -which all implement the @code{buildbot.interfaces.IChangeSource} -Interface. It is unusual to have multiple ChangeSources, so this key -accepts either a single ChangeSource or a sequence of them.} that -defines how the buildmaster learns about source code changes. More -information about what goes here is available in @xref{Getting Source -Code Changes}. - -@example -from buildbot.changes.pb import PBChangeSource -c['change_source'] = PBChangeSource() -@end example -@bcindex c['schedulers'] - -(note: in buildbot-0.7.5 and earlier, this key was named -@code{c['sources']}, and required a list. @code{c['sources']} is -deprecated as of buildbot-0.7.6 and is scheduled to be removed in a -future release). - -@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. - -Scheduler arguments -should always be specified by name (as keyword arguments), to allow -for future expansion: - -@example -sched = Scheduler(name="quick", builderNames=['lin', 'win']) -@end example - -All schedulers have several arguments in common: - -@table @code -@item name - -Each Scheduler must have a unique name. This is used in status -displays, and is also available in the build property @code{scheduler}. - -@item builderNames - -This is the set of builders which this scheduler should trigger, specified -as a list of names (strings). - -@item properties -@cindex Properties - -This is a dictionary specifying properties that will be transmitted -to all builds started by this scheduler. - -@end table - -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. - -@menu -* Scheduler Scheduler:: -* AnyBranchScheduler:: -* Dependent Scheduler:: -* Periodic Scheduler:: -* Nightly Scheduler:: -* Try Schedulers:: -* Triggerable Scheduler:: -@end menu - -@node Scheduler Scheduler, AnyBranchScheduler, Change Sources and Schedulers, Change Sources and Schedulers -@subsection Scheduler Scheduler -@slindex buildbot.scheduler.Scheduler - -This is the original and still most popular 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. - -The arguments to this scheduler are: - -@table @code -@item name - -@item builderNames - -@item properties - -@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 fileIsImportant -A callable which takes one argument, a Change instance, and returns -@code{True} if the change is worth building, and @code{False} if -it is not. Unimportant Changes are accumulated until the build is -triggered by an important change. The default value of None means -that all Changes are important. - -@item categories -A list of categories of changes that this scheduler will respond to. If this -is specified, then any non-matching changes are ignored. - -@end table - -Example: - -@example -from buildbot import scheduler -quick = scheduler.Scheduler(name="quick", - branch=None, - treeStableTimer=60, - builderNames=["quick-linux", "quick-netbsd"]) -full = scheduler.Scheduler(name="full", - branch=None, - treeStableTimer=5*60, - builderNames=["full-linux", "full-netbsd", "full-OSX"]) -c['schedulers'] = [quick, full] -@end example - -In this example, the two ``quick'' builders 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. - -@node AnyBranchScheduler, Dependent Scheduler, Scheduler Scheduler, Change Sources and Schedulers -@subsection AnyBranchScheduler -@slindex buildbot.scheduler.AnyBranchScheduler - -This scheduler uses a tree-stable-timer like the default one, but -follows multiple branches at once. Each branch gets a separate timer. - -The arguments to this scheduler are: - -@table @code -@item name - -@item builderNames - -@item properties - -@item branches -This Scheduler will pay attention to any number of branches, ignoring -Changes that occur on other branches. Branches are specified just as -for the @code{Scheduler} class. - -@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 fileIsImportant -A callable which takes one argument, a Change instance, and returns -@code{True} if the change is worth building, and @code{False} if -it is not. Unimportant Changes are accumulated until the build is -triggered by an important change. The default value of None means -that all Changes are important. -@end table - -@node Dependent Scheduler, Periodic Scheduler, AnyBranchScheduler, Change Sources and Schedulers -@subsection Dependent Scheduler -@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 ``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 build fails on any of the Builders in the upstream set, -the downstream builds will not fire. Note that, for SourceStamps -generated by a ChangeSource, the @code{revision} is None, meaning HEAD. -If any changes are committed between the time the upstream scheduler -begins its build and the time the dependent scheduler begins its -build, then those changes will be included in the downstream build. -See the @pxref{Triggerable Scheduler} for a more flexible dependency -mechanism that can avoid this problem. - -The arguments to this scheduler are: - -@table @code -@item name - -@item builderNames - -@item properties - -@item upstream -The upstream scheduler to watch. Note that this is an ``instance'', -not the name of the scheduler. -@end table - -Example: - -@example -from buildbot import scheduler -tests = scheduler.Scheduler("just-tests", None, 5*60, - ["full-linux", "full-netbsd", "full-OSX"]) -package = scheduler.Dependent("build-package", - tests, # upstream scheduler -- no quotes! - ["make-tarball", "make-deb", "make-rpm"]) -c['schedulers'] = [tests, package] -@end example - -@node Periodic Scheduler, Nightly Scheduler, Dependent Scheduler, Change Sources and Schedulers -@subsection Periodic Scheduler -@slindex buildbot.scheduler.Periodic - -This simple scheduler just triggers a build every N seconds. - -The arguments to this scheduler are: - -@table @code -@item name - -@item builderNames - -@item properties - -@item periodicBuildTimer -The time, in seconds, after which to start a build. -@end table - -Example: - -@example -from buildbot import scheduler -nightly = scheduler.Periodic(name="nightly", - builderNames=["full-solaris"], - periodicBuildTimer=24*60*60) -c['schedulers'] = [nightly] -@end example - -The 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. - -@node Nightly Scheduler, Try Schedulers, Periodic Scheduler, Change Sources and Schedulers -@subsection Nightly Scheduler -@slindex buildbot.scheduler.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. - -Pass some subset of @code{minute}, @code{hour}, @code{dayOfMonth}, -@code{month}, and @code{dayOfWeek}; each may be a single number or -a list of valid values. The builds will be triggered whenever the -current time matches these values. Wildcards are represented by a -'*' string. All fields default to a wildcard except 'minute', so -with no fields this defaults to a build every hour, on the hour. -The full list of parameters is: - -@table @code -@item name - -@item builderNames - -@item properties - -@item branch -The branch to build, just as for @code{Scheduler}. - -@item minute -The minute of the hour on which to start the build. This defaults -to 0, meaning an hourly build. - -@item hour -The hour of the day on which to start the build, in 24-hour notation. -This defaults to *, meaning every hour. - -@item month -The month in which to start the build, with January = 1. This defaults -to *, meaning every month. - -@item dayOfWeek -The day of the week to start a build, with Monday = 0. This defauls -to *, meaning every day of the week. - -@item onlyIfChanged -If this is true, then builds will not be scheduled at the designated time -unless the source has changed since the previous build. -@end table - -For example, the following master.cfg clause will cause a build to be -started every night at 3:00am: - -@example -s = scheduler.Nightly(name='nightly', - builderNames=['builder1', 'builder2'], - hour=3, - minute=0) -@end example - -This scheduler will perform a build each monday morning at 6:23am and -again at 8:23am, but only if someone has committed code in the interim: - -@example -s = scheduler.Nightly(name='BeforeWork', - builderNames=['builder1'], - dayOfWeek=0, - hour=[6,8], - minute=23, - onlyIfChanged=True) -@end example - -The following runs a build every two hours, using Python's @code{range} -function: - -@example -s = Nightly(name='every2hours', - builderNames=['builder1'], - hour=range(0, 24, 2)) -@end example - -Finally, this example will run only on December 24th: - -@example -s = Nightly(name='SleighPreflightCheck', - builderNames=['flying_circuits', 'radar'], - month=12, - dayOfMonth=24, - hour=12, - minute=0) -@end example - -@node Try Schedulers, Triggerable Scheduler, Nightly Scheduler, Change Sources and Schedulers -@subsection Try Schedulers -@slindex buildbot.scheduler.Try_Jobdir -@slindex buildbot.scheduler.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. - -Two implementations are available: @code{Try_Jobdir} and -@code{Try_Userpass}. The former monitors a job directory, specified -by the @code{jobdir} parameter, while the latter listens for PB -connections on a specific @code{port}, and authenticates against -@code{userport}. - -@node Triggerable Scheduler, , Try Schedulers, Change Sources and Schedulers -@subsection Triggerable Scheduler -@cindex Triggers -@slindex buildbot.scheduler.Triggerable - -The @code{Triggerable} scheduler waits to be triggered by a Trigger -step (see @ref{Triggering Schedulers}) in another build. That step -can optionally wait for the scheduler's builds to complete. This -provides two advantages over Dependent schedulers. First, the same -scheduler can be triggered from multiple builds. Second, the ability -to wait for a Triggerable's builds to complete provides a form of -"subroutine call", where one or more builds can "call" a scheduler -to perform some work for them, perhaps on other buildslaves. - -The parameters are just the basics: - -@table @code -@item name -@item builderNames -@item properties -@end table - -This class is only useful in conjunction with the @code{Trigger} step. -Here is a fully-worked example: - -@example -from buildbot import scheduler -from buildbot.process import factory -from buildbot.steps import trigger - -checkin = scheduler.Scheduler(name="checkin", - branch=None, - treeStableTimer=5*60, - builderNames=["checkin"]) -nightly = scheduler.Nightly(name='nightly', - builderNames=['nightly'], - hour=3, - minute=0) - -mktarball = scheduler.Triggerable(name="mktarball", - builderNames=["mktarball"]) -build = scheduler.Triggerable(name="build-all-platforms", - builderNames=["build-all-platforms"]) -test = scheduler.Triggerable(name="distributed-test", - builderNames=["distributed-test"]) -package = scheduler.Triggerable(name="package-all-platforms", - builderNames=["package-all-platforms"]) - -c['schedulers'] = [checkin, nightly, build, test, package] - -# on checkin, make a tarball, build it, and test it -checkin_factory = factory.BuildFactory() -checkin_factory.addStep(trigger.Trigger(schedulerNames=['mktarball'], - waitForFinish=True)) -checkin_factory.addStep(trigger.Trigger(schedulerNames=['build-all-platforms'], - waitForFinish=True)) -checkin_factory.addStep(trigger.Trigger(schedulerNames=['distributed-test'], - waitForFinish=True)) - -# and every night, make a tarball, build it, and package it -nightly_factory = factory.BuildFactory() -nightly_factory.addStep(trigger.Trigger(schedulerNames=['mktarball'], - waitForFinish=True)) -nightly_factory.addStep(trigger.Trigger(schedulerNames=['build-all-platforms'], - waitForFinish=True)) -nightly_factory.addStep(trigger.Trigger(schedulerNames=['package-all-platforms'], - waitForFinish=True)) -@end example - -@node Merging BuildRequests, Setting the slaveport, Change Sources and Schedulers, Configuration -@section Merging BuildRequests - -@bcindex c['mergeRequests'] - -By default, buildbot merges BuildRequests that have the compatible -SourceStamps. This behaviour can be customized with the -@code{c['mergeRequests']} configuration key. This key specifies a function -which is caleld with three arguments: a @code{Builder} and two -@code{BuildRequest} objects. It should return true if the requests can be -merged. For example: - -@example -def mergeRequests(builder, req1, req2): - """Don't merge buildrequest at all""" - return False -c['mergeRequests'] = mergeRequests -@end example - -In many cases, the details of the SourceStamps and BuildRequests are important. -In this example, only BuildRequests with the same "reason" are merged; thus -developers forcing builds for different reasons will see distinct builds. - -@example -def mergeRequests(builder, req1, req2): - if req1.source.canBeMergedWith(req2.source) and req1.reason == req2.reason: - return True - return False -c['mergeRequests'] = mergeRequests -@end example - -@node Setting the slaveport, Buildslave Specifiers, Merging BuildRequests, 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, On-Demand ("Latent") Buildslaves, Setting the slaveport, Configuration -@section Buildslave Specifiers -@bcindex c['slaves'] - -The @code{c['slaves']} key is a list of known buildslaves. In the common case, -each buildslave is defined by an instance of the BuildSlave class. It -represents a standard, manually started machine that will try to connect to -the buildbot master as a slave. Contrast these with the "on-demand" latent -buildslaves, such as the Amazon Web Service Elastic Compute Cloud latent -buildslave discussed below. - -The BuildSlave class is instantiated with two values: (slavename, -slavepassword). These are the same two values that need to be provided to the -buildslave administrator when they create the buildslave. - -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}). - -@example -from buildbot.buildslave import BuildSlave -c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd') - BuildSlave('bot-bsd', 'bsdpasswd') - ] -@end example - -@cindex Properties -@code{BuildSlave} objects can also be created with an optional -@code{properties} argument, a dictionary specifying properties that -will be available to any builds performed on this slave. For example: - -@example -from buildbot.buildslave import BuildSlave -c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd', - properties=@{'os':'solaris'@}), - ] -@end example - -The @code{BuildSlave} constructor can also take an optional -@code{max_builds} parameter to limit the number of builds that it -will execute simultaneously: - -@example -from buildbot.buildslave import BuildSlave -c['slaves'] = [BuildSlave("bot-linux", "linuxpassword", max_builds=2)] -@end example - -Historical note: in buildbot-0.7.5 and earlier, the @code{c['bots']} -key was used instead, and it took a list of (name, password) tuples. -This key is accepted for backwards compatibility, but is deprecated as -of 0.7.6 and will go away in some future release. - -@menu -* When Buildslaves Go Missing:: -@end menu - -@node When Buildslaves Go Missing, , , Buildslave Specifiers -@subsection When Buildslaves Go Missing - -Sometimes, the buildslaves go away. One very common reason for this is -when the buildslave process is started once (manually) and left -running, but then later the machine reboots and the process is not -automatically restarted. - -If you'd like to have the administrator of the buildslave (or other -people) be notified by email when the buildslave has been missing for -too long, just add the @code{notify_on_missing=} argument to the -@code{BuildSlave} definition: - -@example -c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd', - notify_on_missing="bob@@example.com"), - ] -@end example - -By default, this will send email when the buildslave has been -disconnected for more than one hour. Only one email per -connection-loss event will be sent. To change the timeout, use -@code{missing_timeout=} and give it a number of seconds (the default -is 3600). - -You can have the buildmaster send email to multiple recipients: just -provide a list of addresses instead of a single one: - -@example -c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd', - notify_on_missing=["bob@@example.com", - "alice@@example.org"], - missing_timeout=300, # notify after 5 minutes - ), - ] -@end example - -The email sent this way will use a MailNotifier (@pxref{MailNotifier}) -status target, if one is configured. This provides a way for you to -control the ``from'' address of the email, as well as the relayhost -(aka ``smarthost'') to use as an SMTP server. If no MailNotifier is -configured on this buildmaster, the buildslave-missing emails will be -sent using a default configuration. - -Note that if you want to have a MailNotifier for buildslave-missing -emails but not for regular build emails, just create one with -builders=[], as follows: - -@example -from buildbot.status import mail -m = mail.MailNotifier(fromaddr="buildbot@@localhost", builders=[], - relayhost="smtp.example.org") -c['status'].append(m) -c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd', - notify_on_missing="bob@@example.com"), - ] -@end example - -@node On-Demand ("Latent") Buildslaves, Defining Global Properties, Buildslave Specifiers, Configuration -@section On-Demand ("Latent") Buildslaves - -The standard buildbot model has slaves started manually. The previous section -described how to configure the master for this approach. - -Another approach is to let the buildbot master start slaves when builds are -ready, on-demand. Thanks to services such as Amazon Web Services' Elastic -Compute Cloud ("AWS EC2"), this is relatively easy to set up, and can be -very useful for some situations. - -The buildslaves that are started on-demand are called "latent" buildslaves. -As of this writing, buildbot ships with an abstract base class for building -latent buildslaves, and a concrete implementation for AWS EC2. - -@menu -* Amazon Web Services Elastic Compute Cloud ("AWS EC2"):: -* Dangers with Latent Buildslaves:: -* Writing New Latent Buildslaves:: -@end menu - -@node Amazon Web Services Elastic Compute Cloud ("AWS EC2"), Dangers with Latent Buildslaves, , On-Demand ("Latent") Buildslaves -@subsection Amazon Web Services Elastic Compute Cloud ("AWS EC2") - -@url{http://aws.amazon.com/ec2/,,AWS EC2} is a web service that allows you to -start virtual machines in an Amazon data center. Please see their website for -details, incuding costs. Using the AWS EC2 latent buildslaves involves getting -an EC2 account with AWS and setting up payment; customizing one or more EC2 -machine images ("AMIs") on your desired operating system(s) and publishing -them (privately if needed); and configuring the buildbot master to know how to -start your customized images for "substantiating" your latent slaves. - -@menu -* Get an AWS EC2 Account:: -* Create an AMI:: -* Configure the Master with an EC2LatentBuildSlave:: -@end menu - -@node Get an AWS EC2 Account, Create an AMI, , Amazon Web Services Elastic Compute Cloud ("AWS EC2") -@subsubsection Get an AWS EC2 Account - -To start off, to use the AWS EC2 latent buildslave, you need to get an AWS -developer account and sign up for EC2. These instructions may help you get -started: - -@itemize @bullet -@item -Go to http://aws.amazon.com/ and click to "Sign Up Now" for an AWS account. - -@item -Once you are logged into your account, you need to sign up for EC2. -Instructions for how to do this have changed over time because Amazon changes -their website, so the best advice is to hunt for it. After signing up for EC2, -it may say it wants you to upload an x.509 cert. You will need this to create -images (see below) but it is not technically necessary for the buildbot master -configuration. - -@item -You must enter a valid credit card before you will be able to use EC2. Do that -under 'Payment Method'. - -@item -Make sure you're signed up for EC2 by going to 'Your Account'->'Account -Activity' and verifying EC2 is listed. -@end itemize - -@node Create an AMI, Configure the Master with an EC2LatentBuildSlave, Get an AWS EC2 Account, Amazon Web Services Elastic Compute Cloud ("AWS EC2") -@subsubsection Create an AMI - -Now you need to create an AMI and configure the master. You may need to -run through this cycle a few times to get it working, but these instructions -should get you started. - -Creating an AMI is out of the scope of this document. The -@url{http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/,,EC2 Getting Started Guide} -is a good resource for this task. Here are a few additional hints. - -@itemize @bullet -@item -When an instance of the image starts, it needs to automatically start a -buildbot slave that connects to your master (to create a buildbot slave, -@pxref{Creating a buildslave}; to make a daemon, -@pxref{Launching the daemons}). - -@item -You may want to make an instance of the buildbot slave, configure it as a -standard buildslave in the master (i.e., not as a latent slave), and test and -debug it that way before you turn it into an AMI and convert to a latent -slave in the master. -@end itemize - -@node Configure the Master with an EC2LatentBuildSlave, , Create an AMI, Amazon Web Services Elastic Compute Cloud ("AWS EC2") -@subsubsection Configure the Master with an EC2LatentBuildSlave - -Now let's assume you have an AMI that should work with the -EC2LatentBuildSlave. It's now time to set up your buildbot master -configuration. - -You will need some information from your AWS account: the "Access Key Id" and -the "Secret Access Key". If you've built the AMI yourself, you probably -already are familiar with these values. If you have not, and someone has -given you access to an AMI, these hints may help you find the necessary -values: - -@itemize @bullet -@item -While logged into your AWS account, find the "Access Identifiers" link (either -on the left, or via "Your Account" -> "Access Identifiers". - -@item -On the page, you'll see alphanumeric values for "Your Access Key Id:" and -"Your Secret Access Key:". Make a note of these. Later on, we'll call the -first one your "identifier" and the second one your "secret_identifier." -@end itemize - -When creating an EC2LatentBuildSlave in the buildbot master configuration, -the first three arguments are required. The name and password are the first -two arguments, and work the same as with normal buildslaves. The next -argument specifies the type of the EC2 virtual machine (available options as -of this writing include "m1.small", "m1.large", 'm1.xlarge", "c1.medium", -and "c1.xlarge"; see the EC2 documentation for descriptions of these -machines). - -Here is the simplest example of configuring an EC2 latent buildslave. It -specifies all necessary remaining values explicitly in the instantiation. - -@example -from buildbot.ec2buildslave import EC2LatentBuildSlave -c['slaves'] = [EC2LatentBuildSlave('bot1', 'sekrit', 'm1.large', - ami='ami-12345', - identifier='publickey', - secret_identifier='privatekey' - )] -@end example - -The "ami" argument specifies the AMI that the master should start. The -"identifier" argument specifies the AWS "Access Key Id," and the -"secret_identifier" specifies the AWS "Secret Access Key." Both the AMI and -the account information can be specified in alternate ways. - -Note that whoever has your identifier and secret_identifier values can request -AWS work charged to your account, so these values need to be carefully -protected. Another way to specify these access keys is to put them in a -separate file. You can then make the access privileges stricter for this -separate file, and potentially let more people read your main configuration -file. - -By default, you can make an .ec2 directory in the home folder of the user -running the buildbot master. In that directory, create a file called aws_id. -The first line of that file should be your access key id; the second line -should be your secret access key id. Then you can instantiate the build slave -as follows. - -@example -from buildbot.ec2buildslave import EC2LatentBuildSlave -c['slaves'] = [EC2LatentBuildSlave('bot1', 'sekrit', 'm1.large', - ami='ami-12345')] -@end example - -If you want to put the key information in another file, use the -"aws_id_file_path" initialization argument. - -Previous examples used a particular AMI. If the Buildbot master will be -deployed in a process-controlled environment, it may be convenient to -specify the AMI more flexibly. Rather than specifying an individual AMI, -specify one or two AMI filters. - -In all cases, the AMI that sorts last by its location (the S3 bucket and -manifest name) will be preferred. - -One available filter is to specify the acceptable AMI owners, by AWS account -number (the 12 digit number, usually rendered in AWS with hyphens like -"1234-5678-9012", should be entered as in integer). - -@example -from buildbot.ec2buildslave import EC2LatentBuildSlave -bot1 = EC2LatentBuildSlave('bot1', 'sekrit', 'm1.large', - valid_ami_owners=[11111111111, - 22222222222], - identifier='publickey', - secret_identifier='privatekey' - ) -@end example - -The other available filter is to provide a regular expression string that -will be matched against each AMI's location (the S3 bucket and manifest name). - -@example -from buildbot.ec2buildslave import EC2LatentBuildSlave -bot1 = EC2LatentBuildSlave( - 'bot1', 'sekrit', 'm1.large', - valid_ami_location_regex=r'buildbot\-.*/image.manifest.xml', - identifier='publickey', secret_identifier='privatekey') -@end example - -The regular expression can specify a group, which will be preferred for the -sorting. Only the first group is used; subsequent groups are ignored. - -@example -from buildbot.ec2buildslave import EC2LatentBuildSlave -bot1 = EC2LatentBuildSlave( - 'bot1', 'sekrit', 'm1.large', - valid_ami_location_regex=r'buildbot\-.*\-(.*)/image.manifest.xml', - identifier='publickey', secret_identifier='privatekey') -@end example - -If the group can be cast to an integer, it will be. This allows 10 to sort -after 1, for instance. - -@example -from buildbot.ec2buildslave import EC2LatentBuildSlave -bot1 = EC2LatentBuildSlave( - 'bot1', 'sekrit', 'm1.large', - valid_ami_location_regex=r'buildbot\-.*\-(\d+)/image.manifest.xml', - identifier='publickey', secret_identifier='privatekey') -@end example - -In addition to using the password as a handshake between the master and the -slave, you may want to use a firewall to assert that only machines from a -specific IP can connect as slaves. This is possible with AWS EC2 by using -the Elastic IP feature. To configure, generate a Elastic IP in AWS, and then -specify it in your configuration using the "elastic_ip" argument. - -@example -from buildbot.ec2buildslave import EC2LatentBuildSlave -c['slaves'] = [EC2LatentBuildSlave('bot1', 'sekrit', 'm1.large', - 'ami-12345', - identifier='publickey', - secret_identifier='privatekey', - elastic_ip='208.77.188.166' - )] -@end example - -The EC2LatentBuildSlave supports all other configuration from the standard -BuildSlave. The "missing_timeout" and "notify_on_missing" specify how long -to wait for an EC2 instance to attach before considering the attempt to have -failed, and email addresses to alert, respectively. "missing_timeout" -defaults to 20 minutes. - -The "build_wait_timeout" allows you to specify how long an EC2LatentBuildSlave -should wait after a build for another build before it shuts down the EC2 -instance. It defaults to 10 minutes. - -"keypair_name" and "security_name" allow you to specify different names for -these AWS EC2 values. They both default to "latent_buildbot_slave". - -@node Dangers with Latent Buildslaves, Writing New Latent Buildslaves, Amazon Web Services Elastic Compute Cloud ("AWS EC2"), On-Demand ("Latent") Buildslaves -@subsection Dangers with Latent Buildslaves - -Any latent build slave that interacts with a for-fee service, such as the -EC2LatentBuildSlave, brings significant risks. As already identified, the -configuraton will need access to account information that, if obtained by a -criminal, can be used to charge services to your account. Also, bugs in the -buildbot software may lead to unnecessary charges. In particular, if the -master neglects to shut down an instance for some reason, a virtual machine -may be running unnecessarily, charging against your account. Manual and/or -automatic (e.g. nagios with a plugin using a library like boto) -double-checking may be appropriate. - -A comparitively trivial note is that currently if two instances try to attach -to the same latent buildslave, it is likely that the system will become -confused. This should not occur, unless, for instance, you configure a normal -build slave to connect with the authentication of a latent buildbot. If the -situation occurs, stop all attached instances and restart the master. - -@node Writing New Latent Buildslaves, , Dangers with Latent Buildslaves, On-Demand ("Latent") Buildslaves -@subsection Writing New Latent Buildslaves - -Writing a new latent buildslave should only require subclassing -@code{buildbot.buildslave.AbstractLatentBuildSlave} and implementing -start_instance and stop_instance. - -@example -def start_instance(self): - # responsible for starting instance that will try to connect with this - # master. Should return deferred. Problems should use an errback. The - # callback value can be None, or can be an iterable of short strings to - # include in the "substantiate success" status message, such as - # identifying the instance that started. - raise NotImplementedError - -def stop_instance(self, fast=False): - # responsible for shutting down instance. Return a deferred. If `fast`, - # we're trying to shut the master down, so callback as soon as is safe. - # Callback value is ignored. - raise NotImplementedError -@end example - -See @code{buildbot.ec2buildslave.EC2LatentBuildSlave} for an example, or see the -test example @code{buildbot.test_slaves.FakeLatentBuildSlave}. - -@node Defining Global Properties, Defining Builders, On-Demand ("Latent") Buildslaves, Configuration -@section Defining Global Properties -@bcindex c['properties'] -@cindex Properties - -The @code{'properties'} configuration key defines a dictionary -of properties that will be available to all builds started by the -buildmaster: - -@example -c['properties'] = @{ - 'Widget-version' : '1.2', - 'release-stage' : 'alpha' -@} -@end example - -@node Defining Builders, Defining Status Targets, Defining Global Properties, 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['slaves']} 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:: -* Choosing ChangeSources:: -* CVSToys - PBService:: -* Mail-parsing ChangeSources:: -* PBChangeSource:: -* P4Source:: -* BonsaiPoller:: -* SVNPoller:: -* MercurialHook:: -* Bzr Hook:: -* Bzr Poller:: -@end menu - - - -@node Change Sources, Choosing ChangeSources, 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 mail.SVNCommitEmailMaildirSource (watching for email sent by commit-email.pl) -@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) -@item pb.PBChangeSource (listening for connections from -@code{buildbot/changes/hgbuildbot.py} run as an in-process 'changegroup' -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 - -@item Bzr (the newer Bazaar) -@itemize @bullet -@item pb.PBChangeSource (listening for connections from -@code{contrib/bzr_buildbot.py} run in a post-change-branch-tip or commit hook) -@item @code{contrib/bzr_buildbot.py}'s BzrPoller (polling the Bzr repository) -@end itemize - -@item Git -@itemize @bullet -@item pb.PBChangeSource (listening for connections from -@code{contrib/git_buildbot.py} run in the post-receive 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}. - - -@node Choosing ChangeSources, CVSToys - PBService, Change Sources, Getting Source Code Changes -@section Choosing ChangeSources - -The @code{master.cfg} configuration file has a dictionary key named -@code{BuildmasterConfig['change_source']}, which holds the active -@code{IChangeSource} object. The config file will typically create an -object from one of the classes described below and stuff it into this -key. - -Each buildmaster typically has just a single ChangeSource, since it is -only watching a single source tree. But if, for some reason, you need -multiple sources, just set @code{c['change_source']} to a list of -ChangeSources.. it will accept that too. - -@example -s = FreshCVSSourceNewcred(host="host", port=4519, - user="alice", passwd="secret", - prefix="Twisted") -BuildmasterConfig['change_source'] = [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, Mail-parsing ChangeSources, Choosing ChangeSources, Getting Source Code Changes -@section 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['change_source'] = 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 Mail-parsing ChangeSources, PBChangeSource, CVSToys - PBService, Getting Source Code Changes -@section Mail-parsing ChangeSources - -Many projects publish information about changes to their source tree -by sending an email message out to a mailing list, frequently named -PROJECT-commits or PROJECT-changes. Each message usually contains a -description of the change (who made the change, which files were -affected) and sometimes a copy of the diff. Humans can subscribe to -this list to stay informed about what's happening to the source tree. - -The Buildbot can also be subscribed to a -commits mailing list, and -can trigger builds in response to Changes that it hears about. The -buildmaster admin needs to arrange for these email messages to arrive -in a place where the buildmaster can find them, and configure the -buildmaster to parse the messages correctly. Once that is in place, -the email parser will create Change objects and deliver them to the -Schedulers (see @pxref{Change Sources and Schedulers}) just -like any other ChangeSource. - -There are two components to setting up an email-based ChangeSource. -The first is to route the email messages to the buildmaster, which is -done by dropping them into a ``maildir''. The second is to actually -parse the messages, which is highly dependent upon the tool that was -used to create them. Each VC system has a collection of favorite -change-emailing tools, and each has a slightly different format, so -each has a different parsing function. There is a separate -ChangeSource variant for each parsing function. - -Once you've chosen a maildir location and a parsing function, create -the change source and put it in @code{c['change_source']}: - -@example -from buildbot.changes.mail import SyncmailMaildirSource -c['change_source'] = SyncmailMaildirSource("~/maildir-buildbot", - prefix="/trunk/") -@end example - -@menu -* Subscribing the Buildmaster:: -* Using Maildirs:: -* Parsing Email Change Messages:: -@end menu - -@node Subscribing the Buildmaster, Using Maildirs, Mail-parsing ChangeSources, Mail-parsing ChangeSources -@subsection Subscribing the Buildmaster - -The recommended way to install the buildbot is to create a dedicated -account for the buildmaster. If you do this, the account will probably -have a distinct email address (perhaps -@email{buildmaster@@example.org}). Then just arrange for this -account's email to be delivered to a suitable maildir (described in -the next section). - -If the buildbot does not have its own account, ``extension addresses'' -can be used to distinguish between email intended for the buildmaster -and email intended for the rest of the account. In most modern MTAs, -the e.g. @code{foo@@example.org} account has control over every email -address at example.org which begins with "foo", such that email -addressed to @email{account-foo@@example.org} can be delivered to a -different destination than @email{account-bar@@example.org}. qmail -does this by using separate .qmail files for the two destinations -(@file{.qmail-foo} and @file{.qmail-bar}, with @file{.qmail} -controlling the base address and @file{.qmail-default} controlling all -other extensions). Other MTAs have similar mechanisms. - -Thus you can assign an extension address like -@email{foo-buildmaster@@example.org} to the buildmaster, and retain -@email{foo@@example.org} for your own use. - - -@node Using Maildirs, Parsing Email Change Messages, Subscribing the Buildmaster, Mail-parsing ChangeSources -@subsection Using Maildirs - -A ``maildir'' is a simple directory structure originally developed for -qmail that allows safe atomic update without locking. Create a base -directory with three subdirectories: ``new'', ``tmp'', and ``cur''. -When messages arrive, they are put into a uniquely-named file (using -pids, timestamps, and random numbers) in ``tmp''. When the file is -complete, it is atomically renamed into ``new''. Eventually the -buildmaster notices the file in ``new'', reads and parses the -contents, then moves it into ``cur''. A cronjob can be used to delete -files in ``cur'' at leisure. - -Maildirs are frequently created with the @command{maildirmake} tool, -but a simple @command{mkdir -p ~/MAILDIR/@{cur,new,tmp@}} is pretty much -equivalent. - -Many modern MTAs can deliver directly to maildirs. The usual .forward -or .procmailrc syntax is to name the base directory with a trailing -slash, so something like @code{~/MAILDIR/} . qmail and postfix are -maildir-capable MTAs, and procmail is a maildir-capable MDA (Mail -Delivery Agent). - -For MTAs which cannot put files into maildirs directly, the -``safecat'' tool can be executed from a .forward file to accomplish -the same thing. - -The Buildmaster uses the linux DNotify facility to receive immediate -notification when the maildir's ``new'' directory has changed. When -this facility is not available, it polls the directory for new -messages, every 10 seconds by default. - -@node Parsing Email Change Messages, , Using Maildirs, Mail-parsing ChangeSources -@subsection Parsing Email Change Messages - -The second component to setting up an email-based ChangeSource is to -parse the actual notices. This is highly dependent upon the VC system -and commit script in use. - -A couple of common tools used to create these change emails are: - -@table @samp - -@item CVS -@table @samp -@item CVSToys MailNotifier -@ref{FCMaildirSource} -@item Bonsai notification -@ref{BonsaiMaildirSource} -@item syncmail -@ref{SyncmailMaildirSource} -@end table - -@item SVN -@table @samp -@item svnmailer -http://opensource.perlig.de/en/svnmailer/ -@item commit-email.pl -@ref{SVNCommitEmailMaildirSource} -@end table - -@item Mercurial -@table @samp -@item NotifyExtension -http://www.selenic.com/mercurial/wiki/index.cgi/NotifyExtension -@end table - -@item Git -@table @samp -@item post-receive-email -http://git.kernel.org/?p=git/git.git;a=blob;f=contrib/hooks/post-receive-email;hb=HEAD -@end table - -@end table - - -The following sections describe the parsers available for each of -these tools. - -Most of these parsers accept a @code{prefix=} argument, which is used -to limit the set of files that the buildmaster pays attention to. This -is most useful for systems like CVS and SVN which put multiple -projects in a single repository (or use repository names to indicate -branches). Each filename that appears in the email is tested against -the prefix: if the filename does not start with the prefix, the file -is ignored. If the filename @emph{does} start with the prefix, that -prefix is stripped from the filename before any further processing is -done. Thus the prefix usually ends with a slash. - -@menu -* FCMaildirSource:: -* SyncmailMaildirSource:: -* BonsaiMaildirSource:: -* SVNCommitEmailMaildirSource:: -@end menu - -@node FCMaildirSource, SyncmailMaildirSource, Parsing Email Change Messages, Parsing Email Change Messages -@subsubsection FCMaildirSource - - -@csindex buildbot.changes.mail.FCMaildirSource - -http://twistedmatrix.com/users/acapnotic/wares/code/CVSToys/ - -This parser works with the CVSToys @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} knows for to parse these CVSToys -messages and turn them into Change objects. It can be given two -parameters: the directory name of the maildir root, and the prefix to -strip. - -@example -from buildbot.changes.mail import FCMaildirSource -c['change_source'] = FCMaildirSource("~/maildir-buildbot") -@end example - -@node SyncmailMaildirSource, BonsaiMaildirSource, FCMaildirSource, Parsing Email Change Messages -@subsubsection SyncmailMaildirSource - -@csindex buildbot.changes.mail.SyncmailMaildirSource - -http://sourceforge.net/projects/cvs-syncmail - -@code{SyncmailMaildirSource} knows how to parse the message format used by -the CVS ``syncmail'' script. - -@example -from buildbot.changes.mail import SyncmailMaildirSource -c['change_source'] = SyncmailMaildirSource("~/maildir-buildbot") -@end example - -@node BonsaiMaildirSource, SVNCommitEmailMaildirSource, SyncmailMaildirSource, Parsing Email Change Messages -@subsubsection BonsaiMaildirSource - -@csindex buildbot.changes.mail.BonsaiMaildirSource - -http://www.mozilla.org/bonsai.html - -@code{BonsaiMaildirSource} parses messages sent out by Bonsai, the CVS -tree-management system built by Mozilla. - -@example -from buildbot.changes.mail import BonsaiMaildirSource -c['change_source'] = BonsaiMaildirSource("~/maildir-buildbot") -@end example - -@node SVNCommitEmailMaildirSource, , BonsaiMaildirSource, Parsing Email Change Messages -@subsubsection SVNCommitEmailMaildirSource - -@csindex buildbot.changes.mail.SVNCommitEmailMaildirSource - -@code{SVNCommitEmailMaildirSource} parses message sent out by the -@code{commit-email.pl} script, which is included in the Subversion -distribution. - -It does not currently handle branches: all of the Change objects that -it creates will be associated with the default (i.e. trunk) branch. - -@example -from buildbot.changes.mail import SVNCommitEmailMaildirSource -c['change_source'] = SVNCommitEmailMaildirSource("~/maildir-buildbot") -@end example - - -@node PBChangeSource, P4Source, Mail-parsing ChangeSources, Getting Source Code Changes -@section 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}, @file{contrib/arch_buildbot.py}, -@file{contrib/hg_buildbot.py} tools, and the -@code{buildbot.changes.hgbuildbot} hook. 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, Getting Source Code Changes -@section 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{p4bin} -An optional string parameter. Specify the location of the perforce command -line binary (p4). You only need to do this if the perforce binary is not -in the path of the buildbot user. Defaults to ``p4''. - -@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 -s = p4poller.P4Source(p4base='//depot/project/', - split_file=lambda branchfile: branchfile.split('/',1), - ) -c['change_source'] = s -@end example - -@node BonsaiPoller, SVNPoller, P4Source, Getting Source Code Changes -@section 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, MercurialHook, BonsaiPoller, Getting Source Code Changes -@section 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 -c['change_source'] = SVNPoller("svn://svn.twistedmatrix.com/svn/Twisted/trunk") -@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 -c['change_source'] = SVNPoller("svn://svn.twistedmatrix.com/svn/Twisted", - split_file=split_file_branches) -@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 -c['change_source'] = SVNPoller("http://divmod.org/svn/Divmod/trunk/Nevow") -@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 -c['change_source'] = SVNPoller("http://divmod.org/svn/Divmod", - split_file=my_file_splitter) -@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 MercurialHook, Bzr Hook, SVNPoller, Getting Source Code Changes -@section MercurialHook - -Since Mercurial is written in python, the hook script can invoke -Buildbot's @code{sendchange} function directly, rather than having to -spawn an external process. This function delivers the same sort of -changes as @code{buildbot sendchange} and the various hook scripts in -contrib/, so you'll need to add a @code{pb.PBChangeSource} to your -buildmaster to receive these changes. - -To set this up, first choose a Mercurial repository that represents -your central ``official'' source tree. This will be the same -repository that your buildslaves will eventually pull from. Install -Buildbot on the machine that hosts this repository, using the same -version of python as Mercurial is using (so that the Mercurial hook -can import code from buildbot). Then add the following to the -@code{.hg/hgrc} file in that repository, replacing the buildmaster -hostname/portnumber as appropriate for your buildbot: - -@example -[hooks] -changegroup.buildbot = python:buildbot.changes.hgbuildbot.hook - -[hgbuildbot] -master = buildmaster.example.org:9987 -@end example - -(Note that Mercurial lets you define multiple @code{changegroup} hooks -by giving them distinct names, like @code{changegroup.foo} and -@code{changegroup.bar}, which is why we use -@code{changegroup.buildbot} in this example. There is nothing magical -about the ``buildbot'' suffix in the hook name. The -@code{[hgbuildbot]} section @emph{is} special, however, as it is the -only section that the buildbot hook pays attention to.) - -Also note that this runs as a @code{changegroup} hook, rather than as -an @code{incoming} hook. The @code{changegroup} hook is run with -multiple revisions at a time (say, if multiple revisions are being -pushed to this repository in a single @command{hg push} command), -whereas the @code{incoming} hook is run with just one revision at a -time. The @code{hgbuildbot.hook} function will only work with the -@code{changegroup} hook. - -The @code{[hgbuildbot]} section has two other parameters that you -might specify, both of which control the name of the branch that is -attached to the changes coming from this hook. - -One common branch naming policy for Mercurial repositories is to use -it just like Darcs: each branch goes into a separate repository, and -all the branches for a single project share a common parent directory. -For example, you might have @file{/var/repos/PROJECT/trunk/} and -@file{/var/repos/PROJECT/release}. To use this style, use the -@code{branchtype = dirname} setting, which simply uses the last -component of the repository's enclosing directory as the branch name: - -@example -[hgbuildbot] -master = buildmaster.example.org:9987 -branchtype = dirname -@end example - -Another approach is to use Mercurial's built-in branches (the kind -created with @command{hg branch} and listed with @command{hg -branches}). This feature associates persistent names with particular -lines of descent within a single repository. (note that the buildbot -@code{source.Mercurial} checkout step does not yet support this kind -of branch). To have the commit hook deliver this sort of branch name -with the Change object, use @code{branchtype = inrepo}: - -@example -[hgbuildbot] -master = buildmaster.example.org:9987 -branchtype = inrepo -@end example - -Finally, if you want to simply specify the branchname directly, for -all changes, use @code{branch = BRANCHNAME}. This overrides -@code{branchtype}: - -@example -[hgbuildbot] -master = buildmaster.example.org:9987 -branch = trunk -@end example - -If you use @code{branch=} like this, you'll need to put a separate -.hgrc in each repository. If you use @code{branchtype=}, you may be -able to use the same .hgrc for all your repositories, stored in -@file{~/.hgrc} or @file{/etc/mercurial/hgrc}. - - -@node Bzr Hook, Bzr Poller, MercurialHook, Getting Source Code Changes -@section Bzr Hook - -Bzr is also written in Python, and the Bzr hook depends on Twisted to send the -changes. - -To install, put @code{contrib/bzr_buildbot.py} in one of your plugins -locations a bzr plugins directory (e.g., -@code{~/.bazaar/plugins}). Then, in one of your bazaar conf files (e.g., -@code{~/.bazaar/locations.conf}), set the location you want to connect with buildbot -with these keys: - -@table @code -@item buildbot_on -one of 'commit', 'push, or 'change'. Turns the plugin on to report changes via -commit, changes via push, or any changes to the trunk. 'change' is -recommended. - -@item buildbot_server -(required to send to a buildbot master) the URL of the buildbot master to -which you will connect (as of this writing, the same server and port to which -slaves connect). - -@item buildbot_port -(optional, defaults to 9989) the port of the buildbot master to which you will -connect (as of this writing, the same server and port to which slaves connect) - -@item buildbot_pqm -(optional, defaults to not pqm) Normally, the user that commits the revision -is the user that is responsible for the change. When run in a pqm (Patch Queue -Manager, see https://launchpad.net/pqm) environment, the user that commits is -the Patch Queue Manager, and the user that committed the *parent* revision is -responsible for the change. To turn on the pqm mode, set this value to any of -(case-insensitive) "Yes", "Y", "True", or "T". - -@item buildbot_dry_run -(optional, defaults to not a dry run) Normally, the post-commit hook will -attempt to communicate with the configured buildbot server and port. If this -parameter is included and any of (case-insensitive) "Yes", "Y", "True", or -"T", then the hook will simply print what it would have sent, but not attempt -to contact the buildbot master. - -@item buildbot_send_branch_name -(optional, defaults to not sending the branch name) If your buildbot's bzr -source build step uses a repourl, do *not* turn this on. If your buildbot's -bzr build step uses a baseURL, then you may set this value to any of -(case-insensitive) "Yes", "Y", "True", or "T" to have the buildbot master -append the branch name to the baseURL. - -@end table - -When buildbot no longer has a hardcoded password, it will be a configuration -option here as well. - -Here's a simple example that you might have in your -@code{~/.bazaar/locations.conf}. - -@example -[chroot-*:///var/local/myrepo/mybranch] -buildbot_on = change -buildbot_server = localhost -@end example - -@node Bzr Poller, , Bzr Hook, Getting Source Code Changes -@section Bzr Poller - -If you cannot insert a Bzr hook in the server, you can use the Bzr Poller. To -use, put @code{contrib/bzr_buildbot.py} somewhere that your buildbot -configuration can import it. Even putting it in the same directory as the master.cfg -should work. Install the poller in the buildbot configuration as with any -other change source. Minimally, provide a URL that you want to poll (bzr://, -bzr+ssh://, or lp:), though make sure the buildbot user has necessary -privileges. You may also want to specify these optional values. - -@table @code -@item poll_interval -The number of seconds to wait between polls. Defaults to 10 minutes. - -@item branch_name -Any value to be used as the branch name. Defaults to None, or specify a -string, or specify the constants from @code{bzr_buildbot.py} SHORT or FULL to -get the short branch name or full branch address. - -@item blame_merge_author -normally, the user that commits the revision is the user that is responsible -for the change. When run in a pqm (Patch Queue Manager, see -https://launchpad.net/pqm) environment, the user that commits is the Patch -Queue Manager, and the user that committed the merged, *parent* revision is -responsible for the change. set this value to True if this is pointed against -a PQM-managed branch. -@end table - -@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 that goes into the @code{BuildFactory}. -The @code{BuildStep} instances in this list are used as templates to -construct new independent copies for each build (so that state can be -kept on the @code{BuildStep} in one build without affecting a later -build). Each @code{BuildFactory} can be created with a list of steps, -or the factory can be created empty and then steps added to it using -the @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 - -In earlier versions (0.7.5 and older), these steps were specified with -a tuple of (step_class, keyword_arguments). Steps can still be -specified this way, but the preferred form is to pass actual -@code{BuildStep} instances to @code{addStep}, because that gives the -@code{BuildStep} class a chance to do some validation on the -arguments. - -If you have a common set of steps which are used in several factories, the -@code{addSteps} method may be handy. It takes an iterable of @code{BuildStep} -instances. - -@example -setup_steps = [ - source.SVN(svnurl="http://svn.example.org/Trunk/") - shell.ShellCommand(command="./setup") -] -quick = factory.BuildFactory() -quick.addSteps(setup_steps) -quick.addStep(shell.shellCommand(command="make quick")) -@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:: -* Using Build Properties:: -* Source Checkout:: -* ShellCommand:: -* Simple ShellCommand Subclasses:: -* Python BuildSteps:: -* Transferring Files:: -* Steps That Run on the Master:: -* Triggering Schedulers:: -* Writing New BuildSteps:: -@end menu - -@node Common Parameters, Using Build Properties, 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. Steps with @code{alwaysRun=True} are still run. Generally -speaking, haltOnFailure implies flunkOnFailure (the default for most -BuildSteps). In some cases, particularly series of tests, it makes sense -to haltOnFailure if something fails early on but not flunkOnFailure. -This can be achieved with haltOnFailure=True, flunkOnFailure=False. - -@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 alwaysRun -if True, this build step will always be run, even if a previous buildstep -with @code{haltOnFailure=True} has failed. - -@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 Using Build Properties, Source Checkout, Common Parameters, Build Steps -@subsection Using Build Properties -@cindex Properties - -Build properties are a generalized way to provide configuration -information to build steps; see @ref{Build Properties}. - -Some build properties are inherited from external sources -- global -properties, schedulers, or buildslaves. 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): - if self.getProperty("os") == "win": - self.setCommand([ ... ]) # windows-only command - else: - self.setCommand([ ... ]) # equivalent for other systems - ShellCommand.start(self) -@end example - -@heading WithProperties -@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. Most step parameters accept -@code{WithProperties}. Please file bugs for any parameters which -do not. - -@example -from buildbot.steps.shell import ShellCommand -from buildbot.process.properties import 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. - -The dictionary-style interpolation supports a number of more advanced -syntaxes, too. - -@table @code - -@item propname:-replacement -If @code{propname} exists, substitute its value; otherwise, -substitute @code{replacement}. @code{replacement} may be empty -(@code{%(propname:-)s}) - -@item propname:+replacement -If @code{propname} exists, substitute @code{replacement}; otherwise, -substitute an empty string. - -@end table - -Although these are similar to shell substitutions, no other -substitutions are currently supported, and @code{replacement} in the -above cannot contain more substitutions. - -Note: 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")}. - -@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. This is always a -string, although 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. - -@item scheduler - -If the build was started from a scheduler, then this property will -contain the name of that scheduler. - -@end table - - -@node Source Checkout, ShellCommand, Using Build Properties, 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:: -* Bzr:: -* P4:: -* Git:: -@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. - -@item username -if specified, this will be passed to the @code{svn} binary with a -@code{--username} option. - -@item password -if specified, this will be passed to the @code{svn} binary with a -@code{--password} option. The password itself will be suitably obfuscated in -the logs. - -@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['change_source'] = 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://darcs.net/, 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, Bzr, 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 Bzr, P4, Bazaar, Source Checkout -@subsubsection Bzr - -@cindex Bzr Checkout -@bsindex buildbot.steps.source.Bzr - -@code{bzr} is a descendant of Arch/Baz, and is frequently referred to -as simply ``Bazaar''. The repository-vs-workspace model is similar to -Darcs, but it uses a strictly linear sequence of revisions (one -history per branch) like Arch. Branches are put in subdirectories. -This makes it look very much like Mercurial, so it takes the same -arguments: - -@table @code - -@item repourl -(required unless @code{baseURL} is provided): the URL at which the -Bzr 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{bzr checkout} command. -@end table - - - -@node P4, Git, Bzr, 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 Git, , P4, Source Checkout -@subsubsection Git - -@cindex Git Checkout -@bsindex buildbot.steps.source.Git - -The @code{Git} build step clones or updates a @uref{http://git.or.cz/, -Git} repository and checks out the specified branch or revision. Note -that the buildbot supports Git version 1.2.0 and later: earlier -versions (such as the one shipped in Ubuntu 'Dapper') do not support -the @command{git init} command that the buildbot uses. - -The Git step takes the following arguments: - -@table @code -@item repourl -(required): the URL of the upstream Git repository. - -@item branch -(optional): this specifies the name of the branch to use when a Build -does not provide one of its own. If this this parameter is not -specified, and the Build does not provide a branch, the ``master'' -branch will be used. -@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. - -On Windows, commands are run via @code{cmd.exe /c} which works well. However, -if you're running a batch file, the error level does not get propagated -correctly unless you add 'call' before your batch file's name: -@code{cmd=['call', 'myfile.bat', ...]}. - -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 or the environment specified in the -Builder. 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 usePTY -Should this command be run in a @code{pty}? The default is to observe the -configuration of the client (@pxref{Buildslave Options}), but specifying -@code{True} or @code{False} here will override the default. - -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). - -@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 - -@item logEnviron -If this option is true (the default), then the step's logfile will describe the -environment variables on the slave. In situations where the environment is not -relevant and is long, it may be easier to set @code{logEnviron=False}. - -@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:: -* TreeSize:: -* PerlModuleTest:: -* SetProperty:: -@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 warning messages, a summary log is -created with any problems that were seen, and the step is marked as -WARNINGS if any were discovered. The number of warnings is stored in a -Build Property named ``warnings-count'', which is accumulated over all -Compile steps (so if two warnings are found in one step, and three are -found in another step, the overall build will have a -``warnings-count'' property of 5. - -The default regular expression used to detect a warning is -@code{'.*warning[: ].*'} , which is fairly liberal and may cause -false-positives. To use a different regexp, provide a -@code{warningPattern=} argument, or use a subclass which sets the -@code{warningPattern} attribute: - -@example -f.addStep(Compile(command=["make", "test"], - warningPattern="^Warning: ")) -@end example - -The @code{warningPattern=} can also be a pre-compiled python regexp -object: this makes it possible to add flags like @code{re.I} (to use -case-insensitive matching). - -(TODO: this step needs to be extended to look for GCC error messages -as well, and collect them into a separate logfile, along with the -source code filenames involved). - - -@node Test, TreeSize, 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 TreeSize, PerlModuleTest, Test, Simple ShellCommand Subclasses -@subsubsection TreeSize - -@bsindex buildbot.steps.shell.TreeSize - -This is a simple command that uses the 'du' tool to measure the size -of the code tree. It puts the size (as a count of 1024-byte blocks, -aka 'KiB' or 'kibibytes') on the step's status text, and sets a build -property named 'tree-size-KiB' with the same value. - -@node PerlModuleTest, SetProperty, TreeSize, Simple ShellCommand Subclasses -@subsubsection PerlModuleTest - -@bsindex buildbot.steps.shell.PerlModuleTest - -This is a simple command that knows how to run tests of perl modules. -It parses the output to determine the number of tests passed and -failed and total number executed, saving the results for later query. - -@node SetProperty, , PerlModuleTest, Simple ShellCommand Subclasses -@subsubsection SetProperty - -@bsindex buildbot.steps.shell.SetProperty - -This buildstep is similar to ShellCommand, except that it captures the -output of the command into a property. It is usually used like this: - -@example -f.addStep(SetProperty(command="uname -a", property="uname")) -@end example - -This runs @code{uname -a} and captures its stdout, stripped of leading -and trailing whitespace, in the property "uname". To avoid stripping, -add @code{strip=False}. The @code{property} argument can be specified -as a @code{WithProperties} object. - -The more advanced usage allows you to specify a function to extract -properties from the command output. Here you can use regular -expressions, string interpolation, or whatever you would like. -The function is called with three arguments: the exit status of the -command, its standard output as a string, and its standard error as -a string. It should return a dictionary containing all new properties. - -@example -def glob2list(rc, stdout, stderr): - jpgs = [ l.strip() for l in stdout.split('\n') ] - return @{ 'jpgs' : jpgs @} -f.addStep(SetProperty(command="ls -1 *.jpg", extract_fn=glob2list)) -@end example - -Note that any ordering relationship of the contents of stdout and -stderr is lost. For example, given - -@example -f.addStep(SetProperty( - command="echo output1; echo error >&2; echo output2", - extract_fn=my_extract)) -@end example - -Then @code{my_extract} will see @code{stdout="output1\noutput2\n"} -and @code{stderr="error\n"}. - -@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:: -* PyLint:: -@end menu - -@node BuildEPYDoc -@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 -@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 PyLint -@subsubsection PyLint - -@bsindex buildbot.steps.python.PyLint - -Similarly, the @code{buildbot.steps.python.PyLint} step will run pylint and -analyze the results. - -You must supply the command line to be used. There is no default. - -@example -from buildbot.steps.python import PyLint - -... -f.addStep(PyLint(command=["pylint", "src"])) -@end example - - -@node Transferring Files -@subsection Transferring Files - -@cindex File Transfer -@bsindex buildbot.steps.transfer.FileUpload -@bsindex buildbot.steps.transfer.FileDownload -@bsindex buildbot.steps.transfer.DirectoryUpload - -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}. Both of these commands -will create any missing intervening directories. - -@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}). - -@subheading Transfering Directories - -To transfer complete directories from the buildslave to the master, there -is a BuildStep named @code{DirectoryUpload}. It works like @code{FileUpload}, -just for directories. However it does not support the @code{maxsize}, -@code{blocksize} and @code{mode} arguments. As an example, let's assume an -generated project documentation, which consists of many files (like the output -of doxygen or epydoc). We want to move the entire documentation to the -buildmaster, into a @code{~/public_html/docs} directory. On the slave-side -the directory can be found under @code{docs}: - -@example -from buildbot.steps.shell import ShellCommand -from buildbot.steps.transfer import DirectoryUpload - -f.addStep(ShellCommand(command=["make", "docs"])) -f.addStep(DirectoryUpload(slavesrc="docs", - masterdest="~/public_html/docs")) -@end example - -The DirectoryUpload step will create all necessary directories and -transfers empty directories, too. - -@node Steps That Run on the Master -@subsection Steps That Run on the Master - -Occasionally, it is useful to execute some task on the master, for example to -create a directory, deploy a build result, or trigger some other centralized -processing. This is possible, in a limited fashion, with the -@code{MasterShellCommand} step. - -This step operates similarly to a regular @code{ShellCommand}, but executes on -the master, instead of the slave. To be clear, the enclosing @code{Build} -object must still have a slave object, just as for any other step -- only, in -this step, the slave does not do anything. - -In this example, the step renames a tarball based on the day of the week. - -@example -from buildbot.steps.transfer import FileUpload -from buildbot.steps.master import MasterShellCommand - -f.addStep(FileUpload(slavesrc="widgetsoft.tar.gz", - masterdest="/var/buildoutputs/widgetsoft-new.tar.gz")) -f.addStep(MasterShellCommand(command=""" - cd /var/buildoutputs; - mv widgetsoft-new.tar.gz widgetsoft-`date +%a`.tar.gz""")) -@end example - -@node Triggering Schedulers -@subsection Triggering Schedulers - -The counterpart to the Triggerable described in section -@pxref{Triggerable Scheduler} is the Trigger BuildStep. - -@example -from buildbot.steps.trigger import Trigger -f.addStep(Trigger(schedulerNames=['build-prep'], - waitForFinish=True, - updateSourceStamp=True)) -@end example - -The @code{schedulerNames=} argument lists the Triggerables -that should be triggered when this step is executed. Note that -it is possible, but not advisable, to create a cycle where a build -continually triggers itself, because the schedulers are specified -by name. - -If @code{waitForFinish} is True, then the step will not finish until -all of the builds from the triggered schedulers have finished. If this -argument is False (the default) or not given, then the buildstep -succeeds immediately after triggering the schedulers. - -If @code{updateSourceStamp} is True (the default), then step updates -the SourceStamp given to the Triggerables to include -@code{got_revision} (the revision actually used in this build) as -@code{revision} (the revision to use in the triggered builds). This is -useful to ensure that all of the builds use exactly the same -SourceStamp, even if other Changes have occurred while the build was -running. - -@node Writing New BuildSteps -@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 way 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. - -@menu -* Writing BuildStep Constructors:: -* BuildStep LogFiles:: -* Reading Logfiles:: -* Adding LogObservers:: -* BuildStep URLs:: -@end menu - -@node Writing BuildStep Constructors -@subsubsection Writing BuildStep Constructors - -BuildStep classes have some extra equipment, because they are their own -factories. Consider the use of a BuildStep in @file{master.cfg}: - -@example -f.addStep(MyStep(someopt="stuff", anotheropt=1)) -@end example - -This creates a single instance of class @code{MyStep}. However, Buildbot needs -a new object each time the step is executed. this is accomplished by storing -the information required to instantiate a new object in the @code{factory} -attribute. When the time comes to construct a new Build, BuildFactory consults -this attribute (via @code{getStepFactory}) and instantiates a new step object. - -When writing a new step class, then, keep in mind are that you cannot do -anything "interesting" in the constructor -- limit yourself to checking and -storing arguments. To ensure that these arguments are provided to any new -objects, call @code{self.addFactoryArguments} with any keyword arguments your -constructor needs. - -Keep a @code{**kwargs} argument on the end of your options, and pass that up to -the parent class's constructor. - -The whole thing looks like this: - -@example -class Frobinfy(LoggingBuildStep): - def __init__(self, - frob_what="frobee", - frob_how_many=None, - frob_how=None, - **kwargs) - - # check - if frob_how_many is None: - raise TypeError("Frobinfy argument how_many is required") - - # call parent - LoggingBuildStep.__init__(self, **kwargs) - - # and record arguments for later - self.addFactoryArguments( - frob_what=frob_what, - frob_how_many=frob_how_many, - frob_how=frob_how) - -class FastFrobnify(Frobnify): - def __init__(self, - speed=5, - **kwargs) - Frobnify.__init__(self, **kwargs) - self.addFactoryArguments( - speed=speed) -@end example - -@node BuildStep LogFiles -@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 Reading Logfiles -@subsubsection Reading Logfiles - -Once a LogFile has been added to a BuildStep with @code{addLog()}, -@code{addCompleteLog()}, @code{addHTMLLog()}, or @code{logfiles=}, -your BuildStep can retrieve it by using @code{getLog()}: - -@example -class MyBuildStep(ShellCommand): - logfiles = @{ "nodelog": "_test/node.log" @} - - def evaluateCommand(self, cmd): - nodelog = self.getLog("nodelog") - if "STARTED" in nodelog.getText(): - return SUCCESS - else: - return FAILURE -@end example - -For a complete list of the methods you can call on a LogFile, please -see the docstrings on the @code{IStatusLog} class in -@file{buildbot/interfaces.py}. - - -@node Adding LogObservers, BuildStep URLs, Reading 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. (Lines longer than a set maximum -length are dropped; the maximum defaults to 16384 bytes, but you can -change it by calling @code{setMaxLineLength()} on your -@code{LogLineObserver} instance. Use @code{sys.maxint} for effective -infinity.) - -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) - self.progressMetrics += ('tests',) -@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('stdio', counter) - self.progressMetrics += ('tests',) -# 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 ->>> import pprint ->>> pprint.pprint(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 - -Make a fork of buildbot on http://github.com/djmitche/buildbot or post a patch -in a bug at http://buildbot.net. In either case, post a note about your patch -to the mailing list, so others can provide feedback and, eventually, commit it. - -@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 -@slindex buildbot.locks.LockAccess - -Until now, we assumed that a master can run builds at any slave whenever -needed or desired. Some times, you want to enforce additional constraints on -builds. For reasons like limited network bandwidth, old slave machines, or a -self-willed data base server, you may want to limit the number of builds (or -build steps) that can access a resource. - -The mechanism used by Buildbot is known as the read/write lock.@footnote{See -http://en.wikipedia.org/wiki/Read/write_lock_pattern for more information.} It -allows either many readers or a single writer but not a combination of readers -and writers. The general lock has been modified and extended for use in -Buildbot. Firstly, the general lock allows an infinite number of readers. In -Buildbot, we often want to put an upper limit on the number of readers, for -example allowing two out of five possible builds at the same time. To do this, -the lock counts the number of active readers. Secondly, the terms @emph{read -mode} and @emph{write mode} are confusing in Buildbot context. They have been -replaced by @emph{counting mode} (since the lock counts them) and @emph{exclusive -mode}. As a result of these changes, locks in Buildbot allow a number of -builds (upto some fixed number) in counting mode, or they allow one build in -exclusive mode. - -Often, not all slaves are equal. To allow for this situation, Buildbot allows -to have a separate upper limit on the count for each slave. In this way, you -can have at most 3 concurrent builds at a fast slave, 2 at a slightly older -slave, and 1 at all other slaves. - -The final thing you can specify when you introduce a new lock is its scope. -Some constraints are global -- they must be enforced over all slaves. Other -constraints are local to each slave. A @emph{master lock} is used for the -global constraints. You can ensure for example that at most one build (of all -builds running at all slaves) accesses the data base server. With a -@emph{slave lock} you can add a limit local to each slave. With such a lock, -you can for example enforce an upper limit to the number of active builds at a -slave, like above. - -Time for a few examples. Below a master lock is defined to protect a data base, -and a slave lock is created to limit the number of builds at each slave. - -@example -from buildbot import locks - -db_lock = locks.MasterLock("database") -build_lock = locks.SlaveLock("slave_builds", - maxCount = 1, - maxCountForSlave = @{ 'fast': 3, 'new': 2 @}) -@end example - -After importing locks from buildbot, @code{db_lock} is defined to be a master -lock. The @code{"database"} string is used for uniquely identifying the lock. -At the next line, a slave lock called @code{build_lock} is created. It is -identified by the @code{"slave_builds"} string. Since the requirements of the -lock are a bit more complicated, two optional arguments are also specified. The -@code{maxCount} parameter sets the default limit for builds in counting mode to -@code{1}. For the slave called @code{'fast'} however, we want to have at most -three builds, and for the slave called @code{'new'} the upper limit is two -builds running at the same time. - -The next step is using the locks in builds. Buildbot allows a lock to be used -during an entire build (from beginning to end), or only during a single build -step. In the latter case, the lock is claimed for use just before the step -starts, and released again when the step ends. To prevent -deadlocks,@footnote{Deadlock is the situation where two or more slaves each -hold a lock in exclusive mode, and in addition want to claim the lock held by -the other slave exclusively as well. Since locks allow at most one exclusive -user, both slaves will wait forever.} it is not possible to claim or release -locks at other times. - -To use locks, you should add them with a @code{locks} argument. -Each use of a lock is either in counting mode (that is, possibly shared with -other builds) or in exclusive mode. A build or build step proceeds only when it -has acquired all locks. If a build or step needs a lot of locks, it may be -starved@footnote{Starving is the situation that only a few locks are available, -and they are immediately grabbed by another build. As a result, it may take a -long time before all locks needed by the starved build are free at the same -time.} by other builds that need fewer locks. - -To illustrate use of locks, a few examples. - -@example -from buildbot import locks -from buildbot.steps import source, shell -from buildbot.process import factory - -db_lock = locks.MasterLock("database") -build_lock = locks.SlaveLock("slave_builds", - maxCount = 1, - maxCountForSlave = @{ 'fast': 3, 'new': 2 @}) - -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.access('exclusive')])) - -b1 = @{'name': 'full1', 'slavename': 'fast', 'builddir': 'f1', 'factory': f, - 'locks': [build_lock.access('counting')] @} - -b2 = @{'name': 'full2', 'slavename': 'new', 'builddir': 'f2', 'factory': f. - 'locks': [build_lock.access('counting')] @} - -b3 = @{'name': 'full3', 'slavename': 'old', 'builddir': 'f3', 'factory': f. - 'locks': [build_lock.access('counting')] @} - -b4 = @{'name': 'full4', 'slavename': 'other', 'builddir': 'f4', 'factory': f. - 'locks': [build_lock.access('counting')] @} - -c['builders'] = [b1, b2, b3, b4] -@end example - -Here we have four slaves @code{b1}, @code{b2}, @code{b3}, and @code{b4}. Each -slave performs the same checkout, make, and test build step sequence. -We want to enforce that at most one test step is executed between all slaves due -to restrictions with the data base server. This is done by adding the -@code{locks=} parameter with the third step. It takes a list of locks with their -access mode. In this case only the @code{db_lock} is needed. The exclusive -access mode is used to ensure there is at most one slave that executes the test -step. - -In addition to exclusive accessing the data base, we also want slaves to stay -responsive even under the load of a large number of builds being triggered. -For this purpose, the slave lock called @code{build_lock} is defined. Since -the restraint holds for entire builds, the lock is specified in the builder -with @code{'locks': [build_lock.access('counting')]}. -@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 an internal list of -``BuildStep specifications'': a list of @code{(step_class, kwargs)} -tuples for each. These specification tuples are constructed when the -config file is read, by asking the instances passed to @code{addStep} -for their subclass and arguments. - -When asked to create a Build, the @code{BuildFactory} puts a copy of -the list of step specifications into the new Build object. When the -Build is actually started, these step specifications are used to -create the actual set of BuildSteps, which are then executed one at a -time. This serves to give each Build an independent copy of each step. -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 - -(To support config files from buildbot-0.7.5 and earlier, -@code{addStep} also accepts the @code{f.addStep(shell.Compile, -command=["make","build"])} form, although its use is discouraged -because then the @code{Compile} step doesn't get to validate or -complain about its arguments until build time. The modern -pass-by-instance approach allows this validation to occur while the -config file is being loaded, where the admin has a better chance of -noticing problems). - -It is also possible to pass a list of steps 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.: - -@example -from buildbot.steps import source, shell -from buildbot.process import factory - -all_steps = [source.CVS(cvsroot=CVSROOT, cvsmodule="project", mode="update"), - shell.Compile(command=["make", "build"]), - ] -f = factory.BuildFactory(all_steps) -@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, with the exception of steps with @code{alwaysRun} set to -True. @code{haltOnFailure} 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 step's @code{alwaysRun} attribute is True, then it will always -be run, regardless of if previous steps have failed. This is useful -for cleanup steps that should always be run to return the build -directory or build slave into a good state. - -@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/steps/*.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, like 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, like 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 a -command like @code{pydoc buildbot.status.html.WebStatus} 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 -* WebStatus:: -* MailNotifier:: -* 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 WebStatus, MailNotifier, Status Delivery, Status Delivery -@section WebStatus - -@cindex WebStatus -@stindex buildbot.status.web.baseweb.WebStatus - -The @code{buildbot.status.html.WebStatus} status target runs a small -web server inside the buildmaster. You can point a browser at this web -server and retrieve information about every build the buildbot knows -about, as well as find out what the buildbot is currently working on. - -The first page you will see is the ``Welcome Page'', which contains -links to all the other useful pages. This page is simply served from -the @file{public_html/index.html} file in the buildmaster's base -directory, where it is created by the @command{buildbot create-master} -command along with the rest of the buildmaster. - -The most complex resource provided by @code{WebStatus} is the -``Waterfall Display'', which shows a time-based chart of events. This -somewhat-busy display provides detailed information about all steps of -all recent builds, and provides hyperlinks to look at individual build -logs and source changes. By simply reloading this page on a regular -basis, you will see a complete description of everything the buildbot -is currently working on. - -There are also pages with more specialized information. For example, -there is a page which shows the last 20 builds performed by the -buildbot, one line each. Each line is a link to detailed information -about that build. By adding query arguments to the URL used to reach -this page, you can narrow the display to builds that involved certain -branches, or which ran on certain Builders. These pages are described -in great detail below. - - -When the buildmaster is created, a subdirectory named -@file{public_html/} is created in its base directory. By default, @code{WebStatus} -will serve files from this directory: for example, when a user points -their browser at the buildbot's @code{WebStatus} URL, they will see -the contents of the @file{public_html/index.html} file. Likewise, -@file{public_html/robots.txt}, @file{public_html/buildbot.css}, and -@file{public_html/favicon.ico} are all useful things to have in there. -The first time a buildmaster is created, the @file{public_html} -directory is populated with some sample files, which you will probably -want to customize for your own project. These files are all static: -the buildbot does not modify them in any way as it serves them to HTTP -clients. - -@example -from buildbot.status.html import WebStatus -c['status'].append(WebStatus(8080)) -@end example - -Note that the initial robots.txt file has Disallow lines for all of -the dynamically-generated buildbot pages, to discourage web spiders -and search engines from consuming a lot of CPU time as they crawl -through the entire history of your buildbot. If you are running the -buildbot behind a reverse proxy, you'll probably need to put the -robots.txt file somewhere else (at the top level of the parent web -server), and replace the URL prefixes in it with more suitable values. - -If you would like to use an alternative root directory, add the -@code{public_html=..} option to the @code{WebStatus} creation: - -@example -c['status'].append(WebStatus(8080, public_html="/var/www/buildbot")) -@end example - -In addition, if you are familiar with twisted.web @emph{Resource -Trees}, you can write code to add additional pages at places inside -this web space. Just use @code{webstatus.putChild} to place these -resources. - -The following section describes the special URLs and the status views -they provide. - - -@menu -* WebStatus Configuration Parameters:: -* Buildbot Web Resources:: -* XMLRPC server:: -* HTML Waterfall:: -@end menu - -@node WebStatus Configuration Parameters, Buildbot Web Resources, WebStatus, WebStatus -@subsection WebStatus Configuration Parameters - -The most common way to run a @code{WebStatus} is on a regular TCP -port. To do this, just pass in the TCP port number when you create the -@code{WebStatus} instance; this is called the @code{http_port} argument: - -@example -from buildbot.status.html import WebStatus -c['status'].append(WebStatus(8080)) -@end example - -The @code{http_port} argument is actually 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/} . - -The other @code{WebStatus} argument is @code{allowForce}. If set to -True, 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. The default value is False. - - - -@node Buildbot Web Resources, XMLRPC server, WebStatus Configuration Parameters, WebStatus -@subsection Buildbot Web Resources - -Certain URLs are ``magic'', and the pages they serve are created by -code in various classes in the @file{buildbot.status.web} package -instead of being read from disk. The most common way to access these -pages is for the buildmaster admin to write or modify the -@file{index.html} page to contain links to them. Of course other -project web pages can contain links to these buildbot pages as well. - -Many pages can be modified by adding query arguments to the URL. For -example, a page which shows the results of the most recent build -normally does this for all builders at once. But by appending -``?builder=i386'' to the end of the URL, the page will show only the -results for the ``i386'' builder. When used in this way, you can add -multiple ``builder='' arguments to see multiple builders. Remembering -that URL query arguments are separated @emph{from each other} with -ampersands, a URL that ends in ``?builder=i386&builder=ppc'' would -show builds for just those two Builders. - -The @code{branch=} query argument can be used on some pages. This -filters the information displayed by that page down to only the builds -or changes which involved the given branch. Use @code{branch=trunk} to -reference the trunk: if you aren't intentionally using branches, -you're probably using trunk. Multiple @code{branch=} arguments can be -used to examine multiple branches at once (so appending -@code{?branch=foo&branch=bar} to the URL will show builds involving -either branch). No @code{branch=} arguments means to show builds and -changes for all branches. - -Some pages may include the Builder name or the build number in the -main part of the URL itself. For example, a page that describes Build -#7 of the ``i386'' builder would live at @file{/builders/i386/builds/7}. - -The table below lists all of the internal pages and the URLs that can -be used to access them. - -NOTE: of the pages described here, @code{/slave_status_timeline} and -@code{/last_build} have not yet been implemented, and @code{/xmlrpc} -has only a few methods so far. Future releases will improve this. - -@table @code - -@item /waterfall - -This provides a chronologically-oriented display of the activity of -all builders. It is the same display used by the Waterfall display. - -By adding one or more ``builder='' query arguments, the Waterfall is -restricted to only showing information about the given Builders. By -adding one or more ``branch='' query arguments, the display is -restricted to showing information about the given branches. In -addition, adding one or more ``category='' query arguments to the URL -will limit the display to Builders that were defined with one of the -given categories. - -A 'show_events=true' query argument causes the display to include -non-Build events, like slaves attaching and detaching, as well as -reconfiguration events. 'show_events=false' hides these events. The -default is to show them. - -The @code{last_time=}, @code{first_time=}, and @code{show_time=} -arguments will control what interval of time is displayed. The default -is to show the latest events, but these can be used to look at earlier -periods in history. The @code{num_events=} argument also provides a -limit on the size of the displayed page. - -The Waterfall has references to resources many of the other portions -of the URL space: @file{/builders} for access to individual builds, -@file{/changes} for access to information about source code changes, -etc. - -@item /rss - -This provides a rss feed summarizing all failed builds. The same -query-arguments used by 'waterfall' can be added to filter the -feed output. - -@item /atom - -This provides an atom feed summarizing all failed builds. The same -query-arguments used by 'waterfall' can be added to filter the feed -output. - -@item /builders/$BUILDERNAME - -This describes the given Builder, and provides buttons to force a build. - -@item /builders/$BUILDERNAME/builds/$BUILDNUM - -This describes a specific Build. - -@item /builders/$BUILDERNAME/builds/$BUILDNUM/steps/$STEPNAME - -This describes a specific BuildStep. - -@item /builders/$BUILDERNAME/builds/$BUILDNUM/steps/$STEPNAME/logs/$LOGNAME - -This provides an HTML representation of a specific logfile. - -@item /builders/$BUILDERNAME/builds/$BUILDNUM/steps/$STEPNAME/logs/$LOGNAME/text - -This returns the logfile as plain text, without any HTML coloring -markup. It also removes the ``headers'', which are the lines that -describe what command was run and what the environment variable -settings were like. This maybe be useful for saving to disk and -feeding to tools like 'grep'. - -@item /changes - -This provides a brief description of the ChangeSource in use -(@pxref{Change Sources}). - -@item /changes/NN - -This shows detailed information about the numbered Change: who was the -author, what files were changed, what revision number was represented, -etc. - -@item /buildslaves - -This summarizes each BuildSlave, including which Builders are -configured to use it, whether the buildslave is currently connected or -not, and host information retrieved from the buildslave itself. - -@item /one_line_per_build - -This page shows one line of text for each build, merging information -from all Builders@footnote{Apparently this is the same way -http://buildd.debian.org displays build status}. Each line specifies -the name of the Builder, the number of the Build, what revision it -used, and a summary of the results. Successful builds are in green, -while failing builds are in red. The date and time of the build are -added to the right-hand edge of the line. The lines are ordered by -build finish timestamp. - -One or more @code{builder=} or @code{branch=} arguments can be used to -restrict the list. In addition, a @code{numbuilds=} argument will -control how many lines are displayed (20 by default). - -@item /one_box_per_builder - -This page shows a small table, with one box for each Builder, -containing the results of the most recent Build. It does not show the -individual steps, or the current status. This is a simple summary of -buildbot status: if this page is green, then all tests are passing. - -As with @code{/one_line_per_build}, this page will also honor -@code{builder=} and @code{branch=} arguments. - -@item /about - -This page gives a brief summary of the Buildbot itself: software -version, versions of some libraries that the Buildbot depends upon, -etc. It also contains a link to the buildbot.net home page. - -@item /slave_status_timeline - -(note: this page has not yet been implemented) - -This provides a chronological display of configuration and operational -events: master startup/shutdown, slave connect/disconnect, and -config-file changes. When a config-file reload is abandoned because of -an error in the config file, the error is displayed on this page. - -This page does not show any builds. - -@item /last_build/$BUILDERNAME/status.png - -This returns a PNG image that describes the results of the most recent -build, which can be referenced in an IMG tag by other pages, perhaps -from a completely different site. Use it as you would a webcounter. - -@end table - -There are also a set of web-status resources that are intended for use -by other programs, rather than humans. - -@table @code - -@item /xmlrpc - -This runs an XML-RPC server which can be used to query status -information about various builds. See @ref{XMLRPC server} for more -details. - -@end table - -@node XMLRPC server, HTML Waterfall, Buildbot Web Resources, WebStatus -@subsection XMLRPC server - -When using WebStatus, the buildbot runs an XML-RPC server at -@file{/xmlrpc} that can be used by other programs to query build -status. The following table lists the methods that can be invoked -using this interface. - -@table @code -@item getAllBuildsInInterval(start, stop) - -Return a list of builds that have completed after the 'start' -timestamp and before the 'stop' timestamp. This looks at all Builders. - -The timestamps are integers, interpreted as standard unix timestamps -(seconds since epoch). - -Each Build is returned as a tuple in the form: @code{(buildername, -buildnumber, build_end, branchname, revision, results, text)} - -The buildnumber is an integer. 'build_end' is an integer (seconds -since epoch) specifying when the build finished. - -The branchname is a string, which may be an empty string to indicate -None (i.e. the default branch). The revision is a string whose meaning -is specific to the VC system in use, and comes from the 'got_revision' -build property. The results are expressed as a string, one of -('success', 'warnings', 'failure', 'exception'). The text is a list of -short strings that ought to be joined by spaces and include slightly -more data about the results of the build. - -@item getBuild(builder_name, build_number) - -Return information about a specific build. - -This returns a dictionary (aka ``struct'' in XMLRPC terms) with -complete information about the build. It does not include the contents -of the log files, but it has just about everything else. - -@end table - -@node HTML Waterfall, , XMLRPC server, WebStatus -@subsection HTML Waterfall - -@cindex Waterfall -@stindex buildbot.status.html.Waterfall - -The @code{Waterfall} status target, deprecated as of 0.7.6, is a -subset of the regular @code{WebStatus} resource (@pxref{WebStatus}). -This section (and the @code{Waterfall} class itself) will be removed -from a future release. - -@example -from buildbot.status import html -w = html.WebStatus(http_port=8080) -c['status'].append(w) -@end example - - - -@node MailNotifier, IRC Bot, WebStatus, Status Delivery -@section MailNotifier - -@cindex email -@cindex mail -@stindex buildbot.status.mail.MailNotifier - -The buildbot can also send email when builds finish. The most common -use of this is to tell developers when their change has caused the -build to fail. It is also quite common to send a message to a mailing -list (usually named ``builds'' or similar) about every build. - -The @code{MailNotifier} status target is used to accomplish this. You -configure it by specifying who mail should be sent to, under what -circumstances mail should be sent, and how to deliver the mail. It can -be configured to only send out mail for certain builders, and only -send messages when the build fails, or when the builder transitions -from success to failure. It can also be configured to include various -build logs in each message. - - -By default, the message will be sent to the Interested Users list -(@pxref{Doing Things With Users}), which includes all developers who -made changes in the build. You can add additional recipients with the -extraRecipients argument. - -Each MailNotifier sends mail to a single set of recipients. To send -different kinds of mail to different recipients, use multiple -MailNotifiers. - -The following simple example will send an email upon the completion of -each build, to just those developers whose Changes were included in -the build. The email contains a description of the Build, its results, -and URLs where more information can be obtained. - -@example -from buildbot.status.mail import MailNotifier -mn = MailNotifier(fromaddr="buildbot@@example.org", lookup="example.org") -c['status'].append(mn) -@end example - -To get a simple one-message-per-build (say, for a mailing list), use -the following form instead. This form does not send mail to individual -developers (and thus does not need the @code{lookup=} argument, -explained below), instead it only ever sends mail to the ``extra -recipients'' named in the arguments: - -@example -mn = MailNotifier(fromaddr="buildbot@@example.org", - sendToInterestedUsers=False, - extraRecipients=['listaddr@@example.org']) -@end example - -In some cases it is desirable to have different information then what -is provided in a standard MailNotifier message. For this purpose -MailNotifier provides the argument customMesg (a function) which allows -for the creation of messages with unique content. - -For example it can be useful to display the last few lines of a log file -and recent changes when a builder fails: - -@example -def message(attrs): - logLines = 10 - text = list() - text.append("STATUS: %s" % attrs['result'].title()) - text.append("") - text.extend([c.asText() for c in attrs['changes']]) - text.append("") - name, url, lines = attrs['logs'][-1] - text.append("Last %d lines of '%s':" % (logLines, name)) - text.extend(["\t%s\n" % line for line in lines[len(lines)-logLines:]]) - text.append("") - text.append("-buildbot") - return ("\n".join(text), 'plain') - -mn = MailNotifier(fromaddr="buildbot@@example.org", - sendToInterestedUsers=False, - mode='problem', - extraRecipients=['listaddr@@example.org'], - customMesg=message) -@end example - -A customMesg function takes a single dict argument (see below) and returns a -tuple of strings. The first string is the complete text of the message and the -second is the message type ('plain' or 'html'). The 'html' type should be used -when generating an HTML message: - -@example -def message(attrs): - logLines = 10 - text = list() - text.append('<h4>Build status %s.</h4>' % (attrs['result'].title())) - if attrs['changes']: - text.append('<h4>Recent Changes:</h4>') - text.extend([c.asHTML() for c in attrs['changes']]) - name, url, lines = attrs['logs'][-1] - text.append('<h4>Last %d lines of "%s":</h4>' % (logLines, name)) - text.append('<p>') - text.append('<br>'.join([line for line in lines[len(lines)-logLines:]])) - text.append('</p>') - text.append('<br><br>') - text.append('Full log at: %s' % url) - text.append('<br><br>') - text.append('<b>-buildbot</b>') - return ('\n'.join(text), 'html') -@end example - -@heading MailNotifier arguments - -@table @code -@item fromaddr -The email address to be used in the 'From' header. - -@item sendToInterestedUsers -(boolean). If True (the default), send mail to all of the Interested -Users. If False, only send mail to the extraRecipients list. - -@item extraRecipients -(tuple of strings). A list of email addresses to which messages should -be sent (in addition to the InterestedUsers list, which includes any -developers who made Changes that went into this build). It is a good -idea to create a small mailing list and deliver to that, then let -subscribers come and go as they please. - -@item subject -(string). A string to be used as the subject line of the message. -@code{%(builder)s} will be replaced with the name of the builder which -provoked the message. - -@item mode -(string). Default to 'all'. One of: -@table @code -@item all -Send mail about all builds, bothpassing and failing -@item failing -Only send mail about builds which fail -@item problem -Only send mail about a build which failed when the previous build has passed. -If your builds usually pass, then this will only send mail when a problem -occurs. -@end table - -@item builders -(list of strings). A list of builder names for which mail should be -sent. Defaults to None (send mail for all builds). Use either builders -or categories, but not both. - -@item categories -(list of strings). A list of category names to serve status -information for. Defaults to None (all categories). Use either -builders or categories, but not both. - -@item addLogs -(boolean). If True, include all build logs as attachments to the -messages. These can be quite large. This can also be set to a list of -log names, to send a subset of the logs. Defaults to False. - -@item relayhost -(string). The host to which the outbound SMTP connection should be -made. Defaults to 'localhost' - -@item lookup -(implementor of @code{IEmailLookup}). Object which provides -IEmailLookup, which is responsible for mapping User names (which come -from the VC system) into valid email addresses. If not provided, the -notifier will only be able to send mail to the addresses in the -extraRecipients list. Most of the time you can use a simple Domain -instance. As a shortcut, you can pass as string: this will be treated -as if you had provided Domain(str). For example, -lookup='twistedmatrix.com' will allow mail to be sent to all -developers whose SVN usernames match their twistedmatrix.com account -names. See buildbot/status/mail.py for more details. - -@item customMesg -This is a optional function that can be used to generate a custom mail -message. The customMesg function takes a single dict and must return a -tuple containing the message text and type ('html' or 'plain'). Below is a list -of availale keys in the dict passed to customMesg: - -@table @code -@item builderName -(str) Name of the builder that generated this event. -@item projectName -(str) Name of the project. -@item mode -(str) Mode set in MailNotifier. (failing, passing, problem). -@item result -(str) Builder result as a string. 'success', 'warnings', 'failure', 'skipped', or 'exception' -@item buildURL -(str) URL to build page. -@item buildbotURL -(str) URL to buildbot main page. -@item buildText -(str) Build text from build.getText(). -@item slavename -(str) Slavename. -@item reason -(str) Build reason from build.getReason(). -@item responsibleUsers -(List of str) List of responsible users. -@item branch -(str) Name of branch used. If no SourceStamp exists branch -is an empty string. -@item revision -(str) Name of revision used. If no SourceStamp exists revision -is an empty string. -@item patch -(str) Name of patch used. If no SourceStamp exists patch -is an empty string. -@item changes -(list of objs) List of change objects from SourceStamp. A change -object has the following useful information: -@table @code -@item who -(str) who made this change -@item revision -(str) what VC revision is this change -@item branch -(str) on what branch did this change occur -@item when -(str) when did this change occur -@item files -(list of str) what files were affected in this change -@item comments -(str) comments reguarding the change. -@end table -The functions asText and asHTML return a list of strings with -the above information formatted. -@item logs -(List of Tuples) List of tuples where each tuple contains the log name, log url, -and log contents as a list of strings. -@end table -@end table - -@node IRC Bot, PBListener, MailNotifier, 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 buildbot.status import words -irc = words.IRC("irc.example.org", "botnickname", - channels=["channel1", "channel2"], - password="mysecretpassword", - notify_events=@{ - 'exception': 1, - 'successToFailure': 1, - 'failureToSuccess': 1, - @}) -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 join CHANNEL -Join the given IRC channel -@item leave CHANNEL -Leave the given IRC channel -@item notify on|off|list EVENT -Report events relating to builds. If the command is issued as a -private message, then the report will be sent back as a private -message to the user who issued the command. Otherwise, the report -will be sent to the channel. Available events to be notified are: - -@table @code -@item started -A build has started -@item finished -A build has finished -@item success -A build finished successfully -@item failed -A build failed -@item exception -A build generated and exception -@item xToY -The previous build was x, but this one is Y, where x and Y are each -one of success, warnings, failure, exception (except Y is -capitalized). For example: successToFailure will notify if the -previous build was successful, but this one failed -@end table - -@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 - -Additionally, the config file may specify default notification options -as shown in the example earlier. - -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 MailNotifier 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). - -There is an alternate form which accepts a pre-made patch file -(typically the output of a command like 'svn diff'). This ``--diff'' -form does not require a local tree to run from. See @xref{try --diff}. - -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, git) 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. - -@item Git -@code{git branch -v} lists all the branches available in the local -repository along with the revision ID it points to and a short summary -of the last commit. The line containing the currently checked out -branch begins with '* ' (star and space) while all the others start -with ' ' (two spaces). @command{try} scans for this line and extracts -the branch name and revision from it. Then it generates a diff against -the base revision. -@c TODO: I'm not sure if this actually works the way it's intended -@c since the extracted base revision might not actually exist in the -@c upstream repository. Perhaps we need to add a --remote option to -@c specify the remote tracking branch to generate a diff against. - -@c TODO: monotone -@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. - -@menu -* try --diff:: -@end menu - -@node try --diff, , try, try -@subsubsection try --diff - -Sometimes you might have a patch from someone else that you want to -submit to the buildbot. For example, a user may have created a patch -to fix some specific bug and sent it to you by email. You've inspected -the patch and suspect that it might do the job (and have at least -confirmed that it doesn't do anything evil). Now you want to test it -out. - -One approach would be to check out a new local tree, apply the patch, -run your local tests, then use ``buildbot try'' to run the tests on -other platforms. An alternate approach is to use the @command{buildbot -try --diff} form to have the buildbot test the patch without using a -local tree. - -This form takes a @option{--diff} argument which points to a file that -contains the patch you want to apply. By default this patch will be -applied to the TRUNK revision, but if you give the optional -@option{--baserev} argument, a tree of the given revision will be used -as a starting point instead of TRUNK. - -You can also use @command{buildbot try --diff=-} to read the patch -from stdin. - -Each patch has a ``patchlevel'' associated with it. This indicates the -number of slashes (and preceding pathnames) that should be stripped -before applying the diff. This exactly corresponds to the @option{-p} -or @option{--strip} argument to the @command{patch} utility. By -default @command{buildbot try --diff} uses a patchlevel of 0, but you -can override this with the @option{-p} argument. - -When you use @option{--diff}, you do not need to use any of the other -options that relate to a local tree, specifically @option{--vc}, -@option{--try-topfile}, or @option{--try-topdir}. These options will -be ignored. Of course you must still specify how to get to the -buildmaster (with @option{--connect}, @option{--tryhost}, etc). - - -@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 set in -@code{c['change_source']}). - - -@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 --category -This provides the (string) category specifier. If omitted, it defaults -to None, indicating ``no category''. The category property is used -by Schedulers to filter what changes they listen to. - -@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) - [IBuildSlave instances] - [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 - -@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 with exactly 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{change_source} will usually appear in -master.cfg as @code{c['change_source']}. - -@printindex bc - - -@node Index, , Index of master.cfg keys, Top -@unnumbered Index - -@printindex cp - - -@bye |