Jenkins PipeLine
我正在参加「掘金·启航计划」
Jenkins 流水线是一套插件,将持续交付的实现和实施集成到 Jenkins 中。
PipeLine 也就是构建流水线,对于程序员来说,最好的解释就是:使用代码来空值项目的构建、测试、部署等。
使用它的好处有很多,包括但不限于:
- 使用 Pipeline 可以非常灵活的控制整个构建过程
- 可以清楚的知道每个构建阶段使用的时间,方便构建的优化
- 构建出错,使用 stageView 可以快速定位出错的阶段
- 一个 job 可以搞定整个构建,方便管理和维护等
定义流水线使用的是 Groovy 脚本,保存脚本的方式有两种:
- 直接写在Jenkins工程中
- 存放在代码仓库项目目录下的 Jenkinsfile 中。通常认为在 Jenkinsfile 中定义并检查代码控制是最佳实践
上图中的 Pipeline Script 即定义流水线直接写在 Jenkins 工程中,Pipeline script from SCM 就是从代码仓库项目的 Jenkinsfile 中读取流水线。
Pipeline 语法
Jenkinsfile 能使用两种语法进行编写:声明式 和 脚本化
声明式和脚本化的流水线从根本上是不同的。声明式流水线的是 Jenkins 流水线新推出的特性:
- 相比脚本化的流水线语法,它提供更丰富的语法特性
- 更容易编写和读取流水线代码
声明式流水线基础
pipeline {
agent any
stages {
stage('Build') {
steps { }
}
stage('Test') {
steps { }
}
stage('Deploy') {
steps { }
}
}
}
脚本化流水线基础
node {
stage('Build') {
//
}
stage('Test') {
//
}
stage('Deploy') {
//
}
}
声明式 Pipeline 的基本语法(Sections、Directives、Steps、赋值语句)
声明式 Pipeline 的基本语法和表达式遵循与 Groovy 语法相同的规则,但有例外
- 声明式 Pipeline 必须包含在
固定格式 pipeline {} 块内 - 每个声明语句必须独立一行,行尾无需使用分号
- 块只能由
Sections(章节)、Directives(指令)、Steps(步骤)或者赋值语句组成 - 属性引用语句被视为无参数方法调用。例:input 被视为 input()
下文介绍声明式的 Pipeline 的语法
Sections
声明式流水线的 Sections 通常包含一个或多个 Directives 或 Steps。
agent
指定了整个流水线或特定的部分, 将会在Jenkins环境中执行的位置,这取决于 agent 区域的位置。该部分必须在 pipeline 块的顶层被定义, 但是 stage 级别的使用是可选的。
| 参数 | 说明 |
|---|---|
| any | 在任何可用的代理上执行流水线或阶段。如:agent any |
| none | 在 pipeline 块的顶部没有全局变量,该参数将会被分配到整个流水线的运行中并且每个 stage 部分都需要包含他自己的 agent 部分。如:agent any |
| label | 在提供了标签的 Jenkins 环境中可用的代理上执行流水线或阶段。 |
| docker | 使用给定的容器执行流水线或阶段。 |
| dockerfile | 执行流水线或阶段, 使用从源代码库包含的 Dockerfile 构建的容器。 |
post
post 定义一个或多个 steps,这些阶段根据流水线或阶段的完成情况而运行。post 支持以下破石头-condition 块中的其中之一:always、changed、failure、success、unstable 和 aborted。这些条件块允许在 post 部分的步骤的执行取决于流水线或阶段的完成状态。
| Condition | 说明 |
|---|---|
| always | 无论流水线或阶段的完成状态如何,都允许在 post 部分运行该步骤 |
| changed | 只有流水线或阶段的完成状态与他之前的运行不同时,才允许在 post 部分运行该步骤 |
| failure | 只有当前流水线或阶段的完成状态为“failure”,才允许在 post 部分运行该步骤,通常 web UI 是红色的 |
| success | 只有当前流水线或阶段的完成状态为“success”,才允许在 post 部分运行该步骤,通常 web UI 是蓝色或绿色 |
| unstable | 只有当前流水线或阶段的完成状态为"unstable",才允许在 post 部分运行该步骤,通常由于测试失败,代码违规等造成。通常web UI是黄色。 |
| aborted | 只有当前流水线或阶段的完成状态为"aborted",才允许在 post 部分运行该步骤,通常由于流水线被手动的aborted。通常web UI是灰色。 |
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
post {
always {
echo 'I will always say Hello again!'
}
failure {
echo 'pipeline is failure'
}
success {
echo 'pipeline is success'
}
}
}
stages
包含一系列一个或多个 stage 指令,stages 部分是流水线描述的大部分“work”的位置。建议 stages 至少包含一个 stage 指令用于连续交付过程的每个离散部分,比如构建、测试和部署。
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
steps
steps 块定义在 stage 指令中被执行。可以定义一系列一个 step 或多个 step
- 按照惯例,post 部分应该放在流水线的底部。
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
Directive(指令)
stage
stage 指令在 stages 块中定义并且要包含一个 steps 块、一个可选的 agent 块或者其他特定阶段的指令
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
environment(环境变量)
environment 创建一个 键-值对序列,该序列将被定义为所有步骤的环境变量,或者是特定于阶段的步骤, 这取决于 environment 指令在流水线内的位置。
该指令支持一个特殊的助手方法 credentials() ,该方法可用于在Jenkins环境中通过标识符访问预定义的凭证。对于类型为 "Secret Text"的凭证, credentials() 将确保指定的环境变量包含秘密文本内容。
- 顶层流水线块中使用的 environment 指令将适用于流水线中的所有步骤
- 在一个 stage 中定义的 environment 指令只会将给定的环境变量应用于 stage 中的步骤
- environment 块有一个助手方法 credentials() 定义,该方法可以在 jenkins 环境中用于通过标识符访问预定义的凭证
pipeline {
agent any
enviroment {
name = "DBAA"
}
stages {
stage('Start') {
echo "环境变量中name的值为 ${name}"
}
}
}
options
options 指令允许从流水线内部配置特定于流水线的选项。
| 选项 | 说明 |
|---|---|
| buildDiscarder | 为最近的流水线运行的特定数量保存组件和控制台输出。如:options { buildDiscarder(logRotator(numToKeepStr: '1')) } |
| disableConcurrentBuilds | 不允许同时执行流水线。 可被用来防止同时访问共享资源等。如:options { disableConcurrentBuilds() } |
| overrideIndexTriggers | 允许覆盖分支索引触发器的默认处理。 |
| skipStagesAfterUnstable | 一旦构建状态变得 UNSTABLE,跳过该阶段。如:options { skipStagesAfterUnstable() } |
| skipDefaultCheckout | 在agent 指令中,跳过从源代码控制中检出代码的默认情况。 |
| checkoutToSubdirectory | 在工作空间的子目录中自动地执行源代码控制检出。如:options { checkoutToSubdirectory('foo') } |
| retry | 在失败时, 重新尝试整个流水线的指定次数。如:options { retry(3) } |
| timeout | 设置流水线运行的超时时间, 在此之后,Jenkins将中止流水线。如:options { timeout(time: 1, unit: 'HOURS') } |
| timestamps | 预谋所有由流水线生成的控制台输出,与该流水线发出的时间一致。如:options { timestamps() } |
parameters
parameters 指令提供了一个用户在触发流水线时应该提供的参数列表。这些用户指定参数的值可通过 params 对象提供给流水线步骤。
| 可用参数 | 说明 |
|---|---|
| string | 字符串类型的参数。如:string(name: 'branch', defaultValue: 'master', description: '分支名') |
| booleanParam | 布尔参数。如:booleanParam(name: 'isFile', defaultValue: true, description: '是否为文件') |
| text | 文本参数。如:text(name: 'name', defaultValue: 'xiaoming', description: '输入你的名字') |
| choice | 选项参数。如:choice(name: 'ENV_TYPE', choices: ['test', 'dev', 'product'], description: '环境选项') |
| password | 密码参数。如:password(name: 'PASSWORD', defaultValue: '123456', description: '密码') |
triggers(触发器)
triggers 指令定义了流水线被重新触发的自动化方法。对于集成了源(Github 或 BitBucket)的流水线,可能不需要 triggers。
| 触发器 | 说明 |
|---|---|
| cron | 接收 cron 样式的字符串来定义要重新触发流水线的常规间隔。如:triggers { cron('H */4 * * 1-5') } |
| pollSCM | 接收 cron 样式的字符串来定义一个固定的间隔,在这个间隔中,Jenkins 会检查新的源代码更新。如果存在更改, 流水线就会被重新触发。如:triggers { pollSCM('H */4 * * 1-5') } |
| upstream | 接受逗号分隔的工作字符串和阈值。 当字符串中的任何作业以最小阈值结束时,流水线被重新触发。如:triggers { upstream(upstreamProjects: 'job1,job2', threshold: hudson.model.Result.SUCCESS) } |
tools
定义自动安装和放置 PATH 的工具的一部分。如果 agent none 指定,则忽略该操作。
支持的工具有 maven、jdk、gradle
pipeline {
agent any
tools {
maven 'apache-maven-3.0.1'
}
stages {
stage('Example') {
steps {
sh 'mvn --version'
}
}
}
}
input
stage 的 input 指令允许你使用 input step 提示输入。在应用了 options 后,进入 stage 的 agent 或评估 when 条件前,stage 将暂停。如果 input 被批准,stage 将会继续。作为 input 提交的一部分的任何参数都将在环境中用于其他 stage 。
| 配置项 | 说明 |
|---|---|
| message | 必需的。这将在用户提交 input 时呈现给用户 |
| id | input 的可选标识符,默认为 stage 名称 |
| ok | input 表单上的“ok”按钮的可选文本 |
| submitter | 可选的以逗号分隔的用户列表或允许提交 input 的外部组名。默认允许任何用户。 |
| submitterParameter | 环境变量的可选名称。如果存在,用 submitter 名称设置。 |
| parameters | 提示提交者提供的一个可选的参数列表。 |
pipeline {
agent any
stages {
stage('Example') {
input {
message "Should we continue?"
ok "Yes, we should."
submitter "alice,bob"
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
}
}
steps {
echo "Hello, ${PERSON}, nice to meet you."
}
}
}
}
when
when 指令允许流水线根据给定的条件决定是否应该执行阶段。when 指令必须包含至少一个条件,如果 when 指令包含多个条件,所有的子条件必须返回 true,阶段才能执行。这与子条件在 allOf 条件下嵌套的情况相同(可看下面的 allOf 条件)。
| 内置条件 | 说明 |
|---|---|
| branch | 当正在构建的分支与模式给定的分支匹配时,执行这个阶段。如:when { branch 'master' }。注意:该条件只使用于多分支流水线 |
| environment | 当指定的环境变量是给定的值时,执行这个步骤。如:when { environment name: 'DEPLOY_TO', value: 'production' } |
| expression | 当指定的 Groovy 表达式为 true 时,执行这个阶段。如:when { expression { return params.DEBUG_BUILD } } |
| not | 当嵌套条件时错误时,执行这个阶段,必要包含一个条件。如:when { expression { return params.DEBUG_BUILD } } |
| allOf | 当所有的嵌套条件都正确时,执行这个阶段,必须包含至少一个条件,例如: when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } } |
| anyOf | 当至少有一个嵌套条件为真时,执行这个阶段,必须包含至少一个条件,例如: when { anyOf { branch 'master'; branch 'staging' } } |
| 在进入 stage 的 agent 前评估 when | 如果 beforeAgent 被设置为 true, 那么就会首先对 when 条件进行评估 , 并且只有在 when 条件验证为真时才会进入 agent 。 |
Parallel(并行)
声明式流水线的阶段可以在他们内部声明多嵌套 stage,它们将并行执行。注意:一个阶段必须有一个并且只能有一个 steps 或 parallel 的阶段。
pipeline {
agent any
stages {
stage('Non-Parallel Stage') {
steps {
echo 'This stage will be executed first.'
}
}
stage('Parallel Stage') {
when {
branch 'master'
}
failFast true
parallel {
stage('Branch A') {
agent {
label "for-branch-a"
}
steps {
echo "On Branch A"
}
}
stage('Branch B') {
agent {
label "for-branch-b"
}
steps {
echo "On Branch B"
}
}
}
}
}
}
Steps
声明式流水线可以使用所有在流水线步骤引用中记录的步骤,它包含一个完整的步骤列表,其中添加了下面列出的步骤,这些步骤仅仅只能在声明式流水线中使用。
script
script 步骤需要 scripted-pipeline 块并在声明式流水线中执行。
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
script {
def browsers = ['chrome', 'firefox']
for (int i = 0; i < browsers.size(); ++i) {
echo "Testing the ${browsers[i]} browser"
}
}
}
}
}
}
可能出现的问题
Jenkins 构建执行 shell 脚本提示 premission-denied
原因:jenkins 用户的权限不够
解决办法:
- 修改 jenkins 的用户权限
vi /etc/sysconfig/jenkins
# jenkins 文件,修改如下配置
JENKINS_USER="root"
- 修改 jenkins 的用户与组
cd /var/lib
chown -R root:root jenkins
# 重启 jenkins 服务
service jenkins restart
参数化构建功能选了git参数的分支后,拿不到分支变量
解决办法:
不勾选【轻量级检出】