From f256242b7298609fa5a864d40d9ca6d2745a6d2f Mon Sep 17 00:00:00 2001 From: Serghei Anikeev Date: Thu, 6 Oct 2016 21:39:42 +0300 Subject: [PATCH 1/3] Added executionType parameter to have an ability to run phase jobs SEQUENTIALLY or PARALLEL --- .../helpers/step/MultiJobStepContext.groovy | 21 ++++++-- .../dsl/helpers/step/PhaseContext.groovy | 14 ++++- .../step/MultiJobStepContextSpec.groovy | 53 ++++++++++++++++--- 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy index 453d32ea5..c9e3263f7 100644 --- a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy +++ b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy @@ -11,6 +11,10 @@ class MultiJobStepContext extends StepContext { 'SUCCESSFUL', 'UNSTABLE', 'COMPLETED', 'FAILURE', 'ALWAYS' ] + private static final List VALID_EXECUTION_TYPES = [ + 'PARALLEL', 'SEQUENTIALLY' + ] + MultiJobStepContext(JobManagement jobManagement, Item item) { super(jobManagement, item) } @@ -19,14 +23,14 @@ class MultiJobStepContext extends StepContext { * Adds a MultiJob phase. */ void phase(@DslContext(PhaseContext) Closure phaseContext) { - phase(null, 'SUCCESSFUL', phaseContext) + phase(null, 'SUCCESSFUL', 'PARALLEL', phaseContext) } /** * Adds a MultiJob phase. */ void phase(String phaseName, @DslContext(PhaseContext) Closure phaseContext = null) { - phase(phaseName, 'SUCCESSFUL', phaseContext) + phase(phaseName, 'SUCCESSFUL', 'PARALLEL', phaseContext) } /** @@ -35,9 +39,13 @@ class MultiJobStepContext extends StepContext { * {@code continuationCondition} must be one of {@code 'SUCCESSFUL'}, {@code 'UNSTABLE'}, {@code 'COMPLETED'} or * {@code 'FAILURE'}. When version 1.16 or later of the MultiJob plugin is installed, {@code continuationCondition} * can also be set to {@code 'ALWAYS'}. + * {@code executionType} must be one of {@code 'PARALLEL'} or {@code 'SEQUENTIALLY'} */ - void phase(String name, String continuationCondition, @DslContext(PhaseContext) Closure phaseClosure) { - PhaseContext phaseContext = new PhaseContext(jobManagement, item, name, continuationCondition) + void phase( + String name, String continuationCondition, String executionType, + @DslContext(PhaseContext) Closure phaseClosure + ) { + PhaseContext phaseContext = new PhaseContext(jobManagement, item, name, continuationCondition, executionType) ContextHelper.executeInContext(phaseClosure, phaseContext) Preconditions.checkNotNullOrEmpty(phaseContext.phaseName, 'A phase needs a name') @@ -45,10 +53,15 @@ class MultiJobStepContext extends StepContext { VALID_CONTINUATION_CONDITIONS.contains(phaseContext.continuationCondition), "Continuation Condition needs to be one of these values: ${VALID_CONTINUATION_CONDITIONS.join(', ')}" ) + Preconditions.checkArgument( + VALID_EXECUTION_TYPES.contains(phaseContext.executionType), + "Execution Type needs to be one of these values: ${VALID_EXECUTION_TYPES.join(', ')}" + ) stepNodes << new NodeBuilder().'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' { phaseName phaseContext.phaseName delegate.continuationCondition(phaseContext.continuationCondition) + delegate.executionType(phaseContext.executionType) phaseJobs { phaseContext.jobsInPhase.each { PhaseJobContext jobInPhase -> Node phaseJobNode = 'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig' { diff --git a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/PhaseContext.groovy b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/PhaseContext.groovy index 587afbc9e..4571be16b 100644 --- a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/PhaseContext.groovy +++ b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/PhaseContext.groovy @@ -11,14 +11,19 @@ class PhaseContext extends AbstractContext { String phaseName String continuationCondition + String executionType List jobsInPhase = [] - PhaseContext(JobManagement jobManagement, Item item, String phaseName, String continuationCondition) { + PhaseContext( + JobManagement jobManagement, Item item, String phaseName, String continuationCondition, + String executionType + ) { super(jobManagement) this.item = item this.phaseName = phaseName this.continuationCondition = continuationCondition + this.executionType = executionType } /** @@ -35,6 +40,13 @@ class PhaseContext extends AbstractContext { this.continuationCondition = continuationCondition } + /** + * Defines how to run the whole MultiJob phase. + */ + void executionType(String executionType) { + this.executionType = executionType + } + /** * Adds a job to the phase. * diff --git a/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy b/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy index d98d7ff3a..820390dde 100644 --- a/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy +++ b/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy @@ -17,9 +17,10 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[0]) { name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' - children().size() == 3 + children().size() == 4 phaseName[0].value() == 'First' continuationCondition[0].value() == 'SUCCESSFUL' + executionType[0].value() == 'PARALLEL' phaseJobs[0].value().empty } @@ -32,9 +33,10 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[1]) { name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' - children().size() == 3 + children().size() == 4 phaseName[0].value() == 'Second' continuationCondition[0].value() == 'SUCCESSFUL' + executionType[0].value() == 'PARALLEL' phaseJobs[0].children().size() == 1 with(phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[0]) { children().size() == 7 @@ -60,9 +62,10 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[0]) { name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' - children().size() == 3 + children().size() == 4 phaseName[0].value() == 'Third' continuationCondition[0].value() == 'SUCCESSFUL' + executionType[0].value() == 'PARALLEL' phaseJobs[0].children().size() == 3 phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[0].jobName[0].value() == 'JobA' phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[1].jobName[0].value() == 'JobB' @@ -100,9 +103,10 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[0]) { - children().size() == 3 + children().size() == 4 phaseName[0].value() == 'Fourth' continuationCondition[0].value() == 'SUCCESSFUL' + executionType[0].value() == 'PARALLEL' phaseJobs[0].children().size() == 1 with(phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[0]) { children().size() == 8 @@ -188,9 +192,10 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[0]) { name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' - children().size() == 3 + children().size() == 4 phaseName[0].value() == 'Second' continuationCondition[0].value() == 'SUCCESSFUL' + executionType[0].value() == 'PARALLEL' phaseJobs[0].children().size() == 1 with(phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[0]) { children().size() == 7 @@ -220,7 +225,16 @@ class MultiJobStepContextSpec extends Specification { def 'call phase with unsupported condition'() { when: - context.phase('test', 'FOO') { + context.phase('test', 'FOO', 'PARALLEL') { + } + + then: + thrown(DslScriptException) + } + + def 'call phase with unsupported execution type'() { + when: + context.phase('test', 'SUCCESSFUL', 'BAR') { } then: @@ -232,15 +246,16 @@ class MultiJobStepContextSpec extends Specification { jobManagement.isMinimumPluginVersionInstalled('jenkins-multijob-plugin', '1.16') >> true when: - context.phase('test', condition) { + context.phase('test', condition, 'PARALLEL') { } then: with(context.stepNodes[0]) { name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' - children().size() == 3 + children().size() == 4 phaseName[0].value() == 'test' continuationCondition[0].value() == condition + executionType[0].value() == 'PARALLEL' phaseJobs[0].value().empty } @@ -248,6 +263,28 @@ class MultiJobStepContextSpec extends Specification { condition << ['FAILURE', 'ALWAYS'] } + def 'call phase with supported execution type'(String execution) { + setup: + jobManagement.isMinimumPluginVersionInstalled('jenkins-multijob-plugin', '1.16') >> true + + when: + context.phase('test', 'SUCCESSFUL', execution) { + } + + then: + with(context.stepNodes[0]) { + name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' + children().size() == 4 + phaseName[0].value() == 'test' + continuationCondition[0].value() == 'SUCCESSFUL' + executionType[0].value() == execution + phaseJobs[0].value().empty + } + + where: + execution << ['SEQUENTIALLY'] + } + def 'phase works inside conditionalSteps'() { when: context.conditionalSteps { From 792ab8f837dc2c0bf6dd04f3e7b85e930c92d5d7 Mon Sep 17 00:00:00 2001 From: Serghei Anikeev Date: Mon, 10 Oct 2016 16:28:13 +0300 Subject: [PATCH 2/3] Applying suggested fixes --- .../helpers/step/MultiJobStepContext.groovy | 20 ++++------------- .../dsl/helpers/step/PhaseContext.groovy | 19 +++++++++++----- .../step/MultiJobStepContextSpec.groovy | 22 +++++++++++++------ 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy index c9e3263f7..e2e1e6a36 100644 --- a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy +++ b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy @@ -11,10 +11,6 @@ class MultiJobStepContext extends StepContext { 'SUCCESSFUL', 'UNSTABLE', 'COMPLETED', 'FAILURE', 'ALWAYS' ] - private static final List VALID_EXECUTION_TYPES = [ - 'PARALLEL', 'SEQUENTIALLY' - ] - MultiJobStepContext(JobManagement jobManagement, Item item) { super(jobManagement, item) } @@ -23,14 +19,14 @@ class MultiJobStepContext extends StepContext { * Adds a MultiJob phase. */ void phase(@DslContext(PhaseContext) Closure phaseContext) { - phase(null, 'SUCCESSFUL', 'PARALLEL', phaseContext) + phase(null, 'SUCCESSFUL', phaseContext) } /** * Adds a MultiJob phase. */ void phase(String phaseName, @DslContext(PhaseContext) Closure phaseContext = null) { - phase(phaseName, 'SUCCESSFUL', 'PARALLEL', phaseContext) + phase(phaseName, 'SUCCESSFUL', phaseContext) } /** @@ -39,13 +35,9 @@ class MultiJobStepContext extends StepContext { * {@code continuationCondition} must be one of {@code 'SUCCESSFUL'}, {@code 'UNSTABLE'}, {@code 'COMPLETED'} or * {@code 'FAILURE'}. When version 1.16 or later of the MultiJob plugin is installed, {@code continuationCondition} * can also be set to {@code 'ALWAYS'}. - * {@code executionType} must be one of {@code 'PARALLEL'} or {@code 'SEQUENTIALLY'} */ - void phase( - String name, String continuationCondition, String executionType, - @DslContext(PhaseContext) Closure phaseClosure - ) { - PhaseContext phaseContext = new PhaseContext(jobManagement, item, name, continuationCondition, executionType) + void phase(String name, String continuationCondition, @DslContext(PhaseContext) Closure phaseClosure) { + PhaseContext phaseContext = new PhaseContext(jobManagement, item, name, continuationCondition) ContextHelper.executeInContext(phaseClosure, phaseContext) Preconditions.checkNotNullOrEmpty(phaseContext.phaseName, 'A phase needs a name') @@ -53,10 +45,6 @@ class MultiJobStepContext extends StepContext { VALID_CONTINUATION_CONDITIONS.contains(phaseContext.continuationCondition), "Continuation Condition needs to be one of these values: ${VALID_CONTINUATION_CONDITIONS.join(', ')}" ) - Preconditions.checkArgument( - VALID_EXECUTION_TYPES.contains(phaseContext.executionType), - "Execution Type needs to be one of these values: ${VALID_EXECUTION_TYPES.join(', ')}" - ) stepNodes << new NodeBuilder().'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' { phaseName phaseContext.phaseName diff --git a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/PhaseContext.groovy b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/PhaseContext.groovy index 4571be16b..2921b0c5b 100644 --- a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/PhaseContext.groovy +++ b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/PhaseContext.groovy @@ -5,20 +5,23 @@ import javaposse.jobdsl.dsl.ContextHelper import javaposse.jobdsl.dsl.DslContext import javaposse.jobdsl.dsl.Item import javaposse.jobdsl.dsl.JobManagement +import javaposse.jobdsl.dsl.RequiresPlugin +import javaposse.jobdsl.dsl.Preconditions class PhaseContext extends AbstractContext { + private static final List VALID_EXECUTION_TYPES = [ + 'PARALLEL', 'SEQUENTIALLY' + ] + protected final Item item String phaseName String continuationCondition - String executionType + String executionType = 'PARALLEL' List jobsInPhase = [] - PhaseContext( - JobManagement jobManagement, Item item, String phaseName, String continuationCondition, - String executionType - ) { + PhaseContext(JobManagement jobManagement, Item item, String phaseName, String continuationCondition) { super(jobManagement) this.item = item this.phaseName = phaseName @@ -42,8 +45,14 @@ class PhaseContext extends AbstractContext { /** * Defines how to run the whole MultiJob phase. + * @since 1.52 */ + @RequiresPlugin(id = 'jenkins-multijob-plugin', minimumVersion = '1.22') void executionType(String executionType) { + Preconditions.checkArgument( + VALID_EXECUTION_TYPES.contains(executionType), + "Execution Type needs to be one of these values: ${VALID_EXECUTION_TYPES.join(', ')}" + ) this.executionType = executionType } diff --git a/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy b/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy index 820390dde..9c4fe75a1 100644 --- a/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy +++ b/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy @@ -225,28 +225,35 @@ class MultiJobStepContextSpec extends Specification { def 'call phase with unsupported condition'() { when: - context.phase('test', 'FOO', 'PARALLEL') { + context.phase('test', 'FOO') { } then: thrown(DslScriptException) } - def 'call phase with unsupported execution type'() { + def 'call phase with unsupported execution type'(String execution) { + setup: + jobManagement.isMinimumPluginVersionInstalled('jenkins-multijob-plugin', '1.22') >> true + when: - context.phase('test', 'SUCCESSFUL', 'BAR') { + context.phase('test') { + executionType execution } then: thrown(DslScriptException) + + where: + execution << ['FOO'] } def 'call phase with supported condition'(String condition) { setup: - jobManagement.isMinimumPluginVersionInstalled('jenkins-multijob-plugin', '1.16') >> true + jobManagement.isMinimumPluginVersionInstalled('jenkins-multijob-plugin', '1.22') >> true when: - context.phase('test', condition, 'PARALLEL') { + context.phase('test', condition) { } then: @@ -265,10 +272,11 @@ class MultiJobStepContextSpec extends Specification { def 'call phase with supported execution type'(String execution) { setup: - jobManagement.isMinimumPluginVersionInstalled('jenkins-multijob-plugin', '1.16') >> true + jobManagement.isMinimumPluginVersionInstalled('jenkins-multijob-plugin', '1.22') >> true when: - context.phase('test', 'SUCCESSFUL', execution) { + context.phase('test') { + executionType execution } then: From f37a8139d23c77a19ed514fafa1153656af09736 Mon Sep 17 00:00:00 2001 From: Serghei Anikeev Date: Mon, 10 Oct 2016 22:26:26 +0300 Subject: [PATCH 3/3] Applying suggested fixes #2 --- .../helpers/step/MultiJobStepContext.groovy | 4 +++- .../step/MultiJobStepContextSpec.groovy | 24 +++++++------------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy index e2e1e6a36..5f24d1ae4 100644 --- a/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy +++ b/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContext.groovy @@ -49,7 +49,9 @@ class MultiJobStepContext extends StepContext { stepNodes << new NodeBuilder().'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' { phaseName phaseContext.phaseName delegate.continuationCondition(phaseContext.continuationCondition) - delegate.executionType(phaseContext.executionType) + if (jobManagement.isMinimumPluginVersionInstalled('jenkins-multijob-plugin', '1.22')) { + delegate.executionType(phaseContext.executionType) + } phaseJobs { phaseContext.jobsInPhase.each { PhaseJobContext jobInPhase -> Node phaseJobNode = 'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig' { diff --git a/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy b/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy index 9c4fe75a1..26363b497 100644 --- a/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy +++ b/job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/MultiJobStepContextSpec.groovy @@ -17,10 +17,9 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[0]) { name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' - children().size() == 4 + children().size() == 3 phaseName[0].value() == 'First' continuationCondition[0].value() == 'SUCCESSFUL' - executionType[0].value() == 'PARALLEL' phaseJobs[0].value().empty } @@ -33,10 +32,9 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[1]) { name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' - children().size() == 4 + children().size() == 3 phaseName[0].value() == 'Second' continuationCondition[0].value() == 'SUCCESSFUL' - executionType[0].value() == 'PARALLEL' phaseJobs[0].children().size() == 1 with(phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[0]) { children().size() == 7 @@ -62,10 +60,9 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[0]) { name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' - children().size() == 4 + children().size() == 3 phaseName[0].value() == 'Third' continuationCondition[0].value() == 'SUCCESSFUL' - executionType[0].value() == 'PARALLEL' phaseJobs[0].children().size() == 3 phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[0].jobName[0].value() == 'JobA' phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[1].jobName[0].value() == 'JobB' @@ -103,10 +100,9 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[0]) { - children().size() == 4 + children().size() == 3 phaseName[0].value() == 'Fourth' continuationCondition[0].value() == 'SUCCESSFUL' - executionType[0].value() == 'PARALLEL' phaseJobs[0].children().size() == 1 with(phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[0]) { children().size() == 8 @@ -192,10 +188,9 @@ class MultiJobStepContextSpec extends Specification { then: with(context.stepNodes[0]) { name() == 'com.tikal.jenkins.plugins.multijob.MultiJobBuilder' - children().size() == 4 + children().size() == 3 phaseName[0].value() == 'Second' continuationCondition[0].value() == 'SUCCESSFUL' - executionType[0].value() == 'PARALLEL' phaseJobs[0].children().size() == 1 with(phaseJobs[0].'com.tikal.jenkins.plugins.multijob.PhaseJobsConfig'[0]) { children().size() == 7 @@ -232,20 +227,17 @@ class MultiJobStepContextSpec extends Specification { thrown(DslScriptException) } - def 'call phase with unsupported execution type'(String execution) { + def 'call phase with unsupported execution type'() { setup: jobManagement.isMinimumPluginVersionInstalled('jenkins-multijob-plugin', '1.22') >> true when: context.phase('test') { - executionType execution + executionType 'FOO' } then: thrown(DslScriptException) - - where: - execution << ['FOO'] } def 'call phase with supported condition'(String condition) { @@ -290,7 +282,7 @@ class MultiJobStepContextSpec extends Specification { } where: - execution << ['SEQUENTIALLY'] + execution << ['PARALLEL', 'SEQUENTIALLY'] } def 'phase works inside conditionalSteps'() {