简体   繁体   English

从Groovy中的委托范围获取变量

[英]Get variables from delegate scope in Groovy

I'm trying to write a Jenkins Job DSL script and would like to write it as declaratively / DRY-ly as possible. 我正在尝试编写Jenkins Job DSL脚本,并希望尽可能声明性地/ DRY地编写它。 The Jenkins task is calling some other tasks via a MultiJob. Jenkins任务正在通过MultiJob调用其他一些任务。 I have Groovy that originally looks like this (everything's contained within a class because it's referenced elsewhere): 我的Groovy最初看起来像这样(类中包含所有内容,因为它在其他地方被引用):

static void buildDownstream(def parentJob, String commit_a="master",
    String commit_b="master") {
  parentJob.with {
    steps {
      phase('Phase') {
        job("name_1") {
          prop('COMMIT_A', commit_a)
          nodeLabel('NODE_LABEL', NODE_LABEL_MAP["name_1"])
          killPhaseCondition('NEVER')
        }
        job("name_2") {
          prop('COMMIT_A', commit_a)
          prop('COMMIT_B', commit_b)
          nodeLabel('NODE_LABEL', NODE_LABEL_MAP["name_2"])
          killPhaseCondition('NEVER')
        }
        job("name_3") {
          prop('COMMIT_A', commit_a)
          prop('COMMIT_B', commit_b)
          nodeLabel('NODE_LABEL', NODE_LABEL_MAP["name_3"])
          killPhaseCondition('NEVER')
        }
      }
    }
  }
}

I'd like to abstract out the job creation, which contains lots of duplication. 我想抽象出工作创造,其中包含很多重复。 I've ended up with something strange like this: 我最终遇到了这样的奇怪事情:

static void buildDownstream(def parentJob, String commit_a="master",
    String commit_b="master") {
  parentJob.with {
    steps {
      phase('Phase') {
        def phase = ({ owner })();
        { ->
          add_node_label=true;
          { ->
            commit_a = null;
            def self = ({ owner })();
            addJob("name_1", self).call(phase);
          }
          def self = ({ owner })();
          addJob("name_2", self).call(phase);
          addJob("name_3", self).call(phase);
        }
      }
    }
  }
}

private static Closure addJob(String job_name, Closure callingClosure) {
  return { phase ->
    def job_config = {
      if(commit_a != null) {
        prop('COMMIT_A', commit_a)
      }
      if(commit_b != null) {
        prop('COMMIT_B', commit_b)
      }
      if(add_node_label == true) {
        nodeLabel('NODE_LABEL', NODE_LABEL_MAP[job_name])
      }
      killPhaseCondition('NEVER')
    }

    job_config.delegate = callingClosure
    job_config.resolveStrategy = Closure.DELEGATE_ONLY
    phase.job(job_name, job_config)
  }
}

which, probably being totally non-idiomatic Groovy (all this def self = ({ owner })() stuff doesn't sit right with me), doesn't work at all. 可能完全是非惯用的Groovy(所有这些def self = ({ owner })()东西都不适合我),根本不起作用。

Basically, I want to pass all the variables in callingClosure 's scope to the job_config closure without explicitly passing all of them in as arguments. 基本上,我想将callingClosure范围内的所有变量传递给job_config闭包,而不必显式地将所有变量作为参数传递。 (Explicitly passing a map of arguments works, but it gets unwieldy when there are lots of arguments.) How can I do this? (显式传递参数映射是有效的,但是当有很多参数时,它将变得笨拙。)我该怎么做?

(PS: Currently, Groovy is trying to resolve the commit_a variable inside job_config as coming from javaposse.jobdsl.dsl.helpers.step.PhaseContext , which I find strange; didn't I explicitly set the delegate to a closure inside that PhaseContext ?) (PS:目前,Groovy的是试图解决commit_a内部变量job_config从未来javaposse.jobdsl.dsl.helpers.step.PhaseContext ,我觉得奇怪,我没有委托明确设置为内部封闭PhaseContext ? )

EDIT: From another SO question , it appears that I can set phase = delegate (which defaults to owner ?) instead of ({ owner })() and be fine; 编辑:从另一个SO问题来看,看来我可以将phase = delegate (默认为owner ?)而不是[ ({ owner })()为好; I don't really get this either, since job is a property of the PhaseContext , and not its parent (?) 我也不是真的,因为jobPhaseContext的属性,而不是其父(?)

Well, I ended up not trying to ask Groovy to implicitly resolve variables from the delegate context, and instead just passed in the parameters in a map. 好吧,我最终没有尝试让Groovy隐式地解析委托上下文中的变量,而是只将其传递给映射中的参数。

static void buildDownstream(def parentJob, 
    String commit_a="master", String commit_b="master") {
  parentJob.with {
    steps {
      phase('Tests') {
        def params = [COMMIT_A:commit_a] 
        this.getTestJob(delegate, "name_1", params)
        params.COMMIT_B = commit_b
        this.getTestJob(delegate, "name_2", params)
        this.getTestJob(delegate, "name_3", params)
        continuationCondition('ALWAYS')
      }
    }
  }
}

private static void getTestJob(def phase, String job_name, 
    Map properties) {
  phase.job(job_name) {
    properties.each { k, v -> prop(k, v) }
    killPhaseCondition('NEVER')
  }
}

One problem with my original method was that I was trying to access local variables in the closures, but that requires the closure to be evaluated; 我的原始方法的一个问题是我试图访问闭包中的局部变量,但这需要对闭包进行评估。 that turns out to be really weird, and I guess I should just not try to do that. 事实证明这确实很奇怪,我想我不应该尝试这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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