From 4f141d683a0c6cbec0551df1532e1ea31b8fb407 Mon Sep 17 00:00:00 2001 From: stchar Date: Sat, 19 Mar 2022 02:01:52 +0300 Subject: [PATCH 1/2] fix(declarative) stage with sub-stages no agent in call stack --- .../unit/declarative/StageDeclaration.groovy | 15 +++++++---- .../TestDeclarativePipeline.groovy | 22 ++++++++++++++++ .../AgentStageNoSteps_Jenkinsfile | 25 +++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 src/test/jenkins/jenkinsfiles/AgentStageNoSteps_Jenkinsfile diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy index c27770f8..71741b10 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy @@ -56,15 +56,20 @@ class StageDeclaration extends GenericPipelineDeclaration { if (!when || when.execute(delegate)) { super.execute(delegate) + // TODO handle credentials + + Closure stageBody = { agent?.execute(delegate) } + Closure cl = { stage("$name", stageBody) } + if(steps) { + stageBody = stageBody >> steps.rehydrate(delegate, this, delegate) + } + executeWith(delegate, cl) + this.stages.entrySet().forEach { e -> e.value.execute(delegate) } - if(steps) { - Closure stageBody = { agent?.execute(delegate) } >> steps.rehydrate(delegate, this, delegate) - Closure cl = { stage("$name", stageBody) } - executeWith(delegate, cl) - } + if (post) { this.post.execute(delegate) } diff --git a/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy b/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy index fa656cde..e27acd9e 100644 --- a/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy +++ b/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy @@ -765,4 +765,26 @@ class TestDeclarativePipeline extends DeclarativePipelineTest { printCallStack() assertCallStack().contains('writeFile({file=messages/messages.msg, text=text})') } + + @Test void test_agent_in_stage_with_no_steps() { + runScript("AgentStageNoSteps_Jenkinsfile") + assertJobStatusSuccess() + + assertCallStack().contains('post A') + assertCallStack().contains('post B') + assertCallStack().contains('post C') + + assertCallStack().contains('echo(A)') + assertCallStack().contains('echo(C)') + assertCallStack().contains('stage(A, groovy.lang.Closure)') + assertCallStack().contains('stage(C, groovy.lang.Closure)') + assertCallStack().contains('labelA') + assertCallStack().contains('labelC') + // assertion bellow would fail + assertCallStack().contains('stage(B, groovy.lang.Closure)') + assertCallStack().contains('labelB') + + } + } + diff --git a/src/test/jenkins/jenkinsfiles/AgentStageNoSteps_Jenkinsfile b/src/test/jenkins/jenkinsfiles/AgentStageNoSteps_Jenkinsfile new file mode 100644 index 00000000..ca0fccdc --- /dev/null +++ b/src/test/jenkins/jenkinsfiles/AgentStageNoSteps_Jenkinsfile @@ -0,0 +1,25 @@ +pipeline { + agent none + stages { + stage('A') { + agent { label 'labelA' } + post { always {echo 'post A'}} + steps { + echo 'A' + } + } + stage('B') { + agent {label 'labelB'} + post { always {echo 'post B'}} + stages { + stage('C') { + agent {label 'labelC'} + post { always {echo 'post C'}} + steps { + echo 'C' + } + } + } + } + } +} \ No newline at end of file From 866ee5065fb1b2f5390ee9033eb461a9fb3c5680 Mon Sep 17 00:00:00 2001 From: stchar Date: Sat, 19 Mar 2022 02:09:48 +0300 Subject: [PATCH 2/2] bugfix(declarative): Stage with any 2 of parallel, steps, matrix, stages should throw error --- .../unit/declarative/StageDeclaration.groovy | 15 +++++++++++++++ .../TestDeclarativePipeline.groovy | 4 ++++ .../jenkinsfiles/StageAndSteps_Jenkinsfile | 19 +++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 src/test/jenkins/jenkinsfiles/StageAndSteps_Jenkinsfile diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy index 71741b10..8ad5def5 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy @@ -42,9 +42,24 @@ class StageDeclaration extends GenericPipelineDeclaration { def execute(Object delegate) { String name = this.name + def actions = 0 + if(parallel) { + actions++ + } + if(stages.size()>0) { + actions++ + } + if(steps) { + actions++ + } + if (actions > 1 ) { + throw new IllegalArgumentException ("""Only one of "matrix", "parallel", "stages", or "steps" allowed for stage "${name}" """) + } + this.options.each { executeOn(delegate, it) } + if(parallel) { parallel.execute(delegate) } diff --git a/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy b/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy index e27acd9e..0d2011d7 100644 --- a/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy +++ b/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy @@ -786,5 +786,9 @@ class TestDeclarativePipeline extends DeclarativePipelineTest { } + @Test(expected = IllegalArgumentException) + void test_stage_and_steps() { + runScript("StageAndSteps_Jenkinsfile") + } } diff --git a/src/test/jenkins/jenkinsfiles/StageAndSteps_Jenkinsfile b/src/test/jenkins/jenkinsfiles/StageAndSteps_Jenkinsfile new file mode 100644 index 00000000..19721270 --- /dev/null +++ b/src/test/jenkins/jenkinsfiles/StageAndSteps_Jenkinsfile @@ -0,0 +1,19 @@ +pipeline { + agent none + stages { + stage('B') { + agent {label 'labelB'} + post { always {echo 'post B'}} + steps { echo 'B' } + stages { + stage('C') { + agent {label 'labelC'} + post { always {echo 'post C'}} + steps { + echo 'C' + } + } + } + } + } +} \ No newline at end of file