GitHub Post-Receive Hook for Coop
At Business Logic we use Harvest to track our time. Harvest offers an integrated campfire-style chat room called Coop. The cool feature of Coop is it shows the time entries of members in a group, interspersed with the messages in the group. While it’s sometimes useful to see what others are doing as they go, our main use is to look at what your pair was doing 3 days ago when you forgot to do your time. This gives a pretty good idea of what’s going on, but when there isn’t an entry for that day, and you’re trying to do your time, I usually go back and look at our commit history on github.
The trick is to integrate those together, and for that, enter the coop api, github post-receive hooks and sinatra.
Implementation notes
Because the coop api is sort of Restful, but not totally, it took a bit of finagling to get it all together, but it did and is now on github as coop_github_hook. I personally haven’t ever used ActiveResource or sinatra for anything but toying around, so it was nice to be able to use both.
I’m now a big sinatra fan since it makes short-and-simple web services incredibly simple. Here’s the sinatra portion of this hook:
post '/hooks/coop' do
push = JSON.parse(params[:payload])
push['commits'].each do |commit|
Coop::Status.from_github_commit_info(group_id, commit).save
end
"Thanks for playing"
end
The other interesting thing was dealing with the “sort of Restful” Coop status api (chat entries in the group). “Sort of Restful” really means “sort of useable by ActiveResource.” The issue arose in the way coop expects you to send the content for a post. If you have something called a Status which represents a text message, ActiveResource assumes, and Rails by default provides, data that looks like:
<status>
<message>Good morning</message>
</status>
Coop’s api however wants that data to be sent as:
<status>Good morning</status>
To get the data into that format all you have to do is override ActiveResource::Base#encode in your ActiveResource class:
module Coop
class Status < ActiveResource::Base
self.site = "http://coopapp.com/groups/:group_id"
# Co-op takes a non-ActiveResource friendly format for their status, so manually write that format
def encode(options={})
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<status>#{attributes['text']}</status>\n"
end
end
end
I’m not sure if this is something people normally do, but it is a pretty handy way to switch formats.
For usage info hook feel free to checkout the github repo and it’s associated Readme. If you have any problems feel free to shoot me a message over github or email.