玩转Jenkins Pipeline

Jenkins Pipeline的整体介绍

1.Jenkins Pipeline 的核心概念php

Pipeline,简而言之,就是一套运行于Jenkins上的工做流框架,将本来独立运行于单个或者多个节点的任务链接起来,实现单个任务难以完成的复杂流程编排与可视化。css

Pipeline是Jenkins2.X的最核心的特性,帮助Jenkins实现从CI到CD与DevOps的转变node

Pipeline是一组插件,让Jenkins能够实现持续交付管道的落地和实施。nginx

持续交付管道(CD Pipeline)是将软件从版本控制阶段到交付给用户或客户的完整过程的自动化表现。软件的每一次更改(提交到源代码管理系统)都要通过一个复杂的过程才能被发布。web

Pipeline提供了一组可扩展的工具,经过Pipeline Domain Specific Language(DSL)syntax能够达到Pipeline as Code(Jenkinsfile存储在项目的源代码库)的目的。chrome

Stage:阶段,一个Pipeline能够划分红若干个Stage,每一个Stage表明一组操做,例如:“Build”,“Test”,“Deploy”。docker

注意,Stage是一个逻辑分组的概念,能够跨多个Nodeexpress

Node:节点,一个Node就是一个Jenkins节点,或者是Master,或者是Agent,是执行Step的具体运行环境。ruby

Step:步骤,Step是最基本的操做单元,小到建立一个目录,大到构建一个Docker镜像,由各种Jenklins Plugin提供,例如:sh ‘make’bash

Pipeline五大特性

  1. 代码:Pipeline以代码的形式实现,一般被检入源代码控制,使团队可以编辑、审查和迭代其CD流程。
  2. 可持续性:Jenklins重启或者中断后都不会影响Pipeline Job。
  3. 停顿:Pipeline能够选择中止并等待任工输入或批准,而后再继续Pipeline运行。
  4. 多功能:Pipeline支持现实世界的复杂CD要求,包括fork/join子进程,循环和并行执行工做的能力
  5. 可扩展:Pipeline插件支持其DSL的自定义扩展以及与其余插件集成的多个选项。

Pipeline和Freestyle的区别

这里写图片描述

这里写图片描述

Freestyle:
上游/下游Job调度,如
BuildJob —> TestJob —> DeployJob
在DSL Job里面调度多个子Job(利用Build Flow Plugin)

Pipeline:
单个Job中完成全部的任务编排
全局视图

Multibranch Pipeline根据你的代码中Jenlinsfile自动建立Job

Jenlins Pipeline的基础语法
Pipeline脚本是由Groovy语言实现(无需专门学习)

支持两种语法
Declarative 声明式(在Pipeline plugin 2.5中引入)
Scripted Pipeline 脚本式

如何建立最基本的PIpeline
直接在Jenkins Web UI 网页界面中输入脚本
经过建立一个jenkinsfile能够检入项目的源代码管理库

一般推荐在Jenkins中直接从源代码控制(SCM)中载入Jenklinsfile Pipeline

这里写图片描述

声明式Pipeline

声明式Pipeline的基本语法和表达式遵循与Groovy语法相同的规则,但有如下例外:

  1. 声明式pipeline必须包含在固定格式pipeline{}快内
  2. 每一个声明语句必须独立一行,行尾无需使用分号
  3. 块(blocks{})只能包含章节(Sections),指令(Directives),步骤(Steps)或赋值语句
  4. 属性引用语句被视为无参数方法调用。例:输入被视为 input()

块(blocks{})
由大括号括起来的语句,如pipeline{},Section{},parameters{},script{}
章节(Sections)
一般包含一个或多个指令或步骤。如 agent 、post、stages、steps
指令(Directives)
environment、options、parameters、triggers(触发)、stage、tools、when
步骤(Steps)
Pipeline steps reference
执行脚本式pipeline:使用script{}

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{}中

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

paramenters {
    choice(name:'PerformMavenRelease',choices:'False\nTrue',description:'desc')
    password(name:'CredsToUse',description:'Apassword to build with',defaultValue:'')
}
environment {
    BUILD_USR_CHOICE="${params.PerformMavenRelease}"
    BUILD_USR_CREDS="${params.CredsToUse}"
}

triggers 不是必须的 定义pipeline被自动触发的方式选项 cron、pollSCM、upstream

triggers {cron('H 4/* 0 0 1-5')}
triggers {pollSCM('H 4/* 0 0 1-5')}
triggers {upstream(upstreamProjects:'job1,job2',threshold:hudson.model.Result.SUCCESS)}

快速建立一个pipeline
新建 选择pipeline 填写Job 的名字
这里写图片描述
填写相应的pipeline script

pipeline{
    agent any
    stages {
        stage('Build') {
            steps{
                echo 'This is a build step' 
            }
        }
        stage('Test') {
            steps{
                echo 'This is a test step'  
            }
        }
        stage('Deploy') {
            steps{
                echo 'This is a deploy step'    
            }
        }
    }
}

这里写图片描述

保存以后,当即构建

这里写图片描述

经常使用的辅助工具

  • Snipper Generator(代码片断生成器,语法检查器)
  • Replay Pipeline(重放pipeline,能够修改script,修改后的不存入config.xml)
  • DSL Reference 语法参考手册
  • 全局变量引用
  • Stage View
  • BlueOcean(可视化)
  • Pipeline神器:可视化编辑器
  • 命令行Pipeline调试工具

变量的传递

  1. 自定义变量(局部)
def username = 'Jenkins'
echo "Hello Mr.${username}"
#注意必定要用双引号,单引号识别为字符串
  1. 环境变量(局部)
withEnv(['MYTOOL_HOME=/usr/local/mytool']){ sh '$MYTOOL_HOME/bin/start' }
  1. 环境变量(全局)
environment {CC='clang'}
echo "Compiler is ${env.CC}"
  1. 参数化构建(全局)
parameters {string(name:'Jenkins',defaultValue:'Hello',description:'How should I greet the world')}
ehco "${params.Greeting} World!"

判断
when仅用于stage内部
when的内置条件为:

- when {branch 'master'}  - when {environment name:'DEPLOY_TO',value:'production'} #当有环境变量 name 为 DEPLOY_TO 值是 production 条件成立
 - when {expression {return params.DEBUG_BUILD}} #表达式返回值为真时
 - when {not {branch 'master'}}  - when {allOf {branch 'master'; environment name:'DEBUG_TO',value:'production'}} #allOf 全部条件都知足时
 - when {anyOf {branch 'master' ; branch 'staging'}} #anyOf有一个条件知足时便可

判断和异常处理
流程控制if/else条件

node {
    stage('Example'){
        if(env.BRANCH_NAME == 'master'){
            echo 'I only execute on the master branch'
        }else {
            echo 'Iexecute elsewhere'
        }
    }
}

异常处理try/catch/finally

node{
    stage('Example'){
        try{
            sh 'exit 1'
        }
        catch (exc) {
            echo 'something failed,I should sound the klaxons!'
            throw
        }
    }
}

循环
for循环仅存在域脚本式pipeline中,可是能够经过在声明式pipeline中调用script step来执行

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

并发

并发须要放在stages中,stages能够嵌套使用
stage下的steps和parallel不能共存,只能二选一
使用了并发的stage不能再有agent/tools
强制全部并发任务退出,加参数 failFast true

人工确认