I have found a strange issue with Groovy code in Jenkinsfile:
@NonCPS
def test() {
println "Start"
sleep(10)
println "Stop"
}
Thing is, that after sleeping for 10s code never gets to println "Stop"
.
It just seems, that sleep returns after 10 seconds and runs next pipeline steps.
Output is just:
[Pipieline] echo
Start
[Pipeline] sleep
Sleeping for 10 sec
[Pipeline] }
... next pipeline steps
Did anyone had same problem?
When you call sleep(10)
inside your Groovy script, Workflow CPS plugin executes SleepStep
instead of DefaultGroovyStaticMethods.sleep(Object self, long time)
. The problem in your case is caused @NonCPS
function (thanks mkobit for a suggestion!). Consider following example:
node {
stage("Test") {
test()
}
}
@NonCPS
def test() {
echo "Start"
sleep(5)
echo "Stop"
}
Output:
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/test-pipeline
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] echo
Start
[Pipeline] sleep
Sleeping for 5 sec
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
There is no Stop
echoed from the pipeline run. Now, if we only remove @NonCPS
annotation from the function we call in the pipeline:
node {
stage("Test") {
test()
}
}
def test() {
echo "Start"
sleep(5)
echo "Stop"
}
Things get change and Stop
gets echoed as expected:
Started by user admin
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/test-pipeline
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] echo
Start
[Pipeline] sleep
Sleeping for 5 sec
[Pipeline] echo
Stop
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
For more information about usage of @NonCPS
please read following Best Practices For Pipeline Code article.
This issue is well documented in https://wiki.jenkins.io/display/JENKINS/Pipeline+CPS+method+mismatches
Use of Pipeline steps from @NonCPS
Sometimes users will apply the @NonCPS annotation to a method definition, which bypasses the CPS transform inside that method. This can be done to work around limitations in Groovy language coverage (since the body of the method will execute using the native Groovy semantics), or to get better performance (the interpreter imposes a substantial overhead). However such methods must not call CPS-transformed code such as Pipeline steps.
As suggested by Szymon removing the @NonCPS tag will indeed solve the issue, however if you can't remove the @NonCPS tag because it is needed (to solve serialization issues for example) you can overcome this by using the Thread.sleep(long millis) Java method instead.
Notice - an administrator will need to approve this signature if running in sandbox.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With