Jenkins 2.0的到来,pipline进入了视野,jenkins2.0的核心特性. 也是最适合持续交付的feature。html
简单的来讲,就是把Jenkins1.0版本中,Project中的相关配置信息,如SVN/Git的配置,Parameter的配置等都变成Code,即Pipeline as Code。java
随着pipeline交付流水线在团队中的推广,使用pipeline脚本的job也迅速增长。node
优点:web
Pipeline最基本的部分是“step”。基本上,step告诉Jenkins 要作什么,而且做为Declarative Pipeline和Scripted Pipeline语法的基本构建块。
Pipeline支持两种语法:Declarative Pipeline(在Pipeline 2.5中引入,结构化方式)和Scripted Pipeline,二者都支持创建连续输送的Pipeline。chrome
最开始的Pipeline plugin,支持的只有一种脚本类型,就是Scripted Pipeline;
Declarative Pipeline为Pipeline plugin在2.5版本以后新增的一种脚本类型,与原先的Scripted Pipeline同样,均可以用来编写脚本。docker
相关资料:shell
https://stackoverflow.com/questions/43484979/jenkins-scripted-pipeline-or-declarative-pipeline
http://jenkins-ci.361315.n4.nabble.com/Declarative-pipelines-vs-scripted-td4891792.htmlexpress
从检索的资料来看,Declarative Pipeline 是后续Open Blue Ocean所支持的类型。相对而言,Declarative Pipeline比较简单,Declarative Pipeline中,也是能够内嵌Scripted Pipeline代码的。apache
为与BlueOcean脚本编辑器兼容,一般建议使用Declarative Pipeline的方式进行编写,从jenkins社区的动向来看,很明显这种语法结构也会是将来的趋势。maven
Declarative Pipeline是Jenkins Pipeline 的一个相对较新的补充, 它在Pipeline子系统之上提出了一种更为简化和有意义的语法。
全部有效的Declarative Pipeline必须包含在一个pipeline块内,例如:
pipeline { /* insert Declarative Pipeline here */ }
Declarative Pipeline中的基本语句和表达式遵循与Groovy语法相同的规则 ,但有如下例外:
Declarative Pipeline里的Sections一般包含一个或多个Directives或 Steps
agent部分指定整个Pipeline或特定阶段将在Jenkins环境中执行的位置,具体取决于该agent 部分的放置位置。该部分必须在pipeline块内的顶层定义 ,但stage级使用是可选的。
在任何可用的agent 上执行Pipeline或stage。例如:agent any
none
当在pipeline块的顶层使用none时,将不会为整个Pipeline运行分配全局agent ,每一个stage部分将须要包含其本身的agent部分。
label
使用提供的label标签,在Jenkins环境中可用的代理上执行Pipeline或stage。例如:agent { label 'my-defined-label' }
node
agent { node { label 'labelName' } },等同于 agent { label 'labelName' },但node容许其余选项(如customWorkspace)。
docker
定义此参数时,执行Pipeline或stage时会动态供应一个docker节点去接受Docker-based的Pipelines。 docker还能够接受一个args,直接传递给docker run调用。例如:agent { docker 'maven:3-alpine' }或
docker agent { docker { image 'maven:3-alpine' label 'my-defined-label' args '-v /tmp:/tmp' } }
dockerfile
使用从Dockerfile源存储库中包含的容器来构建执行Pipeline或stage 。为了使用此选项,Jenkinsfile必须从Multibranch Pipeline或“Pipeline from SCM"加载。
默认是在Dockerfile源库的根目录:agent { dockerfile true }。若是Dockerfile需在另外一个目录中创建,请使用如下dir选项:agent { dockerfile { dir 'someSubDir' } }。您能够经过docker build ...使用additionalBuildArgs选项,如agent { dockerfile { additionalBuildArgs '--build-arg foo=bar' } }。
参数
any
在任何可用的agent 上执行Pipeline或stage。例如:agent any
none
当在pipeline块的顶层使用none时,将不会为整个Pipeline运行分配全局agent ,每一个stage部分将须要包含其本身的agent部分。
label
使用提供的label标签,在Jenkins环境中可用的代理上执行Pipeline或stage。例如:agent { label 'my-defined-label' }
node
agent { node { label 'labelName' } },等同于 agent { label 'labelName' },但node容许其余选项(如customWorkspace)。
docker
定义此参数时,执行Pipeline或stage时会动态供应一个docker节点去接受Docker-based的Pipelines。 docker还能够接受一个args,直接传递给docker run调用。例如:agent { docker 'maven:3-alpine' }或
docker agent { docker { image 'maven:3-alpine' label 'my-defined-label' args '-v /tmp:/tmp' } }
dockerfile
使用从Dockerfile源存储库中包含的容器来构建执行Pipeline或stage 。为了使用此选项,Jenkinsfile必须从Multibranch Pipeline或“Pipeline from SCM"加载。
默认是在Dockerfile源库的根目录:agent { dockerfile true }。若是Dockerfile需在另外一个目录中创建,请使用如下dir选项:agent { dockerfile { dir 'someSubDir' } }。您能够经过docker build ...使用additionalBuildArgs选项,如agent { dockerfile { additionalBuildArgs '--build-arg foo=bar' } }。
这些是能够应用于两个或多个agent的选项。除非明肯定义,不然不须要。
label
一个字符串。标记在哪里运行pipeline或stage
此选项适用于node,docker和dockerfile,而且 node是必需的。
customWorkspace
一个字符串。自定义运行的工做空间内。它能够是相对路径,在这种状况下,自定义工做区将位于节点上的工做空间根目录下,也能够是绝对路径。例如:
agent { node { label 'my-defined-label' customWorkspace '/some/other/path' } }
reuseNode
一个布尔值,默认为false。若是为true,则在同一工做空间中。
此选项适用于docker和dockerfile,而且仅在 individual stage中使用agent才有效。
pipeline { //Execute all the steps defined in this Pipeline within a newly created container of the given name and tag (maven:3-alpine). agent { docker 'maven:3-alpine' } stages { stage('Example Build') { steps { sh 'mvn -B clean verify' } } } }
pipeline { agent none stages { stage('Example Build') { agent { docker 'maven:3-alpine' } steps { echo 'Hello, Maven' sh 'mvn --version' } } stage('Example Test') { agent { docker 'openjdk:8-jre' } steps { echo 'Hello, JDK' sh 'java -version' } } } }
定义Pipeline或stage运行结束时的操做。post-condition块支持post部件:always,changed,failure,success,unstable,和aborted。这些块容许在Pipeline或stage运行结束时执行步骤,具体取决于Pipeline的状态。
conditions项:
always
运行,不管Pipeline运行的完成状态如何。
changed
只有当前Pipeline运行的状态与先前完成的Pipeline的状态不一样时,才能运行。
failure
仅当当前Pipeline处于“失败”状态时才运行,一般在Web UI中用红色指示表示。
success
仅当当前Pipeline具备“成功”状态时才运行,一般在具备蓝色或绿色指示的Web UI中表示。
unstable
只有当前Pipeline具备“不稳定”状态,一般由测试失败,代码违例等引发,才能运行。一般在具备黄色指示的Web UI中表示。
aborted
只有当前Pipeline处于“停止”状态时,才会运行,一般是因为Pipeline被手动停止。一般在具备灰色指示的Web UI中表示。
pipeline { agent any stages { stage('Example') { steps { echo 'Hello World' } } } post { always { echo 'I will always say Hello again!' } } }
包含一个或多个stage的序列,Pipeline的大部分工做在此执行。建议stages至少包含至少一个stage指令,用于链接各个交付过程,如构建,测试和部署等。
steps包含一个或多个在stage块中执行的step序列。
pipeline { agent any stages { stage('Example') { steps { echo 'Hello World' } } } }
environment指令指定一系列键值对,这些键值对将被定义为全部step或stage-specific step的环境变量,具体取决于environment指令在Pipeline中的位置。
该指令支持一种特殊的方法credentials(),能够经过其在Jenkins环境中的标识符来访问预约义的凭据。
对于类型为“Secret Text”的凭据,该 credentials()方法将确保指定的环境变量包含Secret Text内容;对于“标准用户名和密码”类型的凭证,指定的环境变量将被设置为username:password。
pipeline { agent any environment { CC = 'clang' } stages { stage('Example') { environment { AN_ACCESS_KEY = credentials('my-prefined-secret-text') } steps { sh 'printenv' } } } }
options指令容许在Pipeline自己内配置Pipeline专用选项。Pipeline自己提供了许多选项,例如buildDiscarder,但它们也可能由插件提供,例如 timestamps。
buildDiscarder
pipeline保持构建的最大个数。例如:options { buildDiscarder(logRotator(numToKeepStr: '1')) }
disableConcurrentBuilds
不容许并行执行Pipeline,可用于防止同时访问共享资源等。例如:options { disableConcurrentBuilds() }
skipDefaultCheckout
默认跳过来自源代码控制的代码。例如:options { skipDefaultCheckout() }
skipStagesAfterUnstable
一旦构建状态进入了“Unstable”状态,就跳过此stage。例如:options { skipStagesAfterUnstable() }
timeout
设置Pipeline运行的超时时间。例如:options { timeout(time: 1, unit: 'HOURS') }
retry
失败后,重试整个Pipeline的次数。例如:options { retry(3) }
timestamps
预约义由Pipeline生成的全部控制台输出时间。例如:options { timestamps() }
pipeline { agent any options { timeout(time: 1, unit: 'HOURS') } stages { stage('Example') { steps { echo 'Hello World' } } } }
parameters指令提供用户在触发Pipeline时的参数列表。这些参数值经过该params对象可用于Pipeline步骤,具体用法以下
可用参数
string
A parameter of a string type, for example: parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') }
booleanParam
A boolean parameter, for example: parameters { booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '') }
目前只支持[booleanParam, choice, credentials, file, text, password, run, string]这几种参数类型,其余高级参数化类型还需等待社区支持。
pipeline { agent any parameters { string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?') } stages { stage('Example') { steps { echo "Hello ${params.PERSON}" } } } }
triggers指令定义了Pipeline自动化触发的方式。对于与源代码集成的Pipeline,如GitHub或BitBucket,triggers可能不须要基于webhook的集成也已经存在。目前只有两个可用的触发器:cron和pollSCM。
pipeline { agent any triggers { cron('H 4/* 0 0 1-5') } stages { stage('Example') { steps { echo 'Hello World' } } } }
stage指令在stages部分中,应包含stop部分,可选agent部分或其余特定于stage的指令。实际上,Pipeline完成的全部实际工做都将包含在一个或多个stage指令中。
pipeline { agent any stages { stage('Example') { steps { echo 'Hello World' } } } }
经过tools可自动安装工具,并放置环境变量到PATH。若是agent none,这将被忽略。
pipeline { agent any tools { //工具名称必须在Jenkins 管理Jenkins → 全局工具配置中预配置。 maven 'apache-maven-3.0.1' } stages { stage('Example') { steps { sh 'mvn --version' } } } }
when指令容许Pipeline根据给定的条件肯定是否执行该阶段。该when指令必须至少包含一个条件。若是when指令包含多个条件,则全部子条件必须为stage执行返回true。这与子条件嵌套在一个allOf条件中相同(见下面的例子)。
更复杂的条件结构可以使用嵌套条件建:not,allOf或anyOf。嵌套条件能够嵌套到任意深度。
pipeline { agent any stages { stage('Example Build') { steps { echo 'Hello World' } } stage('Example Deploy') { when { allOf { branch 'production' environment name: 'DEPLOY_TO', value: 'production' } } steps { echo 'Deploying' } } } }
Declarative Pipeline近期新增了对并行嵌套stage的支持,对耗时长,相互不存在依赖的stage可使用此方式提高运行效率。除了parallel stage,单个parallel里的多个step也可使用并行的方式运行。
pipeline { agent any stages { stage('Non-Parallel Stage') { steps { echo 'This stage will be executed first.' } } stage('Parallel Stage') { when { branch 'master' } parallel { stage('Branch A') { agent { label "for-branch-a" } steps { echo "On Branch A" } } stage('Branch B') { agent { label "for-branch-b" } steps { echo "On Branch B" } } } } } }
Declarative Pipeline可使用 Pipeline Steps reference中的全部可用步骤 ,并附加如下仅在Declarative Pipeline中支持的步骤。
script步骤须要一个script Pipeline,并在Declarative Pipeline中执行。对于大多数用例,script在Declarative Pipeline中的步骤不是必须的,但它能够提供一个有用的增强。
pipeline { agent any stages { stage('Example') { steps { echo 'Hello World' script { def browsers = ['chrome', 'firefox'] for (int i = 0; i < browsers.size(); ++i) { echo "Testing the ${browsers[i]} browser" } } } } } }
Groovy脚本不必定适合全部使用者,所以jenkins建立了Declarative pipeline,为编写Jenkins管道提供了一种更简单、更有主见的语法。可是不能否认,因为脚本化的pipeline是基于groovy的一种DSL语言,因此与Declarative pipeline相比为jenkins用户提供了更巨大的灵活性和可扩展性。
pipeline脚本同其它脚本语言同样,从上至下顺序执行,它的流程控制取决于Groovy表达式,如if/else条件语句,举例以下:
Jenkinsfile (Scripted Pipeline) node { stage('Example') { if (env.BRANCH_NAME == 'master') { echo 'I only execute on the master branch' } else { echo 'I execute elsewhere' } } }
pipeline脚本流程控制的另外一种方式是Groovy的异常处理机制。当任何一个步骤因各类缘由而出现异常时,都必须在Groovy中使用try/catch/finally语句块进行处理,举例以下:
Jenkinsfile (Scripted Pipeline) node { stage('Example') { try { sh 'exit 1' } catch (exc) { echo 'Something failed, I should sound the klaxons!' throw } } }
pipeline最核心和基本的部分就是“step”,从根本上来讲,steps做为Declarative pipeline和Scripted pipeline语法的最基本的语句构建块来告诉jenkins应该执行什么操做。
Scripted pipeline没有专门将steps做为它的语法的一部分来介绍,可是在Pipeline Steps reference这篇文档中对pipeline及其插件涉及的steps作了很详细的介绍。若有须要可参考jenkins官网对该部分的介绍Pipeline Steps reference
因为pipeline的一些个性化需求,好比在从新启动jenkins后要求pipeline脚本仍然能够运行,那么pipeline脚本必须将相关数据作序列化,然而这一点 Groovy并不能完美的支持,例如collection.each { item -> /* perform operation */ }
共同点: 二者都是pipeline代码的持久实现,都可以使用pipeline内置的插件或者插件提供的steps,二者均可以利用共享库扩展。区别: 二者不一样之处在于语法和灵活性。Declarative pipeline对用户来讲,语法更严格,有固定的组织结构,更容易生成代码段,使其成为用户更理想的选择。可是Scripted pipeline更加灵活,由于Groovy自己只能对结构和语法进行限制,对于更复杂的pipeline来讲,用户能够根据本身的业务进行灵活的实现和扩展。