举个例子:一般我们进行UI/API自动化用例部署后,只要开发那边Git提交了代码,就会自动触发我们的用例执行,然后发送测试报告,从某种意义上来说,其实就是进行冒烟测试,只是这一部直接自动集成了
那持续集成有什么优点呢?
(1)可以快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。
不像瀑布模型一样到最后产品都完成开发时,才提交测试,那到时候遗留的bug就会很多,会花费很多时间成本(2)防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。
一般在开发阶段,不同的开发不同的需求都会拉不同的分支,等这个分支的代码测试全部验证通过后才会合到master分支,持续集成
语法形式有两种:
- V2.5之后引入,结构化方式:Declarative pipeline
- 基于groovy的语法:Scripts pipeline
— 必须包含在一个pipeline块内,具体来说是:pipeline{}
— 基本的部分 是“steps”,steps即告诉Jenkins要做什么
— 语句分类具体包含 【Sections,Directives,Steps,赋值】 等几大类
agent:即定义pipeline执行节点,是必须出现的指令
-- any:可以在任意agent上执行pipeline
-- none:pipeline将不分配全局agent,每个stage分配自己的agent
-- label:指定运行节点的Label
-- node:自定义运行节点配置
- 指定label
- 指定customWorkspace
-- docker:控制目标节点上的docker运行相关内容
# 指定运行节点为slave,工作区间为mikasaWorkspace
pipeline{
agent{
node{
label "slave"
customWorkspace "mikasaWorkspace"
}
}
}
指令 | 作 用 | 参数 | 备 注 |
stages | 包含一个或多个stage的序列,Pipeline的大部分工作在此执行,必需出现 | 无 | 每个pipeline代码区间中必须只有一个stages |
stage | 包含在stages中,pipeline完成的所有实际工作都需要包含到stage中,必需出现 | 无 | 需要定义stage的名字 |
steps | 包含在stage代码区间中,必需出现 | 无 | 具体执行步骤,包含在stage代码区间中 |
# 外层必须包裹一个stages
# stage:定义一个步骤的名字(提交git源码)
# steps:里面写具体执行步骤(输出更新代码,git源码地址)
stages{
stage('git pull source code')
steps{
echo "updated code"
git "https://github.com/Burden1/Mikasa_pipeline_demo.git"
}
}
post:即定义Pipeline或stage运行结束时的操作,不是必须出现的指令简单来说,它就是【构建后操作】
-- always:无论Pipeline运行的完成状态如何都会运行
-- changed:只有当前pipeline运行的状态与先前完成的pipeline的状态不同时,才能运行
-- failure:只有当前pipeline处于"【失败】"状态时才能运行
-- success:只有当前pipeline处于"【成功】"状态时才能运行
-- unstable:只有当前pipeline处于"【不稳定】"状态时才能运行
-- aborted:只有当前pipeline处于"【中止】"状态时才能运行
# 如果前面的stage操作都运行成功后,就会执行success里面的操作,否则不进入
# always即无论前面的stage操作成功与否,每次执行都会输出'always say goobye'
post{
success{
echo 'goodbye mikasa'
sleep 2
}
always{
echo 'always say goobye'
}
}
environment: 定义pipeline或stage运行时的环境变量,无参数,不是必须出现的指令
代码示例
# 环境里面定义一个mikasa变量
# stages里面输出mikasa,得到结果即:hello mikasa
environment{
mikasa = 'hello mikasa'
}
stages {
stage('print enviroment'){
steps{
echo mikasa
}
}
}
基本使用
options: 定义pipeline的专有属性,不是必须出现的指令
-- buildDiscarder:保持构建的最大个数
-- disableConcurrentBuilds:不允许并行执行pipeline任务
-- timeout:pipeline超时时间
-- retry:失败后,重试整个pipeline的次数
-- timestamps:预定义由pipeline生成的所有控制台输出时间
-- skipStagesAfterUnstable:一旦构建状态进入了“Unstable”状态,就跳过此stage
# 若失败,则重试5次
options{
timeout(time:30,unit:'SECONDS')
buildDiscarder(logRotator(numToKeepStr: '2'))
retry(5)
}
parameters: 定义pipeline的专有参数列表,不是必须出现的指令
支持数据类型:booleanParam,choice,credentials,file,text,password,run,string,类似参数化构建的选项
# 定义三个string类型的参数
# 步骤里面输出参数
parameters{
string(name: 'PERSON',defaultValue:'Jenkins',description:'输入的文本参数')
}
stages {
stage{
steps{
echo "HELLO ${params.PERSON}"
}
}
}
triggers: 定义了pipeline自动化触发的方式,不是必须出现的指令
-- cron: 接受一个cron风格的字符串来定义pipeline触发的常规间隔
-- pollSCM: 接受一个cron风格的字符串来定义Jenkins检查SCM源更改的常规间隔;如果存在新的更改,则pipeline将被重新触发
# 每个小时构建一次
triggers{
pollSCM('H * * * *')
}
基本使用
Scripts Pipeline:是基于groovy语法定制的一种DSL语言
— 灵活性更高
— 可扩展性更好
— 与Declarative pipeline 程序构成方式有不同之处,基本语句也有相似之处
# node包裹起来,里面定义stage,然后判断当前分支是不是master分支,对应输出结果
node {
stage('Example'){
if (env.BRANCH_NAME) == 'master'{
echo 'I ONLY EXECUTE ON THE MASTER BRANCH'
}else{
echo 'i execute elsewhere'
}
}
}
# node包裹起来,然后里面进行try catch,其实使用和java差不多
node{
echo "this is test stage which run on the slave agent"
try{
echo "this is in the try block"
}catch(exc){
echo "Something failed,i am in the catch block"
}finally{
echo "Finally,i am in the finally block"
}
}