Testland
Browse all skills & agents

jenkinsfile-test-stages

Configures Jenkins declarative pipeline test stages - `Jenkinsfile` with stages, parallel + per-agent execution, post-actions (always / failure / success), pipeline-junit-plugin for test reports, lockable resources for shared infra. Use for Jenkins-based CI (common in enterprise / regulated environments).

Install with skills.sh (any agent)

npx skills add testland/qa --skill jenkinsfile-test-stages
View source

jenkinsfile-test-stages

Overview

Jenkins Declarative Pipeline (introduced 2017) is the modern Jenkinsfile syntax - replaces older Scripted Pipeline for most use cases.

A Jenkinsfile defines:

  • Pipeline - top-level container.
  • Agent - where stages run (any agent / specific node / Docker container).
  • Stages - sequential or parallel phases.
  • Steps - commands within a stage.
  • Post - actions after stages (always / success / failure / unstable / changed).

When to use

  • Enterprise / regulated environments using Jenkins.
  • Existing Jenkins infrastructure; migration to GitHub Actions / GitLab CI prohibitive.
  • Self-hosted CI / specialized hardware needs (GPU, specialized drivers).

For new projects in 2026+: GitHub Actions / GitLab CI offer better managed-runner experiences. Jenkins shines in self-hosted

  • plugin-rich environments.

How to use

  1. Add a Jenkinsfile with a pipeline { agent ...; stages { ... } } block; choose agent any, a labelled node, or a Docker image for reproducibility (Steps 1-2).
  2. Define stage('Build') / stage('Test') steps that run your install + test commands via sh.
  3. Parallelize independent suites and fan across an OS × runtime matrix - references/parallel-and-matrix.md.
  4. Add a post {} block to publish JUnit XML, archive artifacts, and notify per outcome - references/post-actions.md.
  5. Inject environment {} + masked withCredentials, serialize shared infra with lock(...), and set triggers / options - references/environment-and-triggers.md.
  6. Reach for retry(2) only on genuinely non-deterministic steps; prefer quarantine.
  7. Review the anti-patterns table before committing.

Step 1 - Basic Jenkinsfile

// Jenkinsfile
pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'npm ci'
            }
        }
        stage('Test') {
            steps {
                sh 'npm test'
            }
        }
    }
}

agent any runs on any available executor; pin via agent { label 'linux' } or agent { docker { image 'node:22' } }.

Step 2 - Docker agent

pipeline {
    agent {
        docker {
            image 'node:22'
            args '-v /tmp:/tmp'
        }
    }

    stages {
        stage('Test') {
            steps {
                sh 'npm ci && npm test'
            }
        }
    }
}

Docker agents provide reproducibility - same Node version on every run.

Advanced pipeline patterns

Deeper stage recipes are split into reference files:

When to retry

stage('Test') {
    steps {
        retry(2) {
            sh 'npm test'
        }
    }
}

Use sparingly - retries hide flake. Prefer flaky-test-quarantine (in the qa-flake-triage plugin).

Worked example

A regulated team runs its suite on a self-hosted Jenkins with a shared integration database.

  1. The Jenkinsfile pins agent { docker { image 'node:22' } } so every run uses the same runtime.
  2. A Tests stage runs Unit and Integration in parallel; the E2E branch overrides its agent to a mcr.microsoft.com/playwright:v1.50.0-noble image.
  3. The Integration step wraps its work in lock(resource: 'shared-test-database') so only one build touches the DB at a time.
  4. withCredentials([...]) injects the registry token, masked in logs; environment { CI = 'true' } marks the run as CI.
  5. post { always { junit 'reports/junit/*.xml'; archiveArtifacts 'coverage/**' } } publishes results either way, and failure { slackSend(...) } pings #ci on a red build.
  6. options { timeout(time: 30, unit: 'MINUTES') } kills hung builds so they don't hold executors.

Result: reproducible runs, no DB contention across parallel builds, and test reports plus notifications on every outcome.

Anti-patterns

Anti-patternWhy it failsFix
Scripted pipeline for new codeDeclarative is the standard; better tooling support.Declarative Pipeline (Step 1).
Plaintext credentials in JenkinsfileSecret leak.withCredentials({...}) (environment-and-triggers).
No post { always {} } for artifact uploadFailure investigation incomplete.Always upload (post-actions).
Single-agent pipeline for parallel workNo parallelism; slow.Parallel stages (parallel-and-matrix).
Missing timeoutHung jobs consume executors indefinitely.options { timeout(...) } (environment-and-triggers).
Skipping agent { docker {...}}Inconsistent runtime per agent; hard to reproduce.Docker agents (Step 2).

Limitations

  • Plugin-heavy ecosystem. Updates can break things; pin versions.
  • Self-hosted infra cost. Manage Jenkins controller + agents.
  • Slower modernization. Jenkins evolves; modern features (matrix, declarative) require version bumps.
  • YAML / Groovy mix. Jenkinsfile is Groovy DSL; some teams prefer YAML.

References

Jenkins - environment, credentials, resource locks, and triggers

View source (opens in new window)

Jenkins - environment, credentials, resource locks, and triggers

Deeper recipes split out of jenkinsfile-test-stages SKILL.md: serializing shared infrastructure, injecting environment plus masked credentials, and scheduling / multi-branch behavior.

Lockable resources

