When a new pull request is opened in the project and the author of the pull request isn't white-listed, builder will ask "Can one of the admins verify this patch?".

"ok to test" to accept this pull request for testing

"test this please" for a one time test run

"add to whitelist" to add the author to the whitelist

If the build fails for other various reasons you can rebuild.

"retest this please" to start a new build

Installation:

I recommend to create GitHub 'bot' user that will be used for communication with GitHub (however you can use your own account if you want).

The user needs to have push rights for your repository (must be collaborator (user repo) or must have Push & Pull rights (organization repo)).

If you want to use GitHub hooks have them set automatically the user needs to have administrator rights for your repository (must be owner (user repo) or must have Push, Pull & Administrative rights (organization repo))

Add GitHub usernames of admins (these usernames will be used as defaults in new jobs).

Under Advanced, you can modify:

The phrase for adding users to the whitelist via comment. (Java regexp)

The phrase for accepting a pull request for testing. (Java regexp)

The phrase for starting a new build. (Java regexp)

The crontab line. This specify default setting for new jobs.

Under Application Setup

There are global and job default extensions that can be configured for things like:

Commit status updates

Build status messages

Adding lines from the build log to the build result message

etc.

Credentials

If you are using Enterprise GitHub set the server api URL in ``GitHub server api URL``. Otherwise leave there ``https://api.github.com``.

A GitHub API token or username password can be used for access to the GitHub API

To setup credentials for a given GitHub Server API URL:

Click Add next to the ``Credentials`` drop down

For a token select ``Kind`` -> ``Secret text``

If you haven't generated an access token you can generate one in ``Test Credentials...``.

Set your 'bot' user's GitHub username and password.

Press the ``Create Access Token`` button

Jenkins will create a token credential, and give you the id of the newly created credentials. The default description is: ``serverAPIUrl + " GitHub auto generated token credentials"``.

For username/password us ``Kind`` -> ``Username with password``

The scope determines what has access to the credentials you are about to create

The first part of the description is used to show different credentials in the drop down, so use something semi-descriptive

Click ``Add``

Credentials will automatically be created in the domain given by the ``GitHub Server API URL`` field.

Select the credentials you just created in the drop down.

The first fifty characters in the Description are used to differentiate credentials per job, so again use something semi-descriptive

Add as many GitHub auth sections as you need, even duplicate server URLs

Save to preserve your changes.

Creating job:

Create a new job.

Add the project's GitHub URL to the "GitHub project" field (the one you can enter into browser. eg: "https://github.com/janinko/ghprb")

Select Git SCM.

Add your GitHub "Repository URL".

Under Advanced, set "refspec" to

