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