持续交付-Jenkinsfile 语法

116 阅读5分钟

获取更多技术文章分享

实现 Pipeline 功能的脚本语言叫做 Jenkinsfile,由 Groovy 语言实现。Jenkinsfile 一般是放在项目根目录,随项目一起受源代码管理软件控制,无需像创建"自由风格"项目一样,每次可能需要拷贝很多设置到新项目,提供了一些直接的好处:

  • Pipeline 上的代码审查/迭代
  • Pipeline 的审计跟踪
  • Pipeline 的唯一真实来源,可以由项目的多个成员查看和编辑 Pipeline 支持:Declarative(在 Pipeline 2.5 中引入)和 Scripted Pipeline 两种格式。两者都支持建立 Pipeline,两者都可以用于在 Web UI 中定义一个流水线 Jenkinsfile,将 Jenkinsfile 文件创建并检查到源代码控制库中通常被认为是最佳做法。

Declared Pipeline

Declared Pipeline树

Declared Pipeline 必须包含在固定格式 Pipeline {} 块内,每个声明语句必须独立一行,行尾无需使用分号。块( blocks{} )只能包含章节(Sections),指令(Directives),步骤(Steps)或赋值语句。

块 blocks{}

由大括号括起来的语句,如 Pipeline{},Section{},parameters{},script{}

章节(Sections)

章节中通常包含一个或多个指令或步骤。如 agent 、post、stages、steps

指令(Directives)

environment、options、parameters、triggers(触发)、stage、tools、when

节点(agent)

必须存在,agent 必须在 Pipeline 块内的顶层定义,但 stage 内是否使用是可选的 参数:any/none/label/node/docker/dockerfile 常用选项 label/cuetomWorkspace/reuseNode 示例:

agent { label 'my-label' }

