Using Groovy to monitor CruiseControl builds

So, I am starting up a new project, and wanted to have a more visible indicator of what my Continuous Integration builds were doing. I am sticking with CruiseControl for this project, even though I recently looked at Continuum, and must say that it is really nice. I probably will start using that more and more as time goes on. But there is also a Ruby version of CruiseControl in the works, so one never knows…

Anyway, for this project it is good ol’ CruiseControl. And, I wanted to monitor it. There are plenty of monitors out there, but I was looking for something in particular. I wanted a big visible sign that something went wrong. The CC server, a desktop PC that will also server as first-stage test server and DB, is sitting in the same area as my partner and I. So, we will be able to see the screen when something goes wrong. And it will provide a cool green glow when everything is alright.

I decided to write my own monitor, after seeing that CruiseControl has a Socket interface for publishing statuses.

While digging around in Groovy in Action (a fabulous book, BTW), I noticed that Groovy scripts can run in interactive mode, so one could write something as simple as this:

groovy -l port -e “System.out.println line”

And one has a simple command line monitor that will just dump the status to the console. Now, this is really no better than doing a:

tail -f cruisecontrol .log

Which it is rather boring… so I decided to use SwingBuilder.

My first experience with SwingBuilder was for my Groovy DSL talk a few weeks ago… I implemented a pseudo-LOGO interpreter on top of Groovy, using SwingBuilder to build my environment. It was the first time in a LONG time that I enjoyed working with Swing.

Here is the code for the monitor:

  1. import java.net.*
  2. import groovy.swing.SwingBuilder
  3. import java.awt.Color
  4. import javax.swing.WindowConstants as WC
  5.  
  6. class Listener {
  7.         def GRAY = new Color(123,123,123,123)
  8.        
  9.         def colorMap = [“Success” : Color.GREEN,
  10.                                “Failure” : Color.RED,
  11.                                “Fixed” : Color.YELLOW]
  12.        
  13.         def swing = new SwingBuilder()
  14.         def frame = swing.frame(title:‘Build Status’,
  15.                                            location:[0,0],
  16.                                            resizable:false,
  17.                                            defaultCloseOperation:WC.EXIT_ON_CLOSE,
  18.                                            background: GRAY) {
  19.                 boxLayout()
  20.                 vbox {
  21.                         panel(  id:‘canvas’, size:[300,600], background: GRAY ) {
  22.                                 vstrut(height:300)
  23.                                 hstrut(width:600)
  24.                         }
  25.             }
  26.         }
  27.                
  28.         def process(socket) {
  29.                 try {
  30.                         socket.inputStream.eachLine { line ->
  31.                                 println “received ‘${line}’ at “ < < new Date().toString()
  32.                                 swing.canvas.background = colorMap[(line =~ /^\w+/)[0]]
  33.                         }
  34.                 }
  35.                 catch(Exception e) {
  36.                         e.printStackTrace()
  37.                         swing.canvas.background = colorMap[“Failure”]
  38.                 }
  39.                 frame.toFront()
  40.         }
  41.        
  42.         def listen(port) {
  43.                 frame.pack()
  44.                 frame.show()
  45.                
  46.                 def server = new ServerSocket(port)
  47.                 while(true) {
  48.                         def socket = server.accept()
  49.                         Thread.startDaemon { process(socket) }
  50.                 }
  51.         }
  52. }
  53.  
  54. new Listener().listen(7600)

The code is fairly straightfoward… open up a ServerSocket listening on a port, waiting for a socket to connect…. when one does, the process method is called and the window’s color is changed to the appropriate color for the status.

Simple, and quick, it didn’t take too long to throw that together, and now I have a tool that can be reused for any other time I use CruiseControl.

Here are the results:

Success!
Screenshot

Failure :(
Failure

Fixed!
Fixed!