Friday, 10 July 2009

Tux Droid with Cruise Control .NET

Tux Droid

So after having my tux droid for a while I decided to put it to good use, opposed to making it swear at my housemates, which no matter how entertaining it was did not seem very productive.
I decided to write a small script that would notify me when a build from Cruise Control.NET failed, or when a broken build has successfully been built. At the moment the tux droid speaks a simple message and flaps it wings a little.

The script uses the tux droid python API to make the noises and pulls down an Xml file, via CruiseControl.NET, using urllib and xml.dom, fairly simple stuff.

You can get a copy of the source, which might be more up-to-date, frm the bzr repository.

# bzr branch http://bzr.yeticode.co.uk/ccnet-tuxbot



Usage:
# python ccnet.py http://localhost/ccnet/XmlServerReport.aspx


download ccnet.py
Update 11-07-2009 12:00AM: update notifcations in ccnet.py script.

#!/usr/bin/python
import sys
import urllib
import time
from xml.dom import minidom
from tuxisalive.api import *

def main(xmlPath):
# load the inital settings that we will use to compare against
projects = []

dom = minidom.parse(urllib.urlopen(xmlPath))
for node in dom.getElementsByTagName('Project'):
projects.append({
'name': node.getAttribute('name'),
'lastBuildStatus': node.getAttribute('lastBuildStatus'),
'lastBuildTime': node.getAttribute('lastBuildTime')
})

# start a loop that will check for a build event every 10 seconds
while True:
try:
dom = minidom.parse(urllib.urlopen(xmlPath))
new_projects = []
for node in dom.getElementsByTagName('Project'):
new_projects.append({
'name': node.getAttribute('name'),
'lastBuildStatus': node.getAttribute('lastBuildStatus'),
'lastBuildTime': node.getAttribute('lastBuildTime')
})
for project in new_projects:
# check to see if the project is in the current list
projectFound = False
for p in projects:
if p['name'] == project['name']:
projectFound = True
# check the status of the project against the old status
# ignore if the old status is failed
if (p['lastBuildStatus'] != 'Failure') and (project['lastBuildStatus'] == 'Failure'):
display_message_fail(project)
if (p['lastBuildStatus'] == 'Failure') and (project['lastBuildStatus'] == 'Success'):
display_message_success(project)
if (project['lastBuildStatus'] == 'Success') and (project['lastBuildTime'] != p['lastBuildTime'] ):
display_message_success_build_again(project)

# reset the project status
p['lastBuildStatus'] = project['lastBuildStatus']
p['lastBuildTime'] = project['lastBuildTime']
if not projectFound:
projects.append(project)
display_message_newproject(project)
time.sleep(10)
except KeyboardInterrupt:
# exit time
break

def display_message_fail(project):
msg = 'Someone has broken the %s build' % (project['name'])
speakPhrase(msg)

def display_message_success(project):
msg = '%s is now fixed' % (project['name'])
speakPhrase(msg)

def display_message_new(project):
msg = '%s has been added to cruise control' % (project['name'])
speakPhrase(msg)

def display_message_success_build_again(project):
msg = '%s has successfuly been built' % (project['name'])
speakPhrase(msg)

def speakPhrase(msg):
tux.mouth.open()

tux.tts.setLocutor("Lucy")
tux.tts.speak(msg.encode('utf-8'));
print msg
tux.flippers.on(4)

tux.mouth.close()

def tuxConnect():
""" Wait connected """
tux.server.autoConnect(CLIENT_LEVEL_RESTRICTED, 'TuxPidgin', 'NONE')
if tux.server.waitConnected(10.0):
if tux.dongle.waitConnected(10.0):
if tux.radio.waitConnected(10.0):
return True
else:
print "radio not connected"
return False
else:
print "radio not connected"
return False
else:
print "server not connected"
return False

def printUsage():
print "ccnet.py [url]"
print "\turl - Url of CruiseControl.NET"
print "\t\t eg. http://localhost/ccnet/XmlServerReport.aspx"

if __name__ == "__main__":
if len(sys.argv) == 2:

tgp_ip = "127.0.0.1"
tgp_port = 270
tux = TuxAPI(tgp_ip, tgp_port)
if not tuxConnect():
sys.exit(1)
tux.tts.setEncoding("utf-8")

speakPhrase("Starting Build Bot")
main(sys.argv[1])
speakPhrase("Stopping Build Bot")
tux.server.disconnect()
tux.destroy()
sys.exit(0)
else:
printUsage()

No comments:

Post a Comment