跳转至

第四章:Pipeline 进阶

when 条件

when 指令允许根据条件执行 stage。

基本条件

pipeline {
    agent any

    stages {
        stage('Deploy to Production') {
            when {
                branch 'main'
            }
            steps {
                echo 'Deploying to production...'
            }
        }

        stage('Deploy to Staging') {
            when {
                branch 'develop'
            }
            steps {
                echo 'Deploying to staging...'
            }
        }

        stage('Deploy Feature') {
            when {
                branch pattern: 'feature/*', comparator: 'GLOB'
            }
            steps {
                echo 'Deploying feature branch...'
            }
        }
    }
}

条件类型

// 分支条件
when { branch 'main' }
when { branch pattern: 'release/*', comparator: 'GLOB' }

// 环境变量条件
when { environment name: 'DEPLOY_TO', value: 'production' }

// 表达式条件
when {
    expression {
        return params.DEPLOY == true
    }
}

// 文件存在条件
when { changeset '**/*.js' }

// 文件变化条件
when { changeset '**/*.{js,ts}' }

// 构建原因
when { buildingTag() }
when { tag 'v*' }

// 触发原因
when { triggeredBy 'SCMTrigger' }
when { triggeredBy 'TimerTrigger' }

组合条件

stage('Deploy') {
    when {
        allOf {
            branch 'main'
            environment name: 'DEPLOY_ENABLED', value: 'true'
        }
    }
    steps {
        echo 'Deploying...'
    }
}

stage('Test') {
    when {
        anyOf {
            branch 'main'
            branch 'develop'
        }
    }
    steps {
        echo 'Running tests...'
    }
}

stage('Skip') {
    when {
        not {
            branch 'main'
        }
    }
    steps {
        echo 'Skipping for non-main branch'
    }
}

beforeAgent

在分配 agent 之前评估条件:

stage('Deploy') {
    when {
        beforeAgent true
        branch 'main'
    }
    agent {
        docker { image 'alpine:latest' }
    }
    steps {
        echo 'Deploying...'
    }
}

并行执行

parallel 阶段

pipeline {
    agent any

    stages {
        stage('Parallel Tests') {
            parallel {
                stage('Unit Tests') {
                    steps {
                        sh 'npm run test:unit'
                    }
                }

                stage('Integration Tests') {
                    steps {
                        sh 'npm run test:integration'
                    }
                }

                stage('E2E Tests') {
                    steps {
                        sh 'npm run test:e2e'
                    }
                }
            }
        }

        stage('Deploy') {
            steps {
                echo 'Deploying...'
            }
        }
    }
}

带 Agent 的并行

pipeline {
    agent none

    stages {
        stage('Build') {
            agent { label 'linux' }
            steps {
                sh 'make build'
            }
        }

        stage('Test') {
            parallel {
                stage('Linux') {
                    agent { label 'linux' }
                    steps {
                        sh 'make test'
                    }
                }

                stage('Windows') {
                    agent { label 'windows' }
                    steps {
                        bat 'make test'
                    }
                }

                stage('macOS') {
                    agent { label 'macos' }
                    steps {
                        sh 'make test'
                    }
                }
            }
        }
    }
}

failFast

任一并行分支失败时终止其他分支:

stage('Test') {
    parallel {
        stage('Unit Tests') {
            steps {
                sh 'npm run test:unit'
            }
        }

        stage('Integration Tests') {
            steps {
                sh 'npm run test:integration'
            }
        }
    }
    // 任一失败,立即终止
    failFast true
}

// 或在 options 中全局设置
pipeline {
    agent any

    options {
        parallelsAlwaysFailFast()
    }

    stages {
        // ...
    }
}

矩阵构建

Matrix 允许使用变量组合执行多次 stage。

pipeline {
    agent any

    matrix {
        axes {
            axis {
                name 'PLATFORM'
                values 'linux', 'windows', 'macos'
            }
            axis {
                name 'BROWSER'
                values 'chrome', 'firefox', 'safari'
            }
            axis {
                name 'NODE_VERSION'
                values '16', '18', '20'
            }
        }

        excludes {
            // macOS 不支持 Safari 以外的浏览器
            exclude {
                axis {
                    name 'PLATFORM'
                    values 'macos'
                }
                axis {
                    name 'BROWSER'
                    values 'chrome', 'firefox'
                }
            }
        }

        agent {
            label "${PLATFORM}"
        }

        stages {
            stage('Build') {
                steps {
                    echo "Building on ${PLATFORM} with Node ${NODE_VERSION}"
                    sh 'npm install'
                    sh 'npm run build'
                }
            }

            stage('Test') {
                steps {
                    echo "Testing on ${PLATFORM} with ${BROWSER}"
                    sh "npm run test -- --browser=${BROWSER}"
                }
            }
        }
    }
}

input 步骤

在 Pipeline 中暂停等待人工确认。

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'npm run build'
            }
        }

        stage('Deploy to Production') {
            input {
                message "Deploy to production?"
                ok "Deploy"
                submitter "admin,devops"
                submitterParameter "APPROVER"
                parameters {
                    string(name: 'RELEASE_NOTES', description: 'Release notes')
                    booleanParam(name: 'FORCE_DEPLOY', defaultValue: false, description: 'Force deploy?')
                }
            }
            steps {
                echo "Approved by: ${APPROVER}"
                echo "Release notes: ${RELEASE_NOTES}"
                sh 'npm run deploy:prod'
            }
        }
    }
}

input 在 stage 级别

stage('Deploy') {
    input {
        message "Select environment"
        parameters {
            choice(name: 'ENV', choices: ['staging', 'production'], description: 'Target environment')
        }
    }
    steps {
        echo "Deploying to ${ENV}"
    }
}

options 指令

超时控制

pipeline {
    agent any

    options {
        timeout(time: 1, unit: 'HOURS')
    }

    stages {
        stage('Build') {
            options {
                timeout(time: 30, unit: 'MINUTES')
            }
            steps {
                sh 'npm run build'
            }
        }
    }
}

重试

pipeline {
    agent any

    options {
        retry(3)
    }

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

跳过默认 checkout

pipeline {
    agent any

    options {
        skipDefaultCheckout true
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
    }
}

构建丢弃策略

pipeline {
    agent any

    options {
        buildDiscarder(logRotator(
            numToKeepStr: '10',
            artifactNumToKeepStr: '5'
        ))
    }

    stages {
        // ...
    }
}

禁止并发构建

pipeline {
    agent any

    options {
        disableConcurrentBuilds()
        // 或中止较早的构建
        disableConcurrentBuilds(abortPrevious: true)
    }

    stages {
        // ...
    }
}

时间戳

pipeline {
    agent any

    options {
        timestamps()
    }

    stages {
        stage('Build') {
            steps {
                echo 'Building...'  // 输出带时间戳
            }
        }
    }
}

安静期

pipeline {
    agent any

    options {
        quietPeriod(10)  // 10 秒安静期
    }

    stages {
        // ...
    }
}

tools 指令

自动安装和配置工具:

pipeline {
    agent any

    tools {
        maven 'Maven-3.9'
        jdk 'JDK-17'
        nodejs 'NodeJS-18'
        gradle 'Gradle-8'
    }

    stages {
        stage('Build') {
            steps {
                sh 'mvn --version'
                sh 'java --version'
                sh 'node --version'
            }
        }
    }
}

错误处理

try-catch

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                script {
                    try {
                        sh 'npm run build'
                    } catch (Exception e) {
                        echo "Build failed: ${e.message}"
                        currentBuild.result = 'UNSTABLE'
                    }
                }
            }
        }
    }
}

catchError

pipeline {
    agent any

    stages {
        stage('Test') {
            steps {
                catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
                    sh 'npm test'
                }
            }
        }

        stage('Deploy') {
            steps {
                echo 'Deploying...'
            }
        }
    }
}

unstable 和 failure

pipeline {
    agent any

    stages {
        stage('Test') {
            steps {
                script {
                    def result = sh(script: 'npm test', returnStatus: true)
                    if (result != 0) {
                        currentBuild.result = 'UNSTABLE'
                    }
                }
            }
        }
    }
}

共享库

创建共享库

目录结构:

vars/
├── standardBuild.groovy
├── deploy.groovy
└── notify.groovy
src/
└── org/
    └── company/
        └── Utils.groovy

使用共享库

@Library('my-shared-library@main') _

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                standardBuild()
            }
        }
    }
}

带参数的共享库

// vars/standardBuild.groovy
def call(Map config) {
    pipeline {
        agent any

        tools {
            nodejs config.nodeVersion ?: 'NodeJS-18'
        }

        stages {
            stage('Install') {
                steps {
                    sh 'npm ci'
                }
            }

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

            stage('Build') {
                steps {
                    sh 'npm run build'
                }
            }
        }
    }
}

// Jenkinsfile
@Library('my-shared-library') _

standardBuild(nodeVersion: 'NodeJS-20')

动态 Pipeline

动态生成 stages

pipeline {
    agent any

    stages {
        stage('Dynamic Stages') {
            steps {
                script {
                    def services = ['api', 'web', 'worker']

                    services.each { service ->
                        stage("Build ${service}") {
                            dir(service) {
                                sh 'npm install'
                                sh 'npm run build'
                            }
                        }
                    }
                }
            }
        }
    }
}

条件化 Pipeline

pipeline {
    agent any

    stages {
        stage('Setup') {
            steps {
                script {
                    // 根据条件设置后续行为
                    if (env.BRANCH_NAME == 'main') {
                        env.DEPLOY_ENV = 'production'
                    } else if (env.BRANCH_NAME == 'develop') {
                        env.DEPLOY_ENV = 'staging'
                    } else {
                        env.DEPLOY_ENV = 'none'
                    }
                }
            }
        }

        stage('Deploy') {
            when {
                expression { env.DEPLOY_ENV != 'none' }
            }
            steps {
                echo "Deploying to ${env.DEPLOY_ENV}"
            }
        }
    }
}

小结

本章介绍了 Pipeline 进阶功能:

  • when 条件控制 stage 执行
  • parallel 并行执行加速构建
  • matrix 矩阵构建实现多配置测试
  • input 人工确认步骤
  • options 配置 Pipeline 行为
  • 错误处理机制
  • 共享库实现代码复用

下一章将介绍多分支 Pipeline。