I’ve had a few people ask me to post this since I twittered about it a couple of months back. Basically, it’s just a trivial little Jabber bot which notifies a list of interested people whenever there’s a commit to a watched subversion repository. (Of course, admitting amongst Ruby people that you use Subversion in this day and age is kind of like confessing to a love for MS-DOS, but I consider it a personal victory to have the folks at work using any sort of SCM.)
The notifier has two pieces: a persistent process, which connects to your Jabber server and listens for requests over DRb on a loopback socket, and the post-commit hook, which you install in your Subversion repository, and which gets executed by Subversion after each commit goes through. The only configuration needed is to pass the JID and password for the sending Jabber account to the notifier (which is accomplished via command-line args when you start it), and providing a list of JIDs to be notified on commit, which is accomplished via a whitespace-delimited plaintext file in the repository hooks directory.
(For those of you who haven’t checked out Subversion’s “hook” support, I highly recommend checking out the appropriate chapter in the Red Book. It’s a pretty nice little trick to have up your sleeve, and something tells me similar tricks are possible with Git repositories as well…)
Here’s the code, in its entirety. First, the post-commit hook:
#!/usr/bin/ruby
# post-commit hook; install in SVN_ROOT/hooks/
# give it a file called 'svn-notify' (in the same dir) containing one JID per line
require 'drb'
NOTIFY = File.read("#{File.dirname(__FILE__)}/svn-notify").split
REPOS = ARGV.shift
REV = ARGV.shift
DRb.start_service
log_msg = `svnlook --revision "#{REV}" log "#{REPOS}"`.chomp
commit_by = `svnlook --revision "#{REV}" author "#{REPOS}"`.chomp
project = File.split(REPOS).last
person = commit_by.split('@').first
msg = "New commit (r#{REV}) to `#{project}' by `#{person}': #{log_msg}"
bot = DRbObject.new nil, 'druby://localhost:99843'
bot.deliver(NOTIFY, msg)
And last but not least, the entire Jabber notifier:
#!/usr/bin/ruby
# Jabber commit notifier
# Run from wherever you like, after installing the 'jabber-simple' gem.
# Pass it the JID and password for your sending user as command-line args.
require 'drb'
require 'rubygems'
require 'xmpp4r-simple'
JID = ARGV.shift
PWD = ARGV.shift || gets.chomp
if JID.nil? or (PWD.nil? or PWD.empty?)
STDERR.puts("usage: #{__FILE__}
(password can be on stdin, too)")
exit 1
end
class RemoteBot
include DRbUndumped
def initialize(bot)
@bot = bot
end
def deliver(to, msg)
@bot.deliver(to, msg)
return true
end
end
xmpp = Jabber::Simple.new(JID, PWD)
DRb.start_service 'druby://localhost:99843', RemoteBot.new(xmpp)
DRb.thread.join
Voila! Now you can compete with your co-workers to see who can spam the other with more (and more creative!) commit messages.
Love the scripts, but when I try to add a second jabber id to svn-notify – no notifications are sent via jabber and the notifier script runs away consuming all cpu. The same behavior occurs with one jabber id per line or separated by a space. The script works fine with only one jabber id
Any chance if you could see if you get similar results?
A mate fixed it for me:
#!/usr/bin/ruby
# post-commit hook; install in SVN_ROOT/hooks/
# give it a file called ’svn-notify’ (in the same dir) containing one JID per line
require ‘drb’
NOTIFY = File.read(”#{File.dirname(__FILE__)}/svn-notify”).split
REPOS = ARGV.shift
REV = ARGV.shift
DRb.start_service
log_msg = `svnlook –revision “#{REV}” log “#{REPOS}”`.chomp
commit_by = `svnlook –revision “#{REV}” author “#{REPOS}”`.chomp
paths_changed = `svnlook –revision “#{REV}” changed “#{REPOS}”`
project = File.split(REPOS).last
person = commit_by.split(’@').first
msg = “New commit (r#{REV}) to `#{project}’ by `#{person}’: #{log_msg}\nChanged:\n#{paths_changed}”
bot = DRbObject.new nil, ‘druby://localhost:34307′
NOTIFY.map { |user| bot.deliver(user, msg) }