Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jenkins Pipeline sleep(10) prevents function from being completed

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?

like image 666
Seitan Avatar asked Jul 06 '18 17:07

Seitan


2 Answers

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.

like image 125
Szymon Stepniak Avatar answered Oct 24 '22 21:10

Szymon Stepniak


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.

like image 1
Noam Helmer Avatar answered Oct 24 '22 22:10

Noam Helmer