Certified Jenkins Engineer

Pipeline Enhancement and Caching

Demo Stash and Unstash

In this guide, we’ll dive into how to leverage the stash and unstash steps to share files between stages. By stashing build artifacts or dependencies once, you can retrieve them later—on any agent or node—without rerunning expensive installation steps.

The image shows a webpage from the Jenkins documentation, specifically detailing the "stash" feature used to save files for later use in a build. The page includes a sidebar with links to various sections of the User Handbook and other resources.

Why Use stash and unstash?

  • Performance: Avoid duplicate work, such as reinstalling dependencies in each stage.
  • Consistency: Ensure the same set of files is used across multiple agents.
  • Resilience: Reduce errors from partial or conflicting installs.

Warning

By default, stashes are discarded when the pipeline finishes. To retain stashes across pipeline restarts, enable preserveStashes() in a Declarative Pipeline or use plugins that persist stash data.


Common Error: Reinstalling Node Modules

Rerunning npm install in every stage can trigger errors like this:

npm install --no-audit --cache .
npm ERR! code ENOTEMPTY
npm ERR! syscall rename
npm ERR! path /var/lib/jenkins/workspace/my-project/node_modules/chai
npm ERR! dest /var/lib/jenkins/workspace/my-project/node_modules/.chai-XYZ
npm ERR! errno -39
npm ERR! ENOTEMPTY: directory not empty, rename '/var/lib/jenkins/workspace/my-project/node_modules/chai' -> '/var/lib/jenkins/workspace/my-project/node_modules/.chai-XYZ'

Instead, stash the node_modules/ folder once and then unstash it in all subsequent stages.


Stash vs. Unstash: At a Glance

StepActionExample
stashSave files for later usestash includes: 'node_modules/', name: 'npm-deps'
unstashRetrieve previously stashed filesunstash 'npm-deps'

Generating the stash Snippet

Use the Pipeline Syntax (Snippet Generator) in Jenkins to build your stash step interactively.

The image shows a Jenkins interface with a "Snippet Generator" for creating pipeline scripts. It includes fields for configuring a stash step, with options for naming and excluding files.

Example output:

stash includes: 'node_modules/', name: 'solar-system-node-modules'

Declarative Pipeline Example

Below is a sample Declarative Jenkinsfile that:

  1. Installs Node.js dependencies
  2. Stashes them
  3. Restores them in later stages
pipeline {
  agent any

  options {
    preserveStashes()   // Keep stashes if the build is restarted
  }

  environment {
    MONGO_DB_CREDS     = credentials('mongo-db-credentials')
    SONAR_SCANNER_HOME = tool('sonarqube-scanner-610')
    GITEA_TOKEN        = credentials('gitea-api-token')
  }

  stages {
    stage('Install Dependencies') {
      options { retry(2); timestamps() }
      steps {
        sh 'node -v'
        sh 'npm install --no-audit'
        stash includes: 'node_modules/', name: 'solar-system-node-modules'
      }
    }

    stage('Dependency Scanning') {
      steps {
        unstash 'solar-system-node-modules'
        // e.g., run vulnerability scanner
      }
    }

    stage('Unit Testing') {
      steps {
        unstash 'solar-system-node-modules'
        sh 'npm test'
      }
    }

    // Additional stages…
  }
}

After pushing this Jenkinsfile, check the build logs:

[2024-11-10T11:12:47.1212] Stashed 4898 file(s)

The image shows a Jenkins pipeline interface for a project named "solar-system," detailing stages like installing dependencies, unit testing, and building a Docker image. It includes a timeline with checkmarks indicating completed steps and a section listing specific tasks with their durations.

As demonstrated, stashing node_modules once and unstashing it in multiple stages—possibly on different agents—saves time, reduces redundant work, and prevents errors from repeated installs.


Watch Video

Watch video content

Previous
Demo Sequential stages