Answer a question

I am trying to have one common shared library which has actual pipeline as code, something like this under vars/demo.groovy

def call(Map pipelineParams) {

pipeline {
  agent {
    docker { image 'centos:latest' }
  }

    stages {
        stage("Env Variables") {
            steps {
                sh "printenv"
                //echo ${SERVICE_NAME}
            }
        }

        stage("test") {
            steps {
                sh "printenv"
            }
    }
  }
    }   
}

And I will be accessing the shared Library from my Jenkinsfile like this.

library identifier: 'mylibraryname@master', 
    //'master' refers to a valid git-ref
    //'mylibraryname' can be any name
    retriever: modernSCM([
      $class: 'GitSCMSource',
      //credentialsId: 'your-credentials-id',
      remote: 'GIT URL'
    ])

demo()

It is working as expected but I want to send an extra environment variable or override existing variables from my Jenkinsfile without making changes to shared library which has my pipeline as code . can you help me with how could this be achieved?

I have tried giving the variables as below:

demo {
    service = 'test'
    var1 = 'value'
}

And tried them accessing this way:

def call(Map pipelineParams) {

pipeline {
  agent {
    docker { image 'centos:latest' }
  }
    stages {
        stage("Env Variables") {
            steps {
                sh "printenv"
                echo "pipelineParams.service"
            }
        }

        stage("test") {
            steps {
                sh ' echo "hello pipelineParams.service '
            }
    }
  }
    }   
}

But getting the following error:

[Pipeline] End of Pipeline

hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: demo.call() is applicable for argument types: (org.jenkinsci.plugins.workflow.cps.CpsClosure2) values: [org.jenkinsci.plugins.workflow.cps.CpsClosure2@cad5c94]

Possible solutions: call(java.util.Map), wait(), any(), wait(long), main([Ljava.lang.String;), each(groovy.lang.Closure)

    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)

    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:64)

    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)

    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)

    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)

    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:160)

    at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23)

    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:157)

    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:142)

    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:158)

Answers

The signature of this is a map as defined here

def call(Map pipelineParams)

So you need to use a map. (https://www.baeldung.com/groovy-maps) What this would look like is:

demo([
    service: 'test',
    var1: 'value'
])

Your echo statement is also not quite right, it should be:

echo(pipelineParams.service)

There is no need to use a GString or a string at all because it is a groovy variable.

Note: I use () in my examples. Strictly speaking you don't need them. I just prefer to code this way so its clear these are method arguments.

You could also just create env vars. Though I probably don't recommend it and would do it more like the way you are currently planning.

withEnv([SERVICE='test', VAR1='value]) {
    demo([:]) // I put an empty map here, if you did this you would change your call method to not have the map though
}

This way above ensures the env vars only live until the end of the closure (the last } brace)

Another way, but this just sets them and they will exist globally and for the rest of the run. Not great.

env.SERVICE = 'test'
env.VAR1 = 'value'

demo([:])

in either case, in your shared lib you would check:

echo env.SERVICE

Again though I think its better the first way your doing it. Accepting a map argument and using those. env vars can be global and cause issues sometimes depending on what your running.

Logo

CI/CD社区为您提供最前沿的新闻资讯和知识内容

更多推荐