How to Customize Checkout for Pipeline Multibranch?

Article ID:226122247
3 minute readKnowledge base

Issue

  • I am using Pipeline Multibranch and/or GitHub Organization and/or Bitbucket Team Project - i.e. any project item that leverage Multibranch Pipelines.

  • I want to define additional behaviors to my SCM for specific branches - like I would do with the checkout step in a simple Pipeline job.

  • I want a pipeline-as-code solution to customize SCM checkout for Multibranch Pipeline Projects.

Resolution

IMPORTANT: The following approach is a workaround and should not be used once JENKINS-37658 has been fixed

For Multibranch Pipelines, the source code can be checked out with a simple checkout scm in the Jenkinsfile. In some cases, a different behavior needs to be defined for specific branches. For that, there is a pipeline-as-code solution.

The checkout step accepts the scm variable. This variable references an Object which means that attributes of this object can be accessed via scm.$attributeName. Therefore the checkout scm can be customized.

In brief, for the following Multibranch configuration:

multibranch simple git config

the following Jenkinsfile:

node {
    checkout scm
}

is equivalent to something like this:

node {
    checkout([
         $class: 'GitSCM',
         branches: scm.branches,
         doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
         extensions: scm.extensions,
         userRemoteConfigs: scm.userRemoteConfigs
    ])
 }

With one difference though: in the latter the access to scm. attributes need to be allowlisted by an administrator in Jenkins*

Some Explanation

In the context of Pipeline Multibranch, for each branch the SCM configuration is "injected" in the variable scm.

This variable is an object implementation of an SCM. For example with Git, the scm references a GitSCM Object. You can see that in the source code and/or when using the Snippet Generator. By default, the snippet generator for checkout  git will generate something like the following:

checkout([$class: 'GitSCM',
    branches: [[name: '*/master']],
    doGenerateSubmoduleConfigurations: false,
    extensions: [],
    submoduleCfg: [],
    userRemoteConfigs: [[]]
])

This object contains attributes, for example branches, extensions, userRemoteConfigs. Inside the Jenkinsfile, these attributes can be accessed via scm.branches, scm.extensions, scm.userRemoteConfigs. Some attributes are mandatory, some are optional or have a default value and therefore don’t need to be specified.

While the Snippet Generator gives a pretty good idea of the attributes accessible, it is sometimes required to have a look at the source code to understand how to map them to the constructor.

Implications

When the Pipeline is read from SCM - like for Multibranch Pipelines - it is sandboxed (see Script Security Plugin). This means that any access to scm attributes need to be approved by an Administrator in Jenkins. This can be controlled under Manage Jenkins  In-process Script Approval.

Example

So we have seen that it is possible to customize our checkout scm step. Here is a simple scenario: for all my branches, I want to checkout the code and carry on with my workflow whereas for the release/* branches I want to Clean before Checkout - which is a Git additional Behavior:

For all branches, my Jenkinsfile looks like this:

node {
    checkout scm

    //Build, Test, Stage, Deploy
    [...]
}

In my feature/* branches, I want to Clean After Checkout so I am gonna change the Jenkinsfile. I use the Snippet Generator for checkout  Git and add the the Additional Behavior Clean After Checkout.

sgenerator git advanced

Let’s see which attribute I need to add:

checkout([$class: 'GitSCM',
    branches: [[name: '*/master']],
    doGenerateSubmoduleConfigurations: false,
    extensions: [[$class: 'CleanCheckout']],
    submoduleCfg: [],
    userRemoteConfigs: [[credentialsId: 'git-credentials', url: 'https://github.com/user/repo.git']]
])

I need to add the [[$class: 'CleanCheckout']] to extensions. Attributes other than branches and userRemoteConfigs don’t need to be specified in my case. So I modify the Jenkinsfile and append this attribute to the scm.extensions that are passed to the flow:

node {
    checkout([
        $class: 'GitSCM',
        branches: scm.branches,
        extensions: scm.extensions + [[$class: 'CleanCheckout']],
        userRemoteConfigs: scm.userRemoteConfigs
    ])

    //Build, Test, Stage, Deploy
    [...]
}

The Jenkins Administrator needs to approve the following methods:

method hudson.plugins.git.GitSCM getBranches
method hudson.plugins.git.GitSCM getUserRemoteConfigs
method hudson.plugins.git.GitSCMBackwardCompatibility getExtensions
staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods plus java.util.Collection java.lang.Object

Further Information

Since the release of the version 2.5.2 of the Git Plugin, it is now possible to specify Advanced Behaviors in the Git SCM configuration of Multibranch Project:

multibranch git scm