引言
前一篇 Jenkins - Pipeline 概念及创建方式 主要介绍 Jenkins Pipeline 的概念及创建方式,今天详细介绍一下 Pipeline 的语法。参考 Jenkins 语法中文网站, Jenkins 语法英文网站。
内容提要:
- Declarative / Scripted Pipeline 风格
- Declarative Pipeline 声明式语法
agent
stages
stage
steps
post
environment
parameters
Declarative / Scripted Pipeline 风格
Jenkins Pipeline 是基于 Groovy 实现的 CI/CD 领域特定语言(DSL),主要分为两类,一类叫做 Declarative Pipeline,一类叫做 Scripted Pipeline。
Declarative Pipeline 声明式:
一般情况下声明式的流水线已经可以满足我们的需要,可读性更强。所有的脚本都是在 pipeline {}
内。
但是有个 Open Issue,就是 pipeline {}
中代码行数超过一定范围, 会出现 Method code too large! error in pipeline Script
,而 Scripted Pipeline 脚本式就没有行数限制。
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building..'
}
}
stage('Test') {
steps {
echo 'Testing..'
}
}
stage('Deploy') {
steps {
echo 'Deploying....'
}
}
}
}
当然 script
脚本式的代码块也可以应用到声明式的 Pipeline
中,可提供更多的灵活性。大多数情况,脚本式步骤在声明式 Pipeline
中不是必须的,最佳实践就是将一些复杂的,共用的脚本步骤提取到 Shared Libraries
中。
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
script {
def browsers = ['chrome', 'firefox']
for (int i = 0; i < browsers.size(); ++i) {
echo "Testing the ${browsers[i]} browser"
}
}
}
}
}
}
Scripted Pipeline 脚本式:
旧版本中 Jenkins 支持的 Pipeline 模式,只有更复杂的情况下才会需要脚本式流水线的参与。
node {
stage('Build') {
echo 'Building..'
}
stage('Test') {
echo 'Testing..'
}
stage('Deploy') {
echo 'Deploying....'
}
}
Declarative Pipeline 声明式语法
Declarative Pipeline 最外层有个 pipeline 表明它是一个声明式流水线,下面会有 7 个主要的部分: agent,stages,stage, steps, post, environment, parameters
agent
它指示 Jenkins 为流水线分配一个执行器和工作区。没有 agent 指令的话,声明式流水线不仅无效,它也不可能完成任何工作!默认情况下,agent 指令确保源代码仓库被检出并在后续阶段的步骤中可被使用。有一些应用于两个或更多 agent 的实现的选项。他们不被要求,除非特别规定。该部分必须在 pipeline 块的顶层被定义, 但是 stage 级别的使用是可选的。
Required | Yes |
Parameters | Described below |
Allowed | In the top-level pipeline block and each stage block |
下面列举部分常用的参数,更多细节可以参考 Agent
-
any
在任何可用的代理上执行流水线或阶段。例如:agent any
-
label
在提供了标签的 Jenkins 环境中可用的代理上执行流水线或阶段。 例如:agent { label 'my-defined-label' }
-
node
agent { node { label 'labelName' } }
和agent { label 'labelName' }
一样, 但是node
允许额外的选项 (比如customWorkspace
)。
label 应用
可以通过设置为 Jenkins 上的 Node 设置 Lable,例如本地部署,默认就一个 Node,打上 windows12 的标签。
所以要用上这个 Node 就可以这样了:
pipeline {
agent { label 'windows12' }
}
stages
包含一系列一个或多个 stage
指令, stages
部分是流水线描述的大部分 “work” 的位置。 建议 stages
至少包含一个 stage
指令用于连续交付过程的每个离散部分,比如构建, 测试, 和部署。
Required | Yes |
Parameters | None |
Allowed | Only once, inside the pipeline block |
例如:
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
stage
stage
指令在 stages
部分进行,流水线所做的所有实际工作都将封装进一个或多个 stage
指令中。
Required | At least one |
Parameters | One mandatory parameter, a string for the name of the stage. |
Allowed | Inside the stages section |
Jenkins 将会按照 Stages
中描述的顺序从上往下的执行。Stages
中可以包括任意多个 Stage
,而 Stage 与 Stages 又能互相嵌套,除此以外还有 parallel
指令可以让内部的 Stage
并行运行。实际上可以把 Stage
当作最小单元,Stages 指定的是顺序运行,而 parallel
指定的是并行运行。
pipeline {
agent none
stages {
stage('Sequential') {
stages {
stage('In Sequential 1') {
steps {
echo "In Sequential 1"
}
}
stage('In Sequential 2') {
steps {
echo "In Sequential 2"
}
}
stage('Parallel In Sequential') {
parallel {
stage('In Parallel 1') {
steps {
echo "In Parallel 1"
}
}
stage('In Parallel 2') {
steps {
echo "In Parallel 2"
}
}
}
}
}
}
}
}
除了指定 Stage
之间的顺序关系之外,我们还可以通过 when
来指定某个 Stage
指定与否:比如要配置只有在 Master
分支上才执行 push,其他分支上都只运行 build
stages {
stage('Build') {
when {
not { branch 'master' }
}
steps {
sh './scripts/run.py build'
}
}
stage('Run') {
when {
branch 'master'
}
steps {
sh './scripts/run.py push'
}
}
}
steps
steps
部分在给定的 stage
指令中执行的定义了一系列的一个或多个 steps
, 是 Pipeline
中最核心的部分.
Required | Yes |
Parameters | None |
Allowed | Inside each stage block |
注意:
- 字符串的处理
Groovy 语法中有不同的字符串类型,其中单引号 ‘abc’ 是 Plain 字符串,不会转义 ${WROKSPACE} 这样的变量,而双引号 “abc” 会做这样的转换。此外还有三单引号 ‘’’ xxx ‘’’ 支持跨行字符串,三双引号 “”" 同理。 - 调用函数的 () 可以省略
使得函数调用形如 updateGitlabCommitStatus name: ‘build’, state: ‘success’,通过 , 来分割不同的参数,支持换行。 - 可以在声明式流水线中通过 script 来插入一段 groovy 脚本
post
post
部分定义一个或多个 steps
,这些阶段根据流水线或阶段的完成情况而 运行(取决于流水线中 post
部分的位置). post
支持以下 post-condition
块中的其中之一: always
, changed
, failure
, success
, unstable
, 和 aborted
。这些条件块允许在 post
部分的步骤的执行取决于流水线或阶段的完成状态。经常用于一些测试完毕后的清理和通知操作。文档中给出了一系列的情况,比较常用的是 always,success 和 failure
Required | Yes |
Parameters | None |
Allowed | In the top-level pipeline block and each stage block |
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
post {
always {
echo 'I will always say Hello again!'
}
failure {
echo 'I will say failure when build is in failure state!'
}
success {
echo 'I will say success when build is in success state!'
}
}
}
environment
environment
指令制定一个 键-值对序列,自定义一上环境变量,该序列将被定义为所有步骤的环境变量,或者是特定于阶段的步骤, 这取决于 environment
指令在流水线内的位置。
自定义的环境变量和 Build-in 的环境变量都可以通过 %env-name%
,或 ${env-name}
形式访问。
顶层流水线块中使用的 environment
指令将适用于流水线中的所有步骤。 在一个 stage
中定义的 environment
指令只会将给定的环境变量应用于 stage 中的步骤。
sh ‘printenv’ 将打印出所有的环境变量,这里就不一一列出来了。
例如下脚本:
${AN_ACCESS_KEY} 只能应用在 stage(‘Example’) 范围内,stage(‘Example2’) 就不行。而 ${ENV_TEST } 整个 pipelien 范围都可以应用到。
pipeline {
agent { label "agent1" }
environment {
ENV_TEST = 'ENV TEST'
}
stages {
stage('Example') {
environment {
AN_ACCESS_KEY = "my-prefined-secret-text"
}
steps {
print "ENV_TEST: ${ENV_TEST}"
print "AN_ACCESS_KEY: ${AN_ACCESS_KEY}"
print "build-in env ${WORKSPACE}"
sh 'printenv'
}
}
stage('Example2') {
steps{
sh 'printenv'
}
}
}
}
parameters
parameters
指令提供了一个用户在触发流水线时应该提供的参数列表。这些用户指定参数的值可通过 params 对象提供给流水线步骤。
string 字符串类型的参数
例如: parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') }
booleanParam 布尔参数
例如: parameters { booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '') }
可通过 ${params.params_name} 或 %{params.params_name}% 访问参数变量。
pipeline {
agent { label "agent1" }
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '')
}
stages {
stage('Example') {
steps {
echo "Hello ${params.PERSON}"
echo "ture or false: ${params.DEBUG_BUILD}"
}
}
}
}
console output: