[Buildbot-devel] Hooking a new TCP-listening service into the BuildMaster
Greg Ward
gerg.ward+buildbot at gmail.com
Thu Jan 31 20:14:33 UTC 2008
Hi all --
I'm integrating Buildbot with an external build database. The idea is
that every build is described in a table 'builds' and queued in a table
'build_queue'. Whenever a build finishes, I want to:
- update 'builds' to record the state of the build (passed/failed),
the current time (so I can track build times), etc.
- send email including info from the build database (eg. build time)
- check 'build_queue' to see if there are any builds waiting to run
and start the next one
To my amazement, I seem to have got all this working with a custom
implementation of IStatusReceiver.
The final piece of the puzzle: if Buildbot is idle, I need to kick it
whenever a build is added to the external build queue. (If a build is
queued while Buildbot is busy, we can ignore the event: the queued build
will start because of the check-queue-on-finish code I've already
implemented.)
My best idea so far:
- implement a little class called BuildTrigger, which uses
reactor.listenTCP() with a tiny little TriggerProtocol
to await client connections
- when a connction is received, do the following
- check that a builder (or buildslave?) is available
- check if there are any builds in the build queue
- if both true: start the next queued build
- in master.cfg, instantiate BuildTrigger and start it listening
But I'm stuck on that "check if a builder is available". Clearly I need
to get my hands on the BuildMaster object. But my BuildTrigger class is
outside the charmed inner circle of Buildbot's own code, even though
it'll be running in the same process. So how do I find my way to the
BuildMaster? I've read enough code that I strongly suspect the answer
will involve Twisted services... but I don't quite see how to make it
all work. Hints? Tips? Advice?
Oh yeah, here are my BuildTrigger and TriggerProtocol classes so far:
class BuildTrigger:
"""
Object that sits around waiting for an incoming TCP connection to
wake it up, at which point it checks if builders/slaves are idle,
checks if any builds are waiting in the build queue, and
(possibly) starts a new build pair.
"""
def __init__(self, port):
self.port = port
def start(self):
factory = protocol.Factory()
factory.protocol = lambda: TriggerProtocol(self)
reactor.listenTCP(self.port, factory)
# called by TriggerProtocol.connectionMade()
def triggerBuild(self):
# 1) dig up the BuildMaster and check if a builder is idle
# 2) connect to the build database and query the build queue
# 3) if appropriate, start a build
class TriggerProtocol(protocol.Protocol):
def __init__(self, trigger):
assert isinstance(trigger, BuildTrigger)
self.trigger = trigger
def connectionMade(self):
self.trigger.triggerBuild()
self.transport.loseConnection()
def connectionLost(self, reason):
pass
Thanks!
Greg
More information about the devel
mailing list