The build master recipe
***********************

The ``collective.buildbot:master`` recipe produces a configuration
file that sets up the build master process. Once the build master is
configured you can run in by executing the controller script under the
buildout's bin directory. The controller script will be named after
the section name, so if you had a ``[buildmaster]`` section in your
buildout.cfg you would get a ``bin/buildmaster`` script.

Supported options
=================

The recipe supports the following options:

``port``
    The port the build master process listens for connections from
    build slaves. The slaves must be configured to use the
    corresponding port in the sections using the
    ``collective.buildbot:slave`` recipe.

``wport``
    The web port for serving the buildbot web interface.

``project-name``
    Project name. Displayed on the web interface.

``project-url``
    Project url, used on the web interface.

``url``
    buildbot url.

``build-slaves``
    A sequence of build slave configurations. Each build slave must be
    defined on a separate line containing the name of the build slave
    and the password for the build slave separated by white space.

``allow-force`` (optional)
    If ``true`` allows users to force builds using the web
    interface. Defaults to ``false``.

``public-html`` (optional)
    Location of a directory that contains custom resources (HTML, CSS,
    images) for the web interface.


Additionally you can use the following options if you need to run an
IRC bot:

``irc-host``
    The irc host to connect to. ie: irc.freenode.net

``irc-channels``
    A list of channels to join, ie: #plone
    If channel has password write it after colon, ie. #private:passwd

``irc-nickname``
    The bot nickname. Defaults to ``buildbot``

``irc-password``
    The password used to identify the bot. Defaults to an empty string

You can also use the following options if you need to run an ``PBListener``:

``listener-port``
    The port on which ``PBListener`` should listen for connections.
    
``listener-user``
    Username used for connection authentication.

``listener-passwd``
    Password used for connection authentication.
    
    
Example usage
=============

We'll start by creating a buildout that uses the recipe::

    >>> write('buildout.cfg',
    ... """
    ... [buildout]
    ... parts = buildmaster
    ... 
    ... [buildmaster]
    ... recipe = collective.buildbot:master
    ... port = 8080
    ... wport = 8082
    ... project-name = The project
    ... project-url = http://example.com/
    ... url = http://example.com/buildbot
    ... slaves = 
    ...     slave1 password
    ...     slave2 password
    ... """)

Running the buildout gives us::

    >>> print system(buildout)
    Installing buildmaster...
    New python executable in /sample-buildout/parts/buildmaster/.../python...
    Installing setuptools.............done.
    Generated script '/sample-buildout/parts/buildmaster/buildbot.tac'.
    Generated config '/sample-buildout/parts/buildmaster/buildbot.cfg'.
    Generated script '/sample-buildout/bin/buildmaster'.

As shown above, the buildout generated the required configuration
files and the runner script under ``bin``. You can control build
master process by running::

  $ ./bin/buildmaster [start | stop | restart]


The Twisted .tac file that is used to launch the buildbot process::

    >>> cat(join('parts', 'buildmaster', 'buildbot.tac'))
    from twisted.application import service
    from buildbot.master import BuildMaster
    import os
    import sys
    import collective.buildbot
    <BLANKLINE>
    basedir = r'/sample-buildout/parts/buildmaster'
    buildbot = os.path.dirname(collective.buildbot.__file__)
    <BLANKLINE>
    configfile = os.path.join(buildbot, 'master.py')
    application = service.Application('buildmaster')
    <BLANKLINE>
    master = BuildMaster(basedir, configfile)
    master.setServiceParent(application)
    <BLANKLINE>

We can also see that the configuration file generated by the recipe reflects
the options we chose in our buildout configuration::

    >>> config_path  = os.path.join('parts', 'buildmaster', 'buildbot.cfg')
    >>> config = ConfigParser()
    >>> _ = config.read(config_path)
    >>> slave_res = []
    >>> for opt, val in (('slave1', 'password'), 
    ...     ('slave2','password'),
    ... ):
    ...     slave_res.append(bool(val == config.get('slaves', opt)))
    >>> False not in slave_res
    True
    
    >>> buildbot_res = []
    >>> for opt, val in (('project-name','The project'),
    ...     ('projects-directory', '%s/parts/projects' % os.getcwd()), 
    ...     ('pollers-directory', '%s/parts/pollers' % os.getcwd()),
    ...     ('wport', '8082'),
    ...     ('project-url', 'http://example.com/'),
    ...     ('port', '8080'),
    ...     ('allow-force', 'false'),
    ... ):
    ...     buildbot_res.append(bool(val == config.get('buildbot', opt)))
    >>> False not in buildbot_res
    True

