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()

Related Posts:

This entry was posted in Development Log and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>