Restoring files

3 minute read

Restarted Pipelines retain the program state, such as the values of variables, from each run, but they do not retain the contents of workspaces on your agents. Subsequent runs of the same Pipeline will overwrite any files used in a particular run.

Always keep the checkpoint step outside of any node block. It should not be associated with either an agent or a workspace. Refer to the example to see a checkpoint correctly placed outside any node block.

Prior to the checkpoint, use the stash step to save important files, such as build products. When this build is restarted from the checkpoint, all of its stashes will be copied into the new build first. You can then use the unstash step to restore some or all of the saved files into your new workspace.

When you use the checkpoint step with the stash and unstash steps, the files that are stashed are not removed when the build is complete. They are saved on disk in the $JENKINS_HOME/jobs/MY_JOB/builds/MY_BUILD/stashes directory. These stashed files can consume excessive disk space over time. CloudBees recommends that you periodically discard the builds to free up disk space.

The workspace used for a specific run of a Pipeline is not guaranteed to be used again after restarting from a checkpoint. If your post-checkpoint steps rely on local files in a workspace, not just the command you run, you will need to consider how to get those files back to their original condition before the checkpoint.

Declarative Pipeline syntax allows an agent at the top-level, giving all stages of the Pipeline access to the same workspace and files. A top level agent prevents you from running steps of your Pipeline without an agent context and its associated workspace.

Set the agent directive for each stage so that checkpoint can be used between stages. The checkpoint may also be isolated in its own stage with no agent or it is possible to use the node step directly in the steps of the stage.

Example using checkpoint in its own stage

pipeline {
  agent none
  stages {
    stage("Build") {
      agent any
      steps {
        echo "Building"
        stash includes: 'path/to/things/*', name: 'my-files'
      }
    }
    stage("Checkpoint") {
      agent none
      steps {
        checkpoint 'Completed Build'
      }
    }
    stage("Deploy") {
      agent any
      steps {
        unstash 'my-files'
        sh 'deploy.sh'
      }
    }
  }
}

Alternative example using node within a stage

pipeline {
  agent none

  stages{
    stage("Build"){
      steps{
        node('') { // this is equivalent to 'agent any'
          echo "Building"
          stash includes: 'path/to/things/*', name: 'my-files'
        }
        checkpoint "Build Done"
      }
    }
    stage("Deploy") {
      agent any
      steps {
        unstash 'my-files'
        sh 'deploy.sh'
      }
    }
  }
}

This Jenkinsfile gives a more complex example of this technique in Scripted Pipeline syntax.

Alternately, you could use other techniques to recover the original files. For example, if prior to the checkpoint you uploaded an artifact to a repository manager, and received an identifier or permalink of some kind which you saved in a local variable, after the checkpoint you can retrieve it using the same identifier.

Jenkins will not prevent you from restoring a checkpoint inside a node block (currently only a warning is issued), but this is unlikely to be useful because you cannot rely on the workspace being identical after the restart. You will still need to use one of the above methods to restore the original files. Also note that Jenkins will attempt to grab the same agent and workspace as the original build used, which could fail in the case of transient "cloud" agents. By contrast, when the checkpoint is outside node, the post-restart node can specify a label which can match any available agent.