Can't check out another branch in Jenkinsfile?

I have two branches on BitBucket: master

and develop

. I also have a TeamBacket Team Folder job configured on my Jenkins server to create this repository. The branch develop

contains the following Jenkins file:

node {
    stage('Checkout') {
        checkout scm
    }

    stage('Try different branch') {
        sh "git branch -r"
        sh "git checkout master"
    }
}

      

When Jenkins starts it, the build fails when trying to check master

:

[Pipeline] stage
[Pipeline] { (Try different branch)
[Pipeline] sh
[e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA] Running shell script
+ git branch -r
  origin/develop
[Pipeline] sh
[e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA] Running shell script
+ git checkout master
error: pathspec 'master' did not match any file(s) known to git.
[Pipeline] }

      

I expected the command git branch -r

to print both origin/master

and origin/develop

but for some reason it only prints the latter.

I read and tried to think of any ways to do this: for example, I tried installing the SSH Agent Plugin for Jenkins and modified the Jenkins file to:

node {
    stage('Checkout') {
        checkout scm
    }

    stage('Try different branch') {
        sshagent(['Bitbucket']) {
            sh "git branch -r"
            sh "git checkout master"
        }
    }
}

      

But he still doesn't find origin/master

. To make matters worse, the SSH agent seems to be killed before it tries to check master

:

[Pipeline] { (Try different branch)
[Pipeline] sshagent
[ssh-agent] Using credentials ThomasKasene (Used to communicate with Bitbucket)
[ssh-agent] Looking for ssh-agent implementation...
[ssh-agent]   Exec ssh-agent (binary ssh-agent on a remote machine)
$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-M6pIguCUpAV4/agent.11899
SSH_AGENT_PID=11902
$ ssh-add /var/jenkins_home/workspace/e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA@tmp/private_key_2394129657382526146.key
Identity added: /var/jenkins_home/workspace/e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA@tmp/private_key_2394129657382526146.key (/var/jenkins_home/workspace/e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA@tmp/private_key_2394129657382526146.key)
[ssh-agent] Started.
[Pipeline] {
[Pipeline] sh
[e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA] Running shell script
+ git branch -r
  origin/develop
[Pipeline] sh
$ ssh-agent -k
unset SSH_AUTH_SOCK;
unset SSH_AGENT_PID;
echo Agent pid 11902 killed;
[ssh-agent] Stopped.
[e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA] Running shell script
+ git checkout master
error: pathspec 'master' did not match any file(s) known to git.
[Pipeline] }

      

My possible plan is to convey something develop

and then combine it into master

, but so far I've had very little luck. Anyone got a possible solution or workaround?

PS: This only seems to be a problem in Jenkinsfile; I have a freestyle that does something similar to what I want and it works great.

+7


source to share


4 answers


After hours of trial and error, I came up with a possible solution. It is partially based on Matt's answer, but I had to change it to make it work.

Matt was mostly right: he checkout scm

just wasn't flexible enough to let me do what I needed, so I had to use GitSCM

it to customize it. Major attractions:

  • Added an extension LocalBranch

    to make sure I check out the actual branch and not just the detached one HEAD

    .
  • Added an extension WipeWorkspace

    to remove everything in the workspace and force the full clone to quit. I don't think this was part of the solution to my question, but it was still handy to have.
  • Specifies SSH credentials using the property credentialsId

    because the repository is private.

For whatever reason, when a step is done checkout

, it only checks out the branch, but doesn't set it to track the remote branch. Until I found a more elegant solution, I had to do it manually.



After everything I've done, I could use regular ones sh "git checkout master"

and even sh "git push"

if I attached them to a step sshagent

.

I've added a working example of a Jenkins resulting file below, but please keep in mind that it shouldn't be used for anything close to production as it's still very rudimentary; hardcoded version numbers and no checks for which branch you are on, eg.

node {
    mvnHome = tool 'Maven'
    mvn = "${mvnHome}/bin/mvn"

    stage('Checkout') {
        checkout([
            $class: 'GitSCM',
            branches: scm.branches,
            extensions: scm.extensions + [[$class: 'LocalBranch'], [$class: 'WipeWorkspace']],
            userRemoteConfigs: [[credentialsId: 'Bitbucket', url: 'git@bitbucket.org:NAVFREG/jenkinsfile-tests.git']],
            doGenerateSubmoduleConfigurations: false
        ])
    }

    stage('Release') {
        // Preparing Git
        sh "git branch -u origin/develop develop"
        sh "git config user.email \"jenkins@thomaskasene.com\""
        sh "git config user.name \"Jenkins\""

        // Making and committing new verison
        sh "${mvn} versions:set -DnewVersion=2.0.0 -DgenerateBackupPoms=false"
        sh "git commit -am \"Released version 2.0.0\""

        // Merging new version into master
        sh "git checkout master"
        sh "git merge develop"
        sh "git checkout develop"

        // Making and committing new snapshot version
        sh "${mvn} versions:set -DnewVersion=3.0.0-SNAPSHOT -DgenerateBackupPoms=false"
        sh "git commit -am \"Made new snapshot version 3.0.0-SNAPSHOT\""

        // Pushing everything to remote repository
        sshagent(['Bitbucket']) {
            sh "git push"
            sh "git checkout master"
            sh "git push"
        }
    }
}

      

+3


source


You can use the built-in function in Jenkins Pipeline built to clone and pull Git. I would also suggest cloning branches into separate directories.



checkout([$class: 'GitSCM',
  branches: [[name: '*/branch_name']],
  doGenerateSubmoduleConfigurations: false,
  extensions: [[$class: 'RelativeTargetDirectory',
    relativeTargetDir: 'different_directory']],
  submoduleCfg: [],
  userRemoteConfigs: [[url: 'git@github.domain:org/repo.git']]])

      

+4


source


I couldn't get the two answers above to work. I started working with Jenkins pipeline by specifying a branch and trying to checkout another branch (develop) on a job that didn't fire:

error: pathspec 'develop' did not match any file(s) known to git.

      

I could see this in the failed task, which indicated that only the activating branch was being checked out:

git fetch --no-tags --progress https://<github URL> +refs/heads/branch-name:refs/remotes/origin/branch-name

      

I got it to work by modifying the remote fetch configuration and fetching all branches by doing the following, only checkout scm

following the default step in the running Jenkinsfile job:

sh """
    git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
    git fetch --all
"""

      

This is thanks to this answer fooobar.com/questions/188886 / ...

This also avoids having to configure Jenkins for a GitSCM approval script , which I had to do to try out the two solutions above

+2


source


The problem is that Jenkins origin

only defines with the discovered branch.

@ swoop81's answer, but if you just want to checkout one branch, you can only get this one.

git config --add remote.origin.fetch +refs/heads/<branch-name>:refs/remotes/origin/<branch-name>
git fetch --no-tags https://<github-url> +refs/heads/<branch-name>:refs/remotes/origin/<branch-name>

      

0


source







All Articles