美文网首页pipeline
Jenkins2.x 实践指南--pipeline语法讲解

Jenkins2.x 实践指南--pipeline语法讲解

作者: 卢纪超 | 来源:发表于2021-10-15 18:12 被阅读0次

    Jenkins pipeline 是基于Groovy语言实现的一种DSL(领域特定语言),用于描述整条流水线是如何进行的。

    1. pipeline的组成

    1.1最简结构

    以下从pipeline最简结构----Hello World 查看Jenkins file文件的构成:

    pipeline {
        agent any
    
        stages {
            stage('Hello') {
                steps {
                    echo 'Hello World'
                }
            }
        }
    }
    
    • pipeline:代表整条流水线,包含整条流水线的逻辑

    • stage:代表流水线的阶段。每个阶段都必须有名称。本例中,Hello就是此阶段的名称

    • stages:流水线中多个stage的容器。stages至少包含一个stage

    • steps:代表阶段中的一个或多个具体步骤(step)的容器。steps至少包含一个步骤。本例中的echo就是一个步骤。在一个stage中有且只有 一个steps

    • agent:指定流水线的执行位置(Jenkins agent)。流水线中的每个每段都必须在某个地方(物理机、虚拟机或Docker 容器)执行。agent部分即指定具体在哪里执行。

      以上的每一个部门都是必需的,少任何一个,Jenkins 都会报错。

    1.2 步骤(Steps)

    pipeline基本结构决定pipeline整体流程,但真正“做事”的还是pipeline中的每一个步骤。步骤是pipeline中已经不能在拆分的最小操作。

    步骤是可插拔的。现有的插件不用修改或者只需要简单修改,就能在Jenkins pipeline中当成一个步骤来使用,大大降低了从现有依赖界面的插件过渡到pipeline中步骤的成本。

    2. post部分

    post {
        failure {
            mail to: 'team@example.com', subject: 'The Pipeline failed :('
        }  
    }
    

    post 部分是在整个pipeline或者阶段完成后一些附件的步骤。

    post步骤是可选的,所以并不包含在pipeline最简结构中,但并不代表它作用不大。

    根据pipeline或阶段的完成状态,post部分分成多种条件块,包括

    • always:不论当前完成状态是什么,都执行。
    • changed:只要当前完成状态与上一次完成状态不同就执行。
    • fixed:上一次完成状态为失败或者不稳定(unstable),当前完成状态 为成功时执行。
    • regression:上一次完成状态为成功,当前完成状态为失败、不稳定或者中止(aborted)时执行。
    • aborted:当前执行结果是中止状态时(一般为人为中止)执行。
    • failure:当前状态为完成失败时执行。
    • success:当前完成状态为成功时执行。
    • unstable:当前完成状态为不稳定时执行。
    • cleanup:清理条件块。不论当前完成状态是什么,在其他所有条件块执行完成后都执行。post部分可以同时包含多种条件块。

    post部分完整示例:

    pipeline {
        agent any
    
        stages {
            stage('build') {
                steps {
                    echo "build stage"
                }
    
                post {
                    always {
                        echo "stage post always"
                    }
                }
            }
        }
        post {
            changed  {
                echo "pipeline post changed"
            }
    
            always {
                echo "pipeline post always"
            }
            
            success {
                echo "pipeline post success"
            }
            
            //....
        }
    }
    

    3. pipeline 支持的指令

    基本结构满足不了现实多变的需求,Jenkins pipeline 通过各种指令(directive)来丰富自己。指令可以被理解为对Jenkins pipeline基本结构的补充。

    Jenkins pipeline 支持的指令有:

    • environment:用于设置环境变量,可定义在stage或pipeline部分。

    • tools:可定义在stage或pipeline部分,它会自动下载并安装我们我们执行的工具,并讲其加入PATH变量中。

    • input: 定义在stage部分,会暂停pipeline,提示你输入内容。

    • options: 用于配置Jenkins pipeline本身的选项,比如options{retry(3)} 指当pipeline失败时再重试2次。options指令可定义在stage或pipeline部分。

    • parallel:并行执行多个step。在pipeline插件1.2版本后,parallel开始支持对多个阶段进行并行执行。

    • parameters:与input不同,parameters是执行pipeline前传入的一些参数。

    • triggers:用于定义执行pipeline的触发器。

    • when: 当满足when定义的条件时,阶段才执行。

      Action:在使用指令时,需要注意的时每个指令都有自己的“作用域”。

    4.配置pipeline本身

    options指令用于配置整个Jenkins pipeline本身的选项。根据具体的选项不同,可以将其放在pipeline块或stage块中。

    常见的几个选项:

    • buildDiscarder:保存最近历史构建记录的数量。当pipeline执行完成后,会在硬盘上保存制品和构建执行日志,如果长时间不清理会占用大量空间,设置次选项后会自动清理。此选项只能在pipeline下的options中使用。示例如下:

      options {
        buildDiscarder(logRotator(numToKeepStr: '10'))
      }         
      
    • checkoutToSubdirectory: Jenkins从版本控制库拉取源码时,默认检出到工作空间的根目录中,此选项可以指定检出到工作空间的子目录中,示例如下:

      options {
          checkoutToSubdirectory('subdir')
      } 
      
    • disableConcurrentBuilds: 同一个pipeline,Jenkins默认时可以同时执行多次的,该选项是为了禁止pipeline同时执行。示例如下:

      options {
          disableConcurrentBuilds()
      }
      

      在某些pipeline存在抢占资源或者调用冲突的场景下,此选项非常有用。设置此选项后,该次执行为结束时,下一次待执行的pipeline显示在pending状态。

    • newContainerPerStage: 当agent为docker 或dockfile时,指定在同一个Jenkins节点上,每个stage都在分别运行在一个新的容器中,而不是所有stage都运行在同一个容器中。

      options {
          newContainerPerStage()
      }
      
    • retry:当发生失败时进行重试,可以指定整个pipeline的重试次数。需要注意的是,这个次数是指总次数,包含第一次失败。以下例子总共会执行四次。当使用retry选项时,options可以被放在stage块中。

      pipeline {
          agent any
      
          options {
              retry(4)
          }
      
          stages {
              stage('build') {
                  steps {
                      echo "ok"
                      error("emmm...")
                 }
              }
          }
      }
      
    • timeout:如果pipeline执行时间过长,超出设置的timeout时间,Jenkin将中止pipeline。

      单位有:SECONDS(秒)、MINUTES(分)、HOURS(小时)。

      当使用timeout选项时,options可以被放在stage块中。

      options {
          timeout(time: 6, unit: 'HOURS')
      }
      

      设置次选项后,强迫团队去处理执行是按过长的pipeline,从而优化pipeline的反馈周期。通常将timeout设置为10分钟就可以了

    5.在声明式pipeline中使用脚本

    在使用声明式pipeline时,直接在steps块中写if-else,或者定义一个变量,Jenkins都会报错。也就是不能再steps块中写Groovy代码。

    Jenkins pipeline专门提供了一个script步骤,能在script步骤中像写代码一样写pipeline逻辑。

    下面的例子是分别在不同的浏览器上跑测试。

    pipeline {
        agent any
        
        stages {
            stage('Example') {
                steps {
                    script {
                       def browers = ['chrome', 'firefox']
                       for(int i = 0; i < browers.size(); ++i){
                            echo "Testing the ${browers[i] brower"
                            }
                       }
                    }
                }
            }
        }
    

    在script块中其实就是Groovy代码。如果在script步骤中写了大量的逻辑,则说明你应该把这些逻辑拆分到不同的阶段,或者放到共享库中。共享库是一种扩展Jenkins pipeline的技术。

    6. pipeline内置基础步骤

    6.1 文件目录相关步骤

    deleteDir:删除当前目录

    deleteDir是一个无参步骤,删除的是当前工作目录。通常它与dir步骤一起使用,用于删除指定目录下的内容。

    dir:切换到目录

    默认pipeline工作在工作目录空间下,dir步骤可以让我们切换到其他目录。使用方法如下:

    {
        dir("/var/logs"){
            deleteDir()
        }
    }
    
    fileExists: 判断文件是否存在。

    如果参数是相对路径,则判断在相对当前工作目录下,该文件是否存在,结果返回布尔类型。

    fileExits('/tmp/a.jar')判断/tmp/a.jar文件是否存在。

    isUnix:判断是否在类UNIX系统

    如果当前pipeline运行在一个类UNIX系统上,则返回true

    pwd:确认当前目录

    pwd与Linux的pwd命令一样,返回当前所在目录。它有一个布尔类型的可选参数:tmp。如果参数值为true,则返回与当前工作空间关联的临时目录。

    writeFile:将内容写入指定文件中

    writeFile支持的参数有:

    • file:文件路径,可以是绝对路径,也可以是相对路径。
    • text:要写入的文件内容。
    • encoding(可选):目标文件的编码。如果为空,则和操作系统系统编码方式保持一致。
    readFile:读取文件内容

    读取指定文件的内容,以文本返回。readFile支持的参数书有:

    • file:文件路径,可以是绝对路径,也可以是相对路径。
    • encoding:读取文件时使用的编码

    示例如下:

    {
        //"amvua2lucyBib299r" 是"jenkins book" 进行Base64编码后的值
        writeFile(file: "base64file", text: "amvua2lucyBib299r", encoding;'Base64')
        def content = readFile(file: "base64file",encoding: 'UTF-8')
        echo "${content}"
        //打印结果: jenkins book
    }
    

    6.2 产出相关步骤

    stash:保存临时文件

    stash步骤可以将一些文件保存起来,以便被同一次构建的其他步骤或阶段使用。如果这个pipeline的所有阶段在同一台机器上执行,则说他是步骤是多余的。所以,通常需要stash的文件都是要跨Jenkins node使用的。

    stash步骤会将文件存储在tar文件中,对于大文件的stash操作将会消耗Jenkins master的计算资源。Jenkins官方文档推荐,当文件大小为5~100MB时,应考虑使用其他替代方案。

    stash步骤的参数列表如下:

    • name:字符串类型,保存文件的集合的唯一标识。
    • allowEmpty:布尔类型,允许stash内容为空。
    • excludes:字符串类型,将哪些文件排除。如果排除多个文件,则使用都好分割。留空代表不排除任何文件。
    • includes:字符串类型,stash哪些文件,留空代表当前文件夹下的所有文件。
    • useDefaultExcludes:布尔类型,如果是true,则代表使用Ant风格路径默认排除文件列表

    除了name参数,其他 参数都是可选的。excludes和includes使用的是Ant风格路径表达式。

    unstash:取出之前stash的文件

    unstash步骤只有一个name参数,即stash时的 唯一标识。通常stash和unstash步骤同时使用。

    示例如下:

    pipeline {
        agent any
        stages {
            stage('stash'){
                agent { label "master" }
                steps {
                    writeFile file: 'a.txt',text: "$BUILD_NUMBER"
                    stash(name: "abc",includes: "a.txt")
                }
            }
            stage('unstash')
            {
                agent {label "node2" }
                steps{
                    unstash("abc")
                    def content = readFile("a.txt")
                    echo "${content}"
                }
            }
        }
    }
    

    stash步骤在master节点上执行,而unstash步骤在node2节点上执行

    6.3 命令相关步骤

    Pipeline:Nodes and Processes插件提供的步骤。它是Pipeline插件的一个组件,基本不需要单独安装。

    sh: 执行shell命令

    sh步骤支持的参数有:

    • script:将要执行的shell脚本,通常在类UNIX系统上可以是多行脚本。
    • encoding:脚本执行后输出日志的编码 ,默认值为脚本运行所在系统的编码。
    • returnStatus:布尔类型,默认脚本返回的是状态码,如果是 一个非零的状态码,则会引发pipeline执行失败。如果returnStatus参数为true,则不论状态码是什么,pipeline的执行都不会受影响。
    • returnStdout:布尔类型,如果是true,则任务的标准输出将作为步骤的返回值,而不是打印到构建日志中(如果有错误,则依然会打印到日志中)。除了script参数,其他参数都是可选的。

    returnStatus和returnStdout参数一般不会同时使用,因为返回值只能有一个。如果同时使用,则只有returnStatus参数生效。

    bat、powershell步骤

    bat步骤执行的是WIndows的批处理命令。powershell步骤执行的是PowerShell脚本,支持3+版本。这两个步骤支持的参数与sh步骤一样。

    6.4 其他步骤

    error:主动报错,中止当前pipeline

    error步骤的执行类似于抛出一个异常。它只有一个必须参数:message。通常省略参数:error("There is an error")。

    tool:使用预定义的工具

    如果在Global Tool Configuration(全局工具配置)中配置了 工具,可以通过tool步骤得到工具路径。

    steps {
        script {
            def t = tool name: 'docker', type: 'org.jenkinsci.plugins.docker.commons.tools.DockerTool'
            echo "${t}" //将打印 /var/lib/docker
        }
    }
    

    tool步骤支持的参数有:

    • name:工具名称

    • type(可选):工具类型,指该工具安装类的全路径类名。

    每个插件的type值都不一样,而且绝大多数的文档根本不屑type值。除了到该插件的源码中查找,还有一种方法可以让我们快速找到type值,就是前往 Jenkins pipeline代码片段生成器中生成该 tool不走的代码即可。

    timeout:代码块超时时间

    为timeout步骤闭包内运行的代码设置超时时间限制。如果超时,将。抛出一个 org.jenkinsci.plugins.workflow.steps.FlowInterruptException异常。timeout步骤支持如下参数:

    • time:整型,超时时间。
    • unit(可选):时间单位,支持的值有NANOSESECONDS、MICROSECONDS、MILLISECONDS、SECONDS、MINUTES(默认)、HOURS、DAYS
    • activity(可选):布尔类型,如果值为true,则只有当日志没有活动后,才真正算作超时。
    waitUntil:等待条件满足

    不断重复waitUntil块内的代码,直到条件为true。waitUntil不负责处理块内代码的异常,遇到异常时直接向外抛出。waitUntil步骤最好与timeout步骤共同使用,避免死循环。示例如下:

    timeout(50) {
        waitUntil {
            script {
                def r = sh script: 'curl http://exmaple', returnStatus:true
                return( r==0 )
            }
        }
    }
    
    retry:重复执行块

    执行N次闭包内的脚本。如果其中某次执行抛出异常,则只中止本次执行,并不会中止整个retry的执行。同时,在执行retry的过程中,用户是无法中止pipeline的。

    steps {
        retry(20) {
            script {
                sh script: 'curl http://exmaple', returnStatus:true
            }
        }
    }
    
    sleep:让pipeline休眠一段时间

    sleep步骤可用于简单地暂停pipeline,其支持的参数有:

    • time:整型,休眠时间。
    • unit(可选):时间单位,支持的值有NANOSESECONDS、MICROSECONDS、MILLISECONDS、SECONDS、MINUTES(默认)、HOURS、DAYS
    sleep(120) //休眠120秒
    sleep(time: '2', unit: 'MINUTES') //休眠2分钟
    

    相关文章

      网友评论

        本文标题:Jenkins2.x 实践指南--pipeline语法讲解

        本文链接:https://www.haomeiwen.com/subject/hosuoltx.html