3. Jenkins pipeline 语法3.1 pipeline 组成
[作者:Surpassme]Jenkins pipeline 是基于Groovy
语言实现的一种DSL
(领域特定语言),用于描述整条流水线是如何进行的。流水线的主要内容包括源码拉取
、构建
、打包
、部署
、测试
、生成报告
等步骤。
从源码管理仓库到生成测试报告这些过程中,可以根据需要分成若干阶段,而每个阶段仅处理一件事情,而每个阶段也可以通过多个步骤来完成,因此我们可以基于这些阶段和步骤些进行抽象,形成工程化的pipeline,因此一个基本的pipeline示例如下所示:
pipeline{ agent any stages{ stage("Sample stage"){ steps { echo "Hi,Surpass.Welcome visit my blog:https://www.cnblogs.com/surpassme/" } } }}
以上示例详细解释如下所示:
- pipeline:代表整条流水线,包含
整条流水线的逻辑
- agent:指定流水线的
运行位置
流水线的中每个阶段都必须在某个地方(例如物理机、虚拟机或容器)运行,因此可能通过指定 agent部分来指定具体在哪里运行。
- stages:流水线中多个stage的容器。该部分
至少包含一个stage
- stage:表示阶段,代表流水线的阶段,每个阶段必须有名称
- steps:表示阶段中的一个或多个具体步骤的容器
1.steps
至少
包含一个步骤
2.在一个stage中仅有一个steps
以上每一个部分都是必需
的,否则Jenkins都会报错
官方参考文档:https://www.jenkins.io/doc/pipeline/steps/
3.2 pipeline 支持的命令
[作者:Surpassme]基本的pipeline结构是无法满足日常现实多变的需求。因此,Jenkins pipeline可以通过各种指令来扩展丰富自己。以下为Jenkins pipeline支持的命令。
3.2.1 environment
[作者:Surpassme]environment
主要用于设置环境变量
。可以定义在stage
和pipeline
部分。环境变量可以分为:Jenkins内置变量
和自定义环境变量
。
3.2.1.1 Jenkins 内置环境变量
[作者:Surpassme]在执行pipeline时,可以通过env
命令来获取Jenkins的全部内置环境变量,其主要使用方法如下所示:
pipeline { agent any stages{ stage("PrintEnviroment"){ steps{ // method A echo "Running ${env.BUILD_ID} on ${env.JENKINS_URL}" // method B echo "Running $env.BUILD_ID on $env.JENKINS_URL" // method C echo "Running ${BUILD_ID} on ${JENKINS_URL}" } } }}
默认情况下,env中的所有环境变量都可以直接在pipeline中使用。因此上面三种方法都可以使用,但
不推荐第三种方法
,因为在出现变量名冲突时,排查问题非常难。
如果需要查看env所有可用的环境变量,可以通过以下方式进行访问。http://jenkins-master-address/pipeline-syntax/globals
。示例如下所示:
http://192.168.188.133:9090/pipeline-syntax/globals
Jenkins 内置环境变量如下所示:
以下为日常经常使用到的内置环境变量简介。如下所示:
- BRANCH_NAME
多分支piple 项目支持。可根据不同的分支执行不同的语句。例如当分支为release时,部署到生产环境,分支为test时,部署至测试环境。
- BUILD_NUMBER
构建号,同一个项目中,持续累加的数字。
- BUILD_URL
当前构建的URL地址,点击该URL,可以快速跳转至构建页面
- WORKSPACE
构建的工作空间,为绝对路径
在调试pipeline时,也可以在pipeline 的开始阶段使用以下代码片断,打印所有env的环境变量,来进行排查问题。如下所示:
sh "printenv"
3.2.1.2 自定义环境变量
[作者:Surpassme]当内置环境变量无法满足要求时,我们也可以定义自己的环境变量。这个时候就需要使用environment
命令来自定义环境变量。示例如下所示:
pipeline { agent any environment{ NAME="Surpass" AGE="28" } stages{ stage("PrintGolbalEnviroment"){ steps{ echo "Global Enviroment is name is ${env.NAME} age is ${env.AGE}" } } stage("PrintLocalEnviroment"){ environment{ CITY="Shanghai" FROM="Wuhan" } steps{ echo "Global Enviroment is name is ${env.NAME} age is ${env.AGE}" echo "Local Enviroment is city is ${env.CITY} from is ${env.FROM}" } } }}
[作者:Surpassme]environment
可以在pipeline
中定义,属于全局环境变量
,代表整个pipeline均可以使用该环境变量。也可以在stage
中定义,属于局部环境变量
,仅限于该阶段内部有效,外部无法使用。
除了以上几中自定义环境变量,还可以通过script
来定义全局变量
,示例如下所示:
pipeline { agent any environment{ NAME="Surpass" AGE="28" } stages{ stage("Set environment by script"){ steps{ script{ env.SURPASS_NAME="Surpass" env.SURPASS_AGE=28 } } } stage("PrintGolbalEnvironment"){ steps{ echo "Global Enviroment is name is ${env.NAME} age is ${env.AGE}" } } stage("PrintLocalEnvironment"){ environment{ CITY="Shanghai" FROM="Wuhan" } steps{ echo "Global Enviroment is name is ${env.NAME} age is ${env.AGE}" echo "Local Enviroment is city is ${env.CITY} from is ${env.FROM}" } } stage("PrintSetEnvironment"){ steps{ echo "print global env by script ${env.SURPASS_NAME}" echo "print global env by script ${env.SURPASS_AGE}" } } }}
在自定义环境变量,需要注意的地方如下所示:
- 1.环境变量是不能跨pipeline进行访问的,即
不同的pipeline间不能共享环境变量
- 2.如果用户自定义的环境变量与env环境变量重名,则被重命名的环境将被
覆盖
3.2.1.3 自定义全局环境变量
[作者:Surpassme]env中的环境变量都是内置的,用户自定义的环境变量是与具体的pipeline相关的。如果需要定义全局并且跨pipeline
自定义环境变量,可以这样设置。
Manage Jenkins->Configure System-> Global properties,勾选 Environment variables,添加对应的环境变量即可。
以上自定义的全局环境变量,会被加入env环境变量列表中,后续使用时可以使用${env.SURPASS_NAME}
和${env.SURPASS_AGE}
来获取。
3.2.2 tools
[作者:Surpassme]可定义在pipeline或stage部分。在运行时,会自动下载
并安装指定的工具和加入PATH变量
中。但在agent none时,会失效
基于在线自动安装,受限于网络不可达、网络速度、网络策略等因素,一般还是建议,还是提前下载到本地,然后在Jenkins进行配置好之后,在pipeline中直接使用即可。
3.2.2.1 Go 语言环境搭建
其操作步骤如下所示:
1.下载golang SDK本地
2.在Jenkins 中安装go插件
3.在Jenkins中进行配置
Manage Jenkins->Configure System-> Global Tool Configuration->GO
- 4.编写pipeline 脚本
pipeline{ agent any tools { go "go-1.19" } stages{ stage("tools demo"){ steps{ sh "go version" sh "go env" } } }}
运行结果如下所示:
3.2.2.2 Python 语言环境搭建
[作者:Surpassme]Python 环境很容易产生版本冲突和第三方库冲突等问题,因此Python通过会进行工程级别的环境隔离。在Jenkins中,我们可以使用插件Pyenv Pipeline Plugin
(https://plugins.jenkins.io/pyenv-pipeline/)来解决此类问题。其操作步骤如下所示:
- 1.在Jenkins中安装Python/pip/virtualenv
- 2.安装插件Pyenv Pipeline Plugin
- 3.编写pipeline 脚本
pipeline{ agent any stages{ stage("python virtual env demo"){ steps{ withPythonEnv("/usr/local/bin/python3") { // Uses the specific python3.5 executable located in /usr/bin sh "python3 --version" sh "python3 -c \"print('hello,Surpass')\"" } } } }}
运行结果如下所示:
3.2.2.3 利用作用域实现多版本编译
[作者:Surpassme]在实际项目中,同一份源码可能会存在多个版本的编译构建等。tools 除了支持pipeline域
也支持stage域
。示例如下所示:
pipeline{ agent any stages{ stage("build with go 1.19"){ tools { go "go-1.15" } steps{ echo "use go 1.15 build" } } stage("build with go 1.19"){ tools { go "go-1.19" } steps{ echo "use go 1.19 build" } } }}
3.2.3 input
[作者:Surpassme]input 命令可以实现pipeline中的交互操作
。利用input命令,我们可以一些简单的场景。
- 实现简易的审核流程
在部署环境前,由相应负责人员进行确认
- 排查定位问题
因为pipeline在遇到input命令时,会暂停执行。因此,我们可以利用这个特性,使运行某个阶段前,暂停执行pipeline
3.2.3.1 常用参数
input 命令的常用参数如下所示:
- message
该参数为必选参数
,input命令的消息提示框消息。
- id
该参数为可选参数
, input命令标识符,默认为stage的名称
- submitter
该参数为可选参数
,类型为字符串类型
,可以进行操作的用户ID或用户组名称,使用,
分隔,在,
左右不允许有空格
。可以用来做权限控制。
- submitterParameter
该参数为可选参数
,类型为字符串类型
,保存input命令的实际操作者的用户名的变量名
- ok
该参数为可选参数
,自定义确定按钮的文本
- parameters
该参数为可选参数
,提供参数列表供input命令使用。
3.2.3.2 简易用法
比如我们现在实现第一种简易的审核流程。示例脚本如下所示:
pipeline{ agent any stages{ stage("input simple use"){ steps{ input message:"Confirm or Cancle ?" } } }}
当执行到input simple use
阶段时,pipeline会暂停,当鼠标移动到该阶段虚线视图上时,会出现一个浮层 ,以供选择。示意图如下所示:
3.2.3.3 复杂用法
示例脚本如下所示:
pipeline{ agent any environment { DEPLOY_ENV="" } stages{ stage("choose deploy nodes"){ steps{ script{ DEPLOY_ENV=input( message: "准备部署到哪个节点?", parameters:[choice( name:'chooseNode', choices:["node-1","node-2","node-3"], description:"选择部署节点") ], ok:"确定", submitter:"admin,Surpass", submitterParameter:"approvers" ) } } } stage("deply"){ steps{ echo "操作人员:${DEPLOY_ENV['approvers']}" echo "部署节点:${DEPLOY_ENV['chooseNode']}" } } }}
因为input返回的值需要跨阶段,因此需要将input的返回值定义为全局变量。
input 命令返回值类型取决于返回的值个数
,详情如下所示:
- 仅返回一个值,返回值类型就是这个值的类型
- 返回多个值,则返回值类型为Map类型
运行结果如下所示:
3.2.4 options
[作者:Surpassme]用于配置pipeline本身
的选项,可以定义在pipeline
和stage
中。常用的配置项如下所示:
- buildDiscarder
[作者:Surpassme]用于配置保存最近历史构建记录的数量。示例如下所示:
options{ buildDiscarder(logRotator(numToKeepStr:'5')) }
此选项只能在pipeline下的 options 中使用
- checkoutToSubdirectory
[作者:Surpassme]Jenkins 从版本控制库中拉取源码时,默认会存放到工作空间目录中,此选项可以指定检出到工作空间的子目录中,示例如下所示:
options{ checkoutToSubdirectory('subdir') }
- disableConcurrentBuilds
[作者:Surpassme]同一个pipeline,Jenkins默认是可以同时执行的,而此选项则是禁止多个pipeline并行执行
,示例如下所示:
options { disableConcurrentBuilds() }
- retry
[作者:Surpassme]当发生失败时进行重试,可以指定整个pipeline的重试次数。示例如下所示:
options{ retry(3) }
需要注意的是这里的重试次数是指总次数,即包含第一次失败。当使用retry选项时,options可以放在stage中
- timeout
[作者:Surpassme]若pipeline执行时间过长,超出了设置的超时时间之后,则Jenkins将中止pipeline。示例如下所示:
options{ timeout(time:1,unit:'SECONDS') }
1.timeout时间单位有SECONDS、MINUTES、HOURS。
2.当使用timeout选项时,options可以放在stage块中
- timestamps
[作者:Surpassme]为控制台输出时间戳。示例如下所示:
options { timestamps() }
3.2.5 parallel
[作者:Surpassme]在pipeline中使用parallel
可以很方便的实现并行构建。
3.2.5.1 阶段并行
示例如下所示:
pipeline{ agent any stages{ stage("Non Parallel stage"){ steps{ echo "This is non-parallel stage" } } stage("Parallel stage"){ failFast true parallel{ stage("Parallel A"){ steps{ echo "Parallel A" } } stage("Parallel B"){ steps{ echo "Parallel B" } } stage("Parallel C"){ steps{ echo "Parallel C" } } } } }}
在使用parallel
时,注意事项如下所示:
- parallel
块本身不允许
包含agent
和tools
- 默认情况下,pipeline要等parallel块下所有的阶段都运行完成,才能确定运行结果。若希望所有并行阶段中某个阶段失败后,就即将中止所有阶段,则需要在parallel同级位置加入
failFast true
failFast true 简单来讲就是表示,只要有一个并行阶段运行失败,则立即退出。
3.2.5.2 步骤并行
[作者:Surpassme]示例如下所示:
pipeline{ agent any stages{ stage("Non-parallel steps"){ steps{ echo "Non-parallel steps" } } stage("Parallel steps"){ steps{ parallel( parallelA:{ echo "parallelA steps" }, parallelB:{ echo "parallelB steps" }, parallelC:{ echo "parallelC steps" } ) } } }}
[作者:Surpassme]阶段并行和步骤并行的主要区别如下所示:
- 写法区别:在阶段并行时,使用的是
大括号
,而步骤并行时,使用的是括号
- 运行区别:阶段并行是运行在不同的executor,而步骤并行,则是运行在同一个executorr
原文地址:https://www.jianshu.com/p/f2895e38a824
本文同步在微信订阅号上发布,如各位小伙伴们喜欢我的文章,也可以关注我的微信订阅号:woaitest,或扫描下面的二维码添加关注:
作者: Surpassme
来源: http://www.jianshu.com/u/28161b7c9995/
http://www.cnblogs.com/surpassme/
声明:本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接 ,否则保留追究法律责任的权利。如有问题,可发送邮件 联系。让我们尊重原创者版权,共同营造良好的IT朋友圈。