在前文《如何让自己少写点bug?》中已经讨论过持续集成系统(简称CI系统)的重要性,它是企业级开代码质量的重要防护网!持续集成开源工具鳞次栉比,但企业级开发用得最广泛的工具当属Jenkins系统,国内很多的通信大厂、互联网大厂都正在使用中!

Jenkins一直是开源CI&CD软件领导者, 安装简易、配置简单、提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。Jenkins 支持各种运行方式,可通过系统包安装、也可以作为Java程序安装,甚至可以通过Docker来安装。而且Jenkins在企业级开发中可以非常便捷地与SVN、Git等代码管理工具无缝对接!

很多人(或项目)使用Jenkins系统目光还仅仅局限于在Jenkins上建议各种各样的Job来完成CI任务,熟不知该种方式随着Jenkins 2.0版本的发布而逐渐淘汰了,Jenkins 2.0的Pipeline才是大趋势。

已经步入2.0时代的Jenkins系统,最大的特色便是加入了Pipeline流水线功能,Pipeline的加持,让Jenkins系统对项目做持续集成时变得更加灵活和强大。


 Pipeline是什么? 

PipelineJenkins 2.0版本的精华所在,是帮助Jenkins实现从CI到CD华丽转身的关键工具!

所谓Pipeline,简单来说,就是一套运行于Jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂发布流程

Pipeline的实现方式是基于一套Groovy DSL,任何发布流程都可以表述为一段Groovy脚本,并且Jenkins 2.0 Pipeline支持从代码仓库(Git/SVN)直接读取脚本,从而实现了Pipeline as Code的理念。


 为什么要用Pipeline? 

这里主要结合我自己对传统Jenkins Job使用的一些痛点来说:

  • 传统的Jenkins Job难以灵活高效地并行(Job间、节点间、任务间、甚至任务内四个维度的并行)
  • 传统的Jenkins Job日益失控的趋势让我们措手不及,Job太多,CI脚本太离散,维护成本实在太高了,而且很危险,一单Jenkins Server挂了,一切都Game Over了
  • 新拉分支的分支代码CI部署太麻烦了
  • 传统的Jenkins Job显示真的是不太直观啊

我想这些理由应该足以让我们把目光转向Jenkins 2.0新增的Pipeline功能!

Pipeline的功能和优点:

  1. 可暂停性:Pipeline基于Groovy脚本可以实现Job的暂停和等待用户的输入或批准然后继续执行。2. 更灵活的并行任务:通过Groovy脚本可以实现Step,Stage间的并行执行,和更复杂的相互依赖关系。
  2. 可扩展性:通过Groovy的脚本编程更容易按需扩展CI任务。
  3. 优雅型性设计Pipeline = 设计代码,非常符合程序员思维
  4. As Code:集中管理CI脚本、用代码库来管理脚本、从代码库直接读取脚本,从而可以将项目CI迅速拉起来!


 Pipeline原理/流程 

Pipeline为用户设计了三个最最基本的概念:

  • Stage:一个Pipeline可以划分为若干个Stage,每个Stage代表一组操作。注意,Stage是一个逻辑分组的概念,可以跨多个Node。
  • Node:一个Node就是一个Jenkins节点,或者是Master,或者是Agent,是执行Step的具体运行期环境。
  • Step:Step是最基本的操作单元,小到创建一个目录,大到构建一个Docker镜像,由各类Jenkins Plugin提供。

一个典型的Stage View如下图所示:

从图中可以十分方便地看到哪些Stage通过,哪些Stage失败,以及构建的时间。

Jenkins 2.0的Pipeline搭建使用的是Groovy脚本,通过Groovy脚本实现工作流管理的步骤如下:

  • 去Jenkins主界面建立Pipeline任务

实际上更常用的是MultiBranch Pipeline(即多分支的Pipeline),上面的图中截图没有包含,但与普通Pipeline基本类似。

  • 使用Groovy脚本自定义工作流

