本文介绍 Jenkins Declarative Pipeline 语法,由于 原文档 的信息过于繁杂,将常用的和罕见的混在一起,难以找到有用信息。本文试着将常用的收集在一起,方便查阅。背景知识请参考 《Jenkins Pipeline 语法简介》,另有《Jenkins Scripted Pipeline 语法简介》 基本特点 顾名思义,Declarative Pipeline 的设计意图,是使用户将所需要的 Pipeline 各种维度的参数 声明 出来,而不是描述出来。相对 Scripted Pipeline 语法简介 , Declarative Pipeline 缺少灵活性,所以 Scripted Pipeline 中使用的部分语法,Declarative Pipeline 中都不能直接使用。 Declarative Pipeline 的特点是结构化的声明语句,各模块的从属关系比较固定,类似填写Jenkins 配置 Job 页面的表单。固定格式的声明语句,还有利于从 BlueOcean 中查看工作流。 基本语法 Declarative Pipeline的基本单元是预设指令(directives)。并不需要记忆预设指令的用法,在 Jenkins 系统中专门有一个 指令生成器(Directive Generator)可供使用。 下面是个简单的例子: pipeline { agent { label 'slave' } stages { stage('Source') { // 拉取代码 steps { git branch: 'develop', url: 'https://' } } stage('Build') { tools { gradle ... } } stage('Test') { steps { script{ mocha ... } } } } } 预设指令 各种预设指令(Directive)的从属关系如下:图中,实线框表示必选模块,虚线框表示可选模块。点击指令名称,可以直达对应章节。 下面逐项解释每一种 Directive 的参数和基本用法。 agent agent 指令用于指定所在模块(pipeline、stage)的运行环境,可以是Jenkins 节点机或者 docker 容器。取值如下: label 表示节点机的 label,在 Jenkins 的 Node List 里设置 agent { label 'slave' } none pipeline 顶层必须设置 agent,如果每个 stage 里有单独设置 agent,那么 pipeline 的 agent 需要设置为 none agent none docker 指定在 docker 容器内执行 agent { docker { image 'images:tag' } } 如果 agent 需要用变量动态指定 label,请使用 Scripted Pipeline environment 指定所在模块(pipeline、stage)的环境变量, key = value 的形式。Job 的参数,需要通过 environment 环境变量的方式 ${params.xxxx} 传递给执行脚本。 上图中的 type 就需要以下面的方式定义环境变量 environment { USER = 'username' PASSWORD = 'xxxxxx' type = "${params.type}" } triggers 指定如何触发 Pipeline ,这个选项里以时间条件触发最为常用: triggers { cron('H */4 * * 1-5') } crontab 的写法(用 H 代替 0)和设置页面上的一致。其实最方便的还是从界面上设置。 libraries 由于 Declarative Pipeline 的声明格式比较固定,如果有需要重复执行的语句片段,需要抽象为函数,就难以支持。可以使用 Shared Libraries 将共同的语句提取出来。 其实如果是简单的逻辑,可以使用Scripted Pipeline 实现。 options 这是所在模块(pipeline、stage)的运行参数设置,有下面一些用途: options { timestamps() //打开控制台日志的时间戳 retry(3) // 指定失败后的重试次数 quietPeriod(30) // 指定启动前等待的秒数 timeout(time: 1, unit: 'HOURS') // 指定任务的超时时间,超时将放弃该任务 } parameters 这是 Job 的运行参数设置,决定 Build With Parameters 界面上的参数列表。只有当 Job 运行一次、解析一次 Jenkinsfile 以后才会更新在界面上。 在 Pipeline 文件的其他模块里,parameters 的设置以 params 对象形象出现,可以用来读取自定义的参数。各类型的参数定义如下: parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value') choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something') password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password') } tools 这是在 Jenkins 里 Manage Jenkins - Global Tool Configuration 里设置过的工具 stages stages是 pipeline 模块下的必选项,这是所有 stage 的集合,其中要包含至少一个 stage stage stage 真正执行语句的模块,有以下的特点: 每一个 stage 在 Blue Ocean 界面上对应一个圆圈; stage可以定义多个; stage 有一个必选参数,就是名称,写在 stage 后面的括号里:stage('Example') {...} stage 里有许多参数和 顶级 pipeline 相同,下面逐个介绍: agent 如果 pipeline 中的 agent 设置为 none,则每个 stage 中必须设置 agent environment 同 pipeline 里的 environment , 规定了当前 stage 内部的环境变量。 tools 同 pipeline 里的 tools , 规定了当前 stage 内部适用的工具。 input 在 stage 开始执行前,暂停执行stage,等待用户输入信息。并不适用全自动化流水线。 input { message '请输入信息' ok '确定' } when 条件判断(类似 if),决定所在的 stage 是否继续执行。when 的用法需要分两个维度解释: 语句维度: when 里支持一些内置的判断条件,比如: when { environment name: 'DEPLOY_TO', value: 'production' // 判断环境变量 equals expected: 2, actual: currentBuild.number // 判断变量的值 expression { BRANCH_NAME ==~ /(production|staging)/ } //Groovy布尔表达式 triggeredBy 'TimerTrigger' // 判断触发原因 branch 'master' // 多分支流水线里,判断当前所在的分支 } 逻辑维度: when 里的条件支持与、或、非等逻辑运算: allOf{}, anyOf{}, not{}. 它们之间可以互相嵌套至任意深度。 when { allOf { branch 'production' environment name: 'DEPLOY_TO', value: 'production' } } 多个条件并列默认是与关系,@allOf{}@ 可以省略,上面的例子等效于: when { branch 'production' environment name: 'DEPLOY_TO', value: 'production' } steps 真正的执行语句是放在 steps 里的,这里可以包括许多 预先定义好的 step , 这里列出一些常用的: steps { echo 'debugging' sleep 120, unit: 'DAYS' retry 3 error() // dir // 指定工作目录 readFile fileExists withEnv script } post post 用于后处理,位于 pipeline 顶级或者 stage 内部。当一定场景满足后,执行条件块内的 steps post 支持的 steps 和 stages 里的 steps 相同。下面是各种常用的场景: 条件 执行场合 always 总是执行 success 前面的 stage 全部成功时执行;如果 post 位于 stage 内部,则是 stage 成功时执行 failure 前面的 stage 有失败时执行;如果 post 位于 stage 内部,则是 stage 失败时执行 嵌套执行结构 stage 下又可以嵌套 stages,继续向下嵌套多个 stage,呈顺序执行。 并行执行结构 一个 stage 可以声明为多个 stage 的并行执行,只要再加一层 parallel 指令,parallel 内的各个 stage 将并行执行,但是内部不能继续嵌套 parallel。基本结构为: stages { stage('Parallel Stage') { parallel { stage('Branch A') { ... } stage('Branch B') { ... } stage('Branch C') { ... } } } } 但是由于 pipeline 文件本身是 Groovy 代码,所以并没有规定在 pipeline {} 以外不允许有 Groovy代码。正相反,额外的辅助代码,可以带来更多更灵活的功能。