[Buildbot-devel] Request for assistance: IRC bot

Brad Hards bradh at frogmouth.net
Mon Oct 24 00:34:53 UTC 2005


I've made a few changes to the IRC bot - see attached patch, based on the
patch from Nathaniel Smith.

At one stage it was successfully announcing build starts and results, but then
either buildbot itself changed (perhaps a mistimed cvs up?) or I broke it. Not
sure which, or why.

The problem appears to be related to "subscribe to get notifications" code
(inlined below)- the log messages don't appear from buildStarted() and
buildFinished(). 

Any suggestions, or comments on the patch as a whole?

Brad

@@ -562,8 +542,13 @@ class IRC(base.StatusReceiverMultiServic
         self.channels = channels
         self.allowForce = allowForce
         self.categories = categories

+        self.watched = [] # list of all builders we are watching
+
+        # allow us to keep track of previous builds
+        self.lastBuilds = {} # name -> last build
+
         # need to stash the factory so we can give it the status object
         self.f = IrcStatusFactory(self.nick, self.channels, self.categories)

         c = internet.TCPClient(host, port, self.f)
@@ -571,16 +556,84 @@ class IRC(base.StatusReceiverMultiServic

     def setServiceParent(self, parent):
         base.StatusReceiverMultiService.setServiceParent(self, parent)
         self.f.status = parent.getStatus()
+        # by subscribing, we will get
+        # builderChangedState, buildStarted, and buildFinished
+        self.f.status.subscribe(self)
         if self.allowForce:
             self.f.control = interfaces.IControl(parent)

+    # unsubscribe ourselves, and unsubscribe from all watched builders
+    def disownServiceParent(self):
+        self.f.status.unsubscribe(self)
+        for w in self.watched:
+            w.unsubscribe(self)
+        return service.Service.disownServiceParent(self)
+
     def stopService(self):
         # make sure the factory will stop reconnecting
         self.f.shutdown()
         return base.StatusReceiverMultiService.stopService(self)

+    def buildStarted(self, builderName, build):
+        log.msg("builder Started1")
+        msg = 'builder %s started' % (builderName)
+        if build.getReason():
+            msg += '; %s' % (build.getReason().rstrip())
+        if build.getETA():
+            msg += '; ETA: %s' % (build.getETA())
+        if build.getSourceStamp():
+            msg += '; Branch: %s, Rev:%s, Patch: %s' % (build.getSourceStamp())
+        self._botMsg(msg)
+
+
+    def buildFinished(self, name, build, results):
+        log.msg("builder Finished1")
+        # get the responsible user
+        users = build.getResponsibleUsers()
+        if not users:
+            users = ["<unknown>"]
+
+        # get the last build status
+        lastBuild = None
+        if name in self.lastBuilds:
+            lastBuild = self.lastBuilds[name]
+
+        # we distinguish between failures that previously failed, and failures that
+        # previously passed
+        if build.getResults() == FAILURE:
+            if not lastBuild or lastBuild.getResults() == SUCCESS:
+                msg = '%s build just failed' % (name)
+            elif lastBuild.getResults() == FAILURE:
+                msg = '%s build is still failing' % (name)
+
+        # we distinguish between passes that previously failed, and passes that
+        # previously passed
+        if build.getResults() == SUCCESS:
+            if lastBuild and lastBuild.getResults() == FAILURE:
+                msg = '%s build just passed' % (name)
+            elif lastBuild.getResults() == SUCCESS:
+                msg = '%s build passed again' % (name)
+
+        if msg:
+            msg += "; changes by %s" % (','.join(users))
+            msg += "[See %s%s/builds/%s for more detail]" % (self.f.status.getBuildbotURL(), name, build.getNumber())
+            self._botMsg(msg)
+
+        # store this build result for the next comparison
+        self.lastBuilds[name] = build
+
+
+    # make the bot msg in all channels if connected
+    def _botMsg(self, msg):
+        bot = self.f.p
+        if not bot:
+            log.msg("No bot, could not say", msg)
+            return
+        for channel in self.channels:
+            log.msg("Saying in channel %s" % channel, msg)
+            bot.msg(channel, msg)

 def main():
     from twisted.internet import app
     a = app.Application("irctest")
-------------- next part --------------
A non-text attachment was scrubbed...
Name: buildbot-irc-2005-10-24.patch
Type: text/x-diff
Size: 11257 bytes
Desc: not available
URL: <http://buildbot.net/pipermail/devel/attachments/20051024/831c17be/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://buildbot.net/pipermail/devel/attachments/20051024/831c17be/attachment-0001.bin>


More information about the devel mailing list