举个例子:一般我们进行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"
- }
- }