Jenkins的Pipeline
简述
- Jenkins Pipeline (或简称为 “Pipeline”)是一组插件
- 是一套运行于jenkins上的工作流程框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化,内容包括执行编译、打包、测试、输出测试报告等步骤
- Jenkins Pipeline 的定义通常被写入到一个文本文件(称为Jenkinsfile)中,该文件可以被放入项目的源代码控制库中
jenkinsfile
简述
- Jenkinsfile 是 是指Jenkins 2.x 核心特性 Pipeline 的脚本文件,由Groovy语言实现
- 支持声明式(Declar-ative)和脚本式(Script)两种方式编写
Groovy
-
方法
- 支持方法默认值
- 支持命名参数
- groovy中的方法调用可以省略括号
-
变量
-
同时支持静态类型和动态类型,在定义变量时,习惯使用def关键字
例如:def x = "abc"
-
支持单引号、双引号,双引号支持插入值
-
支持三引号(单引号、双引号)。都支持换行,双引号支持插入值
-
-
其它
-
groovy语句最后的分号不是必须的
-
支持闭包。闭包还可以直接被当成函数调用,也可以当作一个参数传递给另一个方法
例如:def codeBlock = {print "hello closure"}
-
pipeline的构成
stages
简述
- 用于编写执行编译、打包、测试等的流程操作的执行文件
结构
- pipeline
- 代表整条流水线,包含整条流水线的逻辑
- stages
- 流水线中多个stage的容器,每个stages至少包含一个stage
- stage
- 代表流水线的阶段。每个阶段都必须有名称
- steps
- 代表阶段中的一个或多个具体步骤的容器,steps至少包含一个步骤
- agent
- 指流水线的执行位置。流水线中的每个阶段都必须在某个地方(物理机、虚拟机或docker容器)执行,agent指具体在哪里执行
示例
pipeline {
agent any
stages {
stage('build') {
echo "test"
}
}
}
post
简述
- always
- 不论当前完成状态是什么,都执行
- changed
- 只要当前完成状态与上一次状态不同就执行
- fixed
- 上一次完成状态为失败或不稳定(unstable),当前状态为成功时执行
- regression
- 上一次完成状态为成功,当前完成状态为失败、不稳定、中止(aborted)时执行
- aborted
- 当前执行结果是中止状态时(一般为人为中止)执行
- failure
- 当前完成状态为失败时执行
- success
- 当前完成状态为成功时执行
- unstable
- 当前完成状态为不稳定时执行
- cleanup
- 清理条件块。不论当前完成状态时什么,在其它所有条件块完成后都执行
示例
post {
failure {
mail to : 'xxx@mail.com',
subject : 'test mail'
}
}
基础指令
- environment
- 用于设置环境变量
- tools
- input
- options
- parallel
- parameters
- triggers
- when
基础配置(options)
- buildDiscarder
- 保存最近历史构建记录的数量
- 会在硬盘上保存制品和构建执行日志,如果长时间不清理会占用大量空间,设置此选项后会自动清理
- checkoutToSubdirectory
- Jenkins从版本控制库拉取源码时,默认检出到工作空间的根目录中
- 此选项可以指定检出到工作空间的子目录中
- disableConcurrentbuilds
- 同一个pipeline,Jenkins默认时可以同时执行多次的
- 此选项是为了禁止pipeline同时执行
- newContainerPerStage
- 当agent为docker或dockerfile时,在同一个jenkins节点上,每个stage都分别运行在一个新的容器中,而不是所有stage都运行在同一个容器中
- retry
- 当发生失败时进行重试,可以指定整个pipeline的重试次数
- 这个次数是指总次数,包括第一次失败
- timeout
- 当pipeline执行时间过长,超出我们设置的timeout时间,Jenkins将中止pipeline
- 设置此选项后,强迫团队去处理执行时间过长的pipeline,从而优化pipeline的反馈周期
- 通常设置为10分钟即可
内置基础操作
文件目录相关操作
- dir,切换目录
- deleteDir,删除当前目录
- fileExists,判断文件是否存在
- isUnix,判断是否为类UNIX系统
- pwd,返回当前目录
- writeFile,将内容写入指定文件中
- file,文件路径,相对路径和绝对路径均可
- text,要写入的文件内容
- encoding,目标文件的编码,默认使用操作系统的编码
- readFile,读取文件内容
- file,文件路径,相对路径和绝对路径均可
- encoding,读取文件时使用的编码
制品相关操作
- stash,保存临时文件,用于跨多Jenkins Node使用,官方推荐文件大小为5-100MB,此种方式会消耗主节点的计算资源
- name,保存文件的集合的唯一标识,字符串类型
- allowEmpty,允许stash内容为空,布尔类型
- excludes,排除文件,字符串类型。如果排除多个,则使用逗号分隔;留空不排除任何文件
- includes,stash包含哪些文件,字符串类型。留空代表当前文件夹下的所有文件
- useDefaultExcludes,布尔类型,如果为True,则代表使用ant风格路径默认排除文件列表
- unstash,取出之前stash的文件
- name,stash时声明的name属性的值
命令相关操作
是由Pipeline: Nodes and Processes插件提供的步骤
- sh,执行shell命令
- script,将要执行的shell脚本,通常在类UNIX系统上可以是多行脚本
- encoding,脚本执行后输出日志的编码,默认是系统编码
- returnStatus,脚本执行后返回的状态码,布尔类型。如果是一个非零的状态码,则会引发pipeline执行失败,如果参数值设为true,则不论状态码是什么,pipeline的执行都不会受到影响
- returnStdout,布尔类型,如果值为true,则任务标志输出将作为步骤的返回值,而不是打印到构建日志中;如果有错误,则依然会打印到日志中;returnStatus与returnStdout一般不会同时使用,因为返回值职能有一个,同时使用时,只有returnStatus参数生效
- bat,bat是windows的批处理命令
- powersheel,powersheel是powerShell脚本
- error,主动报错,中止当前pipeline
- message,异常内容
- tool,使用预定义的工具
- name,工具名称
- type,工具类型,指该工具安装类的全路径类名
- timeout,代码块超时时间
- time,超时时间,整形
- unit,时间单位
- activity,布尔类型,如果为true则只有当日志没有活动后,才真正算超时
- waitUntil,等待条件满足
- retry,重复执行块
- sleep,让pipeline休眠一段时间
- time,休眠时间,整形
- unit,时间单位
- 清理磁盘空间,使用Workspace Cleanup插件清理空间
触发方式
简述
- 在我们推送到代码后,自动触发构建
- 自动化是指按照一定的规则,自动执行,而这些规则被称为pipeline的触发条件
- 触发维度
- 时间触发
- 事件触发
时间触发
简述
- 指定义一个时间,时间到了就触发pipeline执行
- 使用trigger指令来定义时间触发,trigger指令只能被定义在pipeline块下
- 支持的三种方式
- cron,定时执行
- pollSCM,轮询代码仓库
- upstream
触发方式
cron,定时执行
pollSCM,轮询代码仓库
- 是指定期到代码仓库询问代码是否有变化,如果有变化就执行
- 建议越频繁越好,此种方式可以尽快得到变更后的质量反馈
事件触发
简述
- 是指发生了某个事件就触发pipeline执行
- 比如手动在界面上触发、其它Job主动触发、HTTP API Webhook触发
触发方式
upstream,由上游任务触发
- upstream的作用就是让下游自行决定依赖哪些上游任务
GitLab通知触发
指GitLab发现源代码有变更时,触发Jenkins执行构建
1.安装GitLab插件
2.安装Git插件
3.在GitLab上创建项目
4.在Jenkins上创建pipeline项目
5.在Jenkins上配置该项目的的Build Triggers
-
手动配置
- 在Jenkins上该项目的配置页中找到Build Triggers部分
- 勾选Build when a change is pushed to GitLab复选框
- 为pipeline生成一个Secret Token,远程访问只有带上Secret token的请求才会被处理
- 将Jenkins暴露的webhook的url地址和pipeline的Secret token复制下来
-
自动配置
-
通过修改Jenkinsfile来实现的
-
示例
pipeline { agent any triggers { gitlab( triggerOnPush:true, triggerOnMergeRequest: true, branchFilterType: 'ALL', secretToken: 'customAccessToken' ) } stages { stage('build') { steps{ echo "test gitlab trigger" } } } }
-
5.1自动配置时的参数列表
- triggerOnPush
- 当GitLab触发push事件时,触发构建
- triggerOnMergeRequest
- 当GitLab触发mergeRequest事件时,触发构建
- branchFilterType
- 符合条件的分支才会被触发
- 可填写的值包括
- ALL,所有分支
- NameBasedFilter,基于分支名进行过滤,多个分支名使用逗号分隔
- RegexBasedFilter,基于正则表达式对分支名进行过滤
- includeBranchesSpec
- 基于branchFilterType的值,输入期望包括的分支规则
- excludeBranchesSpec
- 基于branchFilterType值,输入期望排除的分支的规则
6.在GitLab中的变更推送到Jenkins
- 进入项目在并选择GitLab上的配置页
- 找到Settings→Integrations
- 填写Jenkin的访问地址和Secret token
- 测试整个链路是否通畅
- 选择已经添加的webhook
- 单击test按钮
- 选择push events
- 在Jenkins上该项目的详情页,找到历史构建,可以看到被GitLab触发的构建都会被标记为"Started by GitLab push By Adminstrator"
- 这就说明链路已经通畅了
7.将Jenkins中的构建结果推送到GitLab
- 进入Jenkins
- Configure System页
- 找到Gitlab选项
- 填写GitLab地址
- 根据提示,设置Credentials(凭证),单击Add按钮,输入之前保存的APItoken
- 点击Test Connection按钮,如果返回Success,就说明集成成功
- 在pipeline的post部分,将构建结果更新到GitLab的相应commit记录上
- 在options部分加入gitLabConnection配置,同时传入’gitlab’参数
- 提交代码后,需要手动触发一次构建,pipeline才会生效
使用Generic Webhook Trigger插件实现触发
在Jenkins上安装Generic Webhook Trigger插件(简称JWT)后,JWT会暴露一个API接口,通过远程调用该接口来处理触发项目的构建事件
GWT的触发条件
-
从HTTP POST请求中提取参数值
- genericVariables,提取POST body中的参数
- genericRequestVariables,从URL参数中提取值
- geenericHeaderVariables,从HTTP header中提取值
-
token,GWT插件用于标识Jenkins项目的唯一性
-
根据请求参数值判断是否触发Jenkins项目的执行
-
日志打印控制
-
Webhook响应控制
参数化pipeline
简述
- 参数化pipeline是指可以通过传参来决定pipeline的行为
- 通常使用参数化pipeline来实现一些通用的pipeline
指令
parameters
简述
- 在pipeline中定义参数使用的是parameters指令
- 其只允许被放在pipeline块下
支持的参数类型
- string,字符串类型
- name,参数名
- defaultValue,默认值
- description,描述
- booleanParam,布尔类型
- text,多行文本类型,换行使用\n
- choice,选择参数类型(下拉列表),使用\n来分隔多个选项
- file,文件类型,用户可以上传文件
- password,密码类型
示例
pipeline {
agent any
parameters {
string(
defaultValue:'',
description: '消息',
name: 'message'
)
}
stages {
stage('test') {
steps{
echo "message: ${params.message}"
}
}
}
}
定义多个参数示例
parameters {
string(defaultValue:'',description: '描述',name: 'message')
password(defaultValue:'',description: '密码',name: 'password')
booleanParam(defaultValue:true,description: '状态',name: 'state')
}
由另一个pipeline传参并调用
简述
- 在pipeline中可以使用build步骤实现此功能
- build步骤是由上游pipeline使用的,而upstream方式是由下游pipeline使用的
- build步骤是可以带参数的,而upstream方式只是被动触发,并且不带参数
常用参数
-
job,目标Jenkins任务名称
-
parameters,目标pipeline的参数列表
- 支持的参数
- string
- booleanParam
- text
- password
- propagate,布尔类型,默认为true。如果值为true,则只有当下游pipeline的最终构建状态为SUCCESS时,上游pipeline才算成功;如果值为false,则无论下游最终构建状态是什么,上游pipeline都忽略
- 支持的参数
-
quietPeriod,整型
- 触发下游pipeline后,下游pipeline等待多久执行
- 如果不设置此参数,则等待时长由下游pipeline确定
-
wait
- 布尔类型
- 是否等待下游pipeline执行完成
示例
pipeline {
build {
job:"NextPipelineName",
parameters:[
string(
name:'message',
value:'test pipeline'
)
]
}
}
input
简述
- input步骤会暂停pipeline,直到用户输入参数
使用场景
- 实现简单的审批流程
- 实现手动测试阶段
Conditional BuildStep插件
使用Conditional BuildStep插件处理复杂的逻辑判断
使用pipeline代码片段生成器
通过界面操作就可以生成代码
操作流程
- 进入pipeline项目后
- 单击左边的"pipeline Syntax"
- 在右边的"Sample Step"下拉框中选择需要生成代码的步骤
- 根据提示填入参数
- 点击"Generate Pipeline Script"按钮生成代码
如何设计pipeline
- 了解网站整体架构。这个过程就是了解胸痛是如何服务用户的;其间还可以识别出哪些关键系统
- 找到服务之间、服务与组件之间、组件之间的依赖关系
- 找到对外依赖最少的组件,将其构建、打包、制品管理自动化
- 重复第三步,直到所有(不是绝对)的组件都使用制品库管理起来
- 了解当前架构中所有的服务如何从源代码到最终部署上线的
- 找出第一个相对不那么重要的服务,将在第五步中了解到的手动操作自动化。通常不会照搬手动操作进行自动化,而是会进行一些改动
- 重复第六步,直到所有服务的所有阶段都自动化
- 加入自动化集成测试阶段
补充
在pipeline中自定义函数
使用共享库拓展
- Jenkins提供了共享库技术,可以将重复代码定义在一个独立的代码控制仓库中,其它pipeline可以加载使用它
Jenkins开发插件
- 通过界面使用的插件
- 通过代码使用的插件