<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Development Blog &#187; tux droid</title>
	<atom:link href="http://blog.yeticode.co.uk/tag/tux-droid/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.yeticode.co.uk</link>
	<description>John Tindell's Blog For Development Related Things</description>
	<lastBuildDate>Wed, 23 Jun 2010 18:17:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Tux Droid with Cruise Control .NET</title>
		<link>http://blog.yeticode.co.uk/2009/07/tux-droid-with-cruise-control-net/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=tux-droid-with-cruise-control-net</link>
		<comments>http://blog.yeticode.co.uk/2009/07/tux-droid-with-cruise-control-net/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 08:25:34 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[Development Log]]></category>
		<category><![CDATA[CruiseControl.NET]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tux droid]]></category>

		<guid isPermaLink="false">http://blog.yeticode.co.uk/?p=303</guid>
		<description><![CDATA[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, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://static.yeticode.co.uk/blog/images/posts/tux_droid.jpg" alt="Tux Droid" title="Tux Droid" style="float: left"/></p>
<p>So after having my <a href="http://www.tuxisalive.com/">tux droid</a> 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.<br />
I decided to write a small script that would notify me when a build from <a href="http://ccnetlive.thoughtworks.com/">Cruise Control.NET</a> 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.</p>
<p>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.</p>
<p>You can get a copy of the source, which might be more up-to-date, frm the bzr repository.</p>
<pre>
# bzr branch <a href="http://bzr.yeticode.co.uk/ccnet-tuxbot" rel="nofollow">http://bzr.yeticode.co.uk/ccnet-tuxbot</a>
</pre>
<p><br/></p>
<pre>
Usage:
# python ccnet.py <a href="http://localhost/ccnet/XmlServerReport.aspx" rel="nofollow">http://localhost/ccnet/XmlServerReport.aspx</a>
</pre>
<p><a href="http://static.yeticode.co.uk/blog/downloads/ccnet.py">download ccnet.py</a><br />
<b>Update 11-07-2009 12:00AM:</b> update notifcations in ccnet.py script.</p>
<pre name="code" class="python">
#!/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. <a href="http://localhost/ccnet/XmlServerReport.aspx" rel="nofollow">http://localhost/ccnet/XmlServerReport.aspx</a>"

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()
</pre>
<p><iframe src="http://rcm-uk.amazon.co.uk/e/cm?lt1=_blank&#038;bc1=000000&#038;IS2=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=yetiblog-21&#038;o=2&#038;p=8&#038;l=as1&#038;m=amazon&#038;f=ifr&#038;md=0M5A6TN3AXP2JHJBWT02&#038;asins=B001Q7YIPE" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe></p>]]></content:encoded>
			<wfw:commentRss>http://blog.yeticode.co.uk/2009/07/tux-droid-with-cruise-control-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
