简体   繁体   中英

parallel steps on different nodes on declarative jenkins pipeline cannot access variables defined in global scope

Let me preface this by saying that I don't yet fully understand how jenkins DSL / groovy handles namespace, scope, variables etc.

In order to keep my code DRY I put repeated command sequences into variables. It turns out the variable script below is not readable by the code in doParallelStuff . Why is that? Is there a way to share global variables defined in the script (or elsewhere) among both the main pipleine steps and the doParallelStuff code?

def script = """\
#/bin/bash
python xyz.py
"""

def doParallelStuff() {
  tests["1"] = {
    node {
      stage('ps1') {
        sh script
      }
    }
  }

  tests["2"] = {
    node {
      stage('ps2') {
        sh script
      }
    }
  }
  parallel tests

}

pipeline {
  stages {
    stage("myStage") {
      steps {
        script {
          sh script
          doParallelStuff()
        }
      }
    }
  }
}

The actual steps are a bit more complicated, but this causes an error like the following to be thrown:

hudson.remoting.ProxyException: groovy.lang.MissingPropertyException: No such property: script for class: WorkflowScript

When you define a variable outside of the pipeline directive scope using the def keyword you are defining it in the local scope of the main script, because the pipeline keyword is actually a method that is executed in the main script it can access the variable is they are defined and executed in the same scope (they are actually transformed into a separated class).
When you define a function outside of the pipeline directive, that function has its own scope for variables which is separated from the scope of the main script and therefore it cannot access the defined variable in the top level.

To solve it you can define the variable without the def keyword which will affect the scope in which this variable is created, as without the def (in a groovy script, not class) the variable is added to the global variables of the script (The Binding ) which makes it accessible from any function or code within the groovy script. You can read more on the following question: What is the difference between defining variables using def and without?

So in your case you want a variable that is available for both the pipeline code itself and for the defined functions - so it needs to be available anywhere in the script as a global variable and therefore just define it without the def keyword, and it should do the trick:

 script = """\
 #/bin/bash
 python xyz.py
 """

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM