This is the second out of three posts where I will explain how to hook up Hubot to Github’s API. The goal of these posts is to get notified in Slack when your pull request becomes unmergeable.

If you have never worked with Hubot in Slack before, read the first post: “Hubot: get it running locally in Slack”

Github’s API

Github offers an extensive API to connect to your repositories and automate your daily development workflow. Their documentation is very detailed and extensive and they have excellent guides to help you get started. For the goal of this post, I’ll focus on Pull Request events.

Enable Github’s Pull Request events

As said above, the goal of this project is to get notified in Slack when a merge-conflict occurs. Luckily, Github supports webhooks. That means you can get them to notify you whenever an event, like a push or a commit, happens, which in turn enables you to check the status of your pull request. Read more about all the events at https://developer.github.com/webhooks/

Send events to a webhook.

When an event happens on a pull request, Github gathers all relevant data and sends that event (a payload) to the URL of your choosing. This is called a webhook.

To set this up, go to the settings page of your repository. Select Webhooks. Then click the add webhook button. You have to provide a so called payload URL which is the webhook URL. Since you are running everything locally, you do not yet have a public URL.

Set up ngrok

Ngrok is a tool that enables you to expose your local webserver to the internet. Download it here. Unzip it from your bot’s directory. This will install a small executable in your bot’s root directory:

  $ unzip /path/to/ngrok.zip

Run it on port 8080, which is Hubot’s default port:

  $ ./ngrok http 8080

You should see something like this:

  ngrok by @inconshreveable

  Tunnel Status                 online
  Version                       2.1.3
  Region                        United States (us)
  Web Interface                 http://127.0.0.1:4040
  Forwarding                    http://a3b9e4e6.ngrok.io -> localhost:8080
  Forwarding                    https://a3b9e4e6.ngrok.io -> localhost:8080

  Connections                   ttl     opn     rt1     rt5     p50     p90
                                0       0       0.00    0.00    0.00    0.00

You can use the http:// URL for now, you can open that in your browser to see a nifty web interface.

Set up the webhook.

Copy and paste the entire URL, ending with .io into the Payload URL field of the form. Append /hubot/github/general to the URL. The /hubot part is important because it is a requirement. The next part, in this example /github, can be anything you like and /general is the room’s name in Slack (which you are free to change as well).

Make sure the content type is set to application/json and skip the secret field for now. The secret is used to protect your endpoint so we know that messages are coming from Github, but for brevity we’ll leave this up to you, the reader.

Select Let me select individual events. In this case you only want to receive pull request events. Click Add webhook.

Note: Every time you restart ngrok, you’ll get a new URL. Make sure to update it in your Github repo settings.

Test the webhook.

You will see a list of recent payload deliveries underneath your webhook form right after you save it. There is also a red error mark next to the first delivery.

Now check ngrok in your console. You should see this:

  HTTP Requests
  -------------

  POST /                         404 Not Found

This means 2 things:

  • The request was received by your local server. Yay!
  • The endpoint it’s routed to, doesn’t exist yet.

Note: If you do not have your bot running, you’ll see a 502 Bad Gateway error.

Make Hubot listen to the webhook

In order to get rid of the 404 error, you have to setup an endpoint in your bot that will execute your code when a payload is received. In your favorite editor (I use Vim), create a new coffeescript file called github.coffee inside your bot’s scripts directory.

First things first, export a function:

  module.exports = (robot) ->

This is a requirement and part of the anatomy of a Hubot script. The robot parameter is an instance of your bot.

Create the endpoint:

  robot.router.post '/hubot/github/:room', (req, res) ->
    room = req.params.room
    data = req.body

    console.log("== Pull request data received: #{data.pull_request.number}")

robot.router is a built-in Hubot method. By adding .post you create a route for POST requests. Naturally, if you want to create a route for GET request, you simply call .get .

The string '/hubot/github/:room' is the webhook URL you set up in your Github repo, where :room is a variable you have to define. The callback, (req, res) is called when a POST request comes in. Save the room name and the JSON object that contains all data in 2 variables: room and data. Then, to check that it works, the pull request’s number is printed out and will show up in your terminal.

Finally, you want to tell Github you’ve successfully processed the request. You can do that by sending a success response:

  res.send 'OK'

That’s it! Your Hubot is now listening to pull request events from Github. You can now move on to do stuff with the data you receive