Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check out a Pull-Request with Jenkins Pipeline?

I would like to build a Pipeline that integrates multiple repositories.

The general idea:

  1. Provide a branch name as input.
  2. Use the GitHub-API to find Pull-Requests across several projects, that were created from a branch with that name.
  3. Make (shallow) clones from several repositories, checking out the specified Pull-Requests.

Note that I am not trying to trigger the build itself from a Pull-Request. The triggering Job is just a plain Pipeline script. So checkout scm does not apply in my case. I would be nice to get this triggered from Pull-Requests. The many Multi-Branch plugins for Jenkins do not help me though, because they assume only a single repository to be part of the build.

So far, I mostly avoided calling git from an sh step, because that would bring me close to throwing away any and all Jenkins-Git-integration.

How, if at all, can I use the Pipeline checkout method to directly check out a Pull-Request?

Is this even in scope of the checkout method? Probably, what I am looking for is interacting directly with the JGit client of Jenkins, at which point I might just as well use sh commands...

like image 687
Thomas Hirsch Avatar asked Mar 05 '18 15:03

Thomas Hirsch


4 Answers

It turned out this can be made working by setting a refspec property on the checkout configuration object:

checkoutConfig.with {
    branches = [[ name: 'pr/4711' ]]
    userRemoteConfigs[0].refspec = '+refs/pull/*/head:refs/remotes/origin/pr/*'
}

See also: https://gist.github.com/piscisaureus/3342247

like image 100
Thomas Hirsch Avatar answered Oct 30 '22 15:10

Thomas Hirsch


If you're working with bitbucket:

checkout([$class: 'GitSCM', branches: [[name: 'FETCH_HEAD']], 
doGenerateSubmoduleConfigurations: false, extensions: [
                    [$class: 'LocalBranch'],
                    [$class: 'CleanBeforeCheckout']], 
                    submoduleCfg: [], userRemoteConfigs:  [
                    [refspec: "refs/pull-requests/${prNumber}/from:pr/${prNumber}", 
       credentialsId: "${credentialId}",url: "${cloneurl}"]]])
like image 29
Shivankur Pal Avatar answered Oct 30 '22 14:10

Shivankur Pal


Based on this doc about fetching a pull request.

Assuming you pass the PR number as a parameter:

checkout([$class: 'GitSCM', branches: [[name: "FETCH_HEAD"]],
  extensions: [[$class: 'LocalBranch']],
  userRemoteConfigs: [[refspec: "+refs/pull/${params.PR_NUMBER}/head:refs/remotes/origin/PR-${params.PR_NUMBER}", url: "https://${GITHUB_TOKEN}@github.com/${YOUR_REPO}"]]])

What's going on here:

  • First, you fetch refs for PullRequests
  • Then you checkout to the FETCH_HEAD
  • LocalBranch is required to avoid detached HEAD on the Jenkins agent

Cheers!

like image 2
Yurii Rochniak Avatar answered Oct 30 '22 16:10

Yurii Rochniak


Inspired by previous responses and sources https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit i wrote a simple shared library pipeline step:

checkoutPullRequest.groovy

Void call(String prNbr, String repo) {
    checkout([$class: 'GitSCM',
        branches: [[name: "FETCH_HEAD"]],
        doGenerateSubmoduleConfigurations: false,
        extensions: [[$class: 'LocalBranch'], [$class: 'RelativeTargetDirectory', relativeTargetDir: "${repo}"]],
        userRemoteConfigs: [[refspec: "+refs/pull/${prNbr}/head:refs/remotes/origin/PR-${prNbr} +refs/heads/master:refs/remotes/origin/master",
                            url: "https://${env.GITHUB_TOKEN}@github.com/githubusername/${repo}"]]
    ])
}

so in your pipeline Jenkinsfile you can just use

checkoutPullRequest('926', 'appgitrepo')
like image 1
EddardOmeka Avatar answered Oct 30 '22 16:10

EddardOmeka