[Buildbot-commits] buildbot/buildbot/status words.py,1.52,1.53
Brian Warner
warner at users.sourceforge.net
Mon May 26 23:52:20 UTC 2008
Update of /cvsroot/buildbot/buildbot/buildbot/status
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv22205/buildbot/status
Modified Files:
words.py
Log Message:
[project @ #171:buildbot_irc.patch]
Patch by Neil Hemingway <nhemingway at googlemail.com>: allow the IRC daemon
to notify users on build events, either via private messages or channel
messages
Original author: dustin at v.igoro.us
Date: 2008-05-15 22:35:38+00:00
Index: words.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/words.py,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- words.py 1 Nov 2007 06:42:21 -0000 1.52
+++ words.py 26 May 2008 23:52:18 -0000 1.53
@@ -66,6 +66,8 @@
def __init__(self, channel):
self.channel = channel
+ self.notify_events = {}
+ self.subscribed = 0
silly = {
"What happen ?": "Somebody set up us the bomb.",
@@ -165,6 +167,77 @@
self.emit_status(which)
command_STATUS.usage = "status [<which>] - List status of a builder (or all builders)"
+ def validate_notification_event(self, event):
+ if not re.compile("^(started|finished|success|failed|exception)$").match(event):
+ raise UsageError("try 'notify on|off <EVENT>'")
+
+ def list_notified_events(self):
+ self.send( "The following events are being notified: %r" % self.notify_events.keys() )
+
+ def notify_for(self, *events):
+ for event in events:
+ if self.notify_events.has_key(event):
+ return 1
+ return 0
+
+ def subscribe_to_build_events(self):
+ self.channel.status.subscribe(self)
+ self.subscribed = 1
+
+ def unsubscribe_from_build_events(self):
+ self.channel.status.unsubscribe(self)
+ self.subscribed = 0
+
+ def add_notification_events(self, events):
+ for event in events:
+ self.validate_notification_event(event)
+ self.notify_events[event] = 1
+
+ def remove_notification_events(self, events):
+ for event in events:
+ self.validate_notification_event(event)
+ del self.notify_events[event]
+
+ def remove_all_notification_events(self):
+ self.notify_events = {}
+
+ def command_NOTIFY(self, args, who):
+ args = args.split()
+
+ if not args:
+ raise UsageError("try 'notify on|off|list <EVENT>'")
+ action = args.pop(0)
+ events = args
+
+ if action == "on":
+ if not events: events = ('started','finished')
+ self.add_notification_events(events)
+
+ self.list_notified_events()
+
+ elif action == "off":
+ if events:
+ self.remove_notification_events(events)
+ else:
+ self.remove_all_notification_events()
+
+ self.list_notified_events()
+
+ elif action == "list":
+ self.list_notified_events()
+ return
+
+ else:
+ raise UsageError("try 'notify on|off <EVENT>'")
+
+ if len(self.notify_events) > 0 and not self.subscribed:
+ self.subscribe_to_build_events()
+
+ elif len(self.notify_events) == 0 and self.subscribed:
+ self.unsubscribe_from_build_events()
+
+ command_NOTIFY.usage = "notify on|off|list [<EVENT>] ... - Notify me about build events. event should be one or more of: 'started', 'finished', 'failed', 'success', 'exception', 'successToFailed', 'failedToSuccess'"
+
def command_WATCH(self, args, who):
args = args.split()
if len(args) != 1:
@@ -178,7 +251,7 @@
for build in builds:
assert not build.isFinished()
d = build.waitUntilFinished()
- d.addCallback(self.buildFinished)
+ d.addCallback(self.watchedBuildFinished)
r = "watching build %s #%d until it finishes" \
% (which, build.getNumber())
eta = build.getETA()
@@ -188,7 +261,89 @@
self.send(r)
command_WATCH.usage = "watch <which> - announce the completion of an active build"
- def buildFinished(self, b):
+ def buildsetSubmitted(self, buildset):
+ log.msg('[Contact] Buildset %s added' % (buildset))
+
+ def builderAdded(self, builderName, builder):
+ log.msg('[Contact] Builder %s added' % (builder))
+ builder.subscribe(self)
+
+ def builderChangedState(self, builderName, state):
+ log.msg('[Contact] Builder %s changed state to %s' % (builderName, state))
+
+ def builderRemoved(self, builderName):
+ log.msg('[Contact] Builder %s removed' % (builderName))
+
+ def buildStarted(self, builderName, build):
+ builder = build.getBuilder()
+ log.msg('[Contact] Builder %r in category %s started' % (builder, builder.category))
+
+ # only notify about builders we are interested in
+
+ if (self.channel.categories != None and
+ builder.category not in self.channel.categories):
+ log.msg('Not notifying for a build in the wrong category')
+ return
+
+ if not self.notify_for('started'):
+ log.msg('Not notifying for a build when started-notification disabled')
+ return
+
+ r = "build #%d of %s started" % \
+ (build.getNumber(),
+ builder.getName())
+
+ r += " including [" + ", ".join(map(lambda c: repr(c.revision), build.getChanges())) + "]"
+
+ self.send(r)
+
+ def buildFinished(self, builderName, build, results):
+ builder = build.getBuilder()
+
+ results_descriptions = {
+ SUCCESS: "Success",
+ WARNINGS: "Warnings",
+ FAILURE: "Failure",
+ EXCEPTION: "Exception",
+ }
+
+ # only notify about builders we are interested in
+ log.msg('[Contact] builder %r in category %s finished' % (builder, builder.category))
+
+ if not self.notify_for('finished', 'failed', 'success', 'exception', 'failedToSuccess', 'successToFailed'):
+ return
+
+ if (self.channel.categories != None and
+ builder.category not in self.channel.categories):
+ return
+
+ results = build.getResults()
+
+ r = "build #%d of %s is complete: %s" % \
+ (build.getNumber(),
+ builder.getName(),
+ results_descriptions.get(results, "??"))
+ r += " [%s]" % " ".join(build.getText())
+ buildurl = self.channel.status.getURLForThing(build)
+ if buildurl:
+ r += " Build details are at %s" % buildurl
+
+ if (self.notify_for('finished')) or \
+ (self.notify_for('success') and results == SUCCESS) or \
+ (self.notify_for('failed') and results == FAILURE) or \
+ (self.notify_for('exception') and results == EXCEPTION):
+ self.send(r)
+ return
+
+ prevBuild = build.getPreviousBuild()
+ if prevBuild:
+ prevResult = prevBuild.getResult()
+
+ if (self.notify_for('failureToSuccess') and prevResult == FAILURE and results == SUCCESS) or \
+ (self.notify_for('successToFailure') and prevResult == SUCCESS and results == FAILURE):
+ self.send(r)
+
+ def watchedBuildFinished(self, b):
results = {SUCCESS: "Success",
WARNINGS: "Warnings",
FAILURE: "Failure",
@@ -429,6 +584,20 @@
def act(self, action):
self.channel.me(self.dest, action)
+ def command_JOIN(self, args, who):
+ args = args.split()
+ to_join = args[0]
+ self.channel.join(to_join)
+ self.send("Joined %s" % to_join)
+ command_JOIN.usage = "join channel - Join another channel"
+
+ def command_LEAVE(self, args, who):
+ args = args.split()
+ to_leave = args[0]
+ self.send("Buildbot has been told to leave %s" % to_leave)
+ self.channel.part(to_leave)
+ command_LEAVE.usage = "leave channel - Leave a channel"
+
def handleMessage(self, message, who):
# a message has arrived from 'who'. For broadcast contacts (i.e. when
@@ -541,7 +710,7 @@
# else it's a broadcast message, maybe for us, maybe not. 'channel'
# is '#twisted' or the like.
contact = self.getContact(channel)
- if message.startswith("%s:" % self.nickname):
+ if message.startswith("%s:" % self.nickname) or message.startswith("%s," % self.nickname):
message = message[len("%s:" % self.nickname):]
contact.handleMessage(message, user)
# to track users comings and goings, add code here
More information about the Commits
mailing list