Jenkins 流水线快速理解
流水线 Pipeline
概念
Jenkins Pipeline(简称 Pipeline/流水线)是一套插件,支持实现持续交付管道(CDP,continuous delivery pipelines)并将其集成到 Jenkins 中。
TIPCDP 是将软件从版本控制系统直接交付给客户的流程的自动化表达。对软件的每项更改(在源代码管理中提交)在发布过程中都会经历一个复杂的过程,此过程涉及以可靠且可重复的方式构建软件,以及通过测试和部署的多个阶段来推进构建的软件。
Pipeline 的定义会写在一个文本文件,即 Jenkinsfile,其可以随着代码一起提交到源代码仓库,是 Pipeline-as-code 的基础,此行为将 CDP 视为要像任何其他代码一样进行版本控制和审核。
- Pipeline:是用户定义的 CD 管道模型,Pipeline 的代码定义了整个构建过程,其中通常包括构建、测试然后交付应用程序的阶段。pipeline 块也是声明式管道语法的一部分
- Node(节点):是 Jenkins 环境的一部分,即能够执行 Pipeline 的机器(详见控制器隔离)。node 块也是脚本式管道语法的一部分
- Stage(阶段):用于定义 Pipeline 各个阶段的任务子集(比如构建、测试、部署阶段),许多插件依赖于 Stage 来可视化 Pipeline 的状态或过程
- Step(步骤):指定 Jenkins 在每个阶段里要执行什么操作

Jenkinsfile 语法概览
语法分为两种:声明式(Declarative)、脚本式(Scripted),两者都是 DSL(Pipeline domain-specific language)语言,虽然两者会被 Pipeline 引擎基于 Groovy 语法解析,但是声明式语法是一种更具结构化和限制性的 DSL,其存在是为了能更方便地编写 jenkinsfile,因此无法像脚本式一样能使用 Groovy 绝大多数特性(变量、函数、控制流语句等),两者语法具体比较可看官方文档说明。
在操作演示一节会细讲常用的语法关键词,官方文档直通车戳这里。
声明式管道语法
pipeline { // 声明式语法开头
agent any // agent 指定执行此 Pipeline 的节点
stages { // 阶段块
stage('Build') { // 为阶段命名
steps { // 步骤块
sh 'make' // 这里假设执行 bash 命令
// ... 其它步骤
}
}
stage('Test') { // 可定义多个阶段
steps {
// ... 其它步骤
}
}
stage('Deploy') {
steps {
// ... 其它步骤
}
}
}
}
脚本式管道语法
node { // 脚本式语法开头,表示在任何可用的节点上执行此 Pipeline
stage('Build') { // 指定阶段名称
// // 执行步骤
}
stage('Test') { // 其它阶段
//
}
stage('Deploy') {
//
}
}
操作演示
NOTE默认读者已经安装并运行 Jenkins,并能正确访问 Jenkins GUI。启动方式可看官文:安装 Jenkins。
创建 pipeline
创建流水线有两种方式:传统 GUI 和 Blue Ocean,后者是针对 Pipeline 的 新 GUI 设计,主要提供易于使用的 Pipeline 可视化。由于操作演示专注于 Jenkinsfile 的编写,所以流水线创建方式不再强调(PS:Blue Ocean 支持以可视化的方式创建 Jenkinsfile)。
- 进入 Jenkins GUI Dashboard => New Item 界面,选择 Pipeline,输入名称,点击 OK 即可创建流水线项目
- 进入配置界面后,在 General - Description 输入描述,在 Pipeline - Definition 选择 Pipeline script,即可编写 Jenkinsfile 脚本,最后 Save 并执行构建操作

