02. CI/CD - Jenkins Pipeline(声明式语法)
Pipeline
Pipeline 是一套运行在 Jenkins 上的工作流框架,它能将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。
关于 Jenkins Pipeline:
- Pipeline 脚本是由 Groovy 语言实现的,但是没必要单独去学习 Groovy。
- Pipeline 支持两种语法:Declarative(声明式)和 Scripted Pipeline(脚本式)。
- Pipeline 有两种创建方法:直接在 Jenkins 的 Web UI 中输入脚本,通过创建一个
Jenkinsfile
脚本文件放入项目源码库中使用。 - 一般推荐在 Jenkins 中直接从源代码控制(SCMD)中直接载入 Jenkinsfile Pipeline 这种方法。
在使用之前,需要在 Jenkins 中安装三个插件:
Blue Ocean
:相当于 Jenkins 的 Pipeline 流水线主题。Pipeline
:Pipeline 支持的核心插件。Pipeline: Stage View
:用于在传统界面查看 Pipeline Stage。
安装后从侧边栏打开 Blue Ocean 如图所示:
更多关于 Pipeline 的信息可以在官方文档中看到:
创建 Pipeline
安装 Pipeline 插件之后,再次创建构建就需要选择 流水线
方式的构建了:
如图所示:
这是系统提供的 hello world pipeline 示例:
pipeline {
agent any
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
通过该示例可以发现,Pipeline 核心概念包含三个:
agent
:指定执行节点。stages
:声明步骤。steps
:该步骤具体执行的方法。
执行后查看:
如果 Pipeline 存在问题,可以通过左边的 回放
进行修改调试,等到没问题之后再复制 Pipeline 到配置里面去。
注意,当项目很多的时候,流水线也会很多。它们大致的信息是一样的,如果后期想要修改某个公共的方法,就需要一个一个的去修改构建项目,很麻烦。所以推荐使用版本仓库 Git 对 Pipeline 文件进行统一管理。
声明式语法
声明式语法是 Jenkins Pipeline 内置的方法,它包含系统本身自带的和安装插件之后新增的。
想要使用声明式语法很简单,直接打开 Jenkins 流水线语法生成即可:
用法如图:
其中系统自带的变量也非常重要,这里主要列举几个常用的:
- env:
BRANCH_NAME
:Git 分支名称TAG_NAME
:标签名称BUILD_NUMBER
:本次构建的 IDJOB_NAME
:完整的任务名称,可以是 foo 或者 foo/barJOB_BASE_NAME
:精简的任务名称,如果名称是 foo/bar,则值是 barNODE_NAME
:执行节点的名称JENKINS_URL
:访问地址http://server:port/
JOB_URL
:任务地址http://server:port/job/foo/
BUILD_URL
:构建地址http://server:port/job/foo/15/
节点选择(agent)
支持在 pipeline
和 stage
模块中定义,示例:
pipeline {
// 任意 agent 上面执行
agent any
// 在指定标签的 agent 上运行,在 Kubernetes 环境下比较实用
// agent {
// label 'base'
// }
// 步骤
stages {
stage('节点选择测试') {
steps {
echo "Hello World"
}
}
}
}
变量定义(environment)
支持在 pipeline
和 stage
模块中定义,示例:
pipeline {
// 定义全局环境变量,
environment {
NAME_GLOBAL = "hello"
AGE_GLOBAL = "18"
}
agent any
stages {
stage('环境变量测试') {
// 定义局部环境变量
environment {
NAME_LOCAL = "world"
AGE_LOCAL = "20"
}
steps {
// 输出变量信息,注意,变量使用和 Shell 中一样,单引号则会原样输出
echo "全局变量:${NAME_GLOBAL}-${AGE_GLOBAL}"
echo "局部变量:${NAME_LOCAL}-${AGE_LOCAL}"
// 输出系统变量,在使用的时候也可以使用 ${env.BUILD_NUMBER} 这种形式
echo "构建ID:${BUILD_NUMBER}"
echo "任务名称:${JOB_NAME}"
echo "任务名称简写:${JOB_BASE_NAME}"
echo "节点名称:${NODE_NAME}"
echo "Jenkins 地址:${JENKINS_URL}"
echo "任务地址:${JOB_URL}"
echo "构建地址:${BUILD_URL}"
}
}
}
}
参数化构建(parameters)
支持在 pipeline
模块中定义,示例:
pipeline {
// 参数和变量的使用方法类似,但是参数支持更多的类型
parameters {
booleanParam defaultValue: true, description: '布尔参数', name: 'BOOL_PARAM'
choice choices: ['java', 'python', 'golang'], description: '选项参数', name: 'CHOICE_PARAM'
string defaultValue: 'hello world', description: '字符串参数', name: 'STRING_PARAM', trim: true
}
agent any
stages {
stage('参数化构建测试') {
steps {
// 参数化构建的值调用需要 ${params.xxx} 的方式
echo "布尔参数:${params.BOOL_PARAM}"
echo "选项参数:${params.CHOICE_PARAM}"
echo "字符串参数:${params.STRING_PARAM}"
}
}
}
}
在参数化构建第一次执行后,Jenkins 任务会变成参数化构建配置:
构建设置(options)
支持在 pipeline
模块中定义,示例:
pipeline {
// 构建设置
options {
// 用的比较多的就是 buildDiscarder(丢弃旧的构建)
buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '7', numToKeepStr: '10')
disableConcurrentBuilds()
}
agent any
stages {
stage('构建设置') {
steps {
echo "hello world"
}
}
}
}
构建后续(post)
根据构建结果判断下一步做什么,支持在 pipeline
和 stage
模块中定义,示例:
pipeline {
agent any
stages {
stage('构建后续') {
steps {
echo "hello world"
sleep 30
}
}
}
// 该配置类似与其它编程语言的 switch,在 Jenkins 中一般用于发通知
post {
// 无论如何都会执行
always {
echo "always"
}
// 构建终止执行
aborted {
echo "aborted"
}
// 构建成功执行
success {
echo "success"
}
// 构建失败执行
failure {
echo "failure"
}
}
}
触发构建(triggers)
一般用于配置定时构建,支持在 pipeline
模块中定义,示例:
pipeline {
// 每五分钟触发一次构建
triggers {
cron 'H/5 * * * *'
}
agent any
stages {
stage('触发构建') {
steps {
echo "hello world"
}
}
}
}
用户输入(input)
用的不多,一般不会使用这种方法配置,支持在 stage
模块中定义,示例:
pipeline {
agent any
stages {
stage('用户输入') {
// 用户输入
input {
message '请选择想要发布的环境'
ok '确认'
// 用于接收执行这个 input 的用户
submitterParameter 'INPUT_USER'
parameters {
choice choices: ['test', 'dev', 'prod'], description: '发布环境', name: 'ENV_NAME'
}
}
steps {
echo "执行的用户是:${INPUT_USER}"
}
}
}
}
根据情况执行(when)
一般在多条件的情况下会使用到它,支持在 stage
模块中定义,示例:
pipeline {
agent any
stages {
stage('用户输入') {
// 用户输入
input {
message '请选择想要发布的环境'
ok '确认'
parameters {
choice choices: ['test', 'dev', 'prod'], description: '发布环境', name: 'ENV_NAME'
}
}
steps {
echo "hello world"
// 定义全局变量,让后面使用到它,注意,变量需要括起来
script {
env.ENV_NAME = "${ENV_NAME}"
}
}
}
stage('生产环境') {
when {
environment name: 'ENV_NAME', value: 'prod'
}
steps {
echo "开始发布生产环境"
}
}
stage('其它环境') {
when {
anyOf {
environment name: 'ENV_NAME', value: 'test'
environment name: 'ENV_NAME', value: 'dev'
}
}
steps {
echo "开始发布其它环境"
}
}
stage('发布完成') {
steps {
echo "发布完成"
}
}
}
}
以上就是 Jenkins Pipeline 自带的常用声明式语法。
其它方法
除此上面自带的方法之外,用户在安装插件之后也会新增一些语法。这些都可以使用 片段生成器
直接生成。
其中常用的包含:
build
:触发另外一个构建deleteDir
:删除目录dir
:切换目录,然后执行echo
:输出自定义内容error
:手动抛出错误fileExists
:判断文件是否存在git
:用于拉取代代码parallel
:用于并行执行retry
:重试script
:嵌入 Groovy 脚本sh
:执行脚本sleep
:等待时间timeout
:超时时间