Re-triggering Jenkins Jobs from Github Webhooks

Edit: It turns out this doesn't help as much as I thought. Jenkins ignores duplicate webhook calls, so this is only helpful if your Jenkins missed a call. I'm still searching for a decent way to re-run jobs on a Github repo. :-( I'm leaving the rest of the post in place because it still has some useful information in it.

I recently set up a Jenkins job to run against a Github repo any time a new commit or branch was added. My previous Jenkins integration experience was with Gerrit, which functions rather differently. This caused me some grief, but I think I've figured out how to get everything working.

A lot of my trouble stemmed from the fact that Gerrit uses what I would call a "pull" model for triggering changes, whereas Github uses a "push" model. Specifically, Gerrit publishes an event stream that Jenkins subscribes to and triggers builds on certain events. Github, on the other hand, uses webhooks on the Git repo to trigger Jenkins builds. This has two important implications if you're trying to switch from Gerrit to Github: 1) Your Jenkins needs to be publicly accessible and 2) You can't re-trigger job runs from the Jenkins side.

For 1, I added an ssh tunnel to an externally accessible system. I don't love doing that, but there's no good way around it. For 2, I was stumped for quite a while. You can manually trigger builds of the job from Jenkins, but it just uses the last commit it tested. There's no way to specify the branch or PR you want to test. I finally realized I was looking at it backward. Because of the way the Github integration works, builds must be triggered from the Github side. There is a Jenkins plugin to trigger builds on PR comments, but it didn't work with my job. I think it's because of the type of job I configured, but it didn't help me in any case.

The solution was in the Github webhook settings for the repo. It turns out you can tell it to re-send a webhook message, which effectively re-triggers the job. To do this, browse to the repo's Settings->Webhooks page. You'll need to have admin access to do this, but you probably needed that to configure the webhook in the first place. At the bottom of the page there will be a list of recent deliveries. To re-trigger the job, find the delivery that corresponds to the change you want to test, click the ellipsis button (...) next to the delivery, and then click the "Redeliver" button that will be revealed. I didn't find any reference to the webhook ID in my Jenkins job log, so you may have to just line up timestamps to figure out the appropriate webhook to redeliver. The webhook details will show which commit and branch it relates to, so at least you shouldn't have to redeliver everything that was sent around the right time.

I think my setup is now about equivalent in functionality to what I had with Gerrit, but I had a surprising amount of trouble figuring out the webhook thing since it's kind of buried in the Github UI. I hope this writeup will help someone else who has the same issue.