「持续集成实践系列 」Jenkins 2.x 构建CI自动化流水线常见技巧(二)

简介: 「持续集成实践系列 」Jenkins 2.x 构建CI自动化流水线常见技巧(二)

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


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


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


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


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


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


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

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

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


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

微信图片_20220524160827.png


需要划一个重点:可以简单理解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中,stash和unstash函数允许在流水线的节点间和阶段间保存或获取文件。


基本用法格式:

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


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


提到stash,很多读者可能会把Jenkins stashGit stash功能弄混,需要说明一下,Jenkins stash和Git 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}"
                }
            }
        }
    }
}


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


目录
相关文章
|
2月前
|
人工智能 JavaScript 前端开发
自动化测试框架的演进与实践###
本文深入探讨了自动化测试框架从诞生至今的发展历程,重点分析了当前主流框架的优势与局限性,并结合实际案例,阐述了如何根据项目需求选择合适的自动化测试策略。文章还展望了未来自动化测试领域的技术趋势,为读者提供了宝贵的实践经验和前瞻性思考。 ###
|
1月前
|
Kubernetes Java 持续交付
小团队 CI/CD 实践:无需运维,Java Web应用的自动化部署
本文介绍如何使用GitHub Actions和阿里云Kubernetes(ACK)实现Java Web应用的自动化部署。通过CI/CD流程,开发人员无需手动处理复杂的运维任务,从而提高效率并减少错误。文中详细讲解了Docker与Kubernetes的概念,并演示了从创建Kubernetes集群、配置容器镜像服务到设置GitHub仓库Secrets及编写GitHub Actions工作流的具体步骤。最终实现了代码提交后自动构建、推送镜像并部署到Kubernetes集群的功能。整个过程不仅简化了部署流程,还确保了应用在不同环境中的稳定运行。
75 9
|
2月前
|
机器学习/深度学习 人工智能 jenkins
探索软件测试中的自动化与持续集成
【10月更文挑战第21天】 在软件开发的生命周期中,软件测试扮演着至关重要的角色。随着技术的进步和开发模式的转变,自动化测试和持续集成已经成为提高软件质量和效率的关键手段。本文将深入探讨自动化测试和持续集成的概念、实施策略以及它们如何相互配合以优化软件开发流程。我们将通过分析实际案例,展示这些技术如何在实际项目中发挥作用,以及面临的挑战和解决方案。此外,文章还将讨论未来趋势,包括人工智能在测试领域的应用前景。
97 17
|
2月前
|
运维 监控 持续交付
自动化运维在现代数据中心的应用与实践####
本文探讨了自动化运维技术在现代数据中心中的应用现状与实践案例,分析了其如何提升运维效率、降低成本并增强系统稳定性。通过具体实例,展示了自动化工具如Ansible、Puppet及Docker在环境配置、软件部署、故障恢复等方面的实际应用效果,为读者提供了一套可参考的实施框架。 ####
|
2月前
|
运维 监控 Devops
自动化运维实践:打造高效的DevOps流水线
在软件开发的快节奏中,自动化运维成为提升效率、确保质量的关键。本文将引导你理解自动化运维的价值,通过实际案例分享如何构建一个高效、可靠的DevOps流水线。我们将从持续集成(CI)开始,逐步深入到持续部署(CD),并展示代码示例来具体说明。准备好让你的运维工作飞跃式进步了吗?让我们开始吧!
|
2月前
|
jenkins 测试技术 持续交付
自动化测试框架的搭建与实践
在软件开发领域,自动化测试是提升开发效率、确保软件质量的关键手段。本文将引导读者理解自动化测试的重要性,并介绍如何搭建一个基本的自动化测试框架。通过具体示例和步骤,我们将探索如何有效实施自动化测试策略,以实现软件开发流程的优化。
114 7
|
2月前
|
jenkins 测试技术 持续交付
软件测试中的自动化与持续集成
在现代软件开发过程中,自动化测试和持续集成已成为不可或缺的组成部分。本文将深入探讨自动化测试和持续集成的重要性、优势以及如何有效实施它们以提升软件质量和开发效率。通过具体案例分析,我们将展示这些技术如何在实际项目中发挥作用,并讨论其面临的挑战及应对策略。
80 3
|
2月前
|
存储 测试技术 持续交付
Docker与CI/CD的集成策略及其对软件开发效率和质量的提升作用
本文探讨了Docker与CI/CD的集成策略及其对软件开发效率和质量的提升作用。首先介绍了CI/CD的基本概念,接着阐述了Docker在环境一致性、快速部署、资源隔离和轻量化方面的优势。文章还详细讨论了构建、测试和部署阶段的具体集成方法,以及集成后带来的效率提升、可靠性增强、加速交付和易于管理等好处。最后,通过案例分析展示了集成的实际效果,强调了Docker与CI/CD结合的重要性和未来前景。
61 2
|
3月前
|
机器学习/深度学习 数据采集 人工智能
智能化运维:从自动化到AIOps的演进与实践####
本文探讨了智能运维(AIOps)的崛起背景,深入分析了其核心概念、关键技术、应用场景及面临的挑战,并对比了传统IT运维模式,揭示了AIOps如何引领运维管理向更高效、智能的方向迈进。通过实际案例分析,展示了AIOps在不同行业中的应用成效,为读者提供了对未来智能运维趋势的洞察与思考。 ####
156 1
|
3月前
|
数据可视化 测试技术 API
软件测试中的自动化测试框架选择与实践
在当今快节奏的软件开发环境中,自动化测试成为了确保软件质量和加速交付的关键。本文将探讨自动化测试的重要性,并比较几种流行的自动化测试框架,包括Selenium、Appium和TestComplete。文章还将提供一些最佳实践和案例研究,以帮助读者更好地理解和实施自动化测试策略。

热门文章

最新文章