Target Field awaiting the Twins
Photo by John McNab

In recent years this blog has become a repository for technical posts of little interest to my original audience. In the blog’s former life, I wrote more on politics and baseball. Nothing merged these topics better than the Minnesota Twins’ stadium push.

Through it all, I was both for and against the stadium. I desperately wanted a ballpark for my personal enjoyment of the game I love. But I could not level the economic costs to the public in my mind.

Shane at Greet Machine was the biggest stadium proponent on the web. He engaged anyone and everyone in the ballpark debate - even little old me. Frankly, his passion had me coming around from a self-serving supporter to a true believer in a publicly funded ballpark at the time the Minnesota legislature voted on the bill.

I am just one of hundreds, possibly thousands, of Minnesotans that Shane influenced through his relentless campaign to share information about the new ballpark and the process around getting it built. Shane quite literally helped change the face of Major League Baseball in Minnesota, and I salute him.

Tomorrow the Twins play their first game at Target Field. I will have the good fortune to be in attendance. Certainly Shane will be there as well. If you read this, Shane, I’m buying you a beer (or a suitable alternative) Friday evening as we take in a game of baseball complete with the smell of grass and the coziness of a proper ballpark. Just let me know where you’re sitting.

Whenever by Javan Makhmali is an excellent way to manage the cron tasks that relate to your ruby app. It provides a very powerful and readable ruby syntax for planning a job schedule.

I had a hard time figuring out how to recreate the case of running a job on a specific day per month, however. The following crontab line is an example of running a job on the first day of month every month at 7:13am:

# .---------------- minute (0 - 59) 
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ... 
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)  OR sun,mon,tue,wed,thu,fri,sat 
# |  |  |  |  |
# *  *  *  *  *  command to be executed
  13 7  1  *  *  my_funky_command

The key to understanding the possible syntax is understanding that chronic is whenever’s underlying natural date and time parser. So the whenever syntax for the above cron definition is most elegantly:

every 1.month, :at => 'start of the month at 7:13am' do
  runner 'my_funky_command'
end

Running a job on days other than the beginning or ending of the month is not so straightforward. This GitHub issue explains it best. To running the same command every month at the same time, but on the 15th of the month:

every 1.month, :at => 'January 15th 7:13am' do
  runner 'my_funky_command'
end

‘January’ will be ignored as whenever parses the monthly job into its pieces.

Autotest is a great idea. When it worked for me, I loved it. But I hardly ever used it. Our complicated codebase choked on it - something to do with accounts as subdomains or double-loading of test_helper when running the test suite or some such. Frankly, I don’t remember the details, but I do remember the multiple two-hour wild goose chases to try to get the lovely software to work for me. Unfortunately I wasn’t up to the task.

And the Growl integration problems? Oi!

So this afternoon I decided to give watchr a try. I wasn’t hopeful and time-boxed myself at an hour. No rat hole for me, no sir.

Imagine my surprise when 45 minutes later I not only had watchr working, but I placed it just so in my environment. I could use my script on any Rails app on my system with full growl notification and more!

Automatic testing with Rails

The steps for me to setup watchr were fairly straightforward. On the command line (your symlink will vary, natch):

gem install watchr
ln -s /Users/barry/.gem/ruby/1.8/gems/watchr-0.6/bin/watchr /usr/local/bin/watchr

I am using this Rails watchr script - I haven’t modified it as of yet. I placed it in ~/.watchr/rails.rb.

I placed the following two images into ~/.watchr_images/passed.png and ~/.watchr_images/failed.png respectively:

Rails tests passedRails tests failed

To run watchr on my Rails app, from the code directory:

watchr ~/.watchr/rails.rb

To make this less super-annoying I set a bash alias:

alias watch="watchr ~/.watchr/rails.rb"  # default is Rails cause that's my most frequent workspace

So tomorrow morning I’ll open a terminal window and type:

watch

Life is good!

(My watchr links at Delicious.)

Yesterday at Harvest we launched a little API-accessible robot for our team communication app, Co-op. There are many uses for this API hook, from deploy notices to code commits to fun daily team affirmations. You are only limited by your imagination!

Our first use of the Cobot was to get deployment messages right in our Co-op workstream, including git commit messages. This is what we see today:

Archive: Tuesday, Feb 16 at Team Iridesco @ Harvest Co-op

And our Capistrano deployment script (hat tip to John Nunemaker for the idea):

namespace :co_op do
  desc "Update Co-op with most recent deployment messages."
  task :update do
    require 'net/http'
    require 'base64'
    require 'cgi'
    require 'json'

    app = "Harvest"
    key = "withheld_for_your_protection"

    headers = {
      "Accept"        => "application/json",
      "Content-Type"  => "application/json; charset=utf-8",
      "User-Agent"    => "Co-op Deployment"
    }

    begin
      connection = Net::HTTP.new("coopapp.com", 80)
      connection.open_timeout = 10
      logs = (`git log #{previous_revision}..#{current_revision}`).
               scan(/\n\s\s\s.+\n(?:\n|$)?/).
               map{|l| l.strip}.
               reject {|t| t.match(/^Merge branch \'/)}
      logs_size = logs.size
      logs = logs[0,6]
      logs << '...' if logs_size > 6
      msg = "- #{logs.join('<br />- ')}"
      who_am_i = `whoami`.chomp.capitalize
      connection.post('/groups/5/notes', 
                      {:status => "#{who_am_i} deployed #{app}: " + 
                                  "<br />#{msg}", 
                       :key => key}.to_json, 
                      headers)
      puts 'Deploy notice sent to Co-op'
    rescue Timeout::Error => e
      puts "Timeout after 10s: Seems like Co-op missed your update."
      puts "Use \"cap co_op:update\" to update Co-op " +
           "status later w/o deploying"
    end
  end
end

after  "deploy", "co_op:update"

I haven’t quite got the time to describe what has all went into it, but bjhess.com has relaunched on a new, simple platform with a new design. More details to come!