Skip to end of metadata
Go to start of metadata

Plugin Information

View jenkins-reviewbot on the plugin site for more information.

This plugin pulls a diff from reviewboard request, applies the patch, builds it and reports the build status as a review comment

Source Code

https://github.com/vmware/jenkins-reviewbot

Motivation

The project integrates Jenkins with Reviewboard code review tool (http://www.reviewboard.org/). Jenkins will pick a diff submitted to Reviewboard, run a build, and report build results on the review request: either blessing the request or warning that it will break mainline if committed. This essentially allows to validate commits before they reach mainline, a feature available in GitHub pull requests (CloudBees), TeamCity and Gerrit. Unlike these tools, this project supports any source control system that Reviewboard supports (Git, SVN, Perforce), any hosting, and will require only Jenkins server configuration.

See the presentation at JUG Israel 2013.

How to use this plugin

Prerequisites

Install Patch Parameter Plugin

Configuration

1. In Jenkins configuration set URL of the reviewboard (just the name of the site, no /dashboard or any other suffixes, e.g. http://reviewboard.mycompany.com/), username and password. You can test the connection before saving.

2. Create or clone a job that you wish to run for each review request.

3. Check "This build is parameterized" and add review parameter

4. Also add a post-build action of posting build result to reviewboard

Save the configuration.

Custom patch application command

Since version 2.2 it is possible to use a different method to apply the patch (instead of the default diff4j). In the Reviewboard section of Jenkins global settings page, check "Disable Auto-Apply Patch"

Now the plugin will download the diff from Reviewboard and save it in the workspace file called patch.diff (as it did before). But unlike earlier versions, now the plugin will not apply the patch, unless you also add Apply Patch build step

This allows you to apply the patch differently, for example with a command line specific to your source control. This also allows you to perform actions between patch download and apply.

Configuration with Perforce

  • Because reviewboard includes the full Perforce path (i.e. //depot/project/branch/...) the Jenkins project checkout must include the full path in the workspace.
    //depot/project/branch/... //${JOB_NAME}-workspace/depot/project/branch/...
    
  • To allow the files to be patched, change the Perforce Option default of "noallwrite" to "allwrite".

Using the plugin

Now when you run the job, you will need to provide the URL for review request or review number, e.g. http://reviewboard.mycompany.com/r/12345/ or just 12345.

After the job completes, the result of the run will be posted to review request like this:

Triggering the job

Curl

JENKINS=... e.g. http://jenkins.mycompany.com
JOBNAME=... e.g. Reviewbot
USER=...
PASSWORD=...
REVIEW=... e.g. http://reviewboard.mycompany.com/r/12345/

curl -G -u $USER:$PASSWORD -d delay=0sec --data-urlencode review.url=$REVIEW $JENKINS/job/$JOBNAME/buildWithParameters

Webhooks

With Reviewboard 1.7 you should be able to use webhooks extension, but I didn't test it.

Polling with Jenkins

Create another job (free-style) and add a build step "Check for reviews..." to poll reviewboard

After version 2.0

The job will check for reviews in the specified repositories and/or targeted to Jenkins user. The invoked job must take review url parameter.

Prior to version 2.0

The job will check for reviews that are targeted to jenkins user directly or to groups to which the jenkins user belongs and have been updated in the X hours since the most recently updated review (relative time is used to work around the timezone problem of pre-1.7 Reviewboard). The reviews in which the diff has been changed, but the Jenkins user did not comment on since the last diff, will be tested with the job name provided here.

Backwards compatbility

To achieve the same behavior post 2.0, turn on  "Jenkins User" and leave repository selection at "any" option.

Configuring downstream jobs

When using review url parameter in a job, you can refer to its value by $REVIEW_URL, and use it with Parameterized Trigger Plugin.

Patch in Unified Format and multiple files support

If the diffs downloaded from Reviewboard are in the Unified Format (as is probably the case for Perforce using RBtools) the default patch option will fail  for reviews with multiple files. This is currently a limitation in diff4j. To solve that, use a Custom patch application (see above) such as the shell command "patch -p1 -u -i patch.diff"

patch(1) shell command sometimes return "...hunk FAILED"

There are legitimate reasons for this, for example if the file in the review was already changed on trunk, but Review Board also has a limitation where the CR/CRLF characters in the patch file are converted into LF. This makes patching fail in files with non Linux newline characters.

This Review Board bug is tracked in Issue 2916. Until it's fixed, one work around can be to convert the code with something like this before running the patch.

Working with branches

You can refer to $REVIEW_BRANCH to find out what branch was specified in the review. If none was specified, the value will be master.

Working with repositories

You can refer to $REVIEW_REPOSITORY to find out what repository the review was filed in. If none was specified, the value will be unknown.

Known limitations

  • It is recommended to run the polling job on master (didn't test on slave, suspect it might not work)
  • The internal custom patch application does not support patched in Unified Format with multiple files (it's a limitation in diff4j), see workaround above.* The internal custom patch application does not support patched in Unified Format with multiple files (it's a limitation in diff4j), see workaround above.

Changes

Version 2.2.x

Several enhancements were added:

  • support markdown in Reviewboard messages, instead of URL it will post Jenkins job name and number with a link - configurable per job;
  • repositories list cache in poller job can be disabled (useful if you add repositories after starting Jenkins) - configurable globally;
  • biggest improvement is probably the separation of diff download and patch application (has to be enabled with a global setting). What you can do now is apply the patch with an alternative command that you can define yourself as a build step. You can also combine other actions with the default diff4j patch application which is now available as a standard build action, so you can perform other steps before it.

Version 2.1

Ahead of build notification message is now optional, and can be disabled per job. The job now holds in memory which reviews has been already processed (builds spawned) in order to avoid build duplication.

Version 2.0

Option to poll for reviews in a specific repositories and more issues closed. Special thanks to Damien Nozay for his contributions!

Version 1.4.1 & 1.4.2

Authentication tweaks, fixed a bug with port number in preemptive authentication

Version 1.4

Fixed polling task to support Reviewboard 1.7 date format

Version 1.3

Support for concurrent builds, ahead of build notification message to reviewboard (from poller job) eliminates duplicate builds of same review 

Version 1.2

Support built-in polling

Version 1.1

Fixed several bugs (misplaced temp file caused permissions problem on Linux, improved API use and authentication, injected review url and branch parameters)

Version 1.0

Initial

Miscellaneous

The plugin was tested against Reviewboard version 1.6.13 and 1.7.6

18 Comments

  1. I am hitting the following error after following the setup instructions, connection test to ReviewBoard is successful:

    Jenkins ver. 1.529

    Review Board 1.7.1

    FATAL: patch.diff (No such file or directory)
    java.io.FileNotFoundException: patch.diff (No such file or directory)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:137)
    at hudson.model.FileParameterValue$FileItemImpl.getInputStream(FileParameterValue.java:235)
    at hudson.FilePath.copyFrom(FilePath.java:841)
    at org.jenkinsci.plugins.jenkinsreviewbot.ReviewboardParameterValue$ReviewboardBuildWrapper.setUp(ReviewboardParameterValue.java:190)
    at hudson.model.Build$BuildExecution.doRun(Build.java:154)
    at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:586)
    at hudson.model.Run.execute(Run.java:1603)
    at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:46)
    at hudson.model.ResourceController.execute(ResourceController.java:88)
    at hudson.model.Executor.run(Executor.java:247)

  2. How does the "polling Reviewboard trigger" job know which reviews should be tested?

    1. The job looks at the last updated review, then goes back the time period you specified (default one hour) and considers all reviews in this time slice. Within these reviews, it is looking for ones where the latest diff was uploaded after the latest comment from the Jenkins user, or those where no Jenkins user comments exist. Since v. 1.3, when a review is identified as "needing build" a message is posted to reviewboard, so that next time this review will not be automatically picked for build, unless a new diff is uploaded. 

  3. Yardena Meymann, Thanks for the plugin.

    I have a few questions:

    1. What tool does the plugin use to apply the patch ? What happens if the patch does not apply cleanly ?

    2. Is there a way just to download the patch from reviewboard using this plugin ( and not actually apply the patch. The job configuration can apply and handle patch failures )

    Thanks !

    1. Hi Dinesh,

      1. I am inheriting the tool used by Patch Parameter Plugin. If applying the patch fails, the build will fail, but the message posted to Reviewboard will be different from regular build failure. It will say that the patch could not be applied. Build console will print a detailed message on the failure.

      2. Uhm, no, currently this is not supported.

        Yardena

  4. Hi.  I am unable to find this plugin in the plugin manager. How do I search/download it?

  5. Hi,

    This is a great plugin! Really helps. But I have a little problem with it now. The test connection and builds goes well, but when a build was done, the plugin failed at sending notifications to ReviewBoard. The error is Required credentials not available for BASIC <any realm>@10.50.12.159:81

    Feb 11, 2014 1:34:15 PM WARNING org.apache.commons.httpclient.HttpMethodDirector authenticateHost
    Preemptive authentication requested but no default credentials available

    Feb 11, 2014 1:34:15 PM INFO org.apache.commons.httpclient.auth.AuthChallengeProcessor selectAuthScheme
    basic authentication scheme selected

    Feb 11, 2014 1:34:15 PM INFO org.apache.commons.httpclient.HttpMethodDirector processWWWAuthChallenge
    Failure authenticating with BASIC 'Web API'@xx.xx.xx.159:81

    Could you tell me what`s wrong? And I am uisng SVN reporistory. Thanks!

    1. Hi, I think my situation is weird. After I remove the reviewboard`s username and password in the configuration of Jenkins, it showed me the same error, does that means the plugin failed to read the reviewboard`s username and password?

    2. Hi Allen, I had a bug with authentication in the plugin when Reviewboard was running on port other than 443, it is fixed in the latest version (1.4.2).

  6. Hi

    Now I use reviewboard 1.7.4, jenkins 1.552 and jenkins-reviewbot 1.4.1, when I start an job, occured the following exception, Could you tell me the reason and soulution,thanks.

    Building in workspace /root/.jenkins/jobs/RB-Test/workspaceFATAL: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.w3.org/1999/xhtml", local:"html"). Expected elements are <{}rsp>
    java.lang.RuntimeException: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.w3.org/1999/xhtml", local:"html"). Expected elements are <{}rsp>
    at org.jenkinsci.plugins.jenkinsreviewbot.ReviewboardConnection.unmarshalResponse(ReviewboardConnection.java:267)
    at org.jenkinsci.plugins.jenkinsreviewbot.ReviewboardConnection.getBranch(ReviewboardConnection.java:199)
    at org.jenkinsci.plugins.jenkinsreviewbot.ReviewboardParameterValue.buildEnvVars(ReviewboardParameterValue.java:179)
    at hudson.model.ParametersAction.buildEnvVars(ParametersAction.java:85)
    at hudson.model.AbstractBuild.getEnvironment(AbstractBuild.java:945)
    at hudson.maven.AbstractMavenBuild.getEnvironment(AbstractMavenBuild.java:59)
    at hudson.maven.MavenModuleSetBuild.getEnvironment(MavenModuleSetBuild.java:165)
    at hudson.scm.SubversionSCM.checkout(SubversionSCM.java:865)
    at hudson.model.AbstractProject.checkout(AbstractProject.java:1411)
    at hudson.model.AbstractBuild$AbstractBuildExecution.defaultCheckout(AbstractBuild.java:671)
    at jenkins.scm.SCMCheckoutStrategy.checkout(SCMCheckoutStrategy.java:88)
    at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:580)
    at hudson.model.Run.execute(Run.java:1670)
    at hudson.maven.MavenModuleSetBuild.run(MavenModuleSetBuild.java:519)
    at hudson.model.ResourceController.execute(ResourceController.java:88)
    at hudson.model.Executor.run(Executor.java:231)
    Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.w3.org/1999/xhtml", local:"html"). Expected elements are <{}rsp>
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:647)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:243)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:238)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:105)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1048)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:483)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:465)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:135)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:506)
    at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.startElement(XMLDTDValidator.java:745)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:376)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:602)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3065)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:881)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:489)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:214)
    at org.jenkinsci.plugins.jenkinsreviewbot.ReviewboardConnection.unmarshalResponse(ReviewboardConnection.java:265)
    ... 15 more

    1. This is weird. First of all I suggest you upgrade to latest version. If it still isn't working, please try connecting to your Reviewboard API (e.g. $yourReviewboardServer/api/review-requests/$yourReviewId/) with a rest client, sending "Accept" request header = "application/xml" and see that the response comes back as XML. 

      1. Thanks for your answer.

        Now  I use the latest version, it works.

      2. Hi Yardena

        Is there an method, when create a review request, jenkins can get the review request url then start a parameter job. like jenkins Gerrit Trigger

        There are many projects on one reviewboard site, every project starts one job.  

  7. How is $REVIEW_BRANCH used? It seems to be empty. Echo this variable got nothing in return.

  8. Thanks  Yardena Meymann for awesome plugin

    We are using mercurial and review board. We are planning to implement CI with this plugin.

    1) Review request will be assigned to jenkins user when merge ready,  patch is applied for given review request. Then it will undergo build and test.

    2) In case of success, commit and push to central repository from same workspace.

    Is the right approach and will work ?

    thoughts ?

  9. Hi Yardena,

    Thanks for the release 2.2.x where the diff download is decoupled from the patch application. This allowed our team to use your plugin along with Perforce projects.  

  10. I want to know why when I have multiple jobs kicked off by the reviewboard monitoring, that each job waits on the previous one to finish before it will publish it's results. It would be a rarety if 2 test runs were kicked off on the same patch thread.