上图的实例脚本如下:

  1. node {

  2.    stage('Checkout Code') { // for display purposes

  3.        // Get some code from a GitHub repository

  4.        git 'https://github.com/jglick/simple-maven-project-with-tests.git'

  5.    }


  6.    stage('Build') {

  7.        // Run the maven build

  8.        if (isUnix()) {

  9.            sh "'${MAVEN_HOME}/bin/mvn' -Dmaven.test.failure.ignore clean package"

  10.        } else {

  11.            bat(/"${MAVEN_HOME}\bin\mvn" -Dmaven.test.failure.ignore clean package/)

  12.        }

  13.    }


  14.    stage('Unit test') {

  15.        junit '**/target/surefire-reports/TEST-UT.xml'

  16.        archive 'target/*.jar'

  17.    }

  18. }

  • 开始执行Pipeline

构建过程的stage View如下:

很明显可以看出,这里显示的和Groovy脚本中格式化的代码是一致的,会实时显示各个工作流的执行进度和结果,直观易懂。鼠标移上去,能看到日志信息的缩略图,单击可以调到对应stage的console中。

总而言之,一切都是那么地优雅!


 Pipeline关键DSL语法 

在这里总结一下Pipeline中的关键DSL语法,利用Groovy对其进行组合可以完成任何一项复杂的CI/CD流程,熟悉它们大有裨益。

  • archiveArtifacts

归档文件,举例:

archiveArtifacts 'target/*.jar'
  • bat

执行windows平台下的批处理文件,如

bat "call example.bat"
  • build

触发构建一个jenkins job,如

build 'TEST_JOB'
  • checkout

从SCM系统中checkout repo,如:

checkout([$class: 'SubversionSCM', additionalCredentials: [], excludedCommitMessages: '', excludedRegions: '', excludedRevprop: '', excludedUsers: '', filterChangelog: false, ignoreDirPropChanges: false, includedRegions: '', locations: [[credentialsId: '30e6c1e5-1035-4bdd-8a44-05ba8f885158', depthOption: 'infinity', ignoreExternalsOption: true, local: '.', remote: 'svn://xxxxxx']], workspaceUpdater: [$class: 'UpdateUpdater']])
  • deleteDir()

从workspace中删除当前目录

  • dir

切换目录,如

