Jenkins 2.0开始推行Pipeline as Code,实现从CI到CD的转变。 Pipeline实际上是一套Groovy DSL,用Groovy脚本描述CI/CD的流程,Jenkins可以从代码库中获取脚本,实现了Pipeline as Code。Pipeline将原来独立运行的多个任务连接起来,可以实现更加复杂的CI/CD流程。

为什么要使用Pipeline?对于实践微服务的团队,产品有很多服务组成,传统的在Jenkins中集中进行job配置的方式会成为瓶颈,微服务团队会将CI Job的配置和服务的发布交给具体负责某个服务的团队,这正需要Pipeline as Code; 除此之外,一次产品的发布会涉及到多个服务的协同发布,用单个CI Job实现起来会十分困难,使用Pipeline可以很好的完成这个需求。

1.Pipeline的基本概念和Jenkinsfile

  • Node:一个Node就是一个Jenkins节点,可以是Master,也可以是Slave,是Pipeline中具体Step的运行环境。
  • Stage:一个Pipeline有多个Stage组成,每个Stage包含一组Step。注意一个Stage可以跨多个Node执行,即Stage实际上是Step的逻辑分组。
  • Step:是最基本的运行单元,可以是创建一个目录、从代码库中checkout代码、执行一个shell命令、构建Docker镜像、将服务发布到Kubernetes集群中。Step由Jenkins和Jenkins各种插件提供。

将node、stage、step的Groovy DSL写在一个Jenkinsfile文件中,Jenkinsfile会被放到代码库的根目录下。下面是一个Jenkinsfile的Helloworld的例子:

 1node {
 2   stage('prepare') {
 3       echo 'prepare step1'
 4       echo 'prepare step2'
 5   }
 6   stage('build') {
 7       echo 'build step1'
 8       echo 'build step2'
 9   }
10   stage('deploy') {
11       echo 'deploy step1'
12       echo 'deploy step2'
13   }
14}

2.常用的Step

由于Jenkins的Pipeline是基于Groovy的DSL,所以使用起来十分简单,编写Jenkinsfile的过程实际上就是使用各种Step编排完成CI/CD的过程。 Pipeline Steps Reference Pipeline: Basic Steps是Pipeline Step的文档地址,在编写Jenkinsfile时可以根据需要去查找。 下面简单列举一些常用的Step。

2.1 切换当前的目录

1dir('dir1') {
2    sh 'pwd'
3}

如果切换的目录不存在,将会创建这个目录。

2.2 签出指定分支或tag的代码

从git中获取指定分支的代码:

1git url: 'ssh://[email protected]/demo/apidemo.git', branch: 'develop'

如果需要获取指定tag的代码,需要使用Pipeline: SCM Step的checkout:

1checkout scm: [$class: 'GitSCM', 
2      userRemoteConfigs: [[url: 'ssh://[email protected]/demo/apidemo.git']], 
3      branches: [[name: "refs/tags/1.1.0"]]], changelog: false, poll: false

2.3 修改当前构建的名称和描述

1script {
2    currentBuild.displayName = "#${BUILD_NUMBER}(apidemo)"
3    currentBuild.description = "publish apidemo"
4}

2.4 使用Jenkins全局工具

在Jenkins -> Manage Jenkins -> Global Tool Configuration中配置了各种工具,如JDK、Git、Maven、Gradle、NodeJS、Go、Docker等等。 每种工具都有一个Name,这样不同的Name可以配置不同的版本。可以在Jenkins Pipeline中使用这些工具,例如下面是一个使用gradle构建java工程的例子:

1node {
2   def javaHome = tool 'JDK1.8'
3   def gradleHome = tool 'gradle'
4   env.PATH = "${javaHome}/bin:${env.PATH}"
5   env.PATH = "${gradleHome}/bin:${env.PATH}"
6   stage('build') {
7      sh 'gradle clean --refresh-dependencies build -x test'
8   }
9}

2.5 发送邮件通知

使用Email Extension Plugin的emailext实现,需要提前在jenkins完成Email Extension Plugin的配置。

 1node {
 2   try{
 3      stage('buid') {
 4         sh 'pwd1'
 5      }
 6      
 7   }catch(e) {
 8       emailext (
 9       subject: "Build failed in Jenkins: '${env.JOB_NAME} #${env.BUILD_NUMBER}'",
10       body: """<p>See "<a href="${env.BUILD_URL}">${env.JOB_NAME} #${env.BUILD_NUMBER}</a>"</p>""",
11       recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']]
12       )
13       throw e
14   }
15}

参考