Jenkins 持续集成:Pipeline 脚本化构建

FreeGuideOnline 最新 2026-06-13

Jenkins 持续集成:Pipeline 脚本化构建完全指南

Jenkins Pipeline 是一种将持续交付流水线实现为代码的强大方式。本教程将带你从零开始,掌握使用 Jenkins Pipeline 进行脚本化构建的核心技能。无论你之前是否接触过 CI/CD,都能通过本文学会将构建、测试、部署的全流程用代码定义,并纳入版本控制。

什么是 Jenkins Pipeline?

Jenkins Pipeline 是一套运行于 Jenkins 上的工作流框架,它将原本独立运行于单个或多个节点的任务连接起来,实现单个任务难以完成的复杂发布流程。Pipeline 通过 Jenkinsfile(一个文本文件,通常存放于项目源码仓库根目录)实现 Pipeline as Code,使流水线的定义和变更可以像代码一样被审查、跟踪和回滚。

声明式与脚本式 Pipeline

Jenkins Pipeline 提供两种语法风格:

  • 声明式(Declarative):更结构化和简洁,以 pipeline 块为根,内部包含 agentstagessteps 等,适合大多数用户。它提供了一个更受约束的书写环境,能简化常见流程的编写。
  • 脚本式(Scripted):基于 Groovy 的灵活编程模型,以 node 块为基础,拥有更强大的控制能力与灵活性,适合需要复杂逻辑的自定义流水线。本教程侧重于脚本式 Pipeline,因为它能让你完全掌控流程控制,同时理解声明式语法也更容易。

第一个脚本式 Pipeline

脚本式 Pipeline 的核心是 node 步骤。node 语句会分配一个 Jenkins 执行器,并在该节点的工作区内运行代码块。一个最简单的 Jenkinsfile 示例如下:

node {
    stage('Checkout') {
        checkout scm
    }
    stage('Build') {
        sh 'make'
    }
    stage('Test') {
        sh 'make test'
    }
    stage('Deploy') {
        sh 'make deploy'
    }
}

上述脚本中:

  • node 分配一个执行器,通常是一个安装了 Java 和必要工具的代理节点。
  • stage 用于划分逻辑阶段,会在 Jenkins 界面按阶段展示进度。
  • sh 是 Unix/Linux 上的 shell 命令,对于 Windows 环境则应使用 bat

关键概念与常用步骤

环境变量与凭证

脚本式 Pipeline 中可以直接使用 Groovy 语法设置环境变量:

node {
    // 设置环境变量
    env.BUILD_NAME = "my-app-${env.BUILD_ID}"
    stage('Print Info') {
        echo "Building ${env.BUILD_NAME} on ${env.NODE_NAME}"
    }
}

对于敏感信息如密码、Token,应使用 Jenkins 凭据管理器。通过 withCredentials 绑定使用:

withCredentials([string(credentialsId: 'api-token', variable: 'TOKEN')]) {
    sh 'curl -H "Authorization: Bearer $TOKEN" https://api.example.com'
}

并行执行与错误处理

脚本式 Pipeline 可以轻松实现阶段内的并行执行,以及自定义的重试与超时逻辑。

并行执行:使用 parallel 关键字

node {
    stage('Run Tests') {
        parallel(
            unit: {
                sh './run-unit-tests.sh'
            },
            integration: {
                sh './run-integration-tests.sh'
            }
        )
    }
}

重试与超时:结合 retrytimeout 步骤

stage('Stability Test') {
    retry(3) {
        timeout(time: 10, unit: 'MINUTES') {
            sh 'run-flaky-benchmark.sh'
        }
    }
}

如果 run-flaky-benchmark.sh 失败,retry(3) 会重试最多3次;同时,单次执行超过10分钟会被自动终止并标记为失败。

动态步骤生成

脚本式 Pipeline 由于具备完整的 Groovy 能力,可以根据外部参数或文件内容动态生成阶段:

def services = ['auth', 'payment', 'user']  // 可从配置文件读取
node {
    stage('Build & Push Images') {
        for (s in services) {
            stage("Build ${s}") {
                dir(s) {
                    sh "docker build -t myrepo/${s}:${env.BUILD_ID} ."
                    sh "docker push myrepo/${s}:${env.BUILD_ID}"
                }
            }
        }
    }
}

这种动态能力是脚本式 Pipeline 相对于声明式的主要优势之一。

完整示例:多分支流水线自动部署

假设有一个基于 Maven 的 Java 项目,我们希望在以下场景自动触发构建与部署:

  1. 当提交推送到任意功能分支时,执行构建与单元测试。
  2. 当推送到主分支时,执行完整测试并部署到预发布环境。
  3. 支持手动部署到生产环境(仅从主分支)。

以下是一个接近生产实践的 Jenkinsfile 示例(脚本式):