pipeline { #1
agent any #2
stages { #3
stage('Stage 1') { #4
steps { #5
sh './scripts/build.sh' #6
}
}
stage('Stage 2') {
agent { label 'custom-label' } #7
steps {
echo 'Test step to do sth.'
echo 'Do sth. else.'
}
}
stage('Stage 3') {
agent { #8
docker {
image 'maven:3-alpine'
label 'custom-label'
args '-v /tmp:/tmp' // 要传递给 docker run 的运行时参数
}
}
steps {
sh 'mvn -v' #9
}
post { #10
echo 'Do sth.'
}
}
}
post { #11
always {
echo 'Finished execute.'
}
}
}
- #1:
pipeline { ... }
块是声明式管道语法的开头,所有有效的声明式语法都包含在此块中 - #2:
agent
用于指定整个流水线或特定阶段(如 #7)将在 Jenkins 环境中执行的位置(即执行构建的节点),Jenkins 可以配置多个节点,其可以是物理机、虚拟机或容器。可填内容如下:agent none
:在顶层声明时,表示不指定 agent,而由每个 Stage 自行指定 agent;若顶层配置此项,Stage 也不指定任何 agent(或 agent none),则会构建失败agent any
:在任何可用的节点上执行流水线或阶段agent { label ... }
:如 #7,在拥有指定标签的节点上执行流水线或阶段(Manage Jenkins => Nodes 选择节点配置即可设置 Label)agent { node ... customWorkspace ... }
:与agent label
方式效果等价,但可通过customWorkspace
选项来控制节点的工作空间(默认是/var/#ROOT_DIR/workspace
,根路径是新增节点时指定)agent { docker { ... } }
:使用给定的容器执行流水线或阶段(如 #8)docker args
可填写大多数docker run
时使用的参数,并且会强制抓取镜像(即使镜像已存在)docker label
标签效果与agent label
类似,不过这里是用于指定 docker 容器在拥有指定标签的节点运行,不使用则默认是选择任一节点
agent { dockerfile { ... } }
:使用源码仓库包含的 Dockerfile 构建的容器来执行流水线或阶段agent { kubernetes { ... } }
:与上述所有方式区别在于,执行环境不依赖于 Jenkins 节点,而是在 K8s 集群中动态创建一个 POD 执行构建
- #3:
stages
块用于指定构建的各个阶段,包裹 1~n 个阶段指令,可定义在 pipeline / stage 块中 - #4:
stage('name')
块指定阶段名称,该阶段所有步骤指令也会包裹在其中 - #5:
steps
块指定在所在阶段要执行的 1~n 个步骤,Jenkins 支持的步骤繁多,以下是比较常见的三种: - #10/#11:
post
定义在流水线或特定阶段的运行完成时执行的 1~n 个附加操作(与steps
相似),post 支持多个后置条件块(如 always、success、failure、aborted),比较清晰易懂,其它条件块可看官文
使用 Maven 构建 Java 项目
- 本节将使用 Jenkins 官方文档提供的学习仓库 simple-java-maven-app,读者可自行 fork 玩耍
- 同样创建一个 Pipeline 项目,在 Pipeline - Definition 选择 Pipeline script from SCM,然后填写 fork 的仓库地址(如果是自建的 gitlab 等平台还需要填写访问凭证 Credentials)
- 在 Script Path 指定 Jenkinsfile 在仓库中的位置即可 Save 并执行构建

补充:鉴于笔者的 Jenkins 是 Docker 运行,容器内没有 Maven,有两种方式处理:
- 修改 Jenkinsfile,将 agent 配置修改为 docker 运行一个包含 JDK 和 Maven 的镜像,在此环境中执行构建
- 在 Jenkins 所在机器安装好 Maven,在 Manage Jenkins => Tools 配置 Maven 的路径,然后修改 Jenkinsfile,添加 tools 指令
// 由于笔者宿主机有 Maven,因此直接采用第二种:
pipeline {
agent any
tools {
// 这里的名称即为 Manage Jenkins => Tools 中配置的 Maven 名称
maven 'Maven-3.9.9'
}
// ... 其它指令不变
}
// 第一种方式如下:
pipeline {
agent {
docker {
// 选择一个包含 Maven 和 JDK 的镜像
image 'maven:3.9.9-eclipse-temurin-21-alpine'
// 可选项,如果你的 Jenkins 是容器运行,
// 那么此处映射的宿主机其实就是 Jenkins 容器,Maven 是 Jenkins 容器里的容器
args '-v /opt/maven_repos:/root/.m2'
}
}
// ... 其它指令不变
}
多分支流水线
- 首先在 fork 的仓库 simple-java-maven-app 创建多个分支(比如 dev、prod)
- 进入 Jenkins GUI Dashboard => New Item 界面,选择 Multibranch Pipeline,输入名称,点击 OK 创建多分支流水线项目
- 同样输入仓库地址和 Jenkinsfile 在仓库里的路径

- 创建项目后,Jenkins 会自动扫描一次仓库,来获取分支信息,至于分支的获取策略,可在这里配置

- 其它配置按默认填写即可,或者可根据需要进行填充,最后点击 Save,这样最基本的多分支流水线项目就创建好了
- Jenkins 会拉取项目分支并构建一次,以下是创建项目后的界面

以上述方式创建的项目,每个分支下都有独立的 Jenkinsfile 文件,可以随着分支一起提交并审核,针对环境修改脚本。而如果是项目里的多个分支都基于同一 Jenkinsfile 构建,则可以用 when
指令区分,项目里的 Jenkinsfile 修改如下:
pipeline {
// ... 省略其它
stages {
// ... 省略其它
// 发布到开发环境
stage('Deliver for dev') {
when {
branch 'dev' // 当分支为 dev 时执行该阶段
}
steps {
echo 'This is dev env!!!'
}
}
// 发布到测试环境
stage('Deliver for test') {
when {
branch 'test' // 当分支为 test 时执行该阶段
}
steps {
echo 'This is test env!!!'
}
}
// 发布到生产环境
stage('Deliver for master') {
when {
branch 'master' // 当分支为 master 时执行该阶段
}
steps {
sh './jenkins/scripts/deliver.sh'
}
}
}
}
when 指令指定 Pipeline 根据给定的条件确定是否应该执行该阶段,指令块内必须至少包含一个条件,若有多个条件,则所有条件都为 true 才会执行该阶段。
这里简单列下几种条件,其它详见官文:
- branch:只能在多分支流水线项目使用,内容会被当作 Ant-style path globbing(模式匹配语法)进行解析,支持两个参数
pattern
:匹配内容,comparator
参数未使用时,该参数不用显式指定comparator
:比较方式,EQUALS
(相等)、GLOB
(默认,按 Ant-style 模式匹配)、REGEXP
(按正则表达式匹配)
- changelog:若指定表达式与 Git 提交信息匹配,则执行构建
- not:用于指定嵌套条件为 false 时执行构建,必须包含一个子条件,如
when { not { branch 'dev' } }
- allOf:用于指定嵌套条件都必须为 true 时执行构建,必须包含一个子条件
- anyOf:用于指定嵌套条件有一个为 true 时执行构建,必须包含一个子条件
至于分支自动构建,在项目配置中(下图)可以设置定时扫描,或使用对应 SCM 平台的 WebHook 实现推送后自动构建,在传统 freestyle 项目也都有这些配置,就不再赘述。

Jenkinsfile 常用语法
environment
用于指定环境变量,可在 pipeline/stage
块使用,并能与 credentials() 联合,通过凭证 ID 访问凭证。
pipeline {
agent any
environment {
CC = 'clang'
}
stages {
stage('Example credential') {
environment {
SERVICE_CREDS = credentials('credential-id')
}
steps {
sh 'echo "cc = $CC"'
sh "echo cc = ${env.CC}" // 可通过 env 全局变量访问
sh 'echo "Credential is $SERVICE_CREDS"'
sh 'echo "Service user is $SERVICE_CREDS_USR"' // 获取凭证中的 username
sh 'echo "Service password is $SERVICE_CREDS_PSW"' // 获取凭证中的 password
sh 'printenv' // 打印所有环境变量
sh 'echo job_name = $JOB_NAME' // 环境变量访问方式一
sh 'echo job_branch = ${BRANCH_NAME}' // 环境变量访问方式二
}
}
}
}
parameters
该指令用于指定用户在触发 Pipeline 时应提供的参数列表(即传统 freestyle 项目的 Build with Parameters),这些参数的值可通过 params
对象在 Pipeline 步骤中进行访问。
每个参数都包含三个属性:name、defaultValue、description
,参数类型如下:
string
:字符串text
:文本,可包含多行booleanParam
:布尔参数choice
:选择参数password
:密码- Jenkins 会将此参数标记为敏感数据,会触发一些安全机制:尝试在构建日志中屏蔽该值、限制该值如何被某些 Pipeline 步骤实例化或使用等
- Credentials是该参数在功能上的上位替代,关于凭证、敏感数据大多是配置于 Credentials 一起管理,password 比较侧重于 UI 输入时的视觉保密和临时性、半敏感性的信息输入
pipeline {
agent any
parameters {
string(name: 'BUILD_ADMIN', defaultValue: 'Mr. Jenkins', description: 'Build User')
text(name: 'REMARK', defaultValue: '', description: 'Enter some information about the build')
booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')
// choice 比较特殊,choices 列表的第一个选项才是默认选择
choice(name: 'BUILD_ENV', choices: ['DEV', 'TEST', 'PROD'], description: 'Build environment')
password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
}
stages {
stage('TEST') {
steps {
echo "Hello ${params.BUILD_ADMIN}"
echo "REMARK: ${params.REMARK}"
echo "Toggle: ${params.TOGGLE}"
echo "BUILD_ENV: ${params.BUILD_ENV}"
echo "PASSWORD: ${params.PASSWORD}"
}
}
}
}
用上述脚本创建一个项目后,可以看到左侧出现 Build With Parameters,点击即可进行参数设置。

options
该指令支持从 Pipeline 本身中配置特定于 Pipeline 的选项,如:
- disableConcurrentBuilds:不允许并发执行流水线,可用于防止同时访问共享资源等场景
- skipStagesAfterUnstable:一旦构建状态变为 UNSTABLE,则后续阶段将不再执行
- retry:在失败时, 重新尝试整个流水线的指定次数
- timeout:设置流水线运行的超时时间, 在此之后,Jenkins将中止流水线
- 其它详见官文
pipeline {
agent any
options {
disableConcurrentBuilds()
skipStagesAfterUnstable()
timeout(time: 1, unit: 'HOURS') // 构建超时时间
retry(3) // 最多尝试构建 1+3 次
}
stages {
stage('Test') {
steps {
//...
}
options {
// timeout/retry 也可用在 stage 中使用,针对于所在阶段起作用
timeout(time: 1, unit: 'MINUTES')
retry (1)
}
}
// ... 其它指令
}
}
triggers
触发器指令定义重新触发 Pipeline 的自动化方式,可用触发器有:
- cron:接受 cron 样式字符串以定义应重新触发 Pipeline 的固定间隔,如:
triggers { cron('H */4 * * 1-5') }
- pollSCM:同样接收 cron 样式字符串,在固定间隔中,Jenkins 会检查 SCM 是否有更新,有则会重新触发 Pipeline
- upstream:接受以逗号分隔的作业名称和阈值。当任一作业以最小阈值完成时,将重新触发 Pipeline。该方式跟以往 Freestyle 项目的 Build Triggers => Build after other projects are built 其实是同个作用,当一个或多个指定的「上游 (upstream)」项目成功构建(或其他指定状态)后,自动触发当前项目的构建,可用场景如下:
- 依赖构建:若 B 项目依赖于项目 A 产生的构件(如一个库、一个 API 依赖),当项目 A 成功构建后,项目 B 才应该被构建,那么项目 B 的流水线就可以设置 upstream 为项目 A
- 构建流水线拆分:一个非常复杂和耗时的构建/部署流程可能被拆分成多个独立的 Jenkins Pipeline,以提高模块化、可管理性和并行性
- 触发不同类型的任务:一个上游项目可能是编译和单元测试,成功后触发一个下游项目进行更耗时的集成测试、性能测试或安全扫描
- 扇出构建:这种场景可能比较常见,一个核心库更新后,多个依赖于它的项目都需要重新构建
pipeline {
agent any
triggers {
cron('H */4 * * 1-5')
pollSCM('H */4 * * 1-5')
// 可填阈值:SUCCESS、UNSTABLE、FAILURE,填写 FAILURE 表示构建状态为 SUCCESS、UNSTABLE、FAILURE 时都是符合要求
upstream(upstreamProjects: 'job_name1,job_name2', threshold: hudson.model.Result.SUCCESS)
}
// ... 其它指令
}
tools
用于定义和使用 Jenkins Manage Jenkins => Tools 下的工具,主要支持 JDK、Maven、Gradle。
比如在 Tools 中配置了 Maven,则 Jenkinsfile 可以写:
pipeline {
agent any
tools {
maven 'custom-maven-name' // Tools 中定义的 Maven 名称
}
stages {
stage('Example') {
steps {
sh 'mvn --version' // 命令的执行将会使用上方指定的 Maven 环境
}
}
}
// ... 其它指令
}
input
该指令在执行构建时与 Jenkins 用户进行交互,当 steps
块包含该指令时,会在应用 options 指令后,执行 agent / when 指令之前暂停当前阶段。
包含以下参数:
- message:必填,填写 input 表单时的展示内容
- id:可选,input 指令的标识符,默认为
stage
名称 - ok:可选,input 表单的 ok 按钮文本
- submitter:可选,指定允许提交 input 的用户或外部组名称,管理员不受影响(Jenkins 权限配置需安装 Role-based Authorization Strategy 插件)
- submitterParameter:可选,会返回提交 input 的用户 ID
- parameters:可选,提示用户需要提供的可选参数列表
pipeline {
agent any
stages {
stage('Example') {
input {
message "Should we continue?"
ok "Yes, we should."
submitter "alice, bob"
submitterParameter "SUBMITTER_ID"
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
}
}
steps {
echo "Hello, ${PERSON} and ${SUBMITTER_ID}"
}
}
}
}




分布式构建
控制器隔离
Jenkins 服务属于 Controller/Agent 架构,服务自带一个**内置节点(built-in node)**用于执行构建操作,开箱即用。这是为了更容易使用 Jenkins,但并不推荐长久使用,因为在内置节点上运行的任何构建都具有与 Jenkins 进程相同的控制器文件系统访问权限级别。
Jenkins 控制器就是其服务本身,充当决定如何、何时以及在何处运行作业的角色。同时,配置、授权和身份验证等管理任务也在控制器上执行,该控制器为 HTTP 请求提供服务。
而代理是负责执行具体作业的服务,它是一个小型 Java 客户端进程,与 Jenkins 控制器建立连接后,由控制器委托作业给其执行。
而在内置节点和代理节点中,都有各自的 Executor(执行器),其本质是一个线程,其数量决定了可以并发运行的任务数量。
为了确保 Jenkins 控制器的稳定性,应在内置节点以外的其它节点上(即代理)执行构建,这在 Jenkins 中称为分布式构建(distributed builds)。
分布式构建的存在意义是为了解决两种情况:
- 垂直增长:是指通过配置更多作业或编排更频繁的构建来增加 Jenkins 控制器实例上的负载,这也可能意味着更多的团队依赖于这个控制器(单点风险);
- 水平增长:是指创建额外的 Jenkins 控制器(即运行多个 Jenkins 服务)来适应新的团队或项目,而不是向现有控制器添加新的团队或项目(分开但缺乏统一管理)。
在分布式构建环境中,Jenkins 控制器将仅使用其资源来处理 HTTP 请求和管理构建环境。构建的实际执行将委托给代理。使用此配置,可以水平扩展架构,从而允许单个 Jenkins 安装托管大量项目和构建环境。
要防止构建直接在内置节点上运行,可导航至 Jenkis 的 Manage Jenkins => Nodes。在列表中选择 Built-In Node => Configure。将 executor 数量设置为 0 并保存。同时应确保已设置了其它构建节点(或 Cloud)得以执行构建,否则构建将无法执行。或者在配置了多节点后,可使用 Job Restrictions Plugin 之类的插件来限制哪些 Job 可以在哪些节点(如内置节点)上运行(这与 Jenkinsfile 中的 agent { label ... }
通过标签指定构建节点的表达式无关)。
TIP在 Jenkins 中,Agent(代理)也可称为 Node(节点),两者等价。
配置代理
代理本质是一个 Java 服务,因此需要有 JDK 环境,不过下面以 Docker 为例运行代理,官方镜像已包含了 JDK 环境。
- 首先在要运行代理的机器上生成密钥:
ssh-keygen -f ~/.ssh/jenkins_agent_key
- 在 Jenkins GUI 中创建 Credentials
- 在 Manage Jenkins => Credentials 选择 domains 为 global 的选项新建凭证
- Kind 选择 SSH Username with private key,自由填入 ID、Description、Username,Private Key 则直接拷贝步骤 1 生成密钥,Passphrase 是密码,生成密钥时有填则填,无则忽略,然后创建凭证即可。
- 运行代理,宿主机端口可自定义:
docker run -d --rm --name=agent1 -p 22:22 \
-e "JENKINS_AGENT_SSH_PUBKEY=[拷贝步骤 1 生成的公钥]" \
jenkins/ssh-agent:alpine-jdk21
- 在 Jenkins 上设置代理
- 进入 Manage Jenkins => Nodes 新建节点,输入节点名称并选择类型(仅有 Permanent Agent 可选)
- 详细配置信息如下图所示,而图二关于 Agent 启动方式:
- Launch agents via SSH:通过 Jenkins 控制器访问 Agent 所在机器后启动代理服务(即连接步骤 3 启动的容器),然后代理服务再与控制器进行连接
- Launch agent by connecting it to the controller:手动启动 Agent 服务后,直接连接到 Jenkins 控制器,该方式可看官文


- 节点新建后,会默认启动一次,但会因为密钥授权问题而失败。选择节点进入管理界面,点击左侧的 Trust SSH Host Key 信任密钥(即步骤 4 设置的密钥确认方式),右上角 Launch agent 再次启动即可

- 重新构建项目:在流水线项目的 Jenkinsfile 中指定
agent { label 'agent-1' }
后,在构建日志即可看到构建操作委托到 Agent 去执行了。


Jenkinsfile 与代码分离管理
Jenkins Pileline(包括多分支 Pipeline)项目要求将 Jenkinsfile 保存在代码仓库的根目录,这让 Jenkinsfile 分散到了不同项目的各个分支中,对于后期的统一维护和功能扩展增加了成本。为了将 Jenkinsfile 与代码仓库分离,可通过插件 Pipeline-multibranch-defaults-plugin 实现。
- 安装插件后,进入 Manage Jenkins => Managed files 新建配置 Groovy file,ID 可自定义,默认是 UUID,然后编写 Jenkinsfile 脚本
- 新建一个多分支流水线项目,注意本次在 Build Configuration => Mode 要选择 by default Jenkinsfile,并填入步骤 1 创建的配置文件 ID

- 首次执行构建可能会报错(如
UnapprovedUsageException: script not yet approved for use
),这是因为项目的 Jenkinsfile 若从 SCM 中获取,则默认在 Groovy 沙箱中运行,以防止出现恶意代码。而使用 default Jenkinsfile 则并非如此,因为 Jenkins 认为在配置管理中(由管理员)新增的 Jenkinsfile 会比来源 SCM 的更受信任,并且为了灵活性,避免沙箱环境中操作权限受限,会在非沙箱环境中运行。但是由于 Script Security Plugin 插件(默认安装),它会检查脚本中的方法签名是否已存在于批准列表,否则需要管理员手动批准执行脚本。- 进入 Manage Jenkins => In-process Script Approval 即可看到被拦截的脚本,选择 Approve 批准即可,重新执行构建即可成功
- 也可以直接在步骤 2 的示例图中勾选 Run default Jenkinsfile within Groovy sandbox,表示让默认的 Jenkinsfile 运行在沙箱,那么就无需进行审批

- 以下是 defualt Jenkinsfile 的示例,但要根据实际情况去调整脚本,无法 1复制使用
- 做法理解:假设创建多分支流水线项目名为 Demo-Test,然后在管理 Jenkinsfile 的仓库下创建 Demo-Test/dev、Demo-Test/test 等目录,下面放各自分支的 Jenkinsfile,通过拉取 Jenkinsfile 仓库后,以构建的作业名称和分支来加载对应 Jenkinsfile。
node {
// 保存当前运行的作业名称
def currentJobName = ""
try {
stage('Checkout Jenkinsfile') {
// 获取当前 Job 名称,并赋值给局部变量,通过 env 访问环境变量
def jobNameParts = "${env.JOB_NAME}".replace('%2F', '/').split('/')
// 注意:若流水线项目是建在文件夹下,那么直接取 0 就有问题,因为获取到的会是目录名称,而不是 Job 名称
currentJobName = jobNameParts[0]
echo "Determined job name part for loading: ${currentJobName}"
// 2. clone Jenkinsfile 仓库
git url: 'https://github.com/xxx.git', // 填写 Jenkinsfile 仓库地址,可以是 HTTP 或 SSH
branch: 'main', // 指定拉取的分支,默认是 master
credentialsId: 'jenkins' // 指定访问 SCM 的凭证,在 Jenkins 中配置后填写凭证 ID
echo "Checkout complete."
}
stage('Load Dynamic Jenkinsfile') {
// 根据 Job 名称及构建分支获取对应 Jenkinsfile
def check_groovy_file = "${currentJobName}/${env.BRANCH_NAME}/Jenkinsfile"
// load 指令用于加载 Jenkinsfile
load check_groovy_file
}
} catch (Exception e) {
// 当出现异常时,打印错误信息,并将构建结果设置为 FAILURE
echo "Pipeline failed: ${e.getMessage()}"
currentBuild.result = 'FAILURE'
throw e // 重新抛出异常,使 Pipeline 失败
} finally {
stage('Cleanup') {
echo "Performing cleanup tasks..."
cleanWs() // 可选:清理工作空间
}
}
}
NOTEdefault Jenkinsfile 之所以使用脚本式管道语法,是因为声明式管道语法规定有且仅有一个 pipeline 块,使其无法 load 同样包含 pipeline 块的 Jenkinsfile。而脚本式语法没有此类限制,能容纳此类设计为独立运行的 Jenkinsfile,故常用于编排。当然,你也可以在被 load 的文件仅编写 stages/steps 等指令从而实现构建。
如果 default jenkinsfile 指定了运行的 Agent,那么要注意 load 加载的 Jenkinsfile 是否与 default Jenkinsfile 在同一个 Agent 上运行。若是,并且该 Agent 只配置了一个 Executor,那么就会造成死锁的情况,因为对于 Jenkins 来说,这是两个任务。
总结
Jenkins Pipeline 不难理解,在明白了概念和语法后,就可以上手实操。Pipeline 也是让构建流程更加结构化,并且能像代码一样审计、迭代。对于实际项目的 CI/CD,其实在构建过程会更多的依赖 bash 脚本等的操作,如代码镜像构建、推送、K8S 部署、通知等等,有什么构建需求,就翻翻官网文档,看看提供的操作即可。