Groovy嵌套闭包-如何传递哈希?

时间:2019-02-03 16:13:58

标签: jenkins groovy closures

我想为我的Jenkins构建加载一个闭包,但是将一些对我们系统上正在进行的任何类型的构建(Go,Java,Docker)通用的变量传递给它。由于我是从单独的Groovy文件加载特定的闭包,因此看不到这些变量。为了使示例更简单,我注释掉了负载并包含了该闭包。

我不确定如何执行此操作-如何将配置从buildProject传递到buildSpecificProject?我说错了吗?

#!/usr/bin/groovy

//def buildSpecificProject = load 'buildSpecificProject.groovy'

def buildSpecificProject = {  body->  

   def config = [:]
   body.resolveStrategy = Closure.DELEGATE_FIRST
   body.delegate = config
   body()

   println config.name
   println config.builddirectory
}

def buildProject = { projbody -> 
   def config = [:]
   projbody.resolveStrategy = Closure.DELEGATE_FIRST
   projbody.delegate = config
   projbody()

   config.builddirectory = "/bar"

   return config
}

try {
    def newProjectVersion =  buildSpecificProject { body ->
      buildProject { projbody ->
         name = 'projectname'
         versionPrefix = "4.2.0"
         fetchFromURL = 'git@github.com:myorg/myproject.git'
      }
    }
    println "New Project Version = ${newProjectVersion}\n"
} catch (err) {
    println err
}

1 个答案:

答案 0 :(得分:1)

我真的没有在Jenkins中构建脚本的经验,所以也许我的答案不适用,但是从Groovy的角度来看,情况如下:

buildSpecificProject中的config变量是一个本地变量,除非您公开它或其值,否则您将无法访问该变量。现在,您可以通过实际设置委托来做到这一点。

如果我们说buildProject仅从给buildSpecificProject的块中调用,则给buildProject的块是嵌套在给buildSpecificProject的Closure中的Closure。此Closure对象将具有属性所有者,在这种情况下,该属性所有者将引用封闭的Closure实例(请参见http://groovy-lang.org/closures.html#_owner_of_a_closure)。我们知道其中已将配置设置为委托,因此您可以执行projbody.owner.delegate来访问buildSpecificProject设置的配置。

但是实际上我会考虑做这样的事情:

def buildSpecificProject = {  body ->  
  def config = [:]
  body.resolveStrategy = Closure.DELEGATE_FIRST
  body.delegate = [config: config]  // expose config
  body()

  println config.name
  println config.builddirectory
  return config
}

def buildProject = { config, projbody -> 
   projbody()
   config.builddirectory = "/bar"
}

try {
    def newProjectVersion =  buildSpecificProject { body ->
      // make config accessible to buildProject by providing it as parameter
      buildProject(config) { projbody ->  
         config.name = 'projectname'
         config.versionPrefix = "4.2.0"
         config.fetchFromURL = 'git@github.com:myorg/myproject.git'
      }
    }
    println "New Project Version = ${newProjectVersion}\n"
} catch (err) {
    println err
}

如您所见,buildSpecificProject实际上足以设置委托,我使用一个名为config的键将其设置为包含实际配置的映射。缺点当然是您现在必须执行config.name。还要注意调用“ buildProject(config){projbody->”,该调用将配置传递给buildProject。当然,我们可以将两种想法结合起来:

def buildSpecificProject = {  body ->  
  def config = [:]
  body.resolveStrategy = Closure.DELEGATE_FIRST
  body.delegate = config
  body()

  println config.name
  println config.builddirectory
  return config
}

def buildProject = { config, projbody ->
   projbody()
   config.builddirectory = "/bar"
}

try {
    def newProjectVersion =  buildSpecificProject {
      buildProject(delegate) { projbody ->
         name = 'projectname'
         versionPrefix = "4.2.0"
         fetchFromURL = 'git@github.com:myorg/myproject.git'
      }
    }
    println "New Project Version = ${newProjectVersion}\n"
} catch (err) {
    println err
}

但是我不建议这样做,因为我不希望以这种方式依赖委托。我很容易摔坏。

相关问题