agent {
    node {
            label 'my-label'
                    customWorkspace '/some/other/path'
                        }
                        }
                        
                        agent {
                            docker {
                                    image 'nginx:1.12.2'
                                            label 'my-label'
                                                    args '-v /tmp:/tmp'
                                                        }
                                                        }
                                                        
                                                        ```
                                                        
                                                        ## 构建后(post)
                                                        
                                                        不是必须,用于 Pipeline 的最外层或者 stage{} 中,主要用于表达 Jenkins 完成构建动作之后需要做的事情。
                                                        
                                                        示例:
                                                        
                                                        ```
                                                        pipeline {
                                                            agent any
                                                                stages {
                                                                        stage('Example'){
                                                                                    steps {
                                                                                                    echo 'Hello world'
                                                                                                                }
                                                                                                                        }
                                                                                                                            }
                                                                                                                                post {
                                                                                                                                        always {
                                                                                                                                                    echo 'say goodbay'
                                                                                                                                                            }
                                                                                                                                                                }
                                                                                                                                                                }
                                                                                                                                                                
                                                                                                                                                                ```
                                                                                                                                                                
                                                                                                                                                                ## 阶段集(stages)
                                                                                                                                                                
                                                                                                                                                                必须存在,包括顺序执行的一个或多个 stage 命令,在 Pipeline 内仅能使用一次,通常位于 agent/options 后面。
                                                                                                                                                                ## 步骤(steps)
                                                                                                                                                                
                                                                                                                                                                必须存在,steps 位于 stage 指令块内部,包括一个或多个 step。仅有一个 step 的情况下可以忽略关键字 step 及其{}。
                                                                                                                                                                ## 环境(environment)
                                                                                                                                                                
                                                                                                                                                                不是必须,environment 定义了一组全局的环境变量键值对,存在于 pipeline {} 或者 stage 指令内。执行特殊方法 credentials()可以获取 Jenkins 中预定义的凭证明文内容。
                                                                                                                                                                
                                                                                                                                                                示例:
                                                                                                                                                                ```
                                                                                                                                                                environment {CC='clang'}
                                                                                                                                                                environment {AN_ACCESS_KEY = credentials('my-prefined-secret-text')}
                                                                                                                                                                steps {sh 'printenv'}
                                                                                                                                                                
                                                                                                                                                                ```
                                                                                                                                                                
                                                                                                                                                                
                                                                                                                                                                ## 选项(options)
                                                                                                                                                                
                                                                                                                                                                不是必须,预定义 Pipeline 专有的配置信息,仅可定义一次
                                                                                                                                                                
                                                                                                                                                                示例:
                                                                                                                                                                ```
                                                                                                                                                                pipeline {
                                                                                                                                                                    agent any
                                                                                                                                                                        options{
                                                                                                                                                                                timeout(time:1,unit: 'HOURS')
                                                                                                                                                                                    }
                                                                                                                                                                                    }
                                                                                                                                                                                    
                                                                                                                                                                                    ```
                                                                                                                                                                                    
                                                                                                                                                                                    ## 参数(parameters)
                                                                                                                                                                                    
                                                                                                                                                                                    不是必须, 定义参数化构建的参数可选参数, 参数类型 booleanParam,choice,file,text,password,run,string
                                                                                                                                                                                    示例:
                                                                                                                                                                                    ```
                                                                                                                                                                                    parameters {
                                                                                                                                                                                            string(name: 'PERSON', defaultValue: 'Jenkins', description: '输入的文本参数')
                                                                                                                                                                                                    choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
                                                                                                                                                                                                    }
                                                                                                                                                                                                    
                                                                                                                                                                                                    ```
                                                                                                                                                                                                    
                                                                                                                                                                                                    ## 触发器(rtiggers)
                                                                                                                                                                                                    
                                                                                                                                                                                                    不是必须,定义 Pipeline 被自动触发的方式选项 cron、pollSCM、upstream
                                                                                                                                                                                                    
                                                                                                                                                                                                    示例:
                                                                                                                                                                                                    
                                                                                                                                                                                                    ```
                                                                                                                                                                                                    triggers {
                                                                                                                                                                                                           cron('0 8 * * 1-5')
                                                                                                                                                                                                           }
                                                                                                                                                                                                           
                                                                                                                                                                                                           ```
                                                                                                                                                                                                           
                                                                                                                                                                                                           
                                                                                                                                                                                                           
                                                                                                                                                                                                           ### Script Pipeline
                                                                                                                                                                                                           
                                                                                                                                                                                                           ## Script Pipeline语句树
                                                                                                                                                                                                           
                                                                                                                                                                                                           一个 Script Pipeline 可以划分成若干个 Stage,每个 Stage 代表一组操作,例如 Build,Test;Node 代表 Jenkins 节点,比如 Master, Slave 这样的节点;Step 是最基本的操作单元,在对应 Node 节点上执行的动作语句直接写在 node {} 中。
                                                                                                                                                                                                           ![](https://ceshiren.com/uploads/default/original/3X/d/9/d901aac20d0499248bfb0fecbaaccb49192b019d.png)
                                                                                                                                                                                                           ## 流程控制语句
                                                                                                                                                                                                           
                                                                                                                                                                                                           如同传统的脚本语言一样,Script Pipeline 是从上至下顺序执行,可以使用 Groovy 表达式进行流程控制,如 if/else 语句通过逻辑条件判断来对流程进行控制:
                                                                                                                                                                                                           
                                                                                                                                                                                                           ```
                                                                                                                                                                                                           node {
                                                                                                                                                                                                               stage('Example') {
                                                                                                                                                                                                                       if (env.BRANCH_NAME == 'master') {
                                                                                                                                                                                                                                   echo 'I only execute on the master branch'
                                                                                                                                                                                                                                           } else {
                                                                                                                                                                                                                                                       echo 'I execute elsewhere'
                                                                                                                                                                                                                                                               }
                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                   ```
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                   ## 异常处理语句
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                   Script Pipeline 脚本流程控制的另一种方式是异常处理机制。当任何一个步骤因各种原因而出现异常时,都必须在代码中使用 try/catch/finally 语句块进行异常捕获,并通过预先设定代码进行处理,保证脚本能够顺利执行:
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                   ```
                                                                                                                                                                                                                                                                   stage('Error Handling') {
                                                                                                                                                                                                                                                                       node{
                                                                                                                                                                                                                                                                               echo "This is test demo for the error handling"
                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                       try {
                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                   echo "This is in the try block."
                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                               sh 'exit 1'
                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                       }catch (exc) {
                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                   echo "Something failed, I'm in the catch block."
                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                           }finally {
                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                       echo "Finally, I'm in the finally block."
                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                               }
                                                                                                                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                   ```
                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                   ### Jenkinsfile 中调用plugin功能
                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                   在 Jenkinsfile 中除了可以使用常规的逻辑、流程控制,还可以调用 Jenkins 的插件功能。下面用如下实例进行说明。
                                                                                                                                                                                                                                                                                                                                                                   ## Email Extension插件
                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                   Email Extension 是 Jenkins 中的一个外部插件,用来发送邮件,从 Jenkins 的 Plugin Manager 中进行安装。在 Pipeline 中通过代码调用可以触发该插件的运行,实现发送邮件的功能。
                                                                                                                                                                                                                                                                                                                                                                   ## 基础配置
                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                   在安装好 Email Extension 插件之后,首先需要选择一个准备用来发送 Jenkins 通知邮件的邮箱,发件邮箱的具体参数要提前知晓(通常参数可以从邮箱的配置参数信息页面上查到);之后要在 Manage Jenkins -> Configure System 中将对应参数填写该插件的对应配置项中,必须配置的参数如下:
                                                                                                                                                                                                                                                                                                                                                                   - SMTP server:smtp 服务地址
                                                                                                                                                                                                                                                                                                                                                                   - SMTP port:smtp 端口号
                                                                                                                                                                                                                                                                                                                                                                   - Use SMTP Authentication:启用 smtp 安全校验
                                                                                                                                                                                                                                                                                                                                                                   - User Name:发件人用户名
                                                                                                                                                                                                                                                                                                                                                                   - Password:发件人密码
                                                                                                                                                                                                                                                                                                                                                                   - Default Recipients:默认收件人
                                                                                                                                                                                                                                                                                                                                                                   其他的参数可以根据自己的需要进行配置,Email Extension 配置参考截图如下:
                                                                                                                                                                                                                                                                                                                                                                   ![](https://ceshiren.com/uploads/default/original/3X/7/7/774b2d4dafca0847548e71d4adffc7f32934ff87.png)
                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                   ## Pipeline代码
                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                   ```
                                                                                                                                                                                                                                                                                                                                                                   pipeline{
                                                                                                                                                                                                                                                                                                                                                                       agent {
                                                                                                                                                                                                                                                                                                                                                                               label 'master'
                                                                                                                                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                                                                                                                                       stages{
                                                                                                                                                                                                                                                                                                                                                                                               stage('发送邮件测试') {
                                                                                                                                                                                                                                                                                                                                                                                                           steps{
                                                                                                                                                                                                                                                                                                                                                                                                                           echo 'Test Email'
                                                                                                                                                                                                                                                                                                                                                                                                                                       }
                                                                                                                                                                                                                                                                                                                                                                                                                                               }
                                                                                                                                                                                                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                                                                                                                                                                                                       post {
                                                                                                                                                                                                                                                                                                                                                                                                                                                               always {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                           emailext body: '$DEFAULT_CONTENT', recipientProviders: [[$class: 'RequesterRecipientProvider']], subject: '$DEFAULT_SUBJECT'
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ```
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Declared Pipeline 的入门学习难度相对不高,这种类似我们在做自动化测试时所接触的关键字驱动模式,只要理解其定义好的关键词,按要求填充数据即可。
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       虽然这种方式入门容易,但灵活性欠缺。相比之下 script Pipeline 的好处就是灵活,好封装,易于大规模使用,但需要有一定的编程功底。
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       内容全面升级,4 个月 20+ 项目实战强化训练,资深测试架构师、开源项目作者亲授 BAT 大厂前沿最佳实践,带你一站式掌握测试开发必备核心技能(对标阿里P6+,年薪50W+)!直推 BAT 名企测试经理,普遍涨薪 50%+!
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ### 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ⬇️ 点击“阅读原文”,提升测试核心竞争力!
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       [原文链接](https://mp.weixin.qq.com/s?__biz=MzU3NDM4ODEzMg==&mid=2247499211&idx=1&sn=3a68952c71fa049b2f9202eff62c7b8b&chksm=fd319f00ca461616756ffdc850263e85aec6f6b0d872193224db63de336a1aef8a84ad707a4f#rd) 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       [获取更多技术文章分享](https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=juejin&timestamp=1650446169
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ) ![img](https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=juejin&timestamp=1650446169)