声明式Pipleine是官方推荐的语法,声明式语法更加简洁。所有的声明式Pipeline都必须包含一个 pipeline块中,比如:
pipeline {
//run
}
在声明式Pipeline中的基本语句和表达式遵循Groovy的语法。但是有以下例外:
- 流水线顶层必须是一个块,特别是pipeline{}。
- 不需要分号作为分割符,是按照行分割的。
- 语句块只能由阶段、指令、步骤、赋值语句组成。例如: input被视为input()。
那么Jenkins pipeline支持多少哪些指令呢
pipeline的指令是有作用域的,类似于我们再配置Nginx的参数,有的要放在http模块里面,有的要放在location里面,有的可以放在http和location里面,而pipeline中的也一样,有的可以放在pipeline{}
中,和stage是平行的。有的是放在stage中。当然也有可以两个中任意一个,基本支持如下的指令:
- environment 用于设置环境变量,可定义在stage或pipeline部分
- tools 可定义在pipline或者stage部分。他会自动下载并安装我们指定的工具,并将其假如PATH变量中
- input 定义在stage部分,会暂停pipline。提示输入内容
- option 用于配置Jenkins pipeline本身的选项,定义在stage或者pipeline部分,如重试次数,或者超时配置。
- parallel 并行多个step。
- parameters 与input不同,这个指令定意思传入的参数
- triggers 用于定义执行pipeline的触发器
- when 满足条件才执行。
agent指令
agent
指定了流水线的执行节点。
agent { node { label 'labelname' }}
aget { label ' labelname '}
参数:
- any 在任何可用的节点上执行pipeline。none 没有指定agent的时候默认。
pipline {
agent any
stages {
...
}
}
-
none 没有指定agent的时候默认
-
label 在指定标签上的节点上运行Pipeline。
-
node 允许额外的选项(自定义workspace)。
agent { node {
label "master"
customWorkspace "${workspace}"
}
}
指定了额外的customWorkspace,需要弄node包一层。
post,运行后处理
定义了一个或者多个steps,这些阶段根据流水线或者阶段的完成情况而运行(取决于流水线中post部分的位置)。post支持以下post-condition
块中的其中之一,always 、changed、failure、success、unstable、aborted。这些条件块允许在post部分的步骤的执行取决于流水线或者阶段的完成状态。
当流水线完成后根据完成的状态做一些任务。例如:构建失败后邮件通知。
post {
always {
echo 'I will always say Hello again!'
}
failure{
email : xxxx@dxx.com
}
}
常用的状态:
-
always 无论流水线或者阶段的完成状态。
-
changed 只有当流水线或者阶段完成状态与之前不同时。
-
failure 只有当流水线或者阶段状态为"failure"运行。
-
success 只有当流水线或者阶段状态为"success"运行。
-
unstable 只有当流水线或者阶段状态为"unstable"运行。例如:测试失败。
-
aborted 只有当流水线或者阶段状态为"aborted "运行。例如:手动取消。
-
fixed 上次完成状态为失败或者unstable,当前完成状态为成功时执行
-
regression 上次完成状态为成功,当前完成状态为失败,不稳定或aborted时执行
-
cleaup 不论当前完成状态是什么,在其他所有条件块执行完成后都执行。
注意:post和stages是平级的代码块
stages阶段
stages
是流水线的整个运行阶段,包含一个或多个 stage
, 建议 stages
至少包含一个 stage
。
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
environment,环境变量
environment指令指定一个键值对序列,该序列将定义为所有步骤的环境变量,或者是特定于阶段的步骤,这取决于environment指令在流水线内的位置
该指令支持一个特殊的方法credentials()
.该方法可用于在jenkins环境中通过标识符访问预定义的凭证。对于类型为Secret Text
的凭证,credentials()
将确保指定环境变量包含秘密文本内容。对于类型为SStandard username and password
的凭证,指定的环境变量指定为username:password
,并且两个额外的环境变量被自动定义。分别为MYVARNAME_USR
和MYVARNAME_PSD
。
定义流水线环境变量,可以定义在全局变量或者步骤中的局部变量。这取决于 environment 指令在流水线内的位置。
agent any
//全局变量
environment {
activeEnv = 'dev'
}
stages {
stage('Example') {
//局部变量
environment {
AN_ACCESS_KEY = credentials('my-prefined-secret-text')
}
steps {
sh 'printenv'
}
}
}
options运行选项
定义流水线运行时的配置选项,流水线提供了许多选项, 比如buildDiscarder,但也可以由插件提供, 比如 timestamps。
agent any
options {
timeout(time: 1, unit: 'HOURS')
}
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
其他部分参数:
- buildDiscarder: 为最近的流水线运行的特定数量保存组件和控制台输出。自动清理硬盘上保存的的制品和构建日志。
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
}
- disableConcurrentBuilds: 不允许同时执行流水线。 可被用来防止同时访问共享资源等。
options {
disableConcurrentBuilds(
}
- overrideIndexTriggers: 允许覆盖分支索引触发器的默认处理。
- skipDefaultCheckout: 在agent 指令中,跳过从源代码控制中检出代码的默认情况。
- skipStagesAfterUnstable: 一旦构建状态变得UNSTABLE,跳过该阶段。
- checkoutToSubdirectory: 在工作空间的子目录中自动地执行源代码控制检出。也就是,可以指定检出到工作空间的子目录中。
options {
checkoutToSubdirectory('subdir')
}
- timeout: 设置流水线运行的超时时间, 在此之后,Jenkins将中止流水线。
options {
timeout(time: 10, unit: 'HOURS')
}
- retry: 在失败时, 重新尝试整个流水线的指定次数。注意这个次数包括第一次失败。
options {
retry(4)
}
- timestamps 预测所有由流水线生成的控制台输出,与该流水线发出的时间一致。
parameters参数
为流水线运行时设置项目相关的参数,就不用在UI界面上定义了,比较方便。另外要注意的是,这个指令只允许放在pipeline下面,不能放在stage中。
string 字符串类型的参数, 例如:
parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') }
可以接受三个参数,name、defaultValue、description:
name
:参数名defaultValue
:默认值description
:参数的描述信息
下面我们来看一个例子:
agent any
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
}
stages {
stage('Example') {
steps {
echo "Hello ${params.PERSON}"
}
}
}
这里要注意一个问题。如果是通过jenkins配置来增加参数的化,那么配置完毕就可以看到
但是如果用jenkinsfile里面配置,必须构建一遍以后才能显示
那么,除了string以外,还有什么参数呢,下面我们来一起看一下。
booleanParam 布尔参数, 例如:
parameters {
booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '')
}
text 多行文本类型,如果换行可以使用\n
parameters {
text(name: 'DEBUG_BUILD', defaultValue: 'One\nTwo\nThree\n', description: '')
}
choice 选择参数类型,使用\n
来分隔多个选项
parameters {
choice(name: 'DEBUG_BUILD', defaultValue: 'Dev\nTest\nProd\n', description: '')
}
password类型
parameters {
password(name: 'DEBUG_BUILD', defaultValue: 'SECRET', description: '')
}
当然我们也可以在parameters中使用多个参数类型比如:
parameters {
booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '')
choice(name: 'DEBUG_BUILD', defaultValue: 'Dev\nTest\nProd\n',description: '')
text(name: 'DEBUG_BUILD', defaultValue: 'One\nTwo\nThree\n',description: '')
}
trigger触发器
trigger触发器,定义一个时间,时间到了就会触发pipeline,在不考虑插件的情况下,一般有三种方式,cron
,pollSCM
,upstream
。
cron
为定时执行,也就是,我们可以定一个时间,比如凌晨,自动更新一般项目,把项目代码更新为最新。他的写法也和我们平时配置Linux的定时任务相似
//cron 计划任务定期执行构建。
triggers { cron('H */4 * * 1-5') }
不过你也发现,还是有那么亿点点不一样,这个H又是什么意思。比如当半夜0点执行的时候(0 0 * * *)
这样会产生负载不均衡。H代表hash,就来解决这个问题的,如果我们配置成(H 0 * * **)
,这样代表0点0分,到0点59分任意一个时间点执行。所以我们可以下成下面的样子。
agent any
triggers {
cron('H */4 * * 1-5')
}
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
pollSCM
为轮询代码仓库,也就是,指定时间轮询代码库,如果有变化就执行。这种情况其实用的不算太多。因为可以通过代码库来通知jenkins,比如GitLab通过钩子,在代码有变更的时候通知Jenkins来进行代码发布。关于GitLab来触发Jenkins的内容,会在后面集成其他服务的时候详细说明。
//pollSCM 与cron定义类似,但是由jenkins定期检测源码变化。
triggers { pollSCM('H */4 * * 1-5') }
upstream
是由上游任务来触发
当A任务执行成功或者失败或者中止等情况的时候触发另外一个,或者另外多个任务
// job1和job2都是任务名,当任务成功是,触发构建job1和job2
triggers {
upstream(upstreamProjects: 'job1, job2', threshold: hudson.model.Result.SUCCESS)
}
hudson.model.Result.SUCCESS
是一个枚举值,它表示A任务什么状态触发其他任务。这个状态处理SUCCESS以外还有:
- ABORTED:任务被手动中止
- FAILURE:构建失败
- UNSTABLE:存在一些错误,但是构建没有失败
- NOT_BUILT:在多阶段构建时,前面阶段的问题导致后面阶段无法执行
注意,这里和parameters参数有点类似,需要手动构建一次以后,才会触发
tool构建工具
构建工具maven、ant、gradle,获取通过自动安装或手动放置工具的环境变量。支持maven/jdk/gradle。工具的名称必须在系统设置->全局工具配置中定义。
agent any
tools {
maven 'apache-maven-3.0.1'
}
stages {
stage('Example') {
steps {
sh 'mvn --version'
}
}
}
举例 比如说,我在全局工具中配置了git 如果我想在jenkinsfile中使用这个git
stage("Build"){
steps{
timeout(time:5, unit: 'MINUTES'){
script{
println("运行构建")
gitHome = tool "git"
println(gitHome)
}
}
}
}
输出
我们去取到变量就可以做很多操作,比如
stage("Build"){
steps{
timeout(time:5, unit: 'MINUTES'){
script{
println("运行构建")
gitHome = tool "git"
sh "${gitHome} checkout mastsr"
}
}
}
}
input交互输入
input用户在执行各个阶段的时候,由人工确认是否继续进行。他的使用场景是,可以实现一个简单的审批过程,比如某个阶段需要某个人去点击确认后才可以部署。或者测试同事需要一个手动的测试,测试完成后继续部署。
agent any
stages {
stage('Example') {
input {
message "Should we continue?"
ok "Yes, we should."
submitter "alice,bob"
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
}
}
steps {
echo "Hello, ${PERSON}, nice to meet you."
}
}
}
input 可以用流水线开发工具生成
生成流水线语法,赋值到jenkinsfile中
运行pipline,这里就有选项了
参数解释:
- message 呈现给用户的提示信息。
- id 可选,默认为stage名称。
- ok 默认表单上的ok文本。
- submitter 可选的,以逗号分隔的用户列表或允许提交的外部组名。默认允许任何用户。
- submitterParameter 环境变量的可选名称。如果存在,用submitter 名称设置。
- parameters 提示提交者提供的一个可选的参数列表。
when条件判断
when 指令允许流水线根据给定的条件决定是否应该执行阶段。 when 指令必须包含至少一个条件。比如,我们想根据环境去判断执行不同的构建,那么我们可以下成如下样子
stage("test"){
when {
branch 'test'
}
steps{
echo "deploy test!"
}
}
stage("prod"){
when {
branch 'prod'
}
steps{
echo "deploy prod!"
}
}
那么when都支持哪些条件的判断呢,我们下面来一一介绍:
branch,当正在构建的分支与模式给定的分支匹配时,执行这个阶段,也就是上面我们说的,通过分支去判断。这只适用于多分支流水线例如:
when { branch 'master' }
environment,当指定的环境变量是给定的值时,执行这个步骤,例如:
when { environment name: 'DEPLOY_TO', value: 'production' }
expression, 当指定的Groovy表达式评估为true时,执行这个阶段, 例如:
when { expression { return params.DEBUG_BUILD } }
这里要注意,当表达式返回的是字符串时,他必须转换为布尔值或者null,否则所有的字符串都被当做true处理。
not,当嵌套条件是错误时,执行这个阶段,必须包含一个条件,例如:
when { not { branch 'master' } }
allOf,当所有的嵌套条件都正确时,执行这个阶段,必须包含至少一个条件,例如:
when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }
anyOf,当至少有一个嵌套条件为真时,执行这个阶段,必须包含至少一个条件,例如:
when { anyOf { branch 'master'; branch 'staging' } }
equals,如果期望值和给定的值相同,则执行
when {
equals expected: 2, actual: currentBuild.number
}
buildingTag,如果pipeline所执行的代码被打了tag,则执行。
whne {
buildingTag()
}
tag,如果pipeline所执行的代码被打了tag,并且tag名符合规则,才执行。如果tag值为空,可以写成tag()
,这个效果和buildingTag()
一样,不论tag名称为什么,都执行。那么tag有几种匹配的方式呢?
- EQUALS: 简单的文本比较
when {
tag pattern: "release-3.1", comparator: "EQUALS"
}
- GLOB (默认值): Ant风格的路径表达式。由于是默认的使用的时候可以忽略
when {
tag pattern: "release-*"
}
或者写成完整版
when {
tag pattern: "release-*", comparator: "GLOB"
}
- REGEXP: 正则表达式
when {
tag pattern: "release=\\\d+", comparator: "REGEXP"
}
下面我们来举个例子,我们添加一段参数。
parameters {
string(name: 'TEST', defaultValue: 'ABCD', description: 'code is adbcd')
}
设置一个when的条件
when { environment name: 'TEST', value: 'ABCD' }
steps{
script{
println("获取代码")
}
}
}
构建
我们可以看到构建成功
这个时候我们把参数改变,改为abcde
虽然也构建成功了,但是Checkout阶段被跳过了
parallel并行
声明式流水线的阶段可以在他们内部声明多隔嵌套阶段, 它们将并行执行。 注意,一个阶段必须只有一个 steps 或 parallel的阶段。 嵌套阶段本身不能包含 进一步的 parallel 阶段, 但是其他的阶段的行为与任何其他 stageparallel 的阶段不能包含 agent 或 tools阶段, 因为他们没有相关 steps。
stage("CheckOut"){
failFast true
parallel {
stage("GetCode"){
steps{
script{
println("获取代码")
}
}
}
stage("CheckEnv"){
steps{
script{
println("检查环境")
}
}
}
}
}
failFast true 当其中一个进程失败时,强制所有的 parallel 阶段都被终止。
这里一定要注意,一般结构是steges
里面套了多个步骤也就是套了多个stage
,但是呢parallel
模块是在stage
里面所以,相当于一个stage
里面套了多个stage
并发的构建,从jenkins的页面看的不是很清楚,我们可以Blue Ocean的插件去看,效果如下
script脚本标签
script步骤需要{scripted-pipline}块并在声明式流水线中执行,对于大多数用例来说,应该声明式流水线中的“脚本”步骤是不必要的,但是它可以提供一个有用的"逃生出口",非平凡的规模和/或复杂性的script块应该被转移到共享库
可以通过此标签嵌入脚本式语法。
stage("Build"){
steps{
script{
println("运行构建")
}
}
}
post {
success{
script{
println("流水线成功后,要做的事情")
currentBuild.description = "\n 构建成功"
}
}
效果如下