Jenkins

30Jenkins

What you will master here

  • Jenkins architecture: controller + agents
  • Freestyle vs Pipeline (declarative + scripted)
  • Jenkinsfile syntax, stages, agents, environment
  • Credentials + secrets
  • Parallel + matrix builds
  • Shared libraries
  • Plugins (Allure, JUnit, JaCoCo, etc.)
  • Jenkins vs GitHub Actions vs GitLab CI

30.1 Architecture

30.2 Declarative Pipeline (modern default)

// Jenkinsfile
pipeline {
  agent any

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

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

  triggers {
    pollSCM('H/5 * * * *')   // poll git every 5 min
    cron('H 2 * * *')        // nightly
  }

  stages {
    stage('Checkout') {
      steps { checkout scm }
    }
    stage('Install') {
      steps { sh 'npm ci' }
    }
    stage('Lint') {
      steps { sh 'npm run lint' }
    }
    stage('Test') {
      parallel {
        stage('Unit') { steps { sh 'npm run test:unit' } }
        stage('E2E')  { steps { sh 'npx playwright test' } }
      }
    }
    stage('Deploy') {
      when { branch 'main' }
      steps { sh './deploy.sh' }
    }
  }

  post {
    always {
      junit 'test-results/junit.xml'
      archiveArtifacts artifacts: 'playwright-report/**', allowEmptyArchive: true
    }
    failure {
      mail to: 'team@acme.com', subject: "FAILED: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
           body: "See ${env.BUILD_URL}"
    }
  }
}

30.3 Scripted Pipeline (older Groovy DSL)

node('linux') {
  stage('checkout') { checkout scm }
  stage('install')  { sh 'npm ci' }
  stage('test') {
    try {
      sh 'npx playwright test'
    } finally {
      junit 'test-results/junit.xml'
    }
  }
}

30.4 Credentials & secrets

// Use a credential id stored in Jenkins
withCredentials([
  string(credentialsId: 'JIRA_TOKEN', variable: 'JIRA_TOKEN'),
  usernamePassword(credentialsId: 'docker-hub', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')
]) {
  sh 'docker login -u $DOCKER_USER -p $DOCKER_PASS'
}

30.5 Parallel + matrix

// Static parallel
stage('Test') {
  parallel {
    stage('chromium') { agent { label 'linux' }; steps { sh 'npx playwright test --project=chromium' } }
    stage('firefox')  { agent { label 'linux' }; steps { sh 'npx playwright test --project=firefox' } }
    stage('webkit')   { agent { label 'mac' };   steps { sh 'npx playwright test --project=webkit' } }
  }
}

// Matrix (axis cross-product)
matrix {
  axes {
    axis { name 'OS';      values 'linux','mac','windows' }
    axis { name 'BROWSER'; values 'chromium','firefox' }
  }
  stages {
    stage('test') {
      agent { label "${OS}" }
      steps { sh "npx playwright test --project=${BROWSER}" }
    }
  }
}

30.6 Shared libraries

// vars/runPlaywright.groovy
def call(Map config = [:]) {
  sh "npx playwright test --shard=${config.shard ?: '1/1'}"
  junit 'test-results/junit.xml'
}

// Jenkinsfile in any repo
@Library('test-pipeline-lib') _
pipeline {
  agent any
  stages {
    stage('test') {
      steps { runPlaywright(shard: '1/4') }
    }
  }
}

30.7 Common plugins for SDETs

PluginPurpose
JUnitTest result parsing + trend
AllureRich test reports
JaCoCoCode coverage
HTML PublisherPublish any HTML report (Playwright)
Slack NotificationPost build status
Pipeline Stage ViewVisual stage graph
Blue OceanModern pipeline UI
Configuration as Code (JCasC)Jenkins config from YAML

30.8 Jenkins vs GitHub Actions vs GitLab CI

AspectJenkinsGitHub ActionsGitLab CI
HostingSelf-host (usually)SaaS / self-hosted runnersSaaS / self-hosted runners
ConfigJenkinsfile (Groovy)YAML (.github/workflows/)YAML (.gitlab-ci.yml)
Plugin ecosystemHuge (legacy)Marketplace (growing)Built-in (rich)
Best forEnterprise on-prem, complex orchestrationGitHub-based teams, simple-mediumGitLab teams, full DevOps suite
Operational costYou operate itGitHub operates itGitLab operates it

Module 62 — Jenkins Q&A

What's a Jenkinsfile?
A Groovy DSL file describing the build pipeline as code. Lives in the repo (versioned with the code). Two flavours: declarative (recommended, more structured) and scripted (more powerful, less guarded).
How do you share pipeline code across repos?
Shared libraries — a Git repo with vars/ (global steps) and src/ (Groovy classes). Reference via @Library('name') _ at top of Jenkinsfile. Centralises pipeline patterns across teams.
How do you store secrets in Jenkins?
Credentials Manager — add secret text / username-password / SSH key. Reference in pipeline via withCredentials wrapper; injects as masked env vars. Never echo them.
How do you run a build on a specific agent?
agent { label 'linux-large' }. Labels group agents by capability/OS. agent any picks any available; agent { docker { image '...' } } spins up a container.
How do you parallelise tests?
A parallel block inside a stage runs nested stages concurrently. For shards, generate a map programmatically; for matrix runs, use the matrix directive.
What's the post block?
Runs after the main stages. Conditions: always, success, failure, unstable, changed. Use for publishing reports, sending notifications, cleanup.
How do you publish a Playwright HTML report?
HTML Publisher plugin: publishHTML([reportDir: 'playwright-report', reportFiles: 'index.html', reportName: 'Playwright Report']). Appears as a link on the build page.
Jenkins vs GitHub Actions for an SDET team?
Jenkins if you need full on-prem control, deep enterprise plugin needs, or complex orchestration across heterogeneous platforms. GitHub Actions for simpler/medium teams already on GitHub — less ops, faster setup. Many orgs run both.
What is JCasC?
Jenkins Configuration as Code — declare the controller's full configuration (users, plugins, credentials, agents, jobs) in YAML. Reproducible installs, version-controlled, easier disaster recovery than clicking through the UI.