Jenkins Pipeline Stages, Steps, and Agents

Stages, steps, and agents are the three structural pillars of every Jenkins Pipeline. Understanding each one clearly helps you design pipelines that are organized, efficient, and easy to troubleshoot.

Stages: The Phases of Your Pipeline

A stage represents a logical phase of the pipeline — a distinct chunk of work with a clear purpose. Stages appear as visual boxes in the Jenkins Stage View, making it immediately obvious which phase passed, which failed, and how long each took.

Why Stages Matter

Pipeline without stages (all commands in one block):

  Build → ???  (Hard to know where failure occurred)

Pipeline with stages (clear phases):

  Checkout → Build → Unit Tests → Code Scan → Package → Deploy

  Console shows:
  [Checkout]    ✓ 12s
  [Build]       ✓ 45s
  [Unit Tests]  ✗ 3m 12s  ← FAILED HERE
  [Code Scan]   — (skipped)
  [Package]     — (skipped)
  [Deploy]      — (skipped)

With stages, you immediately know the test phase failed after 3 minutes. Without stages, you have to read through all the console output to find the error.

Stage Best Practices

Good stage naming:
  stage('Build')              ← Clear, short
  stage('Unit Tests')         ← Specific
  stage('Deploy to Staging')  ← Destination is clear
  stage('Smoke Tests')        ← Test type is clear

Bad stage naming:
  stage('Do Stuff')           ← Vague
  stage('Step 3')             ← No meaning
  stage('Build and Test and Deploy and Send Email')  ← Too many things

Steps: The Individual Commands

A step is one action inside a stage. A stage typically contains multiple steps that run in sequence. Steps are the actual work — running commands, checking out code, archiving files.

Step Types Reference

StepExampleWhat It Does
shsh 'npm install'Run a shell command on Linux/Mac
batbat 'npm install'Run a Windows batch command
echoecho 'Starting build'Print to the console log
gitgit url: '...', branch: 'main'Checkout a Git repository
checkout scmcheckout scmCheckout using the job's SCM configuration
archiveArtifactsarchiveArtifacts 'target/*.jar'Save files as downloadable artifacts
junitjunit 'reports/*.xml'Publish test results to Jenkins
timeouttimeout(time:5, unit:'MINUTES')Fail if a step takes too long
retryretry(3) { sh 'flaky-test.sh' }Retry a step up to N times on failure
inputinput 'Deploy to production?'Pause and wait for human approval
sleepsleep 60Wait for N seconds
withEnvwithEnv(['VAR=value']) { sh '...' }Set env variables for wrapped steps
withCredentialswithCredentials([...]) { sh '...' }Inject secrets for wrapped steps
stashstash name: 'built-app', includes: 'target/**'Save files to pass between stages/nodes
unstashunstash 'built-app'Retrieve stashed files

Stash and Unstash: Sharing Files Between Stages

When stages run on different agents, files do not automatically carry over. Use stash to save files after one stage and unstash to retrieve them in another.

Diagram: Stash and Unstash

Stage: Build (runs on agent-1)
  sh 'mvn package'
  stash name: 'jar-file', includes: 'target/*.jar'
        |
        | (file saved in Jenkins controller)
        ↓
Stage: Deploy (runs on agent-2)
  unstash 'jar-file'
  sh 'deploy.sh target/*.jar'

Agents: Where Stages Run

An agent is the machine (or container) that executes a stage. You define agents at the pipeline level (applies to all stages) or at the stage level (overrides for that stage only).

Pipeline-Level Agent

pipeline {
    agent any   // All stages run on any available node
    ...
}

pipeline {
    agent { label 'linux-large' }  // All stages run on a "linux-large" labeled node
    ...
}

pipeline {
    agent none   // No default — every stage must specify its own agent
    ...
}

Stage-Level Agent

Override the agent for specific stages. This is useful when different stages need different environments — for example, build on a Linux server and deploy from a Windows server.

pipeline {
    agent none

    stages {
        stage('Build') {
            agent { label 'linux-maven' }
            steps {
                sh 'mvn clean package'
                stash name: 'app-jar', includes: 'target/*.jar'
            }
        }

        stage('Test on Windows') {
            agent { label 'windows-test' }
            steps {
                unstash 'app-jar'
                bat 'run-tests.bat'
            }
        }

        stage('Deploy') {
            agent { label 'deploy-server' }
            steps {
                unstash 'app-jar'
                sh 'deploy.sh'
            }
        }
    }
}

Docker as Agent

Run a stage inside a Docker container. The container starts, runs the steps, and is destroyed afterward. No setup required on the host machine for language runtimes.

stage('Build with Maven 3.9') {
    agent {
        docker {
            image 'maven:3.9-eclipse-temurin-17'
            args '-v /root/.m2:/root/.m2'   // Mount Maven cache
        }
    }
    steps {
        sh 'mvn clean package'
    }
}

stage('Build with Node 20') {
    agent {
        docker { image 'node:20-alpine' }
    }
    steps {
        sh 'npm ci && npm run build'
    }
}
Diagram: Different Docker containers per stage

  Stage 1: Build Java
    [ maven:3.9 container ]
    → mvn clean package
    → Container destroyed

  Stage 2: Build Frontend
    [ node:20 container ]
    → npm run build
    → Container destroyed

  Stage 3: Security Scan
    [ owasp/dependency-check container ]
    → dependency-check.sh
    → Container destroyed

Each stage gets a fresh, clean environment.

The Manual Approval Step

The input step pauses the pipeline and waits for a human to click Proceed or Abort. Use this before deploying to production environments.

stage('Deploy to Production') {
    steps {
        input message: 'Deploy version 2.14 to production?',
              ok: 'Yes, deploy now',
              submitter: 'deploy-approvers'

        // Only runs if the approver clicked "Yes, deploy now"
        sh 'kubectl apply -f k8s/production/'
    }
}

The submitter field restricts who can approve the deployment. Only users in the deploy-approvers group or user list can click Proceed.

Key Points

  • Stages group related steps into named phases — they appear as visual boxes in Jenkins Stage View.
  • Steps are individual commands: shell scripts, git checkout, archive files, publish tests, and more.
  • Use stash and unstash to pass files between stages running on different agents.
  • Agents define where stages run — any node, a labeled node, or a Docker container.
  • The input step pauses the pipeline for human approval before proceeding to critical stages like production deployment.

Leave a Comment