Dynamic Parallel stages in Jenkins Pipeline outside 'script' block
up vote
1
down vote
favorite
I am trying to construct parallel stages dynamically, as demonstrated here and here. Specifically, I am trying to do this in a function defined outside the scope of the pipeline, e.g.:
pipeline{
stages{
stage('CI'){
steps{
doDynamicParallelSteps()
}
}
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
The problem is, it seems this only works when the dynamic parallel generation code is inside a script{} block within the steps{} block of the pipeline (as seen in the first source).
When running something similar to the code snippet above, I see this error in jenkins:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.lang.String.call() is applicable for argument types: (java.lang.String, org.jenkinsci.plugins.workflow.cps.CpsClosure2) values: [teststage, org.jenkinsci.plugins.workflow.cps.CpsClosure2@2e1b48b4]
Possible solutions: wait(), any(), trim(), size(), next(), size()
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:153)
at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:155)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
at WorkflowScript.parallelHandler(WorkflowScript:1383)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
at sun.reflect.GeneratedMethodAccessor110.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ClosureBlock.eval(ClosureBlock.java:46)
at com.cloudbees.groovy.cps.Next.step(Next.java:83)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$101(SandboxContinuable.java:34)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.lambda$run0$0(SandboxContinuable.java:59)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:58)
at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:182)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:332)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:83)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:244)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:232)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Finished: FAILURE
Is there any way to have it defined as a function in the way I showed in the initial code snippet, or am I stuck with having a ton of script{} blocks in my pipeline definition?
jenkins groovy jenkins-pipeline
add a comment |
up vote
1
down vote
favorite
I am trying to construct parallel stages dynamically, as demonstrated here and here. Specifically, I am trying to do this in a function defined outside the scope of the pipeline, e.g.:
pipeline{
stages{
stage('CI'){
steps{
doDynamicParallelSteps()
}
}
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
The problem is, it seems this only works when the dynamic parallel generation code is inside a script{} block within the steps{} block of the pipeline (as seen in the first source).
When running something similar to the code snippet above, I see this error in jenkins:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.lang.String.call() is applicable for argument types: (java.lang.String, org.jenkinsci.plugins.workflow.cps.CpsClosure2) values: [teststage, org.jenkinsci.plugins.workflow.cps.CpsClosure2@2e1b48b4]
Possible solutions: wait(), any(), trim(), size(), next(), size()
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:153)
at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:155)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
at WorkflowScript.parallelHandler(WorkflowScript:1383)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
at sun.reflect.GeneratedMethodAccessor110.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ClosureBlock.eval(ClosureBlock.java:46)
at com.cloudbees.groovy.cps.Next.step(Next.java:83)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$101(SandboxContinuable.java:34)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.lambda$run0$0(SandboxContinuable.java:59)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:58)
at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:182)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:332)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:83)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:244)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:232)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Finished: FAILURE
Is there any way to have it defined as a function in the way I showed in the initial code snippet, or am I stuck with having a ton of script{} blocks in my pipeline definition?
jenkins groovy jenkins-pipeline
What is in line 1383 of your script? The error seems to be caused there according to the error message
– Joerg S
Nov 11 at 7:22
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I am trying to construct parallel stages dynamically, as demonstrated here and here. Specifically, I am trying to do this in a function defined outside the scope of the pipeline, e.g.:
pipeline{
stages{
stage('CI'){
steps{
doDynamicParallelSteps()
}
}
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
The problem is, it seems this only works when the dynamic parallel generation code is inside a script{} block within the steps{} block of the pipeline (as seen in the first source).
When running something similar to the code snippet above, I see this error in jenkins:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.lang.String.call() is applicable for argument types: (java.lang.String, org.jenkinsci.plugins.workflow.cps.CpsClosure2) values: [teststage, org.jenkinsci.plugins.workflow.cps.CpsClosure2@2e1b48b4]
Possible solutions: wait(), any(), trim(), size(), next(), size()
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:153)
at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:155)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
at WorkflowScript.parallelHandler(WorkflowScript:1383)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
at sun.reflect.GeneratedMethodAccessor110.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ClosureBlock.eval(ClosureBlock.java:46)
at com.cloudbees.groovy.cps.Next.step(Next.java:83)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$101(SandboxContinuable.java:34)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.lambda$run0$0(SandboxContinuable.java:59)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:58)
at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:182)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:332)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:83)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:244)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:232)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Finished: FAILURE
Is there any way to have it defined as a function in the way I showed in the initial code snippet, or am I stuck with having a ton of script{} blocks in my pipeline definition?
jenkins groovy jenkins-pipeline
I am trying to construct parallel stages dynamically, as demonstrated here and here. Specifically, I am trying to do this in a function defined outside the scope of the pipeline, e.g.:
pipeline{
stages{
stage('CI'){
steps{
doDynamicParallelSteps()
}
}
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
The problem is, it seems this only works when the dynamic parallel generation code is inside a script{} block within the steps{} block of the pipeline (as seen in the first source).
When running something similar to the code snippet above, I see this error in jenkins:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.lang.String.call() is applicable for argument types: (java.lang.String, org.jenkinsci.plugins.workflow.cps.CpsClosure2) values: [teststage, org.jenkinsci.plugins.workflow.cps.CpsClosure2@2e1b48b4]
Possible solutions: wait(), any(), trim(), size(), next(), size()
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:153)
at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:155)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
at WorkflowScript.parallelHandler(WorkflowScript:1383)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
at sun.reflect.GeneratedMethodAccessor110.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ClosureBlock.eval(ClosureBlock.java:46)
at com.cloudbees.groovy.cps.Next.step(Next.java:83)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$101(SandboxContinuable.java:34)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.lambda$run0$0(SandboxContinuable.java:59)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:58)
at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:182)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:332)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:83)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:244)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:232)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Finished: FAILURE
Is there any way to have it defined as a function in the way I showed in the initial code snippet, or am I stuck with having a ton of script{} blocks in my pipeline definition?
jenkins groovy jenkins-pipeline
jenkins groovy jenkins-pipeline
edited Nov 10 at 8:46
Szymon Stepniak
16.1k83061
16.1k83061
asked Nov 9 at 23:21
Clayton Keleher
214
214
What is in line 1383 of your script? The error seems to be caused there according to the error message
– Joerg S
Nov 11 at 7:22
add a comment |
What is in line 1383 of your script? The error seems to be caused there according to the error message
– Joerg S
Nov 11 at 7:22
What is in line 1383 of your script? The error seems to be caused there according to the error message
– Joerg S
Nov 11 at 7:22
What is in line 1383 of your script? The error seems to be caused there according to the error message
– Joerg S
Nov 11 at 7:22
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
The declarative pipeline does not allow you to put Groovy code inside steps {}
block - it expects a valid Jenkins pipeline step in this place. This is why script {}
block got introduced that can be put inside the steps {}
block to execute some Groovy code.
If you need flexibility and non-opinionated syntax then you might use scripted pipeline instead. Here you can mix Groovy code with existing pipeline steps with almost no limitations.
Jenkins documentation explains shortly the difference between both approaches and why they exist:
When Jenkins Pipeline was first created, Groovy was selected as the foundation. Jenkins has long shipped with an embedded Groovy engine to provide advanced scripting capabilities for admins and users alike. Additionally, the implementors of Jenkins Pipeline found Groovy to be a solid foundation upon which to build what is now referred to as the "Scripted Pipeline" DSL. [2].
As it is a fully featured programming environment, Scripted Pipeline offers a tremendous amount of flexibility and extensibility to Jenkins users. The Groovy learning-curve isn’t typically desirable for all members of a given team, so Declarative Pipeline was created to offer a simpler and more opinionated syntax for authoring Jenkins Pipeline.
Both are fundamentally the same Pipeline sub-system underneath. They are both durable implementations of "Pipeline as code." They are both able to use steps built into Pipeline or provided by plugins. Both are able to utilize Shared Libraries
Your example in scripted pipeline may look like this:
node {
stage('CI') {
doDynamicParallelSteps()
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
And declarative pipeline with script {}
block in steps would look like this:
pipeline{
agent any
stages{
stage('CI'){
steps{
script {
doDynamicParallelSteps()
}
}
}
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
For some reason this doesn't work for me. I've copied an even simpler version of that block into my pipeline file, and it still does not work and throws the same error as above when it gets to the point of executing theparallel tests
line. For some reason the line it's pointing to in the stacktrace is actually the stage declaration in the dynamic parallel steps function. The strangest part is that I created a separate sample pipeline in the same jenkins instance, and THAT worked. So I guess it's something to do with my specific pipeline file, but I have no idea how to even begin debugging.
– Clayton Keleher
Nov 12 at 23:28
So, a coworker of mine figured out the error, and it's really dumb... One of the arguments of the original function definition (not the same as the code snippet) was called "stage", and it was of type String. This was there so I could pass in context of what stage in the pipeline was calling the function. The problem was, this "stage" variable was overwriting the the stage() declaration in thenode{ stage("..."){ ... } }
block. This is also why we saw the error in the stack trace, with jenkins complaining that String has no method call(). Quite the humbling experience.
– Clayton Keleher
Nov 13 at 1:22
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
The declarative pipeline does not allow you to put Groovy code inside steps {}
block - it expects a valid Jenkins pipeline step in this place. This is why script {}
block got introduced that can be put inside the steps {}
block to execute some Groovy code.
If you need flexibility and non-opinionated syntax then you might use scripted pipeline instead. Here you can mix Groovy code with existing pipeline steps with almost no limitations.
Jenkins documentation explains shortly the difference between both approaches and why they exist:
When Jenkins Pipeline was first created, Groovy was selected as the foundation. Jenkins has long shipped with an embedded Groovy engine to provide advanced scripting capabilities for admins and users alike. Additionally, the implementors of Jenkins Pipeline found Groovy to be a solid foundation upon which to build what is now referred to as the "Scripted Pipeline" DSL. [2].
As it is a fully featured programming environment, Scripted Pipeline offers a tremendous amount of flexibility and extensibility to Jenkins users. The Groovy learning-curve isn’t typically desirable for all members of a given team, so Declarative Pipeline was created to offer a simpler and more opinionated syntax for authoring Jenkins Pipeline.
Both are fundamentally the same Pipeline sub-system underneath. They are both durable implementations of "Pipeline as code." They are both able to use steps built into Pipeline or provided by plugins. Both are able to utilize Shared Libraries
Your example in scripted pipeline may look like this:
node {
stage('CI') {
doDynamicParallelSteps()
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
And declarative pipeline with script {}
block in steps would look like this:
pipeline{
agent any
stages{
stage('CI'){
steps{
script {
doDynamicParallelSteps()
}
}
}
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
For some reason this doesn't work for me. I've copied an even simpler version of that block into my pipeline file, and it still does not work and throws the same error as above when it gets to the point of executing theparallel tests
line. For some reason the line it's pointing to in the stacktrace is actually the stage declaration in the dynamic parallel steps function. The strangest part is that I created a separate sample pipeline in the same jenkins instance, and THAT worked. So I guess it's something to do with my specific pipeline file, but I have no idea how to even begin debugging.
– Clayton Keleher
Nov 12 at 23:28
So, a coworker of mine figured out the error, and it's really dumb... One of the arguments of the original function definition (not the same as the code snippet) was called "stage", and it was of type String. This was there so I could pass in context of what stage in the pipeline was calling the function. The problem was, this "stage" variable was overwriting the the stage() declaration in thenode{ stage("..."){ ... } }
block. This is also why we saw the error in the stack trace, with jenkins complaining that String has no method call(). Quite the humbling experience.
– Clayton Keleher
Nov 13 at 1:22
add a comment |
up vote
1
down vote
The declarative pipeline does not allow you to put Groovy code inside steps {}
block - it expects a valid Jenkins pipeline step in this place. This is why script {}
block got introduced that can be put inside the steps {}
block to execute some Groovy code.
If you need flexibility and non-opinionated syntax then you might use scripted pipeline instead. Here you can mix Groovy code with existing pipeline steps with almost no limitations.
Jenkins documentation explains shortly the difference between both approaches and why they exist:
When Jenkins Pipeline was first created, Groovy was selected as the foundation. Jenkins has long shipped with an embedded Groovy engine to provide advanced scripting capabilities for admins and users alike. Additionally, the implementors of Jenkins Pipeline found Groovy to be a solid foundation upon which to build what is now referred to as the "Scripted Pipeline" DSL. [2].
As it is a fully featured programming environment, Scripted Pipeline offers a tremendous amount of flexibility and extensibility to Jenkins users. The Groovy learning-curve isn’t typically desirable for all members of a given team, so Declarative Pipeline was created to offer a simpler and more opinionated syntax for authoring Jenkins Pipeline.
Both are fundamentally the same Pipeline sub-system underneath. They are both durable implementations of "Pipeline as code." They are both able to use steps built into Pipeline or provided by plugins. Both are able to utilize Shared Libraries
Your example in scripted pipeline may look like this:
node {
stage('CI') {
doDynamicParallelSteps()
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
And declarative pipeline with script {}
block in steps would look like this:
pipeline{
agent any
stages{
stage('CI'){
steps{
script {
doDynamicParallelSteps()
}
}
}
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
For some reason this doesn't work for me. I've copied an even simpler version of that block into my pipeline file, and it still does not work and throws the same error as above when it gets to the point of executing theparallel tests
line. For some reason the line it's pointing to in the stacktrace is actually the stage declaration in the dynamic parallel steps function. The strangest part is that I created a separate sample pipeline in the same jenkins instance, and THAT worked. So I guess it's something to do with my specific pipeline file, but I have no idea how to even begin debugging.
– Clayton Keleher
Nov 12 at 23:28
So, a coworker of mine figured out the error, and it's really dumb... One of the arguments of the original function definition (not the same as the code snippet) was called "stage", and it was of type String. This was there so I could pass in context of what stage in the pipeline was calling the function. The problem was, this "stage" variable was overwriting the the stage() declaration in thenode{ stage("..."){ ... } }
block. This is also why we saw the error in the stack trace, with jenkins complaining that String has no method call(). Quite the humbling experience.
– Clayton Keleher
Nov 13 at 1:22
add a comment |
up vote
1
down vote
up vote
1
down vote
The declarative pipeline does not allow you to put Groovy code inside steps {}
block - it expects a valid Jenkins pipeline step in this place. This is why script {}
block got introduced that can be put inside the steps {}
block to execute some Groovy code.
If you need flexibility and non-opinionated syntax then you might use scripted pipeline instead. Here you can mix Groovy code with existing pipeline steps with almost no limitations.
Jenkins documentation explains shortly the difference between both approaches and why they exist:
When Jenkins Pipeline was first created, Groovy was selected as the foundation. Jenkins has long shipped with an embedded Groovy engine to provide advanced scripting capabilities for admins and users alike. Additionally, the implementors of Jenkins Pipeline found Groovy to be a solid foundation upon which to build what is now referred to as the "Scripted Pipeline" DSL. [2].
As it is a fully featured programming environment, Scripted Pipeline offers a tremendous amount of flexibility and extensibility to Jenkins users. The Groovy learning-curve isn’t typically desirable for all members of a given team, so Declarative Pipeline was created to offer a simpler and more opinionated syntax for authoring Jenkins Pipeline.
Both are fundamentally the same Pipeline sub-system underneath. They are both durable implementations of "Pipeline as code." They are both able to use steps built into Pipeline or provided by plugins. Both are able to utilize Shared Libraries
Your example in scripted pipeline may look like this:
node {
stage('CI') {
doDynamicParallelSteps()
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
And declarative pipeline with script {}
block in steps would look like this:
pipeline{
agent any
stages{
stage('CI'){
steps{
script {
doDynamicParallelSteps()
}
}
}
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
The declarative pipeline does not allow you to put Groovy code inside steps {}
block - it expects a valid Jenkins pipeline step in this place. This is why script {}
block got introduced that can be put inside the steps {}
block to execute some Groovy code.
If you need flexibility and non-opinionated syntax then you might use scripted pipeline instead. Here you can mix Groovy code with existing pipeline steps with almost no limitations.
Jenkins documentation explains shortly the difference between both approaches and why they exist:
When Jenkins Pipeline was first created, Groovy was selected as the foundation. Jenkins has long shipped with an embedded Groovy engine to provide advanced scripting capabilities for admins and users alike. Additionally, the implementors of Jenkins Pipeline found Groovy to be a solid foundation upon which to build what is now referred to as the "Scripted Pipeline" DSL. [2].
As it is a fully featured programming environment, Scripted Pipeline offers a tremendous amount of flexibility and extensibility to Jenkins users. The Groovy learning-curve isn’t typically desirable for all members of a given team, so Declarative Pipeline was created to offer a simpler and more opinionated syntax for authoring Jenkins Pipeline.
Both are fundamentally the same Pipeline sub-system underneath. They are both durable implementations of "Pipeline as code." They are both able to use steps built into Pipeline or provided by plugins. Both are able to utilize Shared Libraries
Your example in scripted pipeline may look like this:
node {
stage('CI') {
doDynamicParallelSteps()
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
And declarative pipeline with script {}
block in steps would look like this:
pipeline{
agent any
stages{
stage('CI'){
steps{
script {
doDynamicParallelSteps()
}
}
}
}
}
def doDynamicParallelSteps(){
tests = [:]
for (f in findFiles(glob: '**/html/*.html')) {
tests["${f}"] = {
node {
stage("${f}") {
echo '${f}'
}
}
}
}
parallel tests
}
answered Nov 10 at 8:45
Szymon Stepniak
16.1k83061
16.1k83061
For some reason this doesn't work for me. I've copied an even simpler version of that block into my pipeline file, and it still does not work and throws the same error as above when it gets to the point of executing theparallel tests
line. For some reason the line it's pointing to in the stacktrace is actually the stage declaration in the dynamic parallel steps function. The strangest part is that I created a separate sample pipeline in the same jenkins instance, and THAT worked. So I guess it's something to do with my specific pipeline file, but I have no idea how to even begin debugging.
– Clayton Keleher
Nov 12 at 23:28
So, a coworker of mine figured out the error, and it's really dumb... One of the arguments of the original function definition (not the same as the code snippet) was called "stage", and it was of type String. This was there so I could pass in context of what stage in the pipeline was calling the function. The problem was, this "stage" variable was overwriting the the stage() declaration in thenode{ stage("..."){ ... } }
block. This is also why we saw the error in the stack trace, with jenkins complaining that String has no method call(). Quite the humbling experience.
– Clayton Keleher
Nov 13 at 1:22
add a comment |
For some reason this doesn't work for me. I've copied an even simpler version of that block into my pipeline file, and it still does not work and throws the same error as above when it gets to the point of executing theparallel tests
line. For some reason the line it's pointing to in the stacktrace is actually the stage declaration in the dynamic parallel steps function. The strangest part is that I created a separate sample pipeline in the same jenkins instance, and THAT worked. So I guess it's something to do with my specific pipeline file, but I have no idea how to even begin debugging.
– Clayton Keleher
Nov 12 at 23:28
So, a coworker of mine figured out the error, and it's really dumb... One of the arguments of the original function definition (not the same as the code snippet) was called "stage", and it was of type String. This was there so I could pass in context of what stage in the pipeline was calling the function. The problem was, this "stage" variable was overwriting the the stage() declaration in thenode{ stage("..."){ ... } }
block. This is also why we saw the error in the stack trace, with jenkins complaining that String has no method call(). Quite the humbling experience.
– Clayton Keleher
Nov 13 at 1:22
For some reason this doesn't work for me. I've copied an even simpler version of that block into my pipeline file, and it still does not work and throws the same error as above when it gets to the point of executing the
parallel tests
line. For some reason the line it's pointing to in the stacktrace is actually the stage declaration in the dynamic parallel steps function. The strangest part is that I created a separate sample pipeline in the same jenkins instance, and THAT worked. So I guess it's something to do with my specific pipeline file, but I have no idea how to even begin debugging.– Clayton Keleher
Nov 12 at 23:28
For some reason this doesn't work for me. I've copied an even simpler version of that block into my pipeline file, and it still does not work and throws the same error as above when it gets to the point of executing the
parallel tests
line. For some reason the line it's pointing to in the stacktrace is actually the stage declaration in the dynamic parallel steps function. The strangest part is that I created a separate sample pipeline in the same jenkins instance, and THAT worked. So I guess it's something to do with my specific pipeline file, but I have no idea how to even begin debugging.– Clayton Keleher
Nov 12 at 23:28
So, a coworker of mine figured out the error, and it's really dumb... One of the arguments of the original function definition (not the same as the code snippet) was called "stage", and it was of type String. This was there so I could pass in context of what stage in the pipeline was calling the function. The problem was, this "stage" variable was overwriting the the stage() declaration in the
node{ stage("..."){ ... } }
block. This is also why we saw the error in the stack trace, with jenkins complaining that String has no method call(). Quite the humbling experience.– Clayton Keleher
Nov 13 at 1:22
So, a coworker of mine figured out the error, and it's really dumb... One of the arguments of the original function definition (not the same as the code snippet) was called "stage", and it was of type String. This was there so I could pass in context of what stage in the pipeline was calling the function. The problem was, this "stage" variable was overwriting the the stage() declaration in the
node{ stage("..."){ ... } }
block. This is also why we saw the error in the stack trace, with jenkins complaining that String has no method call(). Quite the humbling experience.– Clayton Keleher
Nov 13 at 1:22
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234490%2fdynamic-parallel-stages-in-jenkins-pipeline-outside-script-block%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What is in line 1383 of your script? The error seems to be caused there according to the error message
– Joerg S
Nov 11 at 7:22