Search code examples
jenkinsjenkins-pipelinemultibranch-pipeline

Jenkins scripted pipeline: must specify $class with an implementation of class jenkins.scm.api.SCMSource


I have a jenkins multibranch-pipeline. Apparently it checked out the main repo successfully (files are visible in the workspace).

But then I called this method. Goal was to check out (in a dedicated subfolder) the following repository and the same branch that I checked out of the main repo (e.g. if main repo is checked out at "my-target-branch-name" then "bar" repo should also try to check out branch "my-target-branch-name", or "master" as fallback. In fact the whole use case is similar if not the same as the one described in the documentation of the resolveScm step (page might load slowly, be patient)

checkout resolveScm(source: git(url: '[email protected]:foo/bar.git', credentialsId: 'xxx'), targets: [env.BRANCH_NAME, 'master'])

However I got an error:

16:40:38  java.lang.UnsupportedOperationException: must specify $class with an implementation of class jenkins.scm.api.SCMSource
16:40:38    at org.jenkinsci.plugins.structs.describable.DescribableModel.resolveClass(DescribableModel.java:574)
16:40:38    at org.jenkinsci.plugins.structs.describable.DescribableModel.coerce(DescribableModel.java:473)
16:40:38    at org.jenkinsci.plugins.structs.describable.DescribableModel.buildArguments(DescribableModel.java:409)
16:40:38    at org.jenkinsci.plugins.structs.describable.DescribableModel.instantiate(DescribableModel.java:329)
16:40:38    at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:302)
16:40:38    at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:193)
16:40:38    at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
16:40:38    at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1278)
16:40:38    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1172)
16:40:38    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
16:40:38    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
16:40:38    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
16:40:38    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
16:40:38    at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20)
16:40:38  Caused: java.lang.IllegalArgumentException: Could not instantiate {source={[email protected], GIT_AUTHOR_NAME=Jenkins, GIT_BRANCH=origin/master, GIT_COMMIT=xxx, [email protected], GIT_COMMITTER_NAME=Jenkins, GIT_LOCAL_BRANCH=master, GIT_PREVIOUS_COMMIT=yyy, GIT_PREVIOUS_SUCCESSFUL_COMMIT=yyy, [email protected]:foo/bar.git}, targets=[my-target-branch-name, master]} for org.jenkinsci.plugins.workflow.multibranch.ResolveScmStep
16:40:38    at org.jenkinsci.plugins.structs.describable.DescribableModel.instantiate(DescribableModel.java:334)
16:40:38    at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:302)
16:40:38    at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:193)
16:40:38    at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
16:40:38    at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1278)
16:40:38    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1172)
16:40:38    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
16:40:38    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
16:40:38    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
16:40:38    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
16:40:38    at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20)
16:40:38    at fooBar.call(fooBar.groovy:14)
16:40:38    at fooBar.call(fooBar.groovy:258)
16:40:38    at ___cps.transform___(Native Method)
...

Where did I go wrong?

Here is the complete definition of Jenkinsfile:

pipeline {

    agent { label 'small || big' }

    stages {

        stage('Build') {
            steps {
                sh "ls -la"
                sh "rm -rf secondrepo && mkdir secondrepo"
                dir('secondrepo') {
                    checkout resolveScm(source: git(url: '[email protected]:foo/bar.git', credentialsId: 'xxx'), targets: [env.BRANCH_NAME, 'master'])
                }
            }
        }

    }

}

Solution

  • The problem seems to be that there is a clash when one calls git(...) in their script. The source parameter of resolveScm expects an instance of jenkins.scm.api.SCMSource. However, if one calls git() such as in the documentation, then it seems to rather match the functionName in GitStep and create an instance of GitSCM which is not a subclass of SCMSource which is wrong. Instead, by calling git, it should have matched the git symbol in GitSCMSource

    So, in order to get around this issue I enforced the instantiation of a GitSCMSource by specifying the arguments as a map:

    checkout resolveScm(source: [$class: 'GitSCMSource', remote: '[email protected]:foo/bar.git', credentialsId: 'xxx', traits: [gitBranchDiscovery()]], targets: [env.BRANCH_NAME, 'master'])