The Domain Train

So anyway, Innovation Day was coming up at work. Every so often, we all take a day out from our normal sprints and get let loose on ideas.

This is usually aimed at developers and product guys rather than the ops side, so what was I to do?

Well, I figured I’d take the concept of a software release train and… make it real. Every time we deploy new code, I want a train to leave the station and do a little loop before shutting down until the next deployment.

So on the Saturday before Innovation Day, I went shopping, and came home with an Arduino experimenter’s kit, a relay driver, some bits and pieces of wire and a Hornby Caledonian Belle model railway set. And this is what I built (apologies for the portrait mode film, I’ll have a better one after demo day tomorrow)

So, how does this work?

Well, the high-level overview is this

The Arduino has two “modes” represented by two sketches. Off, which flashes an LED based on the “Blink” template, just so I know the train is on standby, and Drive, which does a digitalWrite(high) for about 15 seconds out of the arduino board, through a breadboard with an LED inline, to input 4 on a a 4-channel Relay driver. This relay driver has a 12v input, which goes out via output 4 to the tracks.

So long story short, when the Arduino is in standby, no current runs to the rails, but when it’s in drive mode, we get fifteen seconds of 12V current. (there are also three other outputs available to do more complicated things with 12V, but let’s gloss over that for now)

So far so good. But this requires manual intervention. To start the train, someone needs to press a button. Hardly an automated process. How do we drive this automatically when new code deploys?

Well, we already have post-commit hooks and automatic builds, using Bitbucket and Bamboo, for several of our newer projects. A developer working on these will commit code and merge to a master branch, which will trigger a build and a subsequent deploy, using Octopus.

To get the train running I added a snippet of Powershell code to Octopus based roughly on this. It pulls in some Octopus variables such as project, environment and release number to create a tweet, which goes out via the @DomainTrain account.

Inside the office is my laptop, running a PowerShell script every 30 seconds or so. This checks DomainTrain’s twitter stream, and awaits new messages. When a new message appears, the PowerShell does the following:

  • Fires up the Microsoft Speech API and says “ALL ABOARD!”
  • Reads out the release details from the tweet
  • Starts a steam train sound effect
  • Triggers the “Drive” routine on the Arduino
  • Waits a little while
  • Returns the Arduino to Standby mode
$s = (new-object -com Sapi.SPVoice)
$s.Voice = $s.GetVoices().Item(0)
[void]$s.Speak("All aboard! " + $TweetBody)
$player = New-Object System.Media.SoundPlayer "$home\Powershell\Domain Innovation Day\steam-locomotive-arrive-and-stop-01.wav"
$player.Play()
Start-Job -ScriptBlock {
     $ArduinoPath = "${env:ProgramFiles(x86)}\Arduino"
     Set-Alias -name Ardi  "$ArduinoPath\arduino.exe"
     Ardi --upload "$home\Powershell\Domain Innovation Day\Drive\Drive.ino"
}

It checks whether it’s responded to a message before in about the simplest way I could think of. There’s a text file on disk with tweetIDs. It looks in here to see if it’s run the train before. If the message ID is not there, it fires off a run, then writes the message ID to the file.

$tw = Get-Tweets
$previousruns = Get-Content "$home\Powershell\Domain Innovation Day\Responded.txt"

$ran = $false

foreach($tweet in $tw){
    if(!($previousruns | ? { $_ -eq $tweet.id})) {
        # we've never responded to this one
        Write-Host ("We've never responded to Tweet " + $tweet.id + " with content " + $tweet.text + "")        
        Start-Train -TweetBody $tweet.text -TweetId $tweet.id
        Start-Sleep -s 10
        Stop-Train
        $ran = $true
    }
}

This is maybe non-scalable in the long term, but it’s very, very simple. And pople seem to dig it, if the results so far are to be believed. I had developers, sales people and support staff coming over to chat all day. I even had one of our product managers wielding a soldering iron for several hours tying to get a sound effects board up and running for channel 2.

But why?

Well, because it’s fun. But there’s also a certain level of business value behind this little toy. Successfully implementing Continuous Delivery does require knowledge and buy-in from many disparate arms of a company. Your developers need to write code with the expectation it could be in production at any time (and they need to know when it drops). Your support staff need to understand that bugfixes and feature updates no longer happen once a week. Testers and monitoring guys need to know what code is running where. Even your sales guys need to be enthused that you can react quickly, delivering customer value on a shorter timescale than before. And sure, you can deliver that message with an email. But doing it in a quirky, interesting way will sink in more quickly and make people more excited and intrigued about a subject which is, frankly, a bit dry and boring.

At least, that’s my justification. Really, deep down, I wanted to play with trains on company time.

IMG_0556 IMG_0557 IMG_0560 IMG_0563

Footnote: This is just Version 0.9. Future versions will use the Arduino’s network or WiFi shield to eliminate the need for a laptop altogether, and might run some accessories too. There’s even a possibility that a scrolling LED screen can be added to display deployment details as the train rolls. It might also use a light sensor so that the train always stops in the right place. There’s really no end to the things you can do with this, given time, patience and money. All it needs is a permanent home, which it currently lacks. Watch this space, though.

 

Leave a Reply

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