在上一篇文章中,我们介绍了Jenkins 2.x实现流水线的两种语法,以及在实际工作中该如何选择脚本式语法或声明式语法。原文可查阅:「持续集成实践系列」Jenkins 2.x 搭建CI需要掌握的硬核要点(一)

在使用传统的Jenkins Web界面和项目时,比如自由风格类型的任务,我们对处理流程的控制能力是有限的。所采用的典型形式是任务链:任务完成后触发其他的任务。或者我们可能会包括构建后处理,不管任务成功完成与否,总是去做一些类似发送通知的事情。

除了这些基本的功能外,还可以添加条件性构建步骤插件,通过基于单个或者多个条件的构建步骤来定义更加复杂的流程。但即便如此,相比于我们编写程序时可以直接控制执行流程的方法,条件性构建步骤插件对流程的控制能力依然有限。

在本篇中,我们将聊一下,关于Jenkins流水线DSL语言所提供的用于控制流水线执行流程基本结构和一些常见技巧。

1. Pipeline流水线指令常见结构

正如在系列第一篇文章中介绍到的,Jenkins DSL采用的是Groovy脚本语言。这也意味着如果当你掌握了Groovy语言,可以按照需求在流水线中使用Groovy语言的结构和习惯用法,针对这一类使用者,通常会更倾向于用脚本式语法来实现流水线。但不管采用的是哪种语法,从流水线组成的角度来讲,都是由一些不同指令+步骤构建结构化代码块。

对于脚本式流水线,基本结构如下:

node('worker'){
    stage('阶段'){
        // DSL
    }
}

构建脚本式流水线常用的结构或者说代码块节点主要由nodestage两个组成。

而,声明式流水线基本结构构成环节相对要多一些,整理了一张图如下:


需要划一个重点:可以简单理解node是用于脚本式流水线,而agent则是用于声明式流水线。

Jenkins Pipeline支持的指令(常见):

指令名 说明 作用域
agent 指定流水线或特定阶段在哪里运行。 stage 或pipeline
environment 设置环境变量 stage或pipeline
tools 自动下载并安装指定的工具,并将其加入到PATH变量中 stage或pipeline
input 暂停pipeline,提示输入内容 stage
options 用来指定一些预定义选项 stage 或 pipeline
parallel 并行执行多个step stage
parameters 允许执行pipeline前传入一些参数 pipeline
triggers 定义执行pipeline的触发器 pipeline
when 定义阶段执行的条件 stage
build 触发其他的job steps

options Jenkins Pipeline常见配置参数:

