Search code examples
gitgithubjenkinsjenkins-pipeline

How to merge a successful build of a pull request using a Jenkinsfile


TL;DR: Given the following declarative Jenkinsfile, how can I merge the pull request following a successful build? http://pastebin.com/uivA0MqF

In the (Multibranch) Job configuration, under Branch Source > Advanced I have the following setup:

enter image description here

And in GitHub I have a web hook that listens to pull request and push events.

Edit: I have attempted the following, but it currently fails with a syntax error:

def gitPullRequestNumber = null
...
...
stage ("Merge pull request") {
     steps {
        gitPullRequestNumber = sh "git ls-remote origin 'pull/*/head:develop'"
        sh "curl -X PUT -d '{\'commit_title\': \'Merge pull request\'}'  <<GIT REPO URL>>/pulls/${gitPullRequestNumber}/merge?access_token=<<ACCESS-TOKEN"
     }
}

The error:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:

WorkflowScript: 58: Expected a step @ line 58, column 13.
               gitPullRequestNumber = sh "git ls-remote origin 'pull/*/head:develop'"
               ^

1 error

Background:

We have a master branch and a develop branch. Developers will be doing their pull requests against the develop branch where tests will be run. If the tests pass, the pull request should be merged into the branch. Review of the code is done before a pull request is opened. When decided, the develop branch is merged to the master branch. In the future there may even be only a single branch.

I understand that some may say that it is a good thing this doesn't happen but this is what we are currently trying to achieve.

As mentioned, this all works fine and the job starts and uses the Jenkinsfile for checking out the repo based on direct pushes and/or pull requests, the build starts, the tests run and so on... however the missing piece is merging the pull requests back.


Solution

  • After also checking the checkbox for Build origin PRs (merged with base branch) this enabled a Jenkins-provided environment variable, $CHANGE_ID that in the case of a pull request, is the pull request number. This could then be used in the stage:

    stage ("Merge pull request") {
        steps { 
            withCredentials([usernamePassword(credentialsId: 'credential-value', usernameVariable: 'ACCESS_TOKEN_USERNAME', passwordVariable: 'ACCESS_TOKEN_PASSWORD',)]) {
                sh "curl -X PUT -d '{\"commit_title\": \"Merge pull request\"}'  https://github.ibm.com/api/v3/repos/org-name/repo-name/pulls/$CHANGE_ID/merge?access_token=$ACCESS_TOKEN_PASSWORD"
            }
        }
    }
    

    Update: to verify the merge was actually successful:

    script {
        sh "curl -o - -s -w \"\n%{http_code}\n\" -X PUT -d '{\"commit_title\": \"Merge pull request\"}'  https://github.ibm.com/api/v3/repos/****/****/pulls/$CHANGE_ID/merge?access_token=$JENKINSBOT_PSW | tail -1 > mergeResult.txt"
    
        def mergeResult = readFile('mergeResult.txt').trim()
        if (mergeResult != "200") {
            error "Unable to merge!"
        } else {
            // Send a Slack message, etc
          }
        }
    }