properties([
    parameters([
        string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '部署环境'),
        booleanParam(name: 'RUN_MIGRATIONS', defaultValue: true, description: '是否运行数据库迁移')
    ])
])

node('maven') {
    def branchName = env.BRANCH_NAME
    def isMain = branchName == 'main' || branchName == 'master'

    stage('Checkout') {
        checkout scm
    }

    stage('Build & Unit Test') {
        sh 'mvn clean test'
        junit '**/target/surefire-reports/*.xml'
    }

    stage('Package') {
        sh 'mvn package -DskipTests'
        archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
    }

    // 仅主分支执行集成测试和部署
    if (isMain) {
        stage('Integration Test') {
            parallel(
                apiTest: {
                    sh 'mvn verify -P integration-tests'
                },
                uiTest: {
                    sh 'npm run e2e'
                }
            )
        }

        stage('Deploy to Staging') {
            when { expression { params.DEPLOY_ENV == 'staging' } }
            steps {
                script {
                    withCredentials([
                        sshUserPrivateKey(credentialsId: 'staging-deploy-key', keyFileVariable: 'SSH_KEY')
                    ]) {
                        sh '''
                            scp -i $SSH_KEY target/myapp.jar deploy@staging-server:/apps/
                            ssh -i $SSH_KEY deploy@staging-server "systemctl restart myapp"
                        '''
                    }
                }
            }
        }
    }

    // 手动审批后部署生产
    if (isMain) {
        stage('Production Deployment') {
            input message: '是否部署到生产环境?', submitter: 'ops-team'
            environment {
                DEPLOY_ENV = 'production'
            }
            steps {
                script {
                    // 假设使用类似步骤,凭证不同
                    sh "echo Deploying to production server..."
                }
            }
        }
    }
}

脚本拆解分析

  • properties:定义全局参数,允许用户触发时选择部署环境、是否运行迁移等。
  • node('maven'):指定在标签为 maven 的代理上运行(确保环境有所需工具)。
  • 流控制if (isMain) 使得只有主干分支执行集成测试和部署,功能分支只到单元测试和打包,实现了快速反馈。
  • 凭据使用:私钥凭证在 withCredentials 块内注入为文件变量,提高安全性。
  • 人工审批input 步骤等待指定用户/组确认,然后再执行生产部署。
  • 归档产物archiveArtifacts 将构建产物保存,方便追溯或复用。

将 Pipeline 纳入版本控制

要让 Jenkins 自动读取项目仓库中的 Jenkinsfile,你需要创建 多分支流水线(Multibranch Pipeline) 或使用 组织文件夹(Organization Folder)。两者都会扫描仓库发现所有分支,并自动为含有 Jenkinsfile 的分支构建流水线。

创建步骤:

  1. 进入 Jenkins 首页 → New Item → 选择 Multibranch Pipeline
  2. 在配置中添加源码仓库地址及对应凭据。
  3. 在 “Build Configuration” 中确认 “Mode” 为 “by Jenkinsfile”,默认路径即为仓库根目录下的 Jenkinsfile
  4. 保存后,Jenkins 会扫描所有分支并开始执行。

调试与错误排查

脚本式 Pipeline 出问题时,可以通过以下手段排查:

  • 重放(Replay):在构建页面点击 “Replay”,可以在浏览器中实时修改 Groovy 脚本并重新运行,适合快速修正。
  • 异常捕获:使用 try/catch 捕获特定阶段的错误,并设定自定义操作。
  • 日志增强:在脚本中使用 echo 打印变量、状态,或使用 warnError 将某些错误降级为警告。
  • Blue Ocean 插件:提供可视化的流水线编辑器及运行视图,对初学者更友好。

最佳实践概览

  • 加速反馈:将单元测试放在最前,快速失败;代码分析、集成测试并行执行。
  • 敏感信息外部化:所有密钥、密码必须通过 Credentials 绑定,切勿硬编码。
  • 环境一致性:使用 Docker 容器作为执行环境,通过 docker.image().inside() 避免依赖漂移。
  • 保留关键产物:使用 archiveArtifactsstash/unstash 在阶段间传递文件。
  • 限制作用域:尽量将复杂逻辑封装到共享库中,保持 Jenkinsfile 可读性。

总结

脚本式 Pipeline 为 Jenkins 提供了图灵完备的流程定义能力,让你可以像编写应用程序代码一样构建、测试和部署流水线。从简单的线性构建到复杂的条件分支、并行执行、人机交互,脚本式语法都能从容应对。掌握本指南中的核心概念与示例后,你即可开始将团队的项目持续集成管道转为代码化,拥抱 DevOps 实践。

下一步建议:

  • 阅读 Jenkins 官方文档中的 “Pipeline Steps Reference” 了解所有内置步骤。
  • 探索 Jenkins 共享库,将通用逻辑抽取为可复用的库函数。
  • 尝试将 Docker 集成到流水线中,实现完全可重现的构建环境。