Ășlfurinn

Loosely coupled git hooks

I’m a big fan of AMQP, it’s the current hammer solution to all my nails problems.

I’m developing a personal convention in my projects of having a push hook to automatically deploy the published branch. Instead of dealing with user privileges to let the hook process touch the application directory, I run a small daemon that subscribes to a message queue, and the hook does nothing except sending a message.

My current setup involves simply using the default direct exchange.

The hook then becomes:

EM.run do
  connection = AMQP.connect(host: 'my.broker.host',
                            vhost: '/my-vhost',
                            user: 'my-user',
                            password: 'my-password')
  channel = AMQP::Channel.new connection
  ex = channel.direct ""
  ex.publish '{"action":"generate"}', routing_key: "my-project" do
    connection.disconnect { EM.stop }
  end
end

And the daemon

$0 = "My project generator"
Dir.chdir "/var/www/my-project"

Dante.run "my-project", pid_path: '/var/www/my-project-generator.pid', user: 'www-data', group: 'www-data' do
  EM.run do
    connection = AMQP.connect host: "my.broker.host", vhost: "/my-vhost", user: "my-user", password: "my-password"
    channel = AMQP::Channel.new connection
    queue = channel.queue "my-project", auto_delete: true
    queue.subscribe do |payload|
      message = Oj.load payload
      case message["action"]
      when "generate"
        `my-deploy-script`
      end
    end
  end
end

Dante daemons are started like so:

sudo /var/www/my-project-generator.rb -d

See gist for full code.