Hubot: listen to Github's pull request events
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