jenkins pipeline语法详解
详细说明了jenkins pipeline的语法结构和常用命令
1. 语法比较
Pipeline支持两种语法:声明式和脚本式。
1、相同点:都是"Pipeline as code"的有效实现方式;都能够使用内置于 Pipeline 或由插件提供的steps;都可以使用共享库。
2、不同点:
- 声明式语法
Declarative pipeline鼓励声明式编程模型。通过严格和预定义的结构限制了用户可用的内容,使其变得更加简单、容易上手。
- 脚本式语法
Scripted Pipeline 遵循更命令式的编程模型。就结构和语法的唯一限制往往由 Groovy 本身定义,而不是任何特定于 Pipeline 的系统,这使其具有极大的灵活性和可扩展性,成为高级用户和具有更复杂要求的用户的理想选择。
建议直接使用声明式语法,学习成本较低,适合大部分人入门。
2. 声明式语法介绍
2.1 语法结构

1、Sections
- pipeline:代表整条流水线,包含整条流水线的逻辑。
- agent:指定pipeline运行的节点,可为整个pipeline或特定stage指定运行环境,取决于所定义位置。
- stages:pipeline中多个stage的容器,至少包含一个stage,是pipeline的主体部分。
- steps:stage中的一个或多个具体步骤(step)的容器,steps部分至少包含一个步骤。
- scripts:在Declarative Pipeline中,可采用script指令来执行Scripted Pipeline中的一些脚本
- post:运行后处理步骤,根据定义的位置不同,可依据pipeline或stage的运行结果执行差异化步骤。
2、Directives
- environment:环境变量,可定义为全局变量或特定stage中的局部变量,取决于所定义位置。
- tools:构建工具,可为整个pipeline或特定stage指定在jenkins全局工具中定义过的工具的环境变量,支持maven、jdk、gradle等。
- options:定义pipeline运行时的配置选项。如历史构建记录数量保留,超时时间,失败重试等操作。
- triggers:触发器,定义pipeline运行的触发方式。
- parameters:参数,为流水线运行时设置的参数列表。
- stage:表示Pipeline的一个阶段,如checkout阶段,Build阶段,test阶段等,一个Pipeline中至少需要一个Stage。
- input:交互输入,pipeline运行到input时会自动暂停,根据输入值评估是否继续。
- when:条件判断,允许流水线根据给定的条件决定是否应该执行阶段。
2.2 语法详解
在声明式管道中有效的基本语句和表达式遵循与Groovy 语法相同的规则, 但有以下例外:
-
Pipeline 的顶层必须是一个block,具体来说:
pipeline { }. -
没有分号作为语句分隔符。每个语句都必须在自己的行中。
-
块只能由Sections、 Directives、Steps或赋值语句组成。
-
属性引用语句被视为无参数方法调用。因此,例如,
input被视为input().
您可以使用 声明式指令生成器 来帮助您开始配置声明式管道中的指令和部分。
2.2.1 Sections
2.2.1.1 agent
|
是否必须 |
YES |
|---|---|
|
参数 |
any / none / label / node / docker / dockerfile / kubernetes |
| 描述 |
指定整个Pipeline或特定stage将在Jenkins环境中执行的位置,具体取决于该agent 部分的放置位置 |
| 允许 | pipeline块内或stage指令内 |
参数说明
- any:在任意可用的 agent 上执行Pipeline或stage
- none:在pipeline块的顶层应用时,不会为整个 Pipeline运行分配全局代理,且每个stage中都需要自行定义agent。
- label:在指定标签(或标签条件)的agent中执行Pipeline或stage
- node:使用与lable类似,但node允许附加选项(例如customWorkspace)
- docker:执行Pipeline或stage时会动态供应一个docker节点去接受Docker-based的Pipelines
- dockerfile:使用从Dockerfile源存储库中包含的容器构建的容器执行Pipeline或stage,Jenkinsfile 必须从多分支 Pipeline或 SCM Pipeline加载。
- kubernetes:在Kubernetes集群上部署的Pod内执行 Pipeline或stage,同样Jenkinsfile 必须从多分支 Pipeline或 SCM Pipeline加载,Pod模板在kubernetes {} 块内定义。
参考案例
pipeline {
agent any
agent none
agent {
label 'my-label1 && my-label2'
}
agent { node { label 'labelName' } } // 等同于 agent { label 'labelName' }
// docker 还可以接受一个args直接传递给`docker run`调用以及一个 alwaysPull 选项
// registryUrl和registryCredentialsId参数 有助于指定要使用的Docker注册表及其凭据
agent {
docker {
image 'maven:3-alpine'
label 'my-defined-label'
args '-v /tmp:/tmp'
registryUrl 'https://myregistry.com/'
registryCredentialsId 'myPredefinedCredentialsInJenkins'
}
}
// dockerfile
agent {
// 等同于 to "docker build -f Dockerfile.build --build-arg version=1.0.2 ./build/
dockerfile {
filename 'Dockerfile.build'
// 如果要Dockerfile在另一个目录中构建,请使用以下dir选项
dir 'build'
label 'my-defined-label'
additionalBuildArgs '--build-arg version=1.0.2'
args '-v /tmp:/tmp'
// 同样也接受registryUrl和registryCredentialsId参数
registryUrl 'https://myregistry.com/'
registryCredentialsId 'myPredefinedCredentialsInJenkins'
}
}
// kubernetes: 例如如果要在其中装有Kaniko容器的容器
agent {
kubernetes {
label podlabel
yaml """
kind: Pod
metadata:
name: jenkins-agent
spec:
containers:
- name: kaniko
image: gcr.io/kaniko-project/executor:debug
imagePullPolicy: Always
command:
- /busybox/cat
tty: true
volumeMounts:
- name: aws-secret
mountPath: /root/.aws/
- name: docker-registry-config
mountPath: /kaniko/.docker
restartPolicy: Never
volumes:
- name: aws-secret
secret:
secretName: aws-secret
- name: docker-registry-config
configMap:
name: docker-registry-config
"""
}
} |
2.2.1.2 stages
|
是否必须 |
YES |
|---|---|
|
参数 |
None |
| 描述 |
stages 是 Pipeline描述的大部分“工作”所在的位置, 该部分包含一个或多个阶段指令的序列。对于连续交付过程的每个离散部分,建议stages至少包含一个阶段指令,例如Build,Test,Deploy等 |
| 允许 | pipeline块内,有且仅有一次 |
参考案例
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
} |
2.2.1.3 steps
|
是否必须 |
YES |
|---|---|
|
参数 |
None |
| 描述 |
stage中的一个或多个具体步骤(step)的容器,steps部分至少包含一个步骤。 |
| 允许 | stage指令内 |
steps中的一些常用操作
- error:抛出异常,中断整个pipeline
- timeout: 超时
- waitUntil: 循环运行闭包内容,直到返回true,通常与timeout一起使用
- retry:失败重试
- sleep:睡眠,默认单位秒
pipeline{
agent any
stages{
stage('stash'){
parallel('测试') {
stage('轮询') {
steps{
timeout(time:10, unit:"SECONDS"){
waitUntil{
script{
def rs = sh script: 'docker version', returnStatus: true
return (rs == 0)
}
}
}
}
}
stage('重试') {
steps{
retry(3){
script{
sh script: 'curl https://www.baidu.com', returnStatus: true
}
sleep(3)
}
}
}
stage('错误') {
steps{
retry(3){
error("执行失败")
}
}
}
}
}
}
} |
2.2.1.5 post
|
是否必须 |
NO |
|---|---|
|
参数 |
always / changed / fixed / regression / aborted / failure / success / unstable / unsuccessful / cleanup |
| 描述 |
定义Pipeline或stage运行结束时的操作, 比如消息通知、执行其他job等 |
| 允许 | pipeline块内或stage指令内 |
参数说明
- always :无论运行结果如何,都运行本节中的步骤。
- changed :当前运行结果与之前的运行结果不同时才运行步骤。
- fixed :当前运行成功并且之前的运行失败或不稳定时才运行步骤。
- regression :当前运行失败、不稳定或中止,并且上一次运行成功时,才运行步骤。
- aborted :当前运行中止时才运行步骤,通常是由于手动中止了 Pipeline。通常在web UI中用灰色表示。
- failure :当前运行失败时才运行步骤,通常在Web UI中用红色表示。
- success :当前运行成功时才运行步骤,通常在Web UI中用绿色表示。
- unstable :当前运行不稳定(通常由测试失败,代码冲突等引起)时才运行步骤,通常在Web UI中以黄色表示。
- unsuccessful :当前运行状态不是“成功”时才运行步骤。
- cleanup :其他 post 过程执行完毕后执行,与pipeline和stage运行结果无关。
特殊说明:cleanup和always的区别在于,cleanup会在其他任意一个post执行之后执行。
参考案例
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
post {
always {
echo 'I will always say Hello again!'
}
}
} |
2.2.2 Directives
2.2.2.1 environment
|
是否必须 |
NO |
|---|---|
|
参数 |
None |
| 描述 |
environment指令指定了一系列键值对,这些键值对将被定义为所有步骤或特定阶段步骤的环境变量,具体取决于environment指令在管道中的位置。 |
| 允许 | pipeline块内或stage指令内 |
特别说明:
- environment中的变量将写入到Linux环境变量之中作为全局变量,在shell中可通过变量名访问,而在script pipeline脚本中则需要通过env.变量名称访问。
- 该指令支持一种特殊的辅助方法credentials(),可用于在 Jenkins 环境中通过其标识符访问预定义的凭据。
支持的凭证类型:
- Secret Text :设置为加密文本字符串内容
- Secret File : 设置为临时创建的文件文件的位置, 并自动定义变量存储该文件内容。
- Username and password : 将设置为username:password并且两个其他环境变量将自动定义为MYVARNAME_USR 和MYVARNAME_PSW。
- SSH with Private Key : 设置为临时创建的SSH密钥文件的位置,并且可能会自动定义两个其他环境变量:MYVARNAME_USR和MYVARNAME_PSW(保留密码)。
参考案例
pipeline {
agent any
//定义在pipeline块中,定义的环境变量可应用于Pipeline中的所有步骤。
environment {
CC = 'clang'
}
stages {
stage('Example') {
//在 stage 中定义的 environment指令只会将给定的环境变量应用于Example内的步骤。
environment {
// 在environment块中credentials('凭据名称')定义的帮助程序方法通过其在Jenkins环境中的标识符来访问预定义的凭据
AN_ACCESS_KEY = credentials('wuzz')
}
steps {
sh 'printenv'
echo "${env.AN_ACCESS_KEY}"
echo "${env.CC}"
}
}
}
} |
pipeline {
agent any
environment {
APP_NAME = 'clang'
}
stages {
stage('Example Username/Password') {
environment {
// 变量 = 将用户密码凭证赋予变量
SERVICE_CREDS = credentials('wuzz')
}
steps {
// 注意点: defined: MYVARNAME_USR and MYVARNAME_PSW respectively.
sh 'echo "Service user is $SERVICE_CREDS_USR"'
sh 'echo "Service password is $SERVICE_CREDS_PSW"'
sh 'curl -u $SERVICE_CREDS http://192.168.49.22:8040'
}
}
stage('Example SSH Username with private key') {
environment {
// 变量 = 将 `ssh private` 公密钥进行赋予变量
SSH_CREDS = credentials('wuzz')
}
steps {
// 注意点: defined: MYVARNAME_USR and MYVARNAME_PSW (holding the passphrase).
sh 'echo "SSH private key is located at $SSH_CREDS"'
sh 'echo "SSH user is $SSH_CREDS_USR"'
sh 'echo "SSH passphrase is $SSH_CREDS_PSW"'
// 调用内置变量 (如果变量不存在则输出null) - 值得学习注意。
echo "${JOB_NAME}"
echo env.'JOB_NAME'
println(env.'JOB_NAME')
// 自定义全局变量方式(写入文件中再读取)
script {
sh 'touch ${APP_NAME}'
def projectProduct = sh returnStdout: true, script: "find ${APP_NAME}"
if ( projectProduct != '' ){
echo "${projectProduct}"
writeFile file: 'abc.sh', text: "${projectProduct}"
change_id = readFile 'abc.sh'
print(change_id)
} else {
error "[-Error] : projectProduct 不能为空!"
}
}
}
}
}
} |
2.2.2.2 options
|
是否必须 |
NO |
|---|---|
|
参数 |
None |
| 描述 |
定义流水线运行时的配置选项,常用的有 timeout()、retry() |
| 允许 | pipeline块内且只有一次 |
可用选项
- buildDiscarder: 保存最近历史构建记录的数量。
options { buildDiscarder(logRotator(numToKeepStr: '1')) } - disableConcurrentBuilds: 禁止管道的并发执行。可用于防止同时访问共享资源等。
options { disableConcurrentBuilds() } - checkoutToSubdirectory: Jenkins从版本控制库拉取源码时,默认检出到工作空间的根目录中,此选项可以指定检出到工作空间的子目录中。
options { checkoutToSubdirectory('foo') } - newContainerPerStage: 当agent为docker或dockerfile时,指定在同一个Jenkins节点上,每个stage都分别运行在一个新的容器中,而不是所有stage都运行在同一个容器中。
- disableResume: 禁用恢复,如果控制器重新启动,则不允许pipeline恢复。
options { disableResume() } - overrideIndexTriggers: 允许重写多分支流水线的触发器
# 仅为该作业启用分支索引触发器
options { overrideIndexTriggers(true) }
# 仅为此作业禁用分支索引触发器
options { overrideIndexTriggers(false) } - preserveStashes: 保留最近几次构建中的stash
options { preserveStashes(buildCount: 5) } - quietPeriod: 设置 Pipeline的静默时间段(以秒为单位),以覆盖全局默认值
options { quietPeriod(30) } - retry:如果失败重试整个Pipeline指定次数。该次数是指总次数包括第1次失败。
options { retry(3) } - skipDefaultCheckout: 跳过默认的代码检出(暂未研究出具体用法)。
options { skipDefaultCheckout() } - skipStagesAfterUnstable: 一旦构建状态变得不稳定就跳过各个阶段;
options { skipStagesAfterUnstable() } - timestamps: 为Pipeline 运行生成的所有控制台输出添加时间戳。
options { timestamps() } - parallelsAlwaysFailFast :将 Pipeline中所有后续并行阶段的failfast设置为true。
options { parallelsAlwaysFailFast() }
在包含 Parallel或Matrix 的stage中也可添加 failFast true,Parallel或 Matrix中任何一个单元失败时全部终止。
- timeout(常用): 设置 Pipeline运行的超时时间。
options { timeout(time: 1, unit: 'HOURS') }
参考案例
# Global Timeout, Declarative Pipeline
pipeline {
agent any
options {
// 将全局执行超时指定为一小时,然后Jenkins将中止 Pipeline运行。
timeout(time: 1, unit: 'HOURS')
}
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
Tips: 在 stage 块中支持的 options 要少于 pipeline 块中,只能使用skipDefaultCheckout,timeout,retry,timestamps 等选项 |
2.2.2.3 parameters
|
是否必须 |
NO |
|---|---|
|
参数 |
None |
| 描述 |
参数,为流水线运行时设置相关的参数,不需要在UI界面上额外定义。 |
| 允许 | pipeline块内且只有一次 |
Tips :
- 全局参数, 在shell可通过变量名访问,而在script pipeline脚本中通过params.参数名称访问,如${params.enter_txt}
-
parameters定义之后,需要手动构建一次,才会自动加载到配置好的参数化构建中。
可用参数类型:
//布尔参数
booleanParam(name: 'co',description: '是否检出代码',defaultValue: true )
//字符参数
string(name:'branch',defaultValue:'master', description: '')
//多行文本
text(name: 'enter_txt', defaultValue: 'dfdfv', description: 'Enter some information')
//加密文本
//password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
//单选框
choice(name: 'CHOICE', choices: ['server1', 'server2', 'server3'], description: '请选择需要集成的服务')
//多选框
extendedChoice defaultValue: 'server1', description: '请选择需要集成的服务', multiSelectDelimiter: ',', name: 'server', quoteValue: false, saveJSONParameterToFile: false, type: 'PT_CHECKBOX', value: 'server1,server2,server3,server4', visibleItemCount: 4
参考案例
pipeline {
agent any
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')
booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')
choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
}
stages {
stage('Example') {
steps {
echo "Hello ${params.PERSON}"
echo "Biography: ${params.BIOGRAPHY}"
echo "Toggle: ${params.TOGGLE}"
echo "Choice: ${params.CHOICE}"
echo "Password: ${params.PASSWORD}"
}
}
}
} |
2.2.2.4 triggers
|
是否必须 |
NO |
|---|---|
|
参数 |
None |
| 描述 |
定义Pipeline自动触发的方式 |
| 允许 | pipeline块内且只有一次 |
Tips :
- 全局参数, 在shell可通过变量名访问,而在script pipeline脚本中通过params.参数名称访问,如${params.enter_txt}
-
parameters定义之后,需要手动构建一次,才会自动加载到配置好的参数化构建中。
可用触发器:
- cron : 以Linux中Cron风格的字符串,定时触发
triggers { cron('H */4 * * 1-5') }
- pollSCM : 定时轮询SCM仓库,检测到有更新才触发
triggers { pollSCM('H */4 * * 1-5') }
- upstream : 接受以逗号分隔的作业字符串和阈值。当字符串中的任何作业以最小阈值结束时 Pipeline将被重新触发
triggers { upstream(upstreamProjects: 'job1,job2', threshold: hudson.model.Result.SUCCESS) }
- 其他:插件集成或其他webhook触发,如gitlab
gitlab(triggerOnPush: true, triggerOnMergeRequest: true, branchFilterType: 'All')
2.2.2.5 Jenkins cron syntax
Jenkins cron 语法遵循 cron 实用程序的语法(略有不同)。具体来说,每一行由 5 个字段组成,由 TAB 或空格分隔:
| MINUTE | HOUR | DOM | MONTH | DOW |
|---|---|---|---|---|
|
一小时内的分钟数 (0–59) |
一天中的小时 (0–23) |
月份中的某天 (1–31) |
月份 (1–12) |
星期几 (0–7),其中 0 和 7 是星期日。 |
运算符
* :指定所有有效值
M-N :指定值范围
M-N/X or */X :在指定范围或整个有效范围内按X的间隔步进
A,B,…,Z :枚举多个值
Tips :
- H字符:在 Cron 中使用 H 字符为了使定期计划的任务在系统上产生均匀的负载,H符号可以被认为是在一定范围内的随机值。
例如使用0 0 * * *一打日常工作将导致午夜时分大幅增加。
相反使用H H * * *仍会每天执行一次每个作业,但不是同时执行所有作业,更好地使用有限的资源。
- @yearly,@annually,@monthly, @weekly,@daily,@midnight,并且@hourly也支持方便的别名。这些使用哈希系统进行自动平衡。
@hourly与H * * * *相同,表示该小时中的任何时间
@midnight实际上是指在12:00 AM和2:59 AM之间的某个时间。
参考案例
#每十五分钟一次(可能在 :07, :22, :37, :52)
triggers{ cron('H/15 * * * *') }
#每小时前半段每十分钟一次(三次,可能在 :04, :14, :24)
triggers{ cron('H(0-29)/10 * * * *') }
#每两小时一次,时间为每个工作日上午 9 点 45 分至下午 3 点 45 分,整点后 45 分钟。
triggers{ cron('45 9-16/2 * * 1-5') }
#每个工作日上午 9 点到下午 5 点之间每两小时一次(可能在上午 10 点 38 分、下午 12 点 38 分、下午 2 点 38 分、下午 4 点 38 分)
triggers{ cron('H H(9-16)/2 * * 1-5') }
#除 12 月外,每月 1 日和 15 日每天一次
triggers{ cron('H H 1,15 1-11 *') } |
2.2.2.6 stage
|
是否必须 |
YES |
|---|---|
|
参数 |
steps,必填 |
| 描述 |
stage 指令位于stages中并且应包含Step,可选 agent或其他特定指令, 实际上pipeline所有实际工作都将包含在一个或多个stage中。 |
| 允许 | 在 Pipeline块 -> stages内 |
参考案例
// Declarative
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
} |
2.2.2.7 tools
|
是否必须 |
NO |
|---|---|
|
参数 |
None |
| 描述 |
定义工具,获取通过自动安装或手动安装工具的环境变量,支持maven、jdk、gradle,工具的名称必须预先在Jenkins的系统设置->全局工具配置中定义,才可在pipeline中引用。 |
| 允许 | pipeline块内或stage指令内 |
参考案例
pipeline {
agent any
tools {
maven 'apache-maven-3.0.1'
}
stages {
stage('Example') {
steps {
sh 'mvn --version'
}
}
}
} |
2.2.2.8 input
|
是否必须 |
NO |
|---|---|
|
参数 |
None |
| 描述 |
交互输入,pipeline运行到input时会暂停,等待输入后,如果input 批准,stage将继续。作为input输入提供的任何参数在后续其他stage中均可用。 |
| 允许 | stage指令内 |
配置选项
- message
必填,input界面提示用户的信息 - id
此input的可选标识符,默认为stage名称 - ok
input界面上“确定”按钮的可选文本 - submitter
允许提交此input的用户或外部组名称,多个用户可用,分隔,默认允许任何用户。 - submitterParameter
提交者参数 - parameters
提示提交者提供的可选参数列表。
参考案例
pipeline {
agent any
stages {
stage('Example') {
// 方式1.此种方式只能该块有效
input {
message "Title : 个人信息输入"
ok "完成提交"
submitter "alice,bob"
parameters {
string(name: 'INPUT_PERSON', defaultValue: 'WeiyiGeek', description: 'Message: 请输入您的姓名?')
string(name: 'INPUT_AGE', defaultValue: 'WeiyiGeek', description: 'Message: 请输入您的年龄?')
choice(name: 'INPUT_SEX', choices: ['Male','Female'], description: 'Message: 请选择你的性别?')
booleanParam(name: 'INPUT_AGREE', defaultValue: true, description: 'Message: 是否确定协议?')
}
}
steps {
// 方式2: 注意script必须包含在 steps 块之中(此种方式可以全局传递参数)
script {
env.git_version=input message: 'Titel: 版本', ok: '通过',parameters: [string ( name: 'git_version', trim: true, description: 'Message : 请选择要操作的应用版本?')];
env.deploy_option = input message: 'Titel: 操作', ok: 'deploy', parameters: [choice(name: 'deploy_option', choices: ['deploy', 'rollback', 'redeploy'], description: 'Message : 请选择操作流程?')];
}
// 12.input 输出示例
echo "局部可用 输出示例1: 姓名:${INPUT_PERSON}, 年龄:${INPUT_AGE}, 性别:${INPUT_SEX}, 是否同意协议: ${INPUT_AGREE}"
echo "全局可用 输出示例(script) -> 版本 : ${env.git_version}"
echo "全局可用 输出示例(script) -> 版本 : ${env.deploy_option}"
}
}
// 采用script块中定义input可以调用不同stage中得参数值
stage ('调用') {
steps {
echo "调用1 : ${env.git_version}"
echo "调用2 : ${env.deploy_option}"
}
}
}
} |
2.2.2.9 when
|
是否必须 |
NO |
|---|---|
|
参数 |
条件判断,允许流水线根据给定的条件决定是否应该执行阶段,when 指令必须包含至少一个条件,如果when指令包含多个条件,则所有子条件必须返回true才能执行该阶段。 |
| 允许 | stage指令内 |
嵌套条件:
- allOf:所有条件为真才继续执行。
when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }
- anyOf:任意一个条件为真就执行。
when { anyOf { branch 'master'; branch 'staging' } }
- not:条件为false时才执行
when { not { branch 'master' } }
内置条件
- branch : 当正在构建的分支与给出的分支模式匹配时执行,仅适用于多分支流水线;
when { branch 'master' }
- environment : 当指定的环境变量设置为给定值时执行,
when { expression { return params.DEBUG_BUILD } }
- equals : 当期望值等于实际值时执行阶段,
when { equals expected: 2, actual: currentBuild.number }
- expression : 在指定的Groovy表达式计算为true时执行
注意:当从表达式返回字符串时,它们必须被转换为布尔值,或者返回null来计算为false。简单地返回"0"或"false"仍然会计算为"true"。
when { expression { return params.DEBUG_BUILD } }
- Tag : 如果TAG_NAME变量匹配给定的模式则执行该阶段, 注意如果提供了一个空模式,那么阶段将在TAG_NAME变量存在时执行(与buildingTag()相同)。
when { tag "release-*" }
- buildingTag : 执行构建构建标签的阶段.
when { buildingTag() }
- changelog : 如果构建的SCM更改日志包含给定的正则表达式模式则执行阶段;
when { changelog '.*^\\[DEPENDENCY\\] .+$' }
- changeset : 如果构建的SCM变更集包含一个或多个与给定模式匹配的文件,则执行阶段。
when { changeset "**/*.js" }
when { changeset pattern: ".TEST\\.java", comparator: "REGEXP" } // 正则表达式匹配
when { changeset pattern: "*/*TEST.java", caseSensitive: true } // 区分大小写ANT样式路径
- changeRequest : 如果当前构建是针对“变更请求”的,则执行阶段(也称为GitHub和Bitbucket上的Pull Request,GitLab上的Merge Request,Gerrit变更等)。如果未传递任何参数,则阶段将在每个更改请求上运行
when { changeRequest() }.
可用属性: id / target / branch / fork / url / title / author / authorDisplayName / authorEmail
// 每一个都对应一个CHANGE_*环境变量,
when { changeRequest target: 'master' }.
// comparator 参数后指导属性,以指定匹配时如何计算任何模式:
// * EQUALS用于简单的字符串比较(默认值),
// * GLOB用于ANT风格的路径GLOB(与例如changeset相同),
// * REGEXP用于正则表达式匹配
when { changeRequest authorEmail: "[\\w_-.]+@example.com", comparator: 'REGEXP' }
- triggeredBy : 在给定的参数触发当前构建时执行该阶段。
when { triggeredBy 'SCMTrigger' }
when { triggeredBy 'TimerTrigger' }
when { triggeredBy 'UpstreamCause' }
when { triggeredBy cause: "UserIdCause", detail: "vlinde" }
优先级说明
- when在input指令前评估 : 默认情况下,如果stage中定义了input,则将在input输入后评估该stage的 when 条件。 如果beforeAgent设置为 true,将首先评估 when 条件,只有当 when 条件为 true 时才会进入input。
- when在options指令前评估 : 同上,如果beforeOptions设置为true,将首先评估 when 条件,只有当 when 条件为 true 时才会输入options值。
- when在stage进入agent前评估 : 同上,如果beforeAgent被设置为true,将首先评估 when 条件,只有当when条件为true时才会进入agent。
参考案例
pipeline {
agent none
stages {
stage('Example Build') {
steps {
echo 'Hello World'
}
}
stage('beforeinput') {
when {
beforeInput true // 关键点
branch 'production'
}
input {
message "Deploy to production?"
id "simple-input"
}
steps {
echo 'Deploying'
}
}
stage('beforeagent') {
agent {label "wuzz"}
when {
beforeAgent true // 关键点
branch 'production'
}
steps {
echo 'Deploying'
}
}
stage('beforeoption') {
when {
beforeOptions true // 关键点
branch 'testing'
}
options {
lock label: 'testing-deploy-envs', quantity: 1, variable: 'deployEnv'
}
steps {
echo "Deploying to ${deployEnv}"
}
}
}
} |
参考案例
pipeline {
agent none // beforeAgent
stages {
stage('Example Build') {
steps {
echo 'Hello World'
}
}
stage('Example Deploy') {
// Single Condition - 单一条件
when {
branch 'production'
}
// Multiple Condition - 多重条件
when {
branch 'production'
environment name: 'DEPLOY_TO', value: 'production'
}
// Nested condition - 嵌套条件
when {
allOf {
branch 'production'
environment name: 'DEPLOY_TO', value: 'production'
}
}
// Multiple condition and nested condition - 注意点
when {
branch 'production'
anyOf {
environment name: 'DEPLOY_TO', value: 'production'
environment name: 'DEPLOY_TO', value: 'staging'
}
}
// Expression condition and nested condition - 表达式条件和嵌套条件
when {
expression { BRANCH_NAME ==~ /(production|staging)/ }
anyOf {
environment name: 'DEPLOY_TO', value: 'production'
environment name: 'DEPLOY_TO', value: 'staging'
}
}
// triggeredBy
when {
triggeredBy "TimerTrigger" // 当前Job设置的触发器名称进行监控
}
// 当前面的when都满足时采用执行该阶段步骤,否则丢弃
steps {
echo 'Deploying'
}
}
}
} |
2.2.3 Sequential Stages
声明式pipeline的stages可能有一个包含要按顺序运行的嵌套阶段列表的stage节。
- 一个stage必须具有且只有一个steps, stages, parallel, 或者 matrix。
- 如果stage指令嵌套在parallel 或者 matrix内,则不能在stage指令内嵌套parallel 或者 matrix。 但是,parallel 或者 matrix中的stage指令可以使用stage的所有其他功能,包括agent, tools, when等。
2.2.4 Parallel
Pipeline默认是串行,可以通过parallel配置并行构建,stage可以在他们内部声明多嵌套阶段, 它们将并行执行,一个stage只能有一个 steps 或 parallel。
- 在包含 Parallel的stage中可添加 failFast true,Parallel中任何一个单元失败时全部终止。
参考案例
pipeline {
agent none
options {
parallelsAlwaysFailFast()
}
stages {
// 非时序的阶段
stage('Non-Sequential Stage') {
agent {
label 'wuzz'
}
steps {
echo "On Non-Sequential Stage"
}
}
// 顺序阶段
stage('Sequential Stage') {
agent {
label 'wuzz'
}
environment {
FOR_SEQUENTIAL = "some-value"
}
// 注意点1:
stages {
stage('In Sequential 1') {
steps {
echo "In Sequential 1"
}
}
stage('In Sequential 2') {
steps {
echo "In Sequential 2"
}
}
// 注意点2:可以使用stage的所有其他功能,包括代理、工具、when等
stage('Parallel Stage') {
//在任何一个阶段失败时强制终止所有并行阶段
failFast true
parallel {
stage('Branch A') {
steps {
echo "On Branch A"
}
}
stage('Branch B') {
steps {
echo "On Branch B"
}
}
stage('Branch C') {
stages {
stage('Nested 1') {
steps {
echo "In stage Nested 1 within Branch C"
}
}
stage('Nested 2') {
steps {
echo "In stage Nested 2 within Branch C"
}
}
}
}
}
}
}
}
}
} |
2.2.5 Matrix
matrix定义要并行运行的<名称-值>组合的多维矩阵模型。我们将把这些组合称为 Matrix 中的cell。
- Matrix 中的每个单元可以包括一个或多个stage,使用该单元的配置按顺序运行。注意一个stage必须有且只有一个步骤、阶段、并行或 Matrix 。
- 如果stage指令嵌套在一个并行块或 Matrix 块本身中,则不能在stage指令中嵌套一个并行块或 Matrix 块。然而,一个并行或 Matrix 块中的stage指令可以使用stage的所有其他功能,包括agent、tools、when等。
- 在包含Matrix 的stage中可添加 failFast true,Matrix中任何一个单元失败时全部终止。
matrix组成
- axes:轴线,指定了一个或多个axis指令。每个轴由一个名称和一个值列表组成。每个轴上的所有值都与其他轴上的值组合起来生成单元格。
- excludes:排除,exclude中的axis指令生成一组组合,用于排除axes中生成的组合中需要排除的单元格。
当处理一长串要排除的值时 exclude axis指令可以使用 notValues 代替 values.这将排除与传递给notValues的值之一不匹配的单元格。
- stages:指定每个单元中要顺序执行的一个或多个stage
参考案例
pipeline {
// 参数选择
parameters {
choice(name: 'PLATFORM_FILTER', choices: ['all', 'linux', 'windows', 'mac'], description: 'Run on specific platform')
}
agent none
stages {
stage('BuildAndTest') {
matrix {
agent {
label "wuzz"
}
when { anyOf {
// 参数选择不为空时继续执行
expression { params.PLATFORM_FILTER == 'all' }
expression { params.PLATFORM_FILTER == env.PLATFORM }
} }
// 2 轴 (3 x 4) 十二格组合方式
axes {
axis {
name 'PLATFORM'
values 'linux', 'windows', 'mac'
}
axis {
name 'BROWSER'
values 'firefox', 'chrome', 'safari', 'edge'
}
}
// 排除指定Matrix矩阵中的值 (排除linux和safari组合,并排除使用edge浏览器的任何非windows平台。)
// 即 排除 (linux,safari) , (linux,edge) , (mac,edge) 三种情况
excludes {
exclude {
axis {
name 'PLATFORM'
values 'linux'
}
axis {
name 'BROWSER'
values 'safari'
}
}
exclude {
axis {
name 'PLATFORM'
notValues 'windows'
}
axis {
name 'BROWSER'
values 'edge'
}
}
}
stages {
stage('Build') {
steps {
echo "Do Build for ${PLATFORM} - ${BROWSER}"
}
}
stage('Test') {
steps {
echo "Do Test for ${PLATFORM} - ${BROWSER}"
}
}
}
}
}
}
} |
2.2.4 script
|
是否必须 |
NO |
|---|---|
|
参数 |
None |
| 描述 |
在Declarative Pipeline中,可采用script指令来执行Scripted Pipeline中的一些脚本 |
| 允许 | stage指令内 |
参考案例
pipeline {
agent any
stages {
stage('Example') {
steps {
script {
def browsers = ['chrome', 'firefox']
for (int i = 0; i < browsers.size(); ++i) {
echo "Testing the ${browsers[i]} browser"
}
}
}
}
}
} |
2.3 Basic Steps
2.3.1 字符串和标准输出
2.3.1.1 echo
echo "Hello" |
2.3.1.2 println
println "World!" |
2.3.2 文件目录相关操作
2.3.2.1 isUnix
检查是否在类 Unix环境(如Linux或Mac OS X)上运行,是则返回true,否则返回false。
node {
if(isUnix()){
echo "is unix"
}
} |
2.3.2.2 pwd
查看当前路径
2.3.2.3 dir
改变当前目录,默认pipeline工作在当前job的workspace目录下,dir步骤可以让我们切换到其他目录,且在当前块中均会以此路径为base路径。
node {
dir('123') {
sh """ mkdir 333;cd 333;pwd """
}
} |
2.3.2.4 deleteDir
是一个无参步骤删除的是当前工作目录。通常它与dir步骤一起使用,用于删除指定目录下的内容。
node {
dir('123') {
sh 'touch 1.txt;ls'
deleteDir()
sh 'ls'
}
} |
2.3.2.5 fileExists
检查给定的文件(作为当前目录的相对路径)是否存在。参数file返回 true | false 。
node {
if(fileExists('123/1.txt') == true){
echo "file exists"
}
} |
2.3.2.6 writeFile
将内容写入文件
node {
if(fileExists('123/1.txt') == true){
}
} |
2.3.2.7 readFile
读取文件内容
node {
if(fileExists('123/1.txt') == true){
def data = readFile(file: '123/1.txt')
println(data)
//按行打印,打印一行之后暂停2秒
Thread.sleep(2000)
//按行读取
def lines = data.readLines()
//使用for循环遍历每行
for (line in lines) {
println(line)
//假如是一个csv文件,每行都是以逗号分隔的参数,可以使用split取每一列
String[] str;
str = line.split(',');
println('projectkey:' + str[0])
println('reponame:' + str[1])
println('giturl:' + str[2])
}
}
} |
2.3.3 制品相关操作
2.3.3.1 stash
- stash:暂存一些文件供稍后在构建中使用
- unstash: 释放暂存的文件
参考案例
node {
stash excludes: '2.txt', includes: '
', name: 'txtstash'
}
node {
unstash 'txtstash'
} |
2.3.3.2 archiveArtifacts
- archiveArtifacts:存档构建的成品
- archive:新版本中由archiveArtifacts取代
- unarchive: 将存档的工件复制到工作区
node {
archiveArtifacts allowEmptyArchive: true, artifacts: '123/*.txt', excludes: '2.txt', fingerprint: true, onlyIfSuccessful: true
}
node {
unarchive mapping: ['123/*.txt': '222/']
} |
2.3.3.3 wrap
通用构建包装器:某些特殊的步骤允许调用构建包装器(在freestyle或类似项目中也称为“环境配置”)
node {
wrap([$class: 'TimestamperBuildWrapper']) {
echo "hello world"
}
} |
2.3.4 命令相关操作
2.3.4.1 withEnv
设置环境变量:在块中设置一个或多个环境变量, 这些可用于该范围内生成的任何外部流程。
node {
withEnv(['MYTOOL_HOME=/usr/local/mytool']) {
sh '$MYTOOL_HOME/bin/start'
}
withEnv(['name=tester']) {
echo "$name"
}
} |
Tips: 注意这里我们在Groovy中使用了单引号,所以变量展开是由Bourne shell完成的而不是Jenkins
2.3.4.2 withCredentials
将secret与变量对应起来。在jenkins中创建的密钥,在Pipeline中希望通过变量方式引用,可以通过withCredentials实现。
node {
withCredentials([usernamePassword(credentialsId: 'wuzz', passwordVariable: 'password', usernameVariable: 'username')]) {
sh 'echo $username'
}
} |
Tips: 注意这里我们在Groovy中使用了单引号,所以变量展开是由Bourne shell完成的而不是Jenkins
2.3.4.3 sh\bat\powershell
shell\bat\powershell支持的参数和步骤基本一致,以shell为例
参数说明
script:将要执行的shell脚本,通常在类UNIX系统上可以是多行脚本。
encoding:脚本执行后输出日志的编码,默认值为脚本运行所在系统的编码。
returnStatus:布尔类型,默认脚本返回的是状态码,如果是一个非零的状态码,则会引发pipeline执行失败。如果 returnStatus 参数为true,则不论状态码是什么,pipeline的执行都不会受影响。
returnStdout:布尔类型,如果为true,则任务的标准输出将作为步骤的返回值,而不是打印到构建日志中(如果有错误,则依然会打印到日志中)。除了script参数,其他参数都是可选的。
Tips: returnStatus与returnStdout参数一般不会同时使用,因为返回值只能有一个。如果同时使用则只有returnStatus参数生效。
Tips : 注意采用sh执行echo 1 > 1.txt命令时然后采用readFile读取时带有换行符,解决办法:
# 方式1.采用 $? 判断命令执行成功与否。
# 方式2.采用echo命令输出到文件时加上 -n 选项。
执行shell的几种方式
- 直接执行shell命令:sh '<shell command>'
- 获取标准输出:result = sh(script: "<shell command>", returnStdout: true).trim()
- 获取执行状态:result = sh(script: "<shell command>", returnStatus: true).trim()
参考案例
node {
//获取标准输出
//方式1
result = sh returnStdout: true ,script: "pwd"
result = result.trim()
echo "$result"
//方式2
result = sh(script: "pwd", returnStdout: true).trim()
echo "$result"
//方式3
sh "pwd > commandResult"
result = readFile('commandResult').trim()
echo "$result"
//获取执行状态.net
//方式1
result = sh returnStatus: true ,script: "pwd"
echo "$result"
//方式2
result = sh(script: "pwd", returnStatus: true)
echo "$result"
//方式3
sh 'pwd; echo $? > status'
def r = readFile('status')
echo "$r"
//无需返回值,仅执行shell命令ci
sh 'pwd'
} |
2.3.5 常用循环
2.3.5.1 timeout+waitUntil
node {
timeout(time:10, unit:"SECONDS"){
waitUntil{
script{
def rs = sh script: 'pwd', returnStatus: true
return (rs == 0)
}
}
}
} |
2.3.5.2 switch
node {
timeout(time: 1, unit: 'MINUTES') {
script {
env.deploy_option = input message: '选择操作', ok: 'deploy',
parameters: [choice(name: 'deploy_option', choices: ['deploy', 'rollback', 'redeploy'], description: '选择部署环境')]
switch("${env.deploy_option}"){
case 'deploy':
println('1.deploy prd env')
break;
case 'rollback':
println('2.rollback env')
break;
case 'redeploy':
println('3.redeploy env')
break;
default:
println('error env')
}
}
}
} |
2.3.5.3 for+continue
pipeline {
agent any
stages {
stage('Example') {
steps {
script {
def browsers = ['chrome', 'firefox', 'ie']
for (int i = 0; i < browsers.size(); ++i) {
if (i==1)
continue
echo "Testing the ${browsers[i]} browser"
}
}
}
}
}
} |
2.3.6 其他操作
2.3.6.1 catchError
捕获错误并将构建结果设置为失败。
参考案例
node {
catchError {
sh 'might fail'
}
step([$class: 'Mailer', recipients: '
zhenzhen.wu@163.com'])
} |
2.3.6.2 error
主动报错中止当前 pipeline 并且避免打印堆栈跟踪信息。
参考案例
node {
try {
sh 'might fail && whoami'
echo 'Succeeded!'
} catch (err) {
echo "Failed: ${err} - " + err.toString()
error "[-Error] : 项目部署失败 \n[-Msg] : ${err.getMessage()} "
}
} |
2.3.6.3 mail
参考案例
pipeline {
agent any
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
post {
success {
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: 'zhenzhen.wu@163.com',
sendToIndividuals: true])
}
failure {
step([$class: 'Mailer', recipients: 'zhenzhen.wu@163.com'])
}
}
}
|
2.3.6.4 retry
重试正文最多N次, 如果在块体执行过程中发生任何异常,请重试该块(最多N次)。如果在最后一次尝试时发生异常,那么它将导致中止构建(除非以某种方式捕获并处理它),不会捕获生成的用户中止。
retry(count: 5) # 重试5次 |
2.3.6.5sleep
让pipeline休眠指定的一段时间 , 只需暂停管道构建直到给定的时间已经过期相当于(在Unix上)sh 'sleep…'。
sleep time: 60, unit: 'MINUTES' |
2.3.6.6 getContext
从内部 API 获取上下文对象
node {
def aaa = getContext hudson.FilePath
echo "$aaa"
} |
2.3.6.7 withContext
在块内使用来自内部 API 的上下文对象
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)