title: Get variables from delegate scope in Groovy
body: <p>I'm trying to write a Jenkins Job DSL script and would like to write it as declaratively / DRY-ly as possible. The Jenkins task is calling some other tasks via a MultiJob. I have Groovy that originally looks like this (everything's contained within a class because it's referenced elsewhere):</p>
  
  <pre><code>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')
          }
        }
      }
    }
  }
  </code></pre>
  
  <p>I'd like to abstract out the job creation, which contains lots of duplication. I've ended up with something strange like this:</p>
  
  <pre><code>static void buildDownstream(def parentJob, String commit_a="master",
      String commit_b="master") {
    parentJob.with {
      steps {
        phase('Phase') {
          def phase = ({ owner })();
          { -&gt;
            add_node_label=true;
            { -&gt;
              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 -&gt;
      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)
    }
  }
  </code></pre>
  
  <p>which, probably being totally non-idiomatic Groovy (all this <code>def self = ({ owner })()</code> stuff doesn't sit right with me), doesn't work at all.</p>
  
  <p>Basically, I want to pass all the variables in <code>callingClosure</code>'s scope to the <code>job_config</code> closure without explicitly passing all of them in as arguments. (Explicitly passing a map of arguments works, but it gets unwieldy when there are lots of arguments.) How can I do this?</p>
  
  <p>(P.S: Currently, Groovy is trying to resolve the <code>commit_a</code> variable inside <code>job_config</code> as coming from <code>javaposse.jobdsl.dsl.helpers.step.PhaseContext</code>, which I find strange; didn't I explicitly set the delegate to a closure inside that <code>PhaseContext</code>?)</p>
  
  <p>EDIT: From <a href="https://stackoverflow.com/questions/27931795/how-to-refactor-common-jenkins-jobdsl-code," title="How to refactor common Jenkins Job DSL code">another SO question</a>, it appears that I can set <code>phase</code> = <code>delegate</code> (which defaults to <code>owner</code>?) instead of <code>({ owner })()</code> and be fine; I don't really get this either, since <code>job</code> is a property of the <code>PhaseContext</code>, and not its parent (?)</p>