+refs/pull/*:refs/remotes/origin/pr/*

In "Branch Specifier", enter

${sha1}

or if you want to use the actual commit in the pull request, use

${ghprbActualCommit}

Under "Build Triggers", check "Github pull requests builder".

Add admins for this specific job.

If you want to use GitHub hooks for automatic testing, read the help for "Use github hooks for build triggering" in job configuration. Then you can check the checkbox.

In Advanced, you can modify:

The crontab line for this specific job. This schedules polling to GitHub for new changes in Pull Requests.

The whitelisted users for this specific job.

The organisation names whose members are considered whitelisted for this specific job.

Save to preserve your changes.Make sure you DON'T have "Prune remote branches before build" advanced option selected, since it will prune the branch created to test this build. As noted in issue #507 this may be achieved by unchecking 'Lightweight checkout'.

If you want to manually build the job, in the job setting check "This build is parameterized" and add string parameter named "sha1". When starting build give the "sha1" parameter commit id you want to build or refname (eg: "origin/pr/9/head").

Environment Variables

The plugin makes some very useful environment variables available.

ghprbActualCommit

ghprbActualCommitAuthor

ghprbActualCommitAuthorEmail

ghprbPullDescription

ghprbPullId

ghprbPullLink

ghprbPullTitle

ghprbSourceBranch

ghprbTargetBranch

ghprbCommentBody

sha1

Job DSL Support

The plugin contains an extension for the Job DSL plugin to add DSL syntax for configuring the build trigger and the pull request merger post-build action.

1.23

1.22.x

Fix issue where if a project was disabled the Jenkins Trigger process would crashFix commit status contextAdd one line test results for downstream buildsMiscellaneous bug fixes

1.22

Move commit status over to extension form. It is now configurable, satisfying #81, #73, and #19 at least.

1.21

Move all commenting logic out into extensions.

1.20.1

Null Pointer fix for trigger.Added clarity to error message when access is forbidden.

1.20

PullRequestMerger now notifies the taskListener of failures.AutoCloseFailedPullRequest has been extracted from the published URL check.

1.19

More work for disabled builds.Unified tabs to spaces.Updates to the tests, and added some tests.

1.18

Add support for folder projects.Correcting issue with default credentials.Correcting issue with ghRepository being null when it shouldn't be.Ignoring case when matching repo to url.Changing the wording for pull requests that are mergeable.Change requestForTesting phrase to a textArea.Check if project is disabled, if it is then don't do anything.

1.14

A comment file can be created during the build and added to any comment made to the pull request. podarok#33Added a [skip ci] setting, that can be changed. Adding the skip statement to the pull request body will cause the job not to run. sathiya-mit#29Escaping single quotes in log statements tIGO#38Fixed owner name deduction from url on github hook handling nikicat#40Removed unused Test field from the config

1.13-1

Replacing deprecated Github.connect method. tIGO#39Added a merge plugin for post build. If the build is successful, the job can specify conditions under which the pull request "button" will be pressed.

1.12

1.11.2

Major reduction in the number of requests made to GitHub to avoid rate limit issuesFixed changelog for a build so it reports differences between Pull Request buildFixes bug on getting author email address from GitHub APIsUpdates warning message is URL isn't set on the GitHub project pluginAdds some additional parameters to the build, such as the source branch, pull request link, etc.Success/failure message now put into the comment on Pull Requests

1.5

checkbox enabling sending comments when update of comment status failsoption to enter organisations which members are whitelistedsupport for Enterprise GitHublink to pull request into build descriptionfixes

1.2

21 Comments

Hi there,
I don't know if I should report this as actual bug, but as soon as I try to configure the job as described as above,
I get a "Exception: java.lang.NullPointerException". After this the job will never actually try and fetch data as configured in crontab.
Posting some ugly data after this...
Status Code: 500
Exception: java.lang.NullPointerException
Stacktrace:
javax.servlet.ServletException: java.lang.NullPointerException
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:616)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:659)
at org.kohsuke.stapler.MetaClass$6.doDispatch(MetaClass.java:241)
at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:574)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:659)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:488)
at org.kohsuke.stapler.Stapler.service(Stapler.java:162)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:45)
at winstone.ServletConfiguration.execute(ServletConfiguration.java:248)
at winstone.RequestDispatcher.forward(RequestDispatcher.java:333)
at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:376)
at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:95)
at hudson.plugins.greenballs.GreenBallFilter.doFilter(GreenBallFilter.java:58)
at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:98)
at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:87)
at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:47)
at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:166)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.ui.basicauth.BasicProcessingFilter.doFilter(BasicProcessingFilter.java:173)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at jenkins.security.ApiTokenFilter.doFilter(ApiTokenFilter.java:63)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:66)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:76)
at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:164)
at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:50)
at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:81)
at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
at winstone.RequestDispatcher.forward(RequestDispatcher.java:331)
at winstone.RequestHandlerThread.processRequest(RequestHandlerThread.java:215)
at winstone.RequestHandlerThread.run(RequestHandlerThread.java:138)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at winstone.BoundedExecutorService$1.run(BoundedExecutorService.java:77)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
Caused by: java.lang.NullPointerException
at org.jenkinsci.plugins.ghprb.GhprbTrigger.start(GhprbTrigger.java:65)
at org.jenkinsci.plugins.ghprb.GhprbTrigger.start(GhprbTrigger.java:33)
at hudson.model.AbstractProject.submit(AbstractProject.java:1796)
at hudson.model.Project.submit(Project.java:197)
at hudson.model.Job.doConfigSubmit(Job.java:991)
at hudson.model.AbstractProject.doConfigSubmit(AbstractProject.java:699)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:288)
at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:151)
at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:90)
at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:111)
at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:574)
... 58 more

Could you explain how pull request status is changed in Github? And which configuration of this plugin (related to users: repos' admin, whitelisted, etc) is necessary to mark that status in every Jenkins build?

OK, I did a little more digging and eventually discovered that 1.11.2 has a known issue with the rate limit API of GitHub Enterprise installations. It is fixed in the following pull request, which has been merged:

It seems I have difficulties making this plugin work with multiple repositories ? I want this plugin to look for PR's on a private repository on github, and that works nice - but for testing the contents of the github repo, I need the contents of another repository (locally hosted on our inside). So I use the "Mulitple SCM's" plugin, to clone both repositories, and it appears that this plugin attempts to find the PR SHA in both repositories - which naturally fails.

Am I correct in assuming that multiple repositories is not supported by the plugin ?

I've ran several times into the problem that double quotes or an apostrophe in a commit (e.g. for a revert commit) breaks the build pipeline. The build itself is done with Ant and the non-escaped auto-attached ghprb-params are breaking.

Does this plugin have the capability to detect out-of-date Pull Requests and then merge new changes into those pull requests and trigger Jenkins jobs to run against them automatically?

Example:I have 2 Pull Requests (PR1, PR2) opened against the same master branch. Both of them were opened in parallel, and this plugin behaves as normal, triggering builds against each of these. Say that PR2 succeeds and is merged into master, and PR1 lags behind waiting for a review or something. Does this plugin have the capability to automatically detect this merge was completed, then update PR1 with the new changes to master, and then trigger a build to test the original PR1 commits with the new changes from PR2's merge?

I'm aware of https://help.github.com/articles/about-required-status-checks/ which will update a pull request in Github to let the user know that particular pull request is out of date and needs to be updated before it can be merged. The use could then click on 'Update Branch' and then Github would make a new commit with those changes in it. I'm just wondering if there is a way to automate this whole process via Jenkins. Would this be the plugin for that job, is there another one that will do it, or would it just be best to come up with a script on my own that does this?