2

我正在尝试编写一个 Jenkins Job DSL 脚本,并希望尽可能以声明方式/干式方式编写它。Jenkins 任务通过 MultiJob 调用其他一些任务。我的 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')
        }
      }
    }
  }
}

我想抽象出包含大量重复的工作创造。我最终得到了这样奇怪的东西:

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)
  }
}

这可能完全是非惯用的 Groovy(所有这些def self = ({ owner })()东西都不适合我),根本不起作用。

基本上,我想将callingClosure's 范围内的所有变量都传递给job_config闭包,而不是将所有变量作为参数显式传递。(显式传递参数映射是可行的,但是当有很多参数时它会变得笨拙。)我该怎么做?

(PS:目前,Groovy 正在尝试将commit_a内部变量解析job_config为 from javaposse.jobdsl.dsl.helpers.step.PhaseContext,我觉得这很奇怪;我不是明确地将委托设置为内部的闭包PhaseContext吗?)

编辑:从另一个 SO question看来,我可以设置phase= delegate(默认为owner?)而不是({ owner })()并且很好;我也不是很明白,因为job它是 的属性PhaseContext,而不是它的父级(?)

4

1 回答 1

0

好吧,我最终没有试图让 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')
  }
}

我的原始方法的一个问题是我试图访问闭包中的局部变量,但这需要对闭包进行评估;事实证明这真的很奇怪,我想我不应该尝试这样做。

于 2015-09-03T23:31:56.343 回答