Jenkins入门教程(七):Pipeline条件判断与并行执行
本文将详细介绍Pipeline中的条件判断和并行执行,让你的CI/CD流程更加灵活和高效,包括完整的示例和执行结果。
when条件指令
when指令用于控制stage是否执行,只有满足条件时stage才会运行。
branch条件
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'make build'
}
}
stage('Deploy to Dev') {
when {
branch 'develop'
}
steps {
echo 'Deploying to development environment...'
sh './deploy.sh dev'
}
}
stage('Deploy to Staging') {
when {
branch 'release/*' // 支持通配符
}
steps {
echo 'Deploying to staging environment...'
sh './deploy.sh staging'
}
}
stage('Deploy to Production') {
when {
branch 'main'
}
steps {
echo 'Deploying to production environment...'
sh './deploy.sh prod'
}
}
}
}
// 在main分支执行时的输出
[Pipeline] stage
[Pipeline] { (Build)
[Pipeline] sh
+ make build
...
[Pipeline] stage
[Pipeline] { (Deploy to Dev)
Stage "Deploy to Dev" skipped due to when conditional
[Pipeline] stage
[Pipeline] { (Deploy to Staging)
Stage "Deploy to Staging" skipped due to when conditional
[Pipeline] stage
[Pipeline] { (Deploy to Production)
[Pipeline] echo
Deploying to production environment...
[Pipeline] sh
+ ./deploy.sh prod
expression条件
pipeline {
agent any
parameters {
booleanParam(name: 'RUN_TESTS', defaultValue: true, description: '是否运行测试')
choice(name: 'DEPLOY_ENV', choices: ['none', 'dev', 'staging', 'prod'], description: '部署环境')
}
stages {
stage('Test') {
when {
expression { params.RUN_TESTS == true }
}
steps {
echo 'Running tests...'
sh 'make test'
}
}
stage('Deploy') {
when {
expression { params.DEPLOY_ENV != 'none' }
}
steps {
echo "Deploying to ${params.DEPLOY_ENV}..."
sh "./deploy.sh ${params.DEPLOY_ENV}"
}
}
stage('Production Approval') {
when {
expression { params.DEPLOY_ENV == 'prod' }
}
steps {
input message: 'Approve production deployment?', ok: 'Deploy'
sh './deploy.sh prod --confirm'
}
}
}
}
// 当 RUN_TESTS=false, DEPLOY_ENV=dev 时
[Pipeline] stage
[Pipeline] { (Test)
Stage "Test" skipped due to when conditional
[Pipeline] stage
[Pipeline] { (Deploy)
[Pipeline] echo
Deploying to dev...
[Pipeline] sh
+ ./deploy.sh dev
environment条件
pipeline {
agent any
environment {
DEPLOY_TO = 'production'
}
stages {
stage('Deploy') {
when {
environment name: 'DEPLOY_TO', value: 'production'
}
steps {
echo 'Deploying to production because DEPLOY_TO=production'
}
}
}
}
changeset条件
pipeline {
agent any
stages {
stage('Build Frontend') {
when {
changeset 'frontend/**' // 只有frontend目录有变更时执行
}
steps {
echo 'Frontend files changed, rebuilding...'
dir('frontend') {
sh 'npm install && npm run build'
}
}
}
stage('Build Backend') {
when {
changeset 'backend/**' // 只有backend目录有变更时执行
}
steps {
echo 'Backend files changed, rebuilding...'
dir('backend') {
sh 'mvn clean package'
}
}
}
stage('Build Docs') {
when {
changeset pattern: '.*\\.md$', comparator: 'REGEXP'
}
steps {
echo 'Documentation changed, rebuilding docs...'
sh 'mkdocs build'
}
}
}
}
组合条件
pipeline {
agent any
parameters {
booleanParam(name: 'FORCE_DEPLOY', defaultValue: false)
}
stages {
stage('Deploy to Production') {
when {
// allOf: 所有条件都满足
allOf {
branch 'main'
expression { currentBuild.result == null || currentBuild.result == 'SUCCESS' }
}
}
steps {
echo 'All conditions met, deploying...'
}
}
stage('Emergency Deploy') {
when {
// anyOf: 任一条件满足
anyOf {
branch 'hotfix/*'
expression { params.FORCE_DEPLOY == true }
}
}
steps {
echo 'Emergency deployment triggered'
}
}
stage('Skip on Docs') {
when {
// not: 条件取反
not {
changeset 'docs/**'
}
}
steps {
echo 'Not a docs-only change, running full build'
}
}
}
}
beforeAgent选项
pipeline {
agent none
stages {
stage('Expensive Stage') {
when {
branch 'main'
beforeAgent true // 在分配agent之前评估条件
}
agent {
label 'expensive-gpu-agent'
}
steps {
echo 'Running on expensive agent only for main branch'
}
}
}
}
// 如果不是main分支,不会占用expensive-gpu-agent
并行执行 (parallel)
基本并行
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'make build'
}
}
stage('Test') {
parallel {
stage('Unit Tests') {
steps {
sh '''
echo "Starting Unit Tests..."
sleep 10
echo "Unit Tests completed"
'''
}
}
stage('Integration Tests') {
steps {
sh '''
echo "Starting Integration Tests..."
sleep 15
echo "Integration Tests completed"
'''
}
}
stage('E2E Tests') {
steps {
sh '''
echo "Starting E2E Tests..."
sleep 20
echo "E2E Tests completed"
'''
}
}
}
}
}
}
// 执行结果 - 三个测试同时运行
[Pipeline] parallel
[Pipeline] { (Branch: Unit Tests)
[Pipeline] { (Branch: Integration Tests)
[Pipeline] { (Branch: E2E Tests)
[Pipeline] sh
+ echo 'Starting Unit Tests...'
Starting Unit Tests...
[Pipeline] sh
+ echo 'Starting Integration Tests...'
Starting Integration Tests...
[Pipeline] sh
+ echo 'Starting E2E Tests...'
Starting E2E Tests...
...
// 总耗时约20秒(最长的E2E),而非45秒(串行)
不同节点并行
pipeline {
agent none
stages {
stage('Multi-Platform Build') {
parallel {
stage('Linux Build') {
agent { label 'linux' }
steps {
sh '''
echo "Building on Linux: $(uname -a)"
make build-linux
'''
}
}
stage('Windows Build') {
agent { label 'windows' }
steps {
bat '''
echo Building on Windows
msbuild solution.sln /p:Configuration=Release
'''
}
}
stage('macOS Build') {
agent { label 'macos' }
steps {
sh '''
echo "Building on macOS: $(sw_vers -productVersion)"
xcodebuild -project MyApp.xcodeproj
'''
}
}
}
}
}
}
failFast选项
pipeline {
agent any
stages {
stage('Parallel Tests') {
failFast true // 任一分支失败立即终止其他分支
parallel {
stage('Test A') {
steps {
sh 'make test-a'
}
}
stage('Test B') {
steps {
sh 'make test-b' // 如果这个失败
}
}
stage('Test C') {
steps {
sh 'make test-c' // 这个会被中止
}
}
}
}
}
}
// 输出示例
[Pipeline] parallel
[Pipeline] { (Branch: Test A)
[Pipeline] { (Branch: Test B)
[Pipeline] { (Branch: Test C)
...
[Pipeline] // Branch: Test B failed
Failing parallel stages due to failFast
[Pipeline] // Branch: Test C aborted
矩阵构建 (matrix)
pipeline {
agent none
stages {
stage('Matrix Build') {
matrix {
axes {
axis {
name 'PLATFORM'
values 'linux', 'windows', 'macos'
}
axis {
name 'JAVA_VERSION'
values '11', '17', '21'
}
}
excludes {
// 排除某些组合
exclude {
axis {
name 'PLATFORM'
values 'windows'
}
axis {
name 'JAVA_VERSION'
values '21' // Windows不测试Java 21
}
}
}
agent {
label "${PLATFORM}"
}
stages {
stage('Build') {
steps {
echo "Building on ${PLATFORM} with Java ${JAVA_VERSION}"
sh "java -version"
sh "make build"
}
}
stage('Test') {
steps {
echo "Testing on ${PLATFORM} with Java ${JAVA_VERSION}"
sh "make test"
}
}
}
}
}
}
}
// 会自动生成以下组合并行执行:
// linux + Java 11
// linux + Java 17
// linux + Java 21
// windows + Java 11
// windows + Java 17
// (windows + Java 21 被排除)
// macos + Java 11
// macos + Java 17
// macos + Java 21
错误处理
pipeline {
agent any
stages {
stage('Retry Example') {
steps {
retry(3) {
sh '''
echo "Attempt ${RANDOM}"
# 模拟偶发失败
[ $((RANDOM % 2)) -eq 0 ] && exit 1
echo "Success!"
'''
}
}
}
stage('Timeout Example') {
steps {
timeout(time: 5, unit: 'MINUTES') {
sh '''
echo "Starting long running task..."
# 如果超过5分钟会被中止
make long-task
'''
}
}
}
stage('Continue on Error') {
steps {
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
sh 'exit 1' // 失败但继续
}
echo 'This still runs even after error above'
}
}
stage('Try-Catch') {
steps {
script {
try {
sh 'might-fail-command'
} catch (Exception e) {
echo "Command failed: ${e.message}"
echo 'Running fallback...'
sh 'fallback-command'
}
}
}
}
}
}
完整实战示例
pipeline {
agent any
parameters {
choice(name: 'ENV', choices: ['dev', 'staging', 'prod'], description: 'Deploy environment')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh 'make build'
}
}
stage('Parallel Tests') {
when {
not { changeset 'docs/**' }
}
failFast true
parallel {
stage('Unit Tests') {
steps {
sh 'make test-unit'
}
post {
always {
junit 'reports/unit/*.xml'
}
}
}
stage('Integration Tests') {
steps {
sh 'make test-integration'
}
post {
always {
junit 'reports/integration/*.xml'
}
}
}
stage('Security Scan') {
steps {
sh 'make security-scan'
}
}
}
}
stage('Deploy') {
when {
anyOf {
branch 'main'
branch 'release/*'
expression { params.ENV == 'prod' }
}
}
steps {
echo "Deploying to ${params.ENV}"
timeout(time: 10, unit: 'MINUTES') {
retry(2) {
sh "./deploy.sh ${params.ENV}"
}
}
}
}
}
post {
always {
cleanWs()
}
}
}
总结
本文详细介绍了Pipeline的条件判断(when)、并行执行(parallel)、矩阵构建(matrix)和错误处理。这些特性让Pipeline更加灵活强大,能够处理各种复杂的CI/CD场景。
下一篇我们将学习Pipeline与Git的集成。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。