参数名 说明 例子
buildDiscarder 保留最近历史构建记录的数量 buildDiscarder(logRotator(numToKeepStr: '10')
timestamps 添加时间戳到控制台输出 timestamps()
disableConcurrentBuilds 阻止Jenkins并发执行同一个流水线 disableConcurrentBuilds()
retry pipeline发生失败后重试次数 retry(4)
timeout pipeline运行超时时间 timeout(time:1, unit: 'HOURS')

示例:

pipeline{
    agent any
    options{
        buildDiscarder(logRotator(numToKeepStr: '10')
        timestamps()
        retry(3)
        timeout(time:1, unit: 'HOURS')
    }
    stages{
        stage('demo'){
            steps{
                sh 'echo hello'
            }
        }
    }
}

更多pipeline指令,可参见官方介绍:

https://www.jenkins.io/doc/book/pipeline/syntax/#

下述仅挑几个常用的,用于流水线流程控制选项的指令项,介绍一些常用技巧。

2. 超时(Timeout)

这个timeout步骤允许限制等待某个行为发生时脚本所花费的时间。其语法相当简单。示例如下:

timeout(time:60,unit:'SECONDS'){
    //该代码块中的过程被设置为超时
}

默认的时间单位是min。如果发生超时,该步骤就会抛出一个异常。如果异常没有被处理,将导致整个流水线过程被中止。

通常推荐的做法是,在使用timeout对任何造成流水线暂停的步骤(如一个input步骤)进行封装,这样做的结果是,即使出现差错导致在限定的时间内没有得到期望的输入,流水线也会继续执行。

示例如下:

node{
    def response
    stage('input'){
        timeout(time:10,unit:'SECONDS'){
            response = input message :'Please Input User'
            parameters:[string(defaultValue:'mikezhou',description:'Enter UserId:',name:'userid')]
        }
        echo "Username = " + response
    }
}

在这种情况下,Jenkins将会给用户10s做出反应,如果时间到了,Jenkins会抛出一个异常来中止流水线。

如果实际在设计流水线时,当超时发生时,并不想中止流水线向下执行,可以引入try...catch代码块来封装timeout。

如下代码块所示:

node{
    def response
    stage('input'){
      try {
        timeout(time:10,unit:'SECONDS'){
            response = input message :'Please Input User'
            parameters:[string(defaultValue:'mikezhou',description:'Enter UserId:',name:'userid')]
         }
       }
       catch(err){
            response = 'user1'
      }
    }
}

需要注意的是,在处理异常的时候,可以在捕获异常处设置为期望的默认值。

3. 重试(retry)

这个retry闭包将代码封底装为一个步骤,当代码中有异常发生时,该步骤可以重试n次。其语法如下:

retry(n){
  //代码过程
}

如果达到重试的限制并且发生了一个异常,那么整个过程将会被中止(除非异常被处理,如使用try...catch代码块)

retry(2){
    try {
       def result=build job: "test_job"
       echo result
      }
    catch(err){
        if(!err.getMessage().contains("UNSTABLE"))
        throw err
    }
}

4. 等待直到(waitUntil)

引入waitUntil步骤,会导致整个过程一直等待某件事发生,通常这里的“某件事”指的是可以返回true的闭包。

如果代码过程永不返回true的话,这个步骤将会无期限地等待下去而不会结束。所以一般常见的做法,会结合timeout步骤来封装waitUntil步骤。

例如,使用waitUntil代码块来等待一个标记文件出现:

timeout(time:15,unit:'SECONDS'){
    waitUntil{
        def ret = sh returnStatus:true,script:'test -e /home/jenkins2/marker.txt'
        return (ret==0)
    }
}

再举一个例子,假如我们要等待一个Docker容器运行起来,以便我们可以在流水线中通过REST API调用获取一些数据。在这种情况下,如果这个URL还不可用,就会得到一个异常。为了保证异常被抛出的时候进程不会立即退出,我们可以使用try...catch代码块来捕获异常并且返回false。

timeout(time:150,unit:'SECONDS'){
    waitUntil{
        try{
            sh "docker exec ${containerid} curl --silent http://127.0.0.1:8080/api/v1/registry >/test/output/url.txt"
            return true
        }
        catch(err)
            return false
    }
}

5.Stash暂存:实现跨节点文件共享

在Jenkins的DSL中,stashunstash函数允许在流水线的节点间和阶段间保存或获取文件。

基本用法格式:

stash name:"<name>" [includes:"<pattern>" excludes:"<pattern>"]
unstash "<name>"

我们通过名称或模式来指定一个被包括或被排除的文件的集合。给这些文件的暂存处命名,以便后面通过这个名称使用这些文件。

提到stash,很多读者可能会把Jenkins stashGit stash功能弄混,需要说明一下,Jenkins stashGit stash功能是不同的。Git stash函数是为了暂存一个工作目录的内容,缓存那些还没有提交到本地代码仓库的代码。而Jenkins stash函数是为了暂存文件,以便在节点间共享。

例如,master节点和node节点,实现跨主机共享文件:

pipeline{
    agent none
    stages{
        stage('stash'){
            agent { label "master" }
            steps{
                writeFile file: "test.txt", text: "$BUILD_NUMBER"
                stash name: "test", includes: "test.txt"
            }
        }
        stage('unstash'){
            agent { label "node" }
            steps{
                script{
                    unstash("test")
                    def content = readFile("test.txt")
                    echo "${content}"
                }
            }
        }
    }
}

如果你觉得文章还不错,请大家点赞分享下。你的肯定是我最大的鼓励和支持。

「持续集成实践系列 」Jenkins 2.x 构建CI自动化流水线常见技巧的更多相关文章

  1. 「持续集成实践系列」Jenkins 2.x 搭建CI需要掌握的硬核要点

    1. 前言 随着互联网软件行业快速发展,为了抢占市场先机,企业不得不持续提高软件的交付效率.特别是现在国内越来越多企业已经在逐步引入DevOps研发模式的变迁,在这些背景催促之下,对于企业研发团队所需 ...

  2. fir.im weekly - 「 持续集成 」实践教程合集

    我们常看到许多团队和开发者分享他们的持续集成实践经验,本期 fir.im Weekly 收集了 iOS,Android,PHP ,NodeJS 等项目搭建持续集成的实践,以及一些国内外公司的内部持续集 ...

  3. [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBuild+GitHub)

    本系列文章包含: [独孤九剑]持续集成实践(一)- 引子 [独孤九剑]持续集成实践(二)– MSBuild语法入门 [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBu ...

  4. 基于 Node.js 的轻量「持续集成」工具 CIZE

    CIZE 是什么? CIZE 是一个「持续集成」工具,希望能让开发人员更快捷的搭建一个完整.可靠.便捷的 CI 服务. 甚至可以像 Gulp 或 Grunt 一样,仅仅通过一个 cizefile.js ...

  5. 基于Jenkins的开发测试全流程持续集成实践

    今年一直在公司实践CI,本文将近半年来的一些实践总结一下,可能不太完善或优美,但的确初步解决了我目前所在项目组的一些痛点.当然这仅是一家之言也不够完整,后续还会深入实践和引入Kubernetes进行容 ...

  6. [独孤九剑]持续集成实践(二)– MSBuild语法入门

    本系列文章包含: [独孤九剑]持续集成实践(一)- 引子 [独孤九剑]持续集成实践(二)– MSBuild语法入门 [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBu ...

  7. 什么是云效持续集成?如何关联Jenkins进行持续集成?

    什么是云效持续集成?如何关联Jenkins进行持续集成?云效流水线 Flow是一款企业级.自动化的研发交付流水线, 提供灵活易用的持续集成.持续验证. 持续发布功能,帮助企业高质量.高效率的交付业务. ...

  8. 持续集成之④:GitLab触发jenkins构建项目

    持续集成之④:GitLab触发jenkins构建项目 一:目的为在公司的测试环境当中一旦开发向gitlab仓库提交成功代码,gitlab通知jenkins进行构建项目.代码质量测试然后部署至测试环境, ...

  9. Jenkins持续集成(下)-Jenkins部署Asp.Net网站自动发布

    环境:Windows 2008 R2.Jenkins2.235.1.Visual Studio 2017: 概要 前面写过一篇文章,<自动发布-asp.net自动发布.IIS站点自动发布(集成S ...

随机推荐

  1. poi excel自动转换成javabean 支持引用类型属性二级转换

    最近项目需要使用excel导入功能,导入学生的时候需要指定所在班级,使用excel一次性导入! 将以前的代码改改支持属性内引用类的转换. 测试对象为User对象,javabean结构: private ...

  2. 【图论算法】LCA最近公共祖先问题

    LCA模板题https://www.luogu.com.cn/problem/P3379题意理解 对于有根树T的两个结点u.v,最近公共祖先LCA(u,v)表示一个结点x,满足x是u.v的祖先且x的深 ...

  3. vue v-for 渲染input 输入有问题 解决方案

    v-for循环input标签的时候输入信息两个输入框一同显示输入信息 解决方案: <input :placeholder="items.title" v-model = &q ...

  4. Angular的面试题

    1.Aangular中组件之间通信的方式 答案:Props down 1.调用子组件,通过自定义属性传值 2.子组件内部通过Input来接收属性的值 Events  up 1.在父组件中定义一个有参数 ...

  5. 模拟SWPU邮件登录页面

    模拟SWPU邮件登录页面设计流程 一.开发工具准备 本次开发该页面时使用的开发工具为vscode—— 在下载安装完成后,需要下载各类插件——如汉化.通过浏览器打开网页插件等. 二.开发过程 首先,打开 ...

  6. ES[7.6.x]学习笔记(九)搜索

    搜索是ES最最核心的内容,没有之一.前面章节的内容,索引.动态映射.分词器等都是铺垫,最重要的就是最后点击搜索这一下.下面我们就看看点击搜索这一下的背后,都做了哪些事情. 分数(score) ES的搜 ...

  7. mouseover与mouseenter区别

    学习笔记. mouseover:在鼠标移入元素本身或者子元素时都会触发事件,相当于有一个冒泡过程.而且在鼠标移入子元素中时,父元素会显示离开的状态:相应的,当鼠标从子元素移入父元素,子元素也会显示离开 ...

  8. 基于Javaee的影视创作论坛的设计与实现

    基于Javaee的影视创作论坛的设计与实现主要用功能包括: 首页推荐.用户管理.影片管理.评论管理. 预告片管理.海报管理.公告管理.数据检索.用户注册与登录等等功能.统结构如下 (1)后台管理: 管 ...

  9. thymeleaf将对象Model数据抛到HTML页面

    thymeleaf名称空间  <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymelea ...

  10. GC总结

    概述 GC(Garbage Collection),需要完成的3件事 哪些内存需要回收? 什么时候回收? 如何回收? 为什么需要了解GC和内存分配?更好的监控和调节 排查各种内存溢出,内存泄漏 避免G ...