2

Jenkins Job DSL スクリプトを作成しようとしていますが、できるだけ宣言的/DRY-ly に作成したいと考えています。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、 のスコープ内のすべての変数をクロージャーに渡したいと思います。job_config(引数のマップを明示的に渡すことは機能しますが、多くの引数があると扱いにくくなります。) どうすればこれを行うことができますか?

(PS: 現在、Groovy はcommit_a内部の変数をjob_configから来ているものとして解決しようとしていますがjavaposse.jobdsl.dsl.helpers.step.PhaseContext、これは奇妙だと思います。デリゲートをその内部のクロージャーに明示的に設定しませんでしたPhaseContextか?)

編集:別の SO questionから、代わりにphase= delegate(デフォルトは?) を設定して問題ないようです。は のプロパティであり、その親 (?) ではないため、これもよくわかりません。owner({ owner })()jobPhaseContext

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

私の元の方法の問題の 1 つは、クロージャー内のローカル変数にアクセスしようとしていたことですが、そのためにはクロージャーを評価する必要があります。それは本当に奇妙であることが判明しました。私はそれをやろうとしないほうがいいと思います.

于 2015-09-03T23:31:56.343 に答える