Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-54278

Pipeline builds fail when cleanWs() in post stage

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open (View Workflow)
    • Priority: Blocker
    • Resolution: Unresolved
    • Component/s: ws-cleanup-plugin
    • Labels:
      None
    • Environment:
      Plugin version 0.36
    • Similar Issues:

      Description

      Pipeline builds fail when cleanWs() in post stage.  Reverting to 0.35 works.

      Error reported:

      Required context class hudson.FilePath is missing
      Perhaps you forgot to surround the code with a step that provides this, such as: node
      Error when executing cleanup post condition:
      java.lang.IllegalArgumentException: Failed to prepare cleanWs step
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeDescribable(DSL.java:401)
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:181)
      	at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
      	at sun.reflect.GeneratedMethodAccessor672.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
      	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
      	at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
      	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
      	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:157)
      	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23)
      	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:155)
      	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:155)
      	at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
      	at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:129)
      	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
      	at WorkflowScript.run(WorkflowScript:226)
      	at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.delegateAndExecute(jar:file:/data/jenkins/plugins/pipeline-model-definition/WEB-INF/lib/pipeline-model-definition.jar!/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy:133)
      	at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.runPostConditions(jar:file:/data/jenkins/plugins/pipeline-model-definition/WEB-INF/lib/pipeline-model-definition.jar!/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy:757)
      	at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.catchRequiredContextForNode(jar:file:/data/jenkins/plugins/pipeline-model-definition/WEB-INF/lib/pipeline-model-definition.jar!/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy:402)
      	at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.catchRequiredContextForNode(jar:file:/data/jenkins/plugins/pipeline-model-definition/WEB-INF/lib/pipeline-model-definition.jar!/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy:400)
      	at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.runPostConditions(jar:file:/data/jenkins/plugins/pipeline-model-definition/WEB-INF/lib/pipeline-model-definition.jar!/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy:756)
      	at com.cloudbees.groovy.cps.CpsDefaultGroovyMethods.each(CpsDefaultGroovyMethods:2030)
      	at com.cloudbees.groovy.cps.CpsDefaultGroovyMethods.each(CpsDefaultGroovyMethods:2015)
      	at com.cloudbees.groovy.cps.CpsDefaultGroovyMethods.each(CpsDefaultGroovyMethods:2056)
      	at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.runPostConditions(jar:file:/data/jenkins/plugins/pipeline-model-definition/WEB-INF/lib/pipeline-model-definition.jar!/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy:751)
      	at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.executePostBuild(jar:file:/data/jenkins/plugins/pipeline-model-definition/WEB-INF/lib/pipeline-model-definition.jar!/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy:728)
      	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.fixName(FunctionCallBlock.java:77)
      	at sun.reflect.GeneratedMethodAccessor319.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.ConstantBlock.eval(ConstantBlock.java:21)
      	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:129)
      	at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:268)
      	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)
      Caused by: org.codehaus.groovy.runtime.InvokerInvocationException: org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Required context class hudson.FilePath is missing
      	at org.jenkinsci.plugins.workflow.cps.CpsStepContext.replay(CpsStepContext.java:499)
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:299)
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:209)
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeDescribable(DSL.java:399)
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:181)
      	at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
      	at sun.reflect.GeneratedMethodAccessor672.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
      	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
      	at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
      	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
      	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:157)
      	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23)
      	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:155)
      	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:155)
      	at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
      	at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:129)
      	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
      	... 33 more
      Caused by: org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Required context class hudson.FilePath is missing
      	at org.jenkinsci.plugins.workflow.steps.StepDescriptor.checkContextAvailability(StepDescriptor.java:260)
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:262)
      	... 54 more 

       

      Sample pipeline:

      pipeline {
        agent any
        stages {
          stage('Test') {
            steps {
              echo 'test'
            }
          }
        }
        post {
          always {
            cleanWs()
          }
        }
      }

       

       

        Attachments

          Activity

          Hide
          medianick Nick Jones added a comment -

          Same issue here, under Jenkins 2.190.3 LTS and Workspace Cleanup 0.37, on a Windows Server agent. These are the first builds of a multibranch pipeline on this particular Jenkins instance, filtered to build only a specific PR, and that same PR (thus with the same Jenkinsfile) has been building successfully on a separate Jenkins instance running all the same versions of plugins, etc. A workspace is actually being allocated on the expected node, but cleanWS() still throws this no matter how many times I restart the job.

          Show
          medianick Nick Jones added a comment - Same issue here, under Jenkins 2.190.3 LTS and Workspace Cleanup 0.37, on a Windows Server agent. These are the first builds of a multibranch pipeline on this particular Jenkins instance, filtered to build only a specific PR, and that same PR (thus with the same Jenkinsfile) has been building successfully on a separate Jenkins instance running all the same versions of plugins, etc. A workspace is actually being allocated on the expected node, but cleanWS() still throws this no matter how many times I restart the job.
          Hide
          medianick Nick Jones added a comment -

          Aha – in my case the answer was that an error was being thrown by the build before it got into the pipeline stages, specifically by a credentials('SOME_ID') command being used in a root-level environment block, for a credential ID that didn't exist. This failed the build immediately, but because cleanWS() was in an always block, it tried to execute it, and the agent node hadn't actually been (fully?) allocated yet, hence this error. The error obscured the true root cause, and arguably cleanWs() could have been more tolerant of these conditions rather than throwing, but at least I have an explanation now.

          Show
          medianick Nick Jones added a comment - Aha – in my case the answer was that an error was being thrown by the build before it got into the pipeline stages, specifically by a credentials('SOME_ID') command being used in a root-level environment block, for a credential ID that didn't exist. This failed the build immediately, but because cleanWS() was in an always block, it tried to execute it, and the agent node hadn't actually been (fully?) allocated yet, hence this error. The error obscured the true root cause, and arguably cleanWs() could have been more tolerant of these conditions rather than throwing, but at least I have an explanation now.
          Hide
          olivergondza Oliver Gondža added a comment -

          Thanks for the report. The hypothesis of "failing in case the workspace have not been allocated yet as the build has failed before it did" sounds quite plausible. Are the any cases that cannot be explained by this?

          Show
          olivergondza Oliver Gondža added a comment - Thanks for the report. The hypothesis of "failing in case the workspace have not been allocated yet as the build has failed before it did" sounds quite plausible. Are the any cases that cannot be explained by this?
          Hide
          medianick Nick Jones added a comment -

          Simple repro:

          pipeline {
            agent none
            options {
              skipDefaultCheckout(true)
            }
            stages {
              stage('Prepare') {
                steps {
                  echo 'Preparing...'
                }
              }
            }
            post {
              always {
                cleanWs deleteDirs: true
              }
            }
          }
          

          This was deliberately designed without a pipeline-level agent – it is the skeleton of an implementation I'm working on that will have stage-level agents instead – and the cleanWs failed. It seems this should be more defensively coded so that cleanWs can cleanly exit (at most with a warning) if there simply isn't a workspace to be cleaned. I'll probably end up putting cleanWs in the post blocks for stages that do use agents (which would be a better place for that command anyway), but again, I'd still expect the above to be a no-op (with possibly a warning) rather than throwing an uncaught exception.

          Show
          medianick Nick Jones added a comment - Simple repro: pipeline { agent none options { skipDefaultCheckout( true ) } stages { stage( 'Prepare' ) { steps { echo 'Preparing...' } } } post { always { cleanWs deleteDirs: true } } } This was deliberately designed without a pipeline-level agent – it is the skeleton of an implementation I'm working on that will have stage-level agents instead – and the cleanWs failed. It seems this should be more defensively coded so that cleanWs can cleanly exit (at most with a warning) if there simply isn't a workspace to be cleaned. I'll probably end up putting cleanWs in the post blocks for stages that do use agents (which would be a better place for that command anyway), but again, I'd still expect the above to be a no-op (with possibly a warning) rather than throwing an uncaught exception.
          Hide
          aos Aos Dabbagh added a comment - - edited

          For those of you who are stuck on this: only works if there is an agent available. If you have stage level agents, you then need to add the:

          post {
            always {
              cleanWs()
            }
          }
          

          under that specific stage. A simple example:

           

          pipeline {
            agent none
          
            options {
              timestamps()
            }
          
            stages {
              stage('Main') {
                parallel {
                  stage('Build & Test') {
                    agent {
                      label 'master'
                    }
                    stages {
                      stage('Prepare') {
                        steps {
                          echo 'Prepare...'
                        }
                      }
                    }
          
                    post {
                      always {
                        cleanWs()
                      }
                    }
                  }
          
                  stage('Debian package') {
                    agent {
                      label 'debian'
                    }
                    stages {
                      stage('Build package') {
                        steps {
                          echo 'Building package...'
                        }
                      }
                    }
          
                    post {
                      always {
                        cleanWs()
                      }
                    }
                }
              }
            }
          
          Show
          aos Aos Dabbagh added a comment - - edited For those of you who are stuck on this: only works if there is an agent available. If you have stage level agents, you then need to add the: post { always { cleanWs() } } under that specific stage. A simple example:   pipeline { agent none options { timestamps() } stages { stage( 'Main' ) { parallel { stage( 'Build & Test' ) { agent { label 'master' } stages { stage( 'Prepare' ) { steps { echo 'Prepare...' } } } post { always { cleanWs() } } } stage( 'Debian package ' ) { agent { label 'debian' } stages { stage( 'Build package ' ) { steps { echo 'Building package ...' } } } post { always { cleanWs() } } } } }

            People

            Assignee:
            olivergondza Oliver Gondža
            Reporter:
            therealwaldo Will Freeman
            Votes:
            6 Vote for this issue
            Watchers:
            15 Start watching this issue

              Dates

              Created:
              Updated: