Jenkins Pipeline进阶 - 条件判断、并行执行与流程控制

一、前言
上一篇我们学习了Pipeline的基础语法,能写出基本的构建流程了。但在实际工作中,构建流程往往更加复杂——你可能需要根据不同条件执行不同的步骤,或者让多个测试任务并行运行。本文将带你掌握Pipeline的进阶用法。
二、when指令 - 条件判断
when指令可以控制某个stage是否执行,这是Pipeline中最常用的条件控制方式。
2.1 基本用法
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
stage('Deploy to Dev') {
when {
branch 'develop'
}
steps {
sh './deploy-dev.sh'
}
}
stage('Deploy to Prod') {
when {
branch 'main'
}
steps {
sh './deploy-prod.sh'
}
}
}
}
上面的例子中,当构建 develop 分支时,只执行Deploy to Dev;构建 main 分支时,只执行Deploy to Prod。
2.2 when条件类型
// 1. 分支判断
when { branch 'main' }
when { branch pattern: 'release/.*', comparator: 'REGEXP' }
// 2. 环境变量判断
when { environment name: 'DEPLOY_ENV', value: 'production' }
// 3. 表达式判断
when { expression { return env.BUILD_NUMBER.toInteger() % 2 == 0 } }
when { expression { return params.DEPLOY == true } }
// 4. 构建原因判断
when { buildingTag() } // 构建标签时执行
when { tag 'v*' } // 匹配标签模式
when { changelog '.*BUGFIX.*' } // 变更日志匹配
when { changeRequest() } // PR/MR时执行
when { not { changeRequest() } } // 非PR/MR时执行
// 5. 组合条件
when {
allOf {
branch 'main'
environment name: 'DEPLOY_ENV', value: 'production'
}
}
when {
anyOf {
branch 'main'
branch 'develop'
}
}
when {
not {
branch 'test'
}
}
2.3 实战示例 - 多环境部署
pipeline {
agent any
parameters {
choice(name: 'ENV', choices: ['dev', 'staging', 'production'], description: '部署环境')
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: '跳过测试')
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
stage('Test') {
when {
expression { return !params.SKIP_TESTS }
}
steps {
sh 'mvn test'
}
}
stage('Deploy Dev') {
when {
anyOf {
expression { return params.ENV == 'dev' }
expression { return params.ENV == 'staging' }
expression { return params.ENV == 'production' }
}
}
steps {
sh './deploy.sh dev'
}
}
stage('Deploy Staging') {
when {
anyOf {
expression { return params.ENV == 'staging' }
expression { return params.ENV == 'production' }
}
}
steps {
sh './deploy.sh staging'
}
}
stage('Deploy Production') {
when {
expression { return params.ENV == 'production' }
}
steps {
input '确认部署到生产环境?'
sh './deploy.sh production'
}
}
}
}
三、并行执行 - parallel
当多个任务之间没有依赖关系时,可以让它们并行执行,大大缩短构建时间。
3.1 基本并行
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Parallel Tests') {
parallel {
stage('Unit Tests') {
steps {
sh 'mvn test'
}
}
stage('Integration Tests') {
steps {
sh 'mvn verify -P integration-test'
}
}
stage('Code Quality') {
steps {
sh 'mvn sonar:sonar'
}
}
}
}
stage('Deploy') {
steps {
sh './deploy.sh'
}
}
}
}
3.2 并行中指定不同Agent
pipeline {
agent none
stages {
stage('Build') {
agent { label 'linux' }
steps {
sh 'mvn clean package -DskipTests'
stash includes: 'target/*.jar', name: 'artifact'
}
}
stage('Cross-Platform Tests') {
parallel {
stage('Linux Test') {
agent { label 'linux' }
steps {
unstash 'artifact'
sh 'java -jar target/*.jar test'
}
}
stage('Windows Test') {
agent { label 'windows' }
steps {
unstash 'artifact'
bat 'java -jar target/*.jar test'
}
}
stage('macOS Test') {
agent { label 'macos' }
steps {
unstash 'artifact'
sh 'java -jar target/*.jar test'
}
}
}
}
}
}
3.3 并行矩阵 - matrix
matrix指令是更高级的并行方式,适用于需要在不同配置组合下测试的场景:
pipeline {
agent any
stages {
stage('Matrix Test') {
matrix {
axes {
axis {
name 'BROWSER'
values 'chrome', 'firefox', 'safari'
}
axis {
name 'PLATFORM'
values 'linux', 'windows', 'macos'
}
}
stages {
stage('Test') {
steps {
echo "Testing on ${PLATFORM} with ${BROWSER}"
sh "./run-test.sh ${PLATFORM} ${BROWSER}"
}
}
}
// 排除某些组合
excludes {
exclude {
axis {
name 'BROWSER'
values 'safari'
}
axis {
name 'PLATFORM'
values 'linux', 'windows'
}
}
}
}
}
}
}
上面的matrix会生成9个并行任务(3浏览器 × 3平台),但排除了Safari在Linux和Windows上的组合,实际执行7个并行任务。
四、script块 - 脚本式语法
在Declarative Pipeline中,可以用script块嵌入Scripted Pipeline语法,实现更灵活的控制。
4.1 变量和条件
pipeline {
agent any
stages {
stage('Set Config') {
steps {
script {
// 定义变量
def deployTarget = ''
if (env.BRANCH_NAME == 'main') {
deployTarget = 'production'
} else if (env.BRANCH_NAME == 'develop') {
deployTarget = 'staging'
} else {
deployTarget = 'dev'
}
env.DEPLOY_TARGET = deployTarget
echo "部署目标: ${deployTarget}"
}
}
}
stage('Deploy') {
steps {
sh "./deploy.sh ${env.DEPLOY_TARGET}"
}
}
}
}
4.2 循环处理
pipeline {
agent any
stages {
stage('Deploy Multiple Services') {
steps {
script {
def services = ['user-service', 'order-service', 'payment-service', 'notification-service']
for (service in services) {
echo "部署 ${service}..."
sh "./deploy-service.sh ${service}"
}
}
}
}
}
}
4.3 错误处理
pipeline {
agent any
stages {
stage('Deploy with Retry') {
steps {
script {
def maxRetries = 3
def retryCount = 0
while (retryCount < maxRetries) {
try {
sh './deploy.sh'
echo '部署成功!'
break
} catch (Exception e) {
retryCount++
echo "部署失败,第 ${retryCount} 次重试..."
if (retryCount >= maxRetries) {
error "部署失败,已达最大重试次数"
}
sleep(time: 10, unit: 'SECONDS')
}
}
}
}
}
}
}
五、stash和unstash - 跨阶段传递文件
不同阶段的Agent可能不同,需要用stash/unstash传递构建产物。
pipeline {
agent none
stages {
stage('Build') {
agent { label 'builder' }
steps {
sh 'mvn clean package'
// 保存构建产物
stash includes: 'target/*.jar', name: 'build-artifact'
}
}
stage('Test') {
agent { label 'tester' }
steps {
// 取出构建产物
unstash 'build-artifact'
sh 'java -jar target/*.jar test'
}
}
stage('Deploy') {
agent { label 'deployer' }
steps {
unstash 'build-artifact'
sh 'scp target/*.jar deploy@prod-server:/app/'
}
}
}
}
六、options指令 - Pipeline选项
pipeline {
agent any
options {
// 构建超时时间
timeout(time: 1, unit: 'HOURS')
// 构建重试次数
retry(3)
// 保留构建历史
buildDiscarder(logRotator(numToKeepStr: '10'))
// 禁止并发构建
disableConcurrentBuilds()
// 跳过默认的checkout
skipDefaultCheckout()
// 添加时间戳到日志
timestamps()
// 安静期(防止频繁触发)
quietPeriod(10)
}
stages {
stage('Build') {
options {
// 单个阶段也可以设置超时
timeout(time: 30, unit: 'MINUTES')
}
steps {
sh 'mvn clean package'
}
}
}
}
七、triggers指令 - 触发器
pipeline {
agent any
// 定时触发
triggers {
cron('H 2 * * *') // 每天凌晨2点
pollSCM('H/5 * * * *') // 每5分钟检查SCM
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
}
}
八、实战 - 完整的多环境部署Pipeline
pipeline {
agent any
options {
timeout(time: 2, unit: 'HOURS')
timestamps()
buildDiscarder(logRotator(numToKeepStr: '20'))
disableConcurrentBuilds()
}
environment {
APP_NAME = 'my-application'
REGISTRY = 'registry.example.com'
IMAGE_TAG = "${REGISTRY}/${APP_NAME}:${BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build & Test') {
parallel {
stage('Compile') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Code Quality') {
steps {
sh 'mvn sonar:sonar'
}
}
}
}
stage('Unit Tests') {
steps {
sh 'mvn test'
}
}
stage('Docker Build') {
when {
anyOf {
branch 'main'
branch 'develop'
}
}
steps {
sh "docker build -t ${IMAGE_TAG} ."
sh "docker push ${IMAGE_TAG}"
}
}
stage('Deploy Staging') {
when {
branch 'develop'
}
steps {
sh "kubectl set image deployment/${APP_NAME} ${APP_NAME}=${IMAGE_TAG} -n staging"
}
}
stage('Deploy Production') {
when {
branch 'main'
}
steps {
input '确认部署到生产环境?'
sh "kubectl set image deployment/${APP_NAME} ${APP_NAME}=${IMAGE_TAG} -n production"
}
}
}
post {
always {
cleanWs()
}
success {
echo '🎉 Pipeline执行成功!'
}
failure {
echo '❌ Pipeline执行失败,请检查!'
}
}
}
九、总结
本文详细介绍了Pipeline的进阶用法:
- when指令:分支、环境变量、表达式等条件判断
- parallel:并行执行多个无依赖的阶段,缩短构建时间
- matrix:多配置组合的矩阵式并行
- script块:嵌入脚本式语法,实现复杂逻辑
- stash/unstash:跨阶段传递文件
- options:超时、重试、日志等Pipeline选项
- 实战案例:完整的多环境部署Pipeline
掌握了这些进阶技巧,你就可以写出专业级别的CI/CD流水线了!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。







