【DevOps相关】Jenkins pipeline学习(流水线
在之前的文章中,相当于Jenkins入门:
- 【DevOps相关】安装Jenkins并配置插件,介绍了如何在Docker中安装Jenkins并配置JDK, Maven以及一些插件,如:Git Parameter, Publish over SSH
- 【DevOps相关】通过Jenkins从git上拉取并push到远程服务器,主要讲了本地项目是如何通过Jenkins push到远程服务器中(本地项目--> git远程仓库 --> Jenkins拉取并maven build --> 使用Publish over SSH push到目标服务器 --> 通过Dockerfile在目标服务器中run项目),这里新建的Jenkins项目类型是FreeStyle project。
- 【DevOps相关】Jenkins通过git parameter插件基于git branch构建项目,额外介绍了Git Parameter插件的使用,主要可以用来根据git的branch或tag动态build某个分支上的代码。
除了构建一个自由风格的软件项目外,今天这篇主要讲Jenkins pipeline:
image.png【本文内容】
- 如何使用
Jenkinsfile
来做类型是pipeline
的Jenkins项目的build -
Jenkinsfile
语法学习:-
post
标签,在所有的stage
执行完成之后执行。 - 使用
Conditionals
/When
表达式 - 使用环境变量——
Environmental Variables
(包含Jenkins自带的和自定义的),简单介绍了credentials
和withCredentials
- 使用
tools
标签来激活build工具 - 使用
parameters
- 引入额外的
groovy scripts
-
- 回放功能
网上也有很多文章写的很好:
- jenkins学习之pipeline:https://zhuanlan.zhihu.com/p/41604558
- Jenkins的pipeline项目:https://www.jianshu.com/p/395181d6f575
- 也可通过视频来学习:https://www.youtube.com/watch?v=7KCS70sCoK0
1. Jenkinsfile
对于Jenkins的pipeline来说,Jenkinsfile很重要。它相当于是用code的形式来代替Jenkins GUI上创建jobs的功能。我们可以在自己的项目中创建Jenkinsfile,把jobs通过代码的形式来定义出来。
一个sample: image.pngJenkinsfile有两种语法形式:
一种是Scripted,是最开始就有的语法。用的是groovy引擎,类似:
node {
// groovy script
}
这种语法的优势在于功能强大,自由度也很高,缺点是对于不会groovy的人不友好,上手难。
另一种是Declarative风格的,这种语法是后来新增的,比较容易上手,因为它会预定义好很多框框,我们只要按照一定的语法往里面填就行了。缺点是功能没有上面的强大。类似:
pipeline {
agent any
stages {
stage("build") {
steps {
// todo
}
}
}
}
node开头的语法,就相当于是pipeline + agent any开头,两者作用是一样的。
2. 学习Declarative风格的Jenkinsfile
- pipeline:是必须有的语义结构,且必须在最前面。
- agent:where to execute,any表示可在任何可用的机器上执行pipeline
- stages:where the "work" happens,在它里面,可以定义很多个stage,比如定义build stage,test stage,deploy stage等。
- steps:定义jenkins需要执行的逻辑。
3. 写一个demo
3.1 在项目中编写Jenkinsfile文件:
pipeline {
agent any
stages {
stage("build") {
steps {
echo 'building the application...'
}
}
stage("test") {
steps {
echo 'testing the application...'
}
}
stage("deploy") {
steps {
echo 'deploying the application...'
}
}
}
}
3.2 提交到git仓库:
image.png我在git上有4个分支,我把Jenkinsfile推送至两个分支:
image.png3.3 创建一个多分支流水线(Multibranch Pipeline)
添加Git:
关于凭据的添加,可以参考之前的博文:https://www.jianshu.com/p/533f15b25d42
这里选择的是所有的分支。
【点击确定后,查看日志】
可以看到只有两个branch下有Jenkinsfile,所以另外两个会skip:
点击左侧状态,可以看到两个分支:
这里为什么上次成功时间不一致主要是因为一开始我只在master分支下写了Jenkinsfile。
点击具体的名称后,如点击【master】,可以看到master分布的三个stage(我们在#3.1中定义的):
image.png鼠标移上去可以查看每个stage的log:
image.png具体的log:
image.png3.4默认读取的配置是Jenkinsfile
如果想要改配置文件名,可以在Jenkins 项目详情左侧【配置】中,有个tab叫【Build Configuration】中改: image.png通过上述的例子,我们也发现,基于pipeline的Jenkins项目,脱离了原先的基于GUI的配置,而是使用Jenkinsfile来配置项目,重点就在于如何编写Jenkinsfile。
4. post标签介绍
在所有的stage执行完成之后,我们可以使用post标签来执行接下来的逻辑。
post包含了一些条件:
- always:表示无论build成功还是失败,都会执行。比如发送邮件。
- success:表示build成功后会执行的逻辑。
- failure:表示build失败后会执行的逻辑。
pipeline {
agent any
states {
}
post {
always {
//
}
}
5. 使用Conditionals / When表达式
另一个很有用的功能是,给每个stage定义Conditionals或expression。
5.1 比如我们的test stage只想在dev branch下跑。
展开来讲就是什么条件下,test stage才会生效。比如:
stage("test") {
when {
expression {
BRANCH_NAME == 'dev' || BRANCH_NAME == 'master'
}
steps {
echo 'testing the application...'
}
}
}
5.2 比如build stage只有在dev并且有code改动的时候跑。
这时候CODE_CHANGE的判断就需要使用groovy去写了。
CODE_CHANGE = getGitChange() // to-do, use groovy
pipeline {
agent any
stages {
stage("build") {
when {
expression {
BRANCH_NAME == 'dev' && CODE_CHANGES == true
}
}
steps {
echo 'building the application...'
}
}
}
}
6. 在Jensinsfile中使用环境变量(Environmental Variables)
6.1 使用Jenkins内置的环境变量
可以通过http://localhost:8080/env-vars.html/查看所有的已经预设的环境变量:
6.2 自定义环境变量
在定义的时候,使用标签environment定义,通常value可以从代码中拿,示例是hardcode。在使用的时候,可以通过${}拿。echo的时候需要使用双引号。
还可以通过方法credentials拿到Jenkins中认证,因为有些stage中的插件需要经过Credintials绑定后才可使用。详细参考博文:https://www.jianshu.com/p/6e1c33165af9
pipeline {
agent any
environment {
CUSTOM_TAG = "tag 123"
SERVER_CREDINTIALS = credentials('github')
}
stages {
stage("build") {
steps {
echo 'building the application...'
echo "get custom tag = ${CUSTOM_TAG}"
}
}
}
}
比如以下凭证,就可以通过credentials('github')拿到:
image.png
有时候针对不同的环境,需要更多用法,比用使用:withCredentials:
stage {
steps {
echo 'deploying the application...';
withCredentials([
usernamePassword(credentials: 'github', userVariable: USER, passwordVariable: PWD)
]) {
sh "use the ${USER} and ${PWD} here "
}
])
}
}
注:想要使用方法credentials和withCredentials,需要在Jenkins安装以下插件:
image.png
7. 使用Tools标签来激活build tools(即:自动安装工具)
build tools可以有:build tools:js, jdk, maven, gradle, yarn等等。
比如在steps里可以使用sh "mvn clean package"这种命令,那么需要预先安装好maven(Jenkins支持在全局工具管理中自动安装:gradle, maven以及jdk)。
如何查看名字?
Jenkins首页,左侧【系统管理】-->【全局工具管理】:
比如这里我的maven name叫:maven 3.6.3,那么在Jenkinsfile里可以使用tools标签来声明:
在tools中声明,然后在steps中使用:
pipeline {
agent any
tools {
maven 'maven 3.6.3'
}
stages {
stage ("build") {
steps {
sh 'mvn clean package'
}
}
}
}
8. 使用Parameters
可以在parameters标签中预定义一些参数,string表示需要输入的参考,如果是choice,表示可以进行select选择。
除了string,choice和booleanParam类型,还可以有text,file和password类型。
定义好的parameters,在stage里可以通过params.name来引用:
pipeline {
agent any
parameters {
string(name: 'VERSION', defaultValue: '', description: 'version to deploy')
choice(name: 'SELECT_VERSION', choices: ['v1.0', 'v1.1'], description: 'select target version')
booleanParam(name: 'TEST_FLAG', defaultValue: true, description: '')
}
stages {
stage("test") {
when {
expression {
params.TEST_FLAG == true
}
}
steps {
echo 'testing the application...'
}
}
stage ("deploy") {
steps {
echo 'deploying the application...'
echo "deploying the version with: ${params.SELECT_VERSION}"
}
}
}
}
choice和booleanParam放到Jenkinsfile中测试下,修改到master下的Jenkinsfile。在Jenkins pipeline master的页面,可以看到左侧多了【Build With Parameters】:
image.png点进去可以看到我们预定义的choice和booleanParam:
image.png选择v1.1和testFlag=true,开始构建:
可以看到build成功了,因为testFlag=true,所以test stage也会跑。
image.png 查看deploy的log,也能顺利打印出build页选择的version: image.png
那么如果testFlag=false呢?这时候test stage就会跳过,即变成灰色:
image.png
9. 引入额外的Groovy scripts
我们可以在steps中引入groovy script,例如我们写一个sample groovy脚本,文件名叫:sample.groovy
def buildApp() {
echo 'building the application...'
}
return this
如何在Jenkinsfile中引用:
def gv
stages {
stage ("init") {
steps {
script {
gv = load "sample.groovy"
}
}
}
stage ("build") {
steps {
script {
gv.buildApp()
}
}
}
}
注:在sample.groovy中,可以直接使用${params.TEST_FLAG}这样定义过的parameters。