Hudson Build Status Lava Lamps

This Ruby program lights lava lamps based on the status of a Hudson RSS feed- if the most recent of any builds fails, the red lamp will light; if the most recent of each builds succeeds, the program will light the green lamp.

This solution is based on the Pragmatic Programmer's Lava Lamp solution for Cruise Control: http://www.pragmaticautomation.com/cgi-bin/pragauto.cgi/Monitor/Devices/BubbleBubbleBuildsInTrouble.rdoc

You will need:

Once you can run the program, it's no trouble to automate this through cron or Hudson.

#!/usr/bin/env ruby
require 'net/http'
require 'uri'
require 'rubygems'
require 'atom'

# Light lava lamps based on Hudson build status RSS feed
# Green lamp lights if all builds are good;
# Red lamp lights if any build fails.
#
# Requires atom gem and bottlerocket X10 control software to be installed.
#
class HudsonLava

  def initialize
    @BOTTLE_ROCKET_COMMAND="/usr/local/bin/br"
    @GREEN_LAMP='1' # codes set on X10 lamp moduels
    @RED_LAMP='2'
  end

  def usage
    puts "hudsonLava [hudsonRssFeedUrl]"
    puts "  Light lava lamps based on Hudson build status RSS feed."
    puts "  hudsonRssFeedUrl: URL of RSS feed for builds you want to monitor; must contain SUCCESS and FAILURE messages."
  end

  def parse_args
    if ARGV.size == 1 then
      @FEED_URL = ARGV[0]
    else
      usage
      exit
    end
  end

  def get_rss_feed(feedUrl)
    feedXml = Net::HTTP::get(URI::parse(feedUrl))
    Atom::Feed.new(feedXml)
  end

  def parse_rss_feed(rssFeed)
    buildList = []
    rssFeed.entries.each { |entry|
       buildLine = "#{entry.title} #{entry.published.strftime('%Y-%m-%d')}"
       buildName, buildNumber, buildStatus, buildDate = buildLine.split
       buildNumber = buildNumber[1..-1]
       buildStatus = buildStatus[1..-2]
       buildList += [[buildName, buildNumber, buildStatus, buildDate]]
    }

    buildDataHash = {}
    buildList.each { |buildData|
       buildName, buildNumber, buildStatus, buildDate = buildData

       if buildDataHash.member?(buildName)
          buildDataHash[buildName].addInfo(["#{buildNumber} #{buildStatus} #{buildDate}"])
       else
          buildDataHash[buildName] = BuildData.new
          buildDataHash[buildName].setName("#{buildName}")
          buildDataHash[buildName].setInfo(["#{buildNumber} #{buildStatus} #{buildDate}"])
       end
    }

    buildDataHash
  end

  def get_success_indicator(buildDataHash)
    success = true
    buildDataHash.each { |buildName, buildData|
      if buildData.getInfo().first =~ /FAILED/
         puts "#{buildName} failed."
         success = false
      end
    }
    success
  end

  def lava_lamp(onOff, lampName)
    system "#{@BOTTLE_ROCKET_COMMAND} --#{onOff}=#{lampName}"
  end

  def light_green_lamp
    lava_lamp("on", @GREEN_LAMP)
    lava_lamp("off", @RED_LAMP)
  end

  def light_red_lamp
    lava_lamp("on", @RED_LAMP)
    lava_lamp("off", @GREEN_LAMP)
  end

  def light_lava_lamp(status)
    if status == true
      puts "No failed builds- lamp is green."
      light_green_lamp
    else
      puts "At least one build failed- lamp is red."
      light_red_lamp
    end
  end

  def main
    parse_args
    rssFeed = get_rss_feed(@FEED_URL)
    buildDataHash = parse_rss_feed(rssFeed)
    status = get_success_indicator(buildDataHash)
    light_lava_lamp(status)
  end

end

class BuildData
  def initialize
    @buildName = ""
    @buildInfo = []
  end

  def setName(name)
    @name = name
  end

  def setInfo(info)
    @info = info
  end

  def addInfo(info)
    @info += info
  end

  def getInfo()
    return @info
  end

  def getName()
    return @name
  end

end

if $0 == __FILE__
  HudsonLava.new.main
end

Labels:

Enter labels to add to this page:
Wait Image 
Looking for a label? Just start typing.
  1. Oct 19, 2007

    Anonymous says:

    This script breaks if your projects have a space in them. I replaced bui...

    This script breaks if your projects have a space in them. I replaced

           buildLine = "#{entry.title} #{entry.published.strftime('%Y-%m-%d')}"
           buildName, buildNumber, buildStatus, buildDate = buildLine.split
           buildNumber = buildNumber[1..-1]
    

    with

           buildName, rest = buildLine.split "#"
           buildNumber, buildStatus, buildDate = rest.split 
    


    Also, it's nice for the planet to turn your lamps off at night and on weekends! Add a method:

      def lights_off
        lava_lamp("off", @RED_LAMP)
        lava_lamp("off", @GREEN_LAMP)
      end
    

    and change light_lava_lamp to

      def light_lava_lamp(status)
        # lights off at night and weekends!
        unless Date.today.wday.between? 0,5 and Time.now.hour.between? 8,19
          puts "It's %s, so lights out!" % Time.now.to_s
          lights_off
        else
          if status == true
            puts "At %s: No failed builds- lamp is green." % Time.now.to_s
            light_green_lamp
          else
            puts "At %s: At least one build failed- lamp is red." % Time.now.to_s
            light_red_lamp
          end
        end
      end
    
  2. Feb 12, 2008

    Anonymous says:

    Gday, This line doesn't work with my Hudson ver 1.159: if buildData.getInfo()....

    Gday,

    This line doesn't work with my Hudson ver 1.159:

    if buildData.getInfo().first =~ /FAILED/
    

    Change to

    if buildData.getInfo().first =~ /FAIL/
    

    Cheers,
    Bill

  3. Mar 22, 2009

    Vijay Doshi says:

    Agile toys has a kit that includes a beacon light and the x10 hardware for a rea...

    Agile toys has a kit that includes a beacon light and the x10 hardware for a reasonable price.

     http://www.agiletoys.com

  4. Feb 10, 2010

    Peter Yamamoto says:

    You can skip ruby and use cctray which has x10 integration... This link is what ...

    You can skip ruby and use cctray which has x10 integration...
    This link is what led me to the cctray solution: http://www.lostechies.com/blogs/stevedonie/archive/2009/02/09/cctray-with-hudson.aspx
    Note that hudson already creates an xml file that is cc compatible so all you have to do is add server with the custom url http:://hudsonserver:hudsonport/cc.xml to the cctray. It should see your jobs, then you add the jobs to the monitoring.

    So all you have to do is order the toys, install the x10 automation software, install cctray, run a couple setup flows (x10, cctray) and you're in business!

    Note: you can't seem to run the x10 software at the same time as the cctray. So once you hook up the x10 and test then quit the program. See the discussion here: http://forum.melloware.com/viewtopic.php?f=13&t=6463

    "
    ...

    2. x10nets.exe is from X10, it can be killed.

    3. This error "(win error code: 5)" means you have SOME other software running already. Whether its homeseer or some other application is already locked up the COM port for your X10 device. COM ports can only be opened by 1 application at a time and this means X10 Commander can't access it while its in use. You must kill all other X10 related software you use. That will solve your problem.
    "

    Thanks all!