using github webhooks to trigger jenkins jobs on a pull request

github provides a nice way to fire off notifications to a CI system like jenkins whenever a commit is made against a repository.  This is really useful for kicking off build jobs in jenkins to test the commits that were just made on the repo.  You simply need to go to the administration section of the repository, click on service hooks on the left, click ‘webhook URLs’ at the top of the list, and then enter the URL of the webhook that jenkins is expecting (look at this jenkins plugin for setting up jenkins to recieve these hooks from github).

Recently though, I was looking for a way to make a webhook fire when a pull request is made against a repo, rather than when a commit is made to the repo.  This is so that we could have jenkins run a bunch of tests on the pull request, before deciding whether to merge the pull request in – useful for when you have a lot of developers working on their own forks and regularly submitting pull requests to the main repo.

It turns out that this is not as obvious as one would hope, and requires a bit of messing about with the github API.

By default, when you configure a github webhook, it is configured to only fire when a commit is made against a repo.  There is no easy way to see, or change, this in the github web interface when you set up the webhook.  In order to manipulate the webhook in any way, you need to use the API.

To make changes on a repo via the github API, we need to authorize ourselves.  We’re going to use curl, so if we wanted to we could pass our username and password each time, like this:

# curl https://api.github.com/users/mancdaz --user 'mancdaz'
Enter host password for user 'mancdaz':

Or, and this is a much better option if you want to script any of this stuff, we can grab an oauth token and use it in subsequent requests to save having to keep entering our password.  This is what we’re going to do in our example.  First we need to create an oauth authorization and grab the token:

curl https://api.github.com/authorizations --user "mancdaz" \
--data '{"scopes":["repo"]}' -X POST

You will be returned something like the following:

{
"app": {
"name": "GitHub API",
"url": "http://developer.github.com/v3/oauth/#oauth-authorizations-api"
},
"token": "b2067d190ab94698a592878075d59bb13e4f5e96",
"scopes": [
"repo"
],
"created_at": "2012-07-12T12:55:26Z",
"updated_at": "2012-07-12T12:55:26Z",
"note_url": null,
"note": null,
"id": 498182,
"url": "https://api.github.com/authorizations/498182"
}

Now we can use this token in subsequent requests for manipulating our github account via the API.  So  let’s query our repo and find the webhook we set up in the web interface earlier:

# curl  https://api.github.com/repos/mancdaz/mygithubrepo/hooks?access_token=b2067d190ab94698592878075d59bb13e4f5e96
[
  {
    "created_at": "2012-07-12T11:18:16Z",
    "updated_at": "2012-07-12T11:18:16Z",
    "events": [
      "push"
    ],
    "last_response": {
      "status": "unused",
      "message": null,
      "code": null
    },
    "name": "web",
    "config": {
      "insecure_ssl": "1",
      "content_type": "form",
      "url": "http://jenkins-server.chloky.com/post-hook"
    },
    "id": 341673,
    "active": true,
    "url": "https://api.github.com/repos/mancdaz/mygithubrepo/hooks/341673"
  }
]

Note the important bit from that json output:

"events": [
      "push"
    ]

This basically says that this webhook will only trigger when a commit (push) is made to the repo.  The github API documentation describes numerous different event types that can be added to this list – for our purposes we want to add pull_request, and this is how we do it (note that we get the id of the webhook from the json output above. If you have multiple hooks defined, your output will contain all these hooks so be sure to get the right ID):

# curl  https://api.github.com/repos/mancdaz/mygithubrepo/hooks/341673?access_token=b2067d190ab94698592878075d59bb13e4f5e96 -X PATCH --data '{"events": ["push", "pull_request"]}'
{
  "created_at": "2012-07-12T11:18:16Z",
  "updated_at": "2012-07-12T16:03:21Z",
  "last_response": {
    "status": "unused",
    "message": null,
    "code": null
  },
  "events": [
    "push",
    "pull_request"
  ],
  "name": "web",
  "config": {
    "insecure_ssl": "1",
    "content_type": "form",
    "url": "http://jenkins-server.chloky.com/post-hook"
  },
  "id": 341673,
  "active": true,
  "url": "https://api.github.com/repos/mancdaz/mygithubrepo/hooks/341673"
}

See!

"events": [
    "push",
    "pull_request"
  ],

This webhook will now trigger whenever either a commit OR a pull request is made against our repo. Exactly what you do in your jenkins/with this webhook is up to you. We use it to kick off a bunch of integration tests in jenkins to test the proposed patch, and then actually merge and close (again using the API) the pull request automatically. Pretty sweet.

4 thoughts on “using github webhooks to trigger jenkins jobs on a pull request

  1. Could you share the jenkins configuration you are using for handling the the pull requests?

    This is a perfect candidate for a new jenkins plugin :)

    Cheers

    • Hi Gabriel,

      I actually have another post coming where I talk about how we handle the json payload that is sent by github to our jenkins server, and the subsequent steps that we take to process that payload. Once posted, let me know if it is useful.

      Darren

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>