dir('/home/jenkins'){// 切换到/home/jenkins目录中做一些事情 // some block }

  • echo

打印信息,如 echo 'hello world'

  • emailtext

利用Jenkins发送邮件,内容、主题全都可以自定义,如

emailext body:'Subject_test',subject:'Subject_test',to:'hansonwang99@163.com.cn' // 邮件的正文body,主题subject,收件人to等可以进行自定义

  • error

抛出一个错误信号,可以自行在代码里抛出,如 error 'read_error'

  • fileExists

检查工作空间某个路径里是否存在某个file,举例:

fileExists '/home/test.txt'  // 检查是否存在test.txt
  • input

等待外界用户的交互输入,举例:

input message: '', parameters: [string(defaultValue: '默认值', description: '版本号', name: 'version')] // 在某一步骤,等待用户输入version参数才能往下执行
  • isUnix

用于判断当前任务是否运行于Unix-like节点上,举例:

defflag =isUnix() if(flag ==false){// 可以据此进行判断 echo "not run on a unix node !" }

  • load

调用一个外部groovy脚本,举例:

load 'D:\\jenkins\\workspace\\test.groovy'
  • node

分配节点给某个任务运行,举例:

node('节点标签') { // 在对应标签的节点上运行某项任务    Task()}
  • parallel

并行地执行任务,可以说是最实用高效的工具了,举例:

parallel(   //并行地执行android unit tests和android e2e tests两个任务    'android unit tests': {        runCmdOnDockerImage(androidImageName, 'bash /app/ContainerShip/scripts/run-android-docker-unit-tests.sh', '--privileged --rm')    },    'android e2e tests': {    runCmdOnDockerImage(androidImageName, 'bash /app/ContainerShip/scripts/run-ci-e2e-tests.sh --android --js', '--rm')    })
  • properties: 

设置Job的属性,举例:

properties([parameters([string(defaultValue: '1.0.0', description: '版本号', name: 'VERSION')]), pipelineTriggers([])]) // 为job设置了一个VERSION参数
  • pwd

    显示当前目录

  • readFile

从工作空间中读取文件,举例:

def editionName = readFile '/home/Test/exam.txt'
  • retry

重复body内代码N次,举例:

retry(10) {    // some block}
  • sh

执行shell脚本,如:sh "sh test.sh"

  • sleep

延时,如延时2小时:sleep time: 2, unit: 'HOURS'

  • stage

创建任务的stage,举例:

stage('stage name') {    // some block}
  • stash

存放文件为后续构建使用,举例:

dir('target') {    stash name: 'war', includes: 'x.war'}
  • unstash

将stash步骤中存放的文件在当前工作空间中重建,举例:

def deploy(id) {    unstash 'war'    sh "cp x.war /tmp/${id}.war"}
  • timeout

时间限制,举例

timeout(time: 4, unit: 'SECONDS') {    // some block}
  • timestamps

    用于在控制台加时间戳,举例:

timestamps {    // some block}
  • touch

创建文件,举例:

touch file: 'TEST.txt', timestamp: 0
  • unzip

    解压文件,举例:

unzip dir: '/home/workspace', glob: '', zipFile: 'TEST.zip'
  • validateDeclarativePipeline

检查给定的文件是否包含一个有效的Declarative Pipeline,返回T或者F

validateDeclarativePipeline '/home/wospace'
  • waitUntil

等待,直到条件满足

waitUntil {    // some block}
  • withCredentials

使用凭据

withCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) {    sh '''      set +x      curl -u $USERPASS https://private.server/ > output    '''}
  • withEnv

设置环境变量,注意近本次运行有效!

withEnv(['MYTOOL_HOME=/usr/local/mytool']) {    sh '$MYTOOL_HOME/bin/start'}
  • writeFile

写文件到某个路径

writeFile file: '/home/workspace', text: 'hello world'
  • writeJSON

写JSON文件,用法基本同上

  • zip

创建zip文件

zip dir: '/home/workspace', glob: '', zipFile: 'TEST.zip'
  • ws

自定义工作空间,在其中做一些工作,效果类似于Dir命令,举例:

ws('/home/jenkins_workspace') {    // some block}

后   记

若有错误或者不当之处,可在本公众号内反馈,一起学习交流!

更多热文在此:

  ●  Spring Boot 系列实战文章合集(源码已开源)

  ●  程序员写简历时必须注意的技术词汇拼写

  ●  前后端都分离了,该搞个好用的API管理系统了!

  ●  从一份配置清单详解Nginx服务器配置

  ●  如何在Windows下像Mac一样优雅的开发

  ●  Docker容器可视化监控中心搭建

  ●  利用ELK搭建Docker容器化应用日志中心

  ●  真实IT领域2/8法则,扎心了!

  ●  一文详解 Linux系统常用监控工具


更多 务实、能看懂、可复现的 技术文章、资源尽在公众号 CodeSheep,欢迎扫码订阅,第一时间获取更新 ⬇️⬇️⬇️


©著作权归作者所有:来自51CTO博客作者mb5fdcae83766b7的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. Vue.js流程图插件 可自定义流程节点事件
  2. hadoop 3节点高可用分布式安装
  3. shell脚本之灵活调用函数技巧
  4. Shell脚本高效检测主机存活
  5. 【从0到1学习边缘容器系列-4】弱网环境利器之分布式节点状态判定
  6. 分布式作业 Elastic-Job-Lite 源码分析 —— 主节点选举
  7. CentOS7 上搭建多节点 Elasticsearch集群
  8. 5、Shell命令脚本
  9. 脚本实现Oracle19c_pdb单实例自动安装部署

随机推荐

  1. 使用U3D 实现 Android(安卓)Launcher(提
  2. android 按行读取txt文本内容
  3. Android(安卓)Studio 工程.GitIgnore应该
  4. android 底部弹出提示框的实现方式
  5. Android 软件盘回车键修改
  6. Android不同版本的新特性
  7. 2013年01月小记
  8. Android中LayoutInflater实例
  9. [Unity3D]Android实现手机震动功能
  10. Android ListView圆角