pipeline {
    agent any

    stages {
        stage('Integration') {
            steps {
                lock(resource: 'shared-test-database') {
                    sh 'npm run test:integration'
                }
            }
        }
    }
}

lock(...) uses the Lockable Resources Plugin to serialize access to shared resources (test DB, license-locked tool, etc.).

Environment + credentials

pipeline {
    agent any

    environment {
        CI = 'true'
        NODE_ENV = 'test'
    }

    stages {
        stage('Test') {
            steps {
                withCredentials([string(credentialsId: 'npm-auth-token', variable: 'NODE_AUTH_TOKEN')]) {
                    sh 'npm ci && npm test'
                }
            }
        }
    }
}

withCredentials([...]) masks secrets in build logs.

Multi-branch + scheduled

pipeline {
    agent any

    triggers {
        cron('0 4 * * *')   // daily at 4 AM
        pollSCM('*/15 * * * *')   // poll every 15 min (or use webhook)
    }

    options {
        timeout(time: 30, unit: 'MINUTES')
        timestamps()
        ansiColor('xterm')
        buildDiscarder(logRotator(numToKeepStr: '20'))
    }

    stages { /* ... */ }
}

Per-branch behavior via Multibranch Pipeline job type (separate config in Jenkins UI).

Jenkins - parallel and matrix stages

View source (opens in new window)

Jenkins - parallel and matrix stages

Deeper recipes split out of jenkinsfile-test-stages SKILL.md: running stages concurrently, and fanning a stage across an OS × runtime matrix.

Parallel stages

pipeline {
    agent any

    stages {
        stage('Tests') {
            parallel {
                stage('Unit') {
                    steps { sh 'npm test' }
                }
                stage('Integration') {
                    steps { sh 'npm run test:integration' }
                }
                stage('E2E') {
                    agent {
                        docker { image 'mcr.microsoft.com/playwright:v1.50.0-noble' }
                    }
                    steps { sh 'npx playwright test' }
                }
            }
        }
    }
}

Parallel stages can have different agents - useful when E2E needs a Playwright-equipped image.

Matrix builds (Jenkins 2.302+)

pipeline {
    agent none

    stages {
        stage('Test matrix') {
            matrix {
                axes {
                    axis {
                        name 'OS'
                        values 'linux', 'macos', 'windows'
                    }
                    axis {
                        name 'NODE_VERSION'
                        values '20', '22'
                    }
                }
                stages {
                    stage('Test') {
                        agent { label "${OS}" }
                        steps {
                            sh 'npm ci && npm test'
                        }
                    }
                }
            }
        }
    }
}

Matrix runs all OS × Node combinations in parallel.

Jenkins - post actions

View source (opens in new window)

Jenkins - post actions

Deeper recipe split out of jenkinsfile-test-stages SKILL.md: the post {} block that runs after stages - JUnit publishing, artifact archiving, and outcome-specific notifications.

Post actions

pipeline {
    agent any

    stages {
        stage('Test') {
            steps {
                sh 'npm test'
            }
        }
    }

    post {
        always {
            // Always run - even on failure
            junit 'reports/junit/*.xml'
            archiveArtifacts artifacts: 'coverage/**', allowEmptyArchive: true
        }
        success {
            slackSend(channel: '#ci', message: "✅ Build ${env.BUILD_NUMBER} passed")
        }
        failure {
            slackSend(channel: '#ci', message: "❌ Build ${env.BUILD_NUMBER} failed: ${env.BUILD_URL}")
        }
        unstable {
            // E.g., tests passed but with warnings
            mail to: 'team@example.com', subject: "Build ${env.BUILD_NUMBER} unstable"
        }
    }
}

post { always {} } runs on any outcome - essential for artifact upload + notifications.

The junit '...' step (from JUnit Plugin) parses XML and renders results in Jenkins UI.

Related skills

ci-test-job-conventions

Pure-reference for cross-CI test workflow conventions - when to shard (and how many shards), retry policy (which failures are safe to retry), flake-quarantine integration, artifact retention, per-trigger cadence (per-PR vs per-merge vs nightly), concurrency-cancel patterns, per-job timeouts, secret management, and cross-CI portability. Use as the team's reference for CI test-workflow design across GitHub Actions / GitLab CI / Jenkins / CircleCI; per-CI reporting and per-language reporter / cache-key lookups live in references/.

circleci-test-configs

Configures CircleCI test workflows - `.circleci/config.yml` with workflows, jobs, executors, parallelism (test splitting), orbs (reusable shared config), insights for analytics, contexts for per-team secrets. Use for CircleCI-hosted CI when the team values its parallelism + insights features.

github-actions-test-jobs

Configures GitHub Actions test workflows - `.github/workflows/test.yml` with matrix builds (OS × runtime), JUnit XML artifact upload, retry/sharding, services (PostgreSQL, Redis), per-trigger filtering (pull_request, push, schedule, workflow_dispatch). Use when the project hosts on GitHub and the team wants idiomatic GitHub Actions patterns for test workflows.

gitlab-ci-test-jobs

Configures GitLab CI/CD test stages - `.gitlab-ci.yml` with parallel matrix, artifact reports (junit, coverage), services (postgres, redis), needs / dependencies between jobs, only/except + rules for trigger filtering, retry policy. Use when the project hosts on GitLab and the team wants idiomatic GitLab